gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/sm2soft/sm2.go (about) 1 // Copyright (c) 2022 zhaochun 2 // core-gm is licensed under Mulan PSL v2. 3 // You can use this software according to the terms and conditions of the Mulan PSL v2. 4 // You may obtain a copy of Mulan PSL v2 at: 5 // http://license.coscl.org.cn/MulanPSL2 6 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 7 // See the Mulan PSL v2 for more details. 8 9 /* 10 sm2soft 是sm2的纯软实现,基于tjfoc国密算法库`tjfoc/gmsm`做了少量修改。 11 对应版权声明: thrid_licenses/github.com/tjfoc/gmsm/版权声明 12 */ 13 14 package sm2soft 15 16 // reference to ecdsa 17 import ( 18 "bytes" 19 "crypto" 20 "crypto/elliptic" 21 "crypto/rand" 22 "encoding/asn1" 23 "encoding/binary" 24 "errors" 25 "io" 26 "math/big" 27 28 "gitee.com/ks-custle/core-gm/sm3" 29 "golang.org/x/crypto/cryptobyte" 30 cbasn1 "golang.org/x/crypto/cryptobyte/asn1" 31 ) 32 33 var ( 34 defaultUid = []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38} 35 C1C3C2 = 0 36 C1C2C3 = 1 37 ) 38 39 // PublicKey SM2公钥结构体 40 type PublicKey struct { 41 elliptic.Curve // 椭圆曲线 42 X, Y *big.Int // 公钥座标 43 } 44 45 func (pub *PublicKey) Equal(x crypto.PublicKey) bool { 46 xx, ok := x.(*PublicKey) 47 if !ok { 48 return false 49 } 50 return pub.X.Cmp(xx.X) == 0 && pub.Y.Cmp(xx.Y) == 0 && 51 // Standard library Curve implementations are singletons, so this check 52 // will work for those. Other Curves might be equivalent even if not 53 // singletons, but there is no definitive way to check for that, and 54 // better to err on the side of safety. 55 pub.Curve == xx.Curve 56 } 57 58 // PrivateKey SM2私钥结构体 59 type PrivateKey struct { 60 PublicKey // 公钥 61 D *big.Int // 私钥,[1,n-1]区间的随机数 62 } 63 64 type sm2Cipher struct { 65 XCoordinate *big.Int 66 YCoordinate *big.Int 67 HASH []byte 68 CipherText []byte 69 } 70 71 // Public The SM2's private key contains the public key 72 func (priv *PrivateKey) Public() crypto.PublicKey { 73 return &priv.PublicKey 74 } 75 76 func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool { 77 xx, ok := x.(*PrivateKey) 78 if !ok { 79 return false 80 } 81 return priv.PublicKey.Equal(&xx.PublicKey) && priv.D.Cmp(xx.D) == 0 82 } 83 84 var errZeroParam = errors.New("zero parameter") 85 var one = new(big.Int).SetInt64(1) 86 var two = new(big.Int).SetInt64(2) 87 88 // sign format = 30 + len(z) + 02 + len(r) + r + 02 + len(s) + s, z being what follows its size, ie 02+len(r)+r+02+len(s)+s 89 90 // Sign 使用priv私钥对签名内容摘要做SM2签名,参数signer目前没有使用,但仍要求传入外部对明文消息做摘要的散列算法。 91 // 返回的签名为DER字节数组,对(r,s)做了asn1编码。 92 // - random : 随机数获取用, 如 rand.Reader 93 // - signContentDigest : 签名内容摘要(散列值) 94 // - signer : 外部对签名内容进行摘要计算使用的散列函数 95 // 96 //goland:noinspection GoUnusedParameter 97 func (priv *PrivateKey) Sign(random io.Reader, signContentDigest []byte, signer crypto.SignerOpts) ([]byte, error) { 98 r, s, err := Sm2Sign(priv, signContentDigest, nil, random) 99 if err != nil { 100 return nil, err 101 } 102 var b cryptobyte.Builder 103 b.AddASN1(cbasn1.SEQUENCE, func(b *cryptobyte.Builder) { 104 b.AddASN1BigInt(r) 105 b.AddASN1BigInt(s) 106 }) 107 return b.Bytes() 108 } 109 110 // SignASN1 使用私钥priv对一个hash值进行签名。 111 // 返回的签名为DER字节数组,对(r,s)做了asn1编码。 112 // 113 //goland:noinspection GoUnusedExportedFunction 114 func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) { 115 return priv.Sign(rand, hash, nil) 116 } 117 118 // Verify 使用pub公钥对签名sig做验签。 119 // - signContentDigest : 签名内容摘要(散列值) 120 // - sig : 签名DER字节数组(对(r,s)做了asn1编码,因此会先做asn1解码) 121 func (pub *PublicKey) Verify(signContentDigest []byte, sig []byte) bool { 122 var ( 123 r, s = &big.Int{}, &big.Int{} 124 inner cryptobyte.String 125 ) 126 input := cryptobyte.String(sig) 127 if !input.ReadASN1(&inner, cbasn1.SEQUENCE) || 128 !input.Empty() || 129 !inner.ReadASN1Integer(r) || 130 !inner.ReadASN1Integer(s) || 131 !inner.Empty() { 132 return false 133 } 134 return Sm2Verify(pub, signContentDigest, defaultUid, r, s) 135 } 136 137 // VerifyASN1 使用公钥pub对hash和sig进行验签。 138 // - pub 公钥 139 // - hash 签名内容摘要(散列值) 140 // - sig 签名DER字节数组(对(r,s)做了asn1编码,因此会先做asn1解码) 141 // 142 //goland:noinspection GoUnusedExportedFunction 143 func VerifyASN1(pub *PublicKey, hash, sig []byte) bool { 144 return pub.Verify(hash, sig) 145 } 146 147 // Sm3Digest 对签名内容进行SM3摘要计算,摘要计算前混入sm2椭圆曲线部分参数与公钥并预散列一次。 148 func (pub *PublicKey) Sm3Digest(msg, uid []byte) ([]byte, error) { 149 if len(uid) == 0 { 150 uid = defaultUid 151 } 152 153 za, err := ZA(pub, uid) 154 if err != nil { 155 return nil, err 156 } 157 158 e, err := msgHash(za, msg) 159 if err != nil { 160 return nil, err 161 } 162 163 return e.Bytes(), nil 164 } 165 166 //****************************Encryption algorithm****************************// 167 168 // EncryptAsn1 sm2加密,C1C3C2,asn1编码 169 func (pub *PublicKey) EncryptAsn1(data []byte, random io.Reader) ([]byte, error) { 170 return EncryptAsn1(pub, data, random) 171 } 172 173 // DecryptAsn1 sm2解密,C1C3C2,asn1解码 174 func (priv *PrivateKey) DecryptAsn1(data []byte) ([]byte, error) { 175 return DecryptAsn1(priv, data) 176 } 177 178 //**************************Key agreement algorithm**************************// 179 180 // KeyExchangeB 协商第二部,用户B调用, 返回共享密钥k 181 func KeyExchangeB(klen int, ida, idb []byte, priB *PrivateKey, pubA *PublicKey, rpri *PrivateKey, rpubA *PublicKey) (k, s1, s2 []byte, err error) { 182 return keyExchange(klen, ida, idb, priB, pubA, rpri, rpubA, false) 183 } 184 185 // KeyExchangeA 协商第二部,用户A调用,返回共享密钥k 186 func KeyExchangeA(klen int, ida, idb []byte, priA *PrivateKey, pubB *PublicKey, rpri *PrivateKey, rpubB *PublicKey) (k, s1, s2 []byte, err error) { 187 return keyExchange(klen, ida, idb, priA, pubB, rpri, rpubB, true) 188 } 189 190 //****************************************************************************// 191 192 // Sm2Sign SM2签名 193 // - priv : 签名私钥 *sm2.PrivateKey 194 // - signContentDigest : 签名内容摘要(散列值) 195 // - uid : 内部混合摘要计算用uid, 长度16的字节数组,可以传 nil 196 // - random : 随机数获取用 197 func Sm2Sign(priv *PrivateKey, signContentDigest, uid []byte, random io.Reader) (r, s *big.Int, err error) { 198 // 对签名内容进行摘要计算 199 digest, err := priv.PublicKey.Sm3Digest(signContentDigest, uid) 200 if err != nil { 201 return nil, nil, err 202 } 203 e := new(big.Int).SetBytes(digest) 204 c := priv.PublicKey.Curve 205 N := c.Params().N 206 if N.Sign() == 0 { 207 return nil, nil, errZeroParam 208 } 209 var k *big.Int 210 // SM2签名实现 211 for { 212 for { 213 // 生成随机数k 214 k, err = randFieldElement(c, random) 215 if err != nil { 216 r = nil 217 return 218 } 219 // 计算P = k*G,返回值的x赋予了r 220 r, _ = priv.Curve.ScalarBaseMult(k.Bytes()) 221 // 计算 r = (e + P(x)) mod n 222 // e + P(x) 223 r.Add(r, e) 224 // (e + P(x)) mod n 225 r.Mod(r, N) 226 if r.Sign() != 0 { 227 if t := new(big.Int).Add(r, k); t.Cmp(N) != 0 { 228 break 229 } 230 } 231 232 } 233 // 计算 s = (((1 + d)^-1) (k-rd)) mod n 234 // rd 235 rD := new(big.Int).Mul(priv.D, r) 236 // k - rd 237 s = new(big.Int).Sub(k, rD) 238 // 1 + d 239 d1 := new(big.Int).Add(priv.D, one) 240 // (1 + d)^-1 241 d1Inv := new(big.Int).ModInverse(d1, N) 242 // ((1 + d)^-1) × (k-rd) 243 s.Mul(s, d1Inv) 244 // (((1 + d)^-1) (k-rd)) mod n 245 s.Mod(s, N) 246 if s.Sign() != 0 { 247 break 248 } 249 } 250 return 251 } 252 253 // Sm2Verify SM2验签 254 // - pub : 验签公钥, *sm2.PublicKey 255 // - signContentDigest : 签名内容摘要(散列值) 256 // - uid : 内部混合摘要计算用uid, 长度16的字节数组,可以传 nil 257 // - r, s : 签名 258 func Sm2Verify(pub *PublicKey, signContentDigest, uid []byte, r, s *big.Int) bool { 259 c := pub.Curve 260 N := c.Params().N 261 one := new(big.Int).SetInt64(1) 262 if r.Cmp(one) < 0 || s.Cmp(one) < 0 { 263 return false 264 } 265 if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 { 266 return false 267 } 268 if len(uid) == 0 { 269 uid = defaultUid 270 } 271 // 获取za: sm3(ENTLA || IDA || a || b || xG || yG || xA || yA) 272 za, err := ZA(pub, uid) 273 if err != nil { 274 return false 275 } 276 // 混合za与签名内容明文,并做sm3摘要 277 e, err := msgHash(za, signContentDigest) 278 if err != nil { 279 return false 280 } 281 // 计算 t = (r + s) mod n 282 t := new(big.Int).Add(r, s) 283 t.Mod(t, N) 284 if t.Sign() == 0 { 285 return false 286 } 287 var x *big.Int 288 // 计算 s*G 289 x1, y1 := c.ScalarBaseMult(s.Bytes()) 290 // 计算 t*pub 291 x2, y2 := c.ScalarMult(pub.X, pub.Y, t.Bytes()) 292 // 计算 s*G + t*pub 结果只要x轴座标 293 x, _ = c.Add(x1, y1, x2, y2) 294 // 计算 e + x 295 x.Add(x, e) 296 // 计算 R = (e + x) mod n 297 x.Mod(x, N) 298 // 判断 R == r 299 return x.Cmp(r) == 0 300 } 301 302 // Verify SM2验签 303 // - pub : 验签公钥, *sm2.PublicKey 304 // - hash : 签名内容摘要(散列值) 305 // - r, s : 签名 306 // 307 //goland:noinspection GoUnusedExportedFunction 308 func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { 309 return Sm2Verify(pub, hash, nil, r, s) 310 } 311 312 /* 313 za, err := ZA(pub, uid) 314 if err != nil { 315 return 316 } 317 e, err := msgHash(za, msg) 318 hash=e.getBytes() 319 */ 320 // 并非sm2验签 321 // func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { 322 // c := pub.Curve 323 // N := c.Params().N 324 325 // if r.Sign() <= 0 || s.Sign() <= 0 { 326 // return false 327 // } 328 // if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 { 329 // return false 330 // } 331 332 // // 调整算法细节以实现SM2 333 // t := new(big.Int).Add(r, s) 334 // t.Mod(t, N) 335 // if t.Sign() == 0 { 336 // return false 337 // } 338 339 // var x *big.Int 340 // x1, y1 := c.ScalarBaseMult(s.Bytes()) 341 // x2, y2 := c.ScalarMult(pub.X, pub.Y, t.Bytes()) 342 // x, _ = c.Add(x1, y1, x2, y2) 343 344 // e := new(big.Int).SetBytes(hash) 345 // x.Add(x, e) 346 // x.Mod(x, N) 347 // return x.Cmp(r) == 0 348 // } 349 350 // Encrypt sm2非对称加密,支持C1C3C2(mode = 0)与C1C2C3(mode = 1)两种模式,默认使用C1C3C2模式。 351 // 不同的模式表示不同的密文结构,其中C1C2C3的意义: 352 // C1 : sm2椭圆曲线上的某个点,每次加密得到的点不一样 353 // C2 : 密文 354 // C3 : 明文加盐后的摘要 355 func Encrypt(pub *PublicKey, data []byte, random io.Reader, mode int) ([]byte, error) { 356 length := len(data) 357 for { 358 var c []byte 359 curve := pub.Curve 360 // 获取随机数k 361 k, err := randFieldElement(curve, random) 362 if err != nil { 363 return nil, err 364 } 365 // 计算点C1 = k*G ,因为k是随机数,所以C1每次加密都是随机的 366 x1, y1 := curve.ScalarBaseMult(k.Bytes()) 367 // 计算点(x2,y2) = k*pub,利用公钥计算出一个随机的点P 368 x2, y2 := curve.ScalarMult(pub.X, pub.Y, k.Bytes()) 369 x1Buf := x1.Bytes() 370 y1Buf := y1.Bytes() 371 x2Buf := x2.Bytes() 372 y2Buf := y2.Bytes() 373 // 填充满32个字节长度 374 if n := len(x1Buf); n < 32 { 375 x1Buf = append(zeroByteSlice()[:32-n], x1Buf...) 376 } 377 if n := len(y1Buf); n < 32 { 378 y1Buf = append(zeroByteSlice()[:32-n], y1Buf...) 379 } 380 if n := len(x2Buf); n < 32 { 381 x2Buf = append(zeroByteSlice()[:32-n], x2Buf...) 382 } 383 if n := len(y2Buf); n < 32 { 384 y2Buf = append(zeroByteSlice()[:32-n], y2Buf...) 385 } 386 // 填入C1(x) 387 c = append(c, x1Buf...) 388 // 填入C1(y) 389 c = append(c, y1Buf...) 390 391 // 计算C3 : 按 x2 data y2 的顺序混合数据并做sm3摘要 392 var tm []byte 393 tm = append(tm, x2Buf...) 394 tm = append(tm, data...) 395 tm = append(tm, y2Buf...) 396 h := sm3.Sm3Sum(tm) 397 // 填入C3 398 c = append(c, h...) 399 400 // 使用密钥派生函数kdf,基于P计算长度等于data长度的派生密钥 ct 401 ct, ok := kdf(length, x2Buf, y2Buf) 402 if !ok { 403 continue 404 } 405 // 填入ct 406 c = append(c, ct...) 407 // 利用ct对data进行异或加密,并覆盖c中对应内容 408 for i := 0; i < length; i++ { 409 c[96+i] ^= data[i] 410 } 411 412 // 此时c的内容是 c1c3c2,需要根据传入的参数mode判断是否需要重新排列。 413 switch mode { 414 case C1C3C2: 415 return append([]byte{0x04}, c...), nil 416 case C1C2C3: 417 // 如果是 C1C2C3 模式,那么需要将c切分后重新组装 418 c1 := make([]byte, 64) 419 c2 := make([]byte, len(c)-96) 420 c3 := make([]byte, 32) 421 // C1,即 x1Buf+y1Buf 422 copy(c1, c[:64]) 423 // C3,即 x2+data+y2混合后的SM3摘要 424 copy(c3, c[64:96]) 425 // C2,即 使用kdf派生出的密钥对data进行加密后的密文 426 copy(c2, c[96:]) 427 // 按C1C2C3的顺序组装结果 428 var ciphertext []byte 429 ciphertext = append(ciphertext, c1...) 430 ciphertext = append(ciphertext, c2...) 431 ciphertext = append(ciphertext, c3...) 432 return append([]byte{0x04}, ciphertext...), nil 433 default: 434 return append([]byte{0x04}, c...), nil 435 } 436 } 437 } 438 439 // Decrypt sm2非对称解密 440 func Decrypt(priv *PrivateKey, data []byte, mode int) ([]byte, error) { 441 switch mode { 442 case C1C3C2: 443 data = data[1:] 444 case C1C2C3: 445 // C1C2C3重新组装为 C1C3C2 446 data = data[1:] 447 c1 := make([]byte, 64) 448 c2 := make([]byte, len(data)-96) 449 c3 := make([]byte, 32) 450 copy(c1, data[:64]) //x1,y1 451 copy(c2, data[64:len(data)-32]) //密文 452 copy(c3, data[len(data)-32:]) //hash 453 var c []byte 454 c = append(c, c1...) 455 c = append(c, c3...) 456 c = append(c, c2...) 457 data = c 458 default: 459 data = data[1:] 460 } 461 length := len(data) - 96 462 curve := priv.Curve 463 // 取出C1的x和y 464 x := new(big.Int).SetBytes(data[:32]) 465 y := new(big.Int).SetBytes(data[32:64]) 466 // 根据C1计算 P = d*C1 467 x2, y2 := curve.ScalarMult(x, y, priv.D.Bytes()) 468 x2Buf := x2.Bytes() 469 y2Buf := y2.Bytes() 470 if n := len(x2Buf); n < 32 { 471 x2Buf = append(zeroByteSlice()[:32-n], x2Buf...) 472 } 473 if n := len(y2Buf); n < 32 { 474 y2Buf = append(zeroByteSlice()[:32-n], y2Buf...) 475 } 476 // 使用密钥派生函数kdf,基于P计算派生密钥 c 477 c, ok := kdf(length, x2Buf, y2Buf) 478 if !ok { 479 return nil, errors.New("decrypt: failed to decrypt") 480 } 481 // 使用派生密钥c对C2部分做异或计算解密 482 // 解密结果覆盖到c中,此时c即明文 483 for i := 0; i < length; i++ { 484 c[i] ^= data[i+96] 485 } 486 // 重新混合明文并计算摘要,与C3进行比较 487 var tm []byte 488 tm = append(tm, x2Buf...) 489 tm = append(tm, c...) 490 tm = append(tm, y2Buf...) 491 h := sm3.Sm3Sum(tm) 492 if !bytes.Equal(h, data[64:96]) { 493 return c, errors.New("decrypt: failed to decrypt") 494 } 495 return c, nil 496 } 497 498 // keyExchange 为SM2密钥交换算法的第二部和第三步复用部分,协商的双方均调用此函数计算共同的字节串 499 // klen: 密钥长度 500 // ida, idb: 协商双方的标识,ida为密钥协商算法发起方标识,idb为响应方标识 501 // pri: 函数调用者的密钥 502 // pub: 对方的公钥 503 // rpri: 函数调用者生成的临时SM2密钥 504 // rpub: 对方发来的临时SM2公钥 505 // thisIsA: 如果是A调用,文档中的协商第三步,设置为true,否则设置为false 506 // 返回 k 为klen长度的字节串 507 func keyExchange(klen int, ida, idb []byte, pri *PrivateKey, pub *PublicKey, rpri *PrivateKey, rpub *PublicKey, thisISA bool) (k, s1, s2 []byte, err error) { 508 curve := P256Sm2() 509 N := curve.Params().N 510 x2hat := keXHat(rpri.PublicKey.X) 511 x2rb := new(big.Int).Mul(x2hat, rpri.D) 512 tbt := new(big.Int).Add(pri.D, x2rb) 513 tb := new(big.Int).Mod(tbt, N) 514 if !curve.IsOnCurve(rpub.X, rpub.Y) { 515 err = errors.New("ra not on curve") 516 return 517 } 518 x1hat := keXHat(rpub.X) 519 ramx1, ramy1 := curve.ScalarMult(rpub.X, rpub.Y, x1hat.Bytes()) 520 vxt, vyt := curve.Add(pub.X, pub.Y, ramx1, ramy1) 521 522 vx, vy := curve.ScalarMult(vxt, vyt, tb.Bytes()) 523 pza := pub 524 if thisISA { 525 pza = &pri.PublicKey 526 } 527 za, err := ZA(pza, ida) 528 if err != nil { 529 return 530 } 531 zero := new(big.Int) 532 if vx.Cmp(zero) == 0 || vy.Cmp(zero) == 0 { 533 err = errors.New("v is infinite") 534 return 535 } 536 pzb := pub 537 if !thisISA { 538 pzb = &pri.PublicKey 539 } 540 zb, _ := ZA(pzb, idb) 541 k, ok := kdf(klen, vx.Bytes(), vy.Bytes(), za, zb) 542 if !ok { 543 err = errors.New("kdf: zero key") 544 return 545 } 546 h1 := BytesCombine(vx.Bytes(), za, zb, rpub.X.Bytes(), rpub.Y.Bytes(), rpri.X.Bytes(), rpri.Y.Bytes()) 547 if !thisISA { 548 h1 = BytesCombine(vx.Bytes(), za, zb, rpri.X.Bytes(), rpri.Y.Bytes(), rpub.X.Bytes(), rpub.Y.Bytes()) 549 } 550 hash := sm3.Sm3Sum(h1) 551 h2 := BytesCombine([]byte{0x02}, vy.Bytes(), hash) 552 S1 := sm3.Sm3Sum(h2) 553 h3 := BytesCombine([]byte{0x03}, vy.Bytes(), hash) 554 S2 := sm3.Sm3Sum(h3) 555 return k, S1, S2, nil 556 } 557 558 func msgHash(za, msg []byte) (*big.Int, error) { 559 e := sm3.New() 560 e.Write(za) 561 e.Write(msg) 562 return new(big.Int).SetBytes(e.Sum(nil)[:32]), nil 563 } 564 565 // ZA = H256(ENTLA || IDA || a || b || xG || yG || xA || yA) 566 func ZA(pub *PublicKey, uid []byte) ([]byte, error) { 567 za := sm3.New() 568 uidLen := len(uid) 569 if uidLen >= 8192 { 570 return []byte{}, errors.New("SM2: uid too large") 571 } 572 Entla := uint16(8 * uidLen) 573 za.Write([]byte{byte((Entla >> 8) & 0xFF)}) 574 za.Write([]byte{byte(Entla & 0xFF)}) 575 if uidLen > 0 { 576 za.Write(uid) 577 } 578 za.Write(sm2P256ToBig(&sm2P256.a).Bytes()) 579 za.Write(sm2P256.B.Bytes()) 580 za.Write(sm2P256.Gx.Bytes()) 581 za.Write(sm2P256.Gy.Bytes()) 582 583 xBuf := pub.X.Bytes() 584 yBuf := pub.Y.Bytes() 585 if n := len(xBuf); n < 32 { 586 xBuf = append(zeroByteSlice()[:32-n], xBuf...) 587 } 588 if n := len(yBuf); n < 32 { 589 yBuf = append(zeroByteSlice()[:32-n], yBuf...) 590 } 591 za.Write(xBuf) 592 za.Write(yBuf) 593 return za.Sum(nil)[:32], nil 594 } 595 596 // 32byte 597 func zeroByteSlice() []byte { 598 return []byte{ 599 0, 0, 0, 0, 600 0, 0, 0, 0, 601 0, 0, 0, 0, 602 0, 0, 0, 0, 603 0, 0, 0, 0, 604 0, 0, 0, 0, 605 0, 0, 0, 0, 606 0, 0, 0, 0, 607 } 608 } 609 610 // EncryptAsn1 sm2加密,返回asn.1编码格式的密文内容 611 func EncryptAsn1(pub *PublicKey, data []byte, rand io.Reader) ([]byte, error) { 612 cipher, err := Encrypt(pub, data, rand, C1C3C2) 613 if err != nil { 614 return nil, err 615 } 616 return CipherMarshal(cipher) 617 } 618 619 // DecryptAsn1 sm2解密,解析asn.1编码格式的密文内容 620 func DecryptAsn1(pub *PrivateKey, data []byte) ([]byte, error) { 621 cipher, err := CipherUnmarshal(data) 622 if err != nil { 623 return nil, err 624 } 625 return Decrypt(pub, cipher, C1C3C2) 626 } 627 628 // CipherMarshal sm2密文转asn.1编码格式 629 // 630 // sm2密文结构如下: 631 // - x 632 // - y 633 // - hash 634 // - CipherText 635 func CipherMarshal(data []byte) ([]byte, error) { 636 data = data[1:] 637 x := new(big.Int).SetBytes(data[:32]) 638 y := new(big.Int).SetBytes(data[32:64]) 639 hash := data[64:96] 640 cipherText := data[96:] 641 return asn1.Marshal(sm2Cipher{x, y, hash, cipherText}) 642 } 643 644 // CipherUnmarshal sm2密文asn.1编码格式转C1|C3|C2拼接格式 645 func CipherUnmarshal(data []byte) ([]byte, error) { 646 var cipher sm2Cipher 647 _, err := asn1.Unmarshal(data, &cipher) 648 if err != nil { 649 return nil, err 650 } 651 x := cipher.XCoordinate.Bytes() 652 y := cipher.YCoordinate.Bytes() 653 hash := cipher.HASH 654 if err != nil { 655 return nil, err 656 } 657 cipherText := cipher.CipherText 658 if err != nil { 659 return nil, err 660 } 661 if n := len(x); n < 32 { 662 x = append(zeroByteSlice()[:32-n], x...) 663 } 664 if n := len(y); n < 32 { 665 y = append(zeroByteSlice()[:32-n], y...) 666 } 667 var c []byte 668 c = append(c, x...) // x分量 669 c = append(c, y...) // y分 670 c = append(c, hash...) // x分量 671 c = append(c, cipherText...) // y分 672 return append([]byte{0x04}, c...), nil 673 } 674 675 // keXHat 计算 x = 2^w + (x & (2^w-1)) 676 // 密钥协商算法辅助函数 677 func keXHat(x *big.Int) (xul *big.Int) { 678 buf := x.Bytes() 679 for i := 0; i < len(buf)-16; i++ { 680 buf[i] = 0 681 } 682 if len(buf) >= 16 { 683 c := buf[len(buf)-16] 684 buf[len(buf)-16] = c & 0x7f 685 } 686 687 r := new(big.Int).SetBytes(buf) 688 _2w := new(big.Int).SetBytes([]byte{ 689 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) 691 return r.Add(r, _2w) 692 } 693 694 func BytesCombine(pBytes ...[]byte) []byte { 695 length := len(pBytes) 696 s := make([][]byte, length) 697 for index := 0; index < length; index++ { 698 s[index] = pBytes[index] 699 } 700 sep := []byte("") 701 return bytes.Join(s, sep) 702 } 703 704 func intToBytes(x int) []byte { 705 var buf = make([]byte, 4) 706 707 binary.BigEndian.PutUint32(buf, uint32(x)) 708 return buf 709 } 710 711 func kdf(length int, x ...[]byte) ([]byte, bool) { 712 var c []byte 713 714 ct := 1 715 h := sm3.New() 716 for i, j := 0, (length+31)/32; i < j; i++ { 717 h.Reset() 718 for _, xx := range x { 719 h.Write(xx) 720 } 721 h.Write(intToBytes(ct)) 722 hash := h.Sum(nil) 723 if i+1 == j && length%32 != 0 { 724 c = append(c, hash[:length%32]...) 725 } else { 726 c = append(c, hash...) 727 } 728 ct++ 729 } 730 for i := 0; i < length; i++ { 731 if c[i] != 0 { 732 return c, true 733 } 734 } 735 return c, false 736 } 737 738 // 选取一个位于[1~n-1]之间的随机数k,n是椭圆曲线的参数N 739 func randFieldElement(c elliptic.Curve, random io.Reader) (k *big.Int, err error) { 740 if random == nil { 741 random = rand.Reader //If there is no external trusted random source,please use rand.Reader to instead of it. 742 } 743 params := c.Params() 744 b := make([]byte, params.BitSize/8+8) 745 _, err = io.ReadFull(random, b) 746 if err != nil { 747 return 748 } 749 k = new(big.Int).SetBytes(b) 750 n := new(big.Int).Sub(params.N, one) 751 k.Mod(k, n) 752 k.Add(k, one) 753 return 754 } 755 756 // GenerateKey 基于P256Sm2曲线生成sm2的公私钥 757 func GenerateKey(random io.Reader) (*PrivateKey, error) { 758 c := P256Sm2() 759 if random == nil { 760 random = rand.Reader //If there is no external trusted random source,please use rand.Reader to instead of it. 761 } 762 params := c.Params() 763 b := make([]byte, params.BitSize/8+8) 764 _, err := io.ReadFull(random, b) 765 if err != nil { 766 return nil, err 767 } 768 // 生成随机数k 769 k := new(big.Int).SetBytes(b) 770 // n = N - 2 771 n := new(big.Int).Sub(params.N, two) 772 // k = k mod n 773 k.Mod(k, n) 774 // k = k + 1 775 k.Add(k, one) 776 priv := new(PrivateKey) 777 // 设置曲线 778 priv.PublicKey.Curve = c 779 // 设置私钥 780 priv.D = k 781 // 公钥 = k * G 782 priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) 783 784 return priv, nil 785 } 786 787 // ecdsa的实现中,使用zeroReader辅助生成一个cipher.StreamReader用作随机数生成的 rand io.Reader。 788 // sm2目前没有采用这种方式,所以这里将相关代码注释掉了。 789 790 // type zr struct { 791 // io.Reader 792 // } 793 794 // func (z *zr) Read(dst []byte) (n int, err error) { 795 // for i := range dst { 796 // dst[i] = 0 797 // } 798 // return len(dst), nil 799 // } 800 801 // var zeroReader = &zr{} 802 803 func getLastBit(a *big.Int) uint { 804 return a.Bit(0) 805 } 806 807 // Decrypt crypto.Decrypter 808 func (priv *PrivateKey) Decrypt(_ io.Reader, msg []byte, _ crypto.DecrypterOpts) (plaintext []byte, err error) { 809 return Decrypt(priv, msg, C1C3C2) 810 }