github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/sm2/sm2.go (about) 1 // Copyright 2022 s1ren@github.com/hxx258456. 2 3 package sm2 4 5 /* 6 sm2/sm2.go sm2国密算法实现,包括签名验签与非对称加解密 7 8 为*sm2.PrivateKey绑定方法: 9 Public 10 Equal 11 SignWithZA 12 Sign 13 DecryptAsn1 14 Decrypt 15 16 为*sm2.PublicKey绑定方法: 17 Equal 18 Verify 19 EncryptAsn1 20 Encrypt 21 22 提供函数: 23 P256Sm2 24 GenerateKey 25 IsSM2PublicKey 26 NewSM2SignerOption 27 DefaultSM2SignerOption 28 SignASN1WithOpts 29 SignASN1 30 Sign 31 Sm2Sign 32 SignWithZA 33 SignAfterZA 34 VerifyASN1 35 VerifyASN1WithoutZA 36 Verify 37 Sm2Verify 38 VerifyWithZA 39 CalculateZA 40 Encrypt 41 Decrypt 42 EncryptDefault 43 EncryptAsn1 44 DecryptDefault 45 DecryptAsn1 46 ASN1Ciphertext2Plain 47 PlainCiphertext2ASN1 48 AdjustCiphertextSplicingOrder 49 NewPlainEncrypterOpts 50 NewPlainDecrypterOpts 51 52 */ 53 54 // Further references: 55 // [NSA]: Suite B implementer's guide to FIPS 186-3 56 // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.182.4503&rep=rep1&type=pdf 57 // [SECG]: SECG, SEC1 58 // http://www.secg.org/sec1-v2.pdf 59 // [GM/T]: SM2 GB/T 32918.2-2016, GB/T 32918.4-2016 60 // 61 62 import ( 63 "crypto" 64 "crypto/aes" 65 "crypto/cipher" 66 "crypto/elliptic" 67 "crypto/sha512" 68 "encoding/binary" 69 "errors" 70 "fmt" 71 "io" 72 "math/big" 73 "strings" 74 "sync" 75 76 "github.com/hxx258456/ccgo/sm3" 77 "golang.org/x/crypto/cryptobyte" 78 "golang.org/x/crypto/cryptobyte/asn1" 79 ) 80 81 // PublicKey SM2公钥结构体 82 type PublicKey struct { 83 elliptic.Curve // 椭圆曲线 84 X, Y *big.Int // 公钥座标 85 } 86 87 func (pub *PublicKey) Equal(x crypto.PublicKey) bool { 88 xx, ok := x.(*PublicKey) 89 if !ok { 90 return false 91 } 92 return pub.X.Cmp(xx.X) == 0 && pub.Y.Cmp(xx.Y) == 0 && 93 // Standard library Curve implementations are singletons, so this check 94 // will work for those. Other Curves might be equivalent even if not 95 // singletons, but there is no definitive way to check for that, and 96 // better to err on the side of safety. 97 pub.Curve == xx.Curve 98 } 99 100 // PrivateKey SM2私钥结构体 101 type PrivateKey struct { 102 PublicKey // 公钥 103 D *big.Int // 私钥,[1,n-1]区间的随机数 104 } 105 106 // Public The SM2's private key contains the public key 107 func (priv *PrivateKey) Public() crypto.PublicKey { 108 return &priv.PublicKey 109 } 110 111 func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool { 112 xx, ok := x.(*PrivateKey) 113 if !ok { 114 return false 115 } 116 return priv.PublicKey.Equal(&xx.PublicKey) && priv.D.Cmp(xx.D) == 0 117 } 118 119 var ( 120 one = new(big.Int).SetInt64(1) 121 initonce sync.Once 122 ) 123 124 // P256Sm2 获取sm2p256曲线 125 // P256Sm2 init and return the singleton. 126 func P256Sm2() elliptic.Curve { 127 initonce.Do(initP256) 128 return p256 129 } 130 131 // 选取一个位于[1~n-1]之间的随机数k,n是椭圆曲线的参数N 132 // randFieldElement returns a random element of the order of the given 133 // curve using the procedure given in FIPS 186-4, Appendix B.5.1. 134 func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) { 135 params := c.Params() 136 b := make([]byte, params.BitSize/8+8) // (N + 64) / 8 = (256 + 64) / 8 137 _, err = io.ReadFull(rand, b) 138 if err != nil { 139 return 140 } 141 142 k = new(big.Int).SetBytes(b) // 5.Convert returned_bits to the (non-negtive) integrer c 143 n := new(big.Int).Sub(params.N, one) 144 k.Mod(k, n) 145 k.Add(k, one) // 6. k = (c mod (n-1)) + 1, here n = params.N 146 return 147 } 148 149 // GenerateKey 生成sm2的公私钥对 150 // GenerateKey generates a public and private key pair. 151 func GenerateKey(rand io.Reader) (*PrivateKey, error) { 152 c := P256Sm2() 153 // 生成随机数k 154 k, err := randFieldElement(c, rand) 155 if err != nil { 156 return nil, err 157 } 158 priv := new(PrivateKey) 159 // 设置曲线为sm2p256 160 priv.PublicKey.Curve = c 161 // 设置私钥为随机数k 162 priv.D = k 163 // 计算公钥座标 k*G 164 priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) 165 return priv, nil 166 } 167 168 var errZeroParam = errors.New("zero parameter") 169 170 // IsSM2PublicKey check if given public key is a SM2 public key or not 171 // 172 //goland:noinspection GoUnusedExportedFunction 173 func IsSM2PublicKey(publicKey interface{}) bool { 174 pub, ok := publicKey.(*PublicKey) 175 return ok && strings.EqualFold(P256Sm2().Params().Name, pub.Curve.Params().Name) 176 } 177 178 // ↓↓↓↓↓↓↓↓↓↓ 签名与验签 ↓↓↓↓↓↓↓↓↓↓ 179 180 var defaultUID = []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38} 181 182 // directSigning is a standard Hash value that signals that no pre-hashing 183 // should be performed. 184 var directSigning crypto.Hash = 0 185 186 // SM2SignerOption sm2签名参数 187 // SM2SignerOption implements crypto.SignerOpts interface. 188 // It is specific for SM2, used in private key's Sign method. 189 // 190 //goland:noinspection GoNameStartsWithPackageName 191 type SM2SignerOption struct { 192 // ZA计算用唯一标识符,只在ForceZA为true时使用。 193 UID []byte 194 // 是否强制使用国密签名标准,即对签名内容进行ZA混合散列后再签名。 195 // 该值为true则代表进行ZA混合散列。 196 ForceZA bool 197 } 198 199 // NewSM2SignerOption 生成一个新的sm2签名参数 200 // 201 // forceZA为true而uid为空时,使用defaultUID 202 func NewSM2SignerOption(forceZA bool, uid []byte) *SM2SignerOption { 203 opt := &SM2SignerOption{ 204 UID: uid, 205 ForceZA: forceZA, 206 } 207 if forceZA && len(uid) == 0 { 208 // ForceGMSign为true而uid为空时,使用defaultUID 209 opt.UID = defaultUID 210 } 211 return opt 212 } 213 214 // DefaultSM2SignerOption 生成一个默认的sm2签名参数 215 func DefaultSM2SignerOption() *SM2SignerOption { 216 return &SM2SignerOption{ 217 UID: defaultUID, 218 ForceZA: true, 219 } 220 } 221 222 // HashFunc 为sm2.SM2SignerOption实现crypto.SignerOpts接口 223 func (*SM2SignerOption) HashFunc() crypto.Hash { 224 return directSigning 225 } 226 227 // Signer SM2 special signer 228 type Signer interface { 229 SignWithZA(rand io.Reader, uid, msg []byte) ([]byte, error) 230 } 231 232 // SignWithZA 为sm2.PrivateKey实现SignWithZA方法。 233 // 234 // 该方法强制对msg做ZA混合散列 235 // 236 // SignWithZA signs uid, msg with priv, reading randomness from rand. Compliance with GB/T 32918.2-2016. 237 // Deprecated: please use Sign method directly. 238 func (priv *PrivateKey) SignWithZA(rand io.Reader, uid, msg []byte) ([]byte, error) { 239 return priv.Sign(rand, msg, NewSM2SignerOption(true, uid)) 240 } 241 242 // SignASN1WithOpts SignASN1使用私钥priv对签名摘要hash进行签名,并将签名转为asn1格式字节数组。 243 // 244 // 是否对hash做ZA混合散列取决于opts类型是否*sm2.SM2SignerOption且opts.ForceGMSign为true。 245 // 如果opts传nil,则对hash做ZA混合散列。 246 // 247 //goland:noinspection GoUnusedExportedFunction 248 func SignASN1WithOpts(rand io.Reader, priv *PrivateKey, hash []byte, opts crypto.SignerOpts) ([]byte, error) { 249 return priv.Sign(rand, hash, opts) 250 } 251 252 // SignASN1 SignASN1使用私钥priv对签名摘要hash进行签名,并将签名转为asn1格式字节数组。 253 // 254 // 会对hash做ZA混合散列。 255 func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) { 256 return priv.Sign(rand, hash, nil) 257 } 258 259 // Sign 为sm2.PrivateKey实现Sign方法。 260 // 261 // 如果opts类型是*sm2.SM2SignerOption且opts.ForceGMSign为true,或opts传nil, 262 // 263 // 则将对digest进行ZA混合散列后再对其进行签名。 264 func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { 265 var r, s *big.Int 266 var err error 267 if opts == nil { 268 opts = DefaultSM2SignerOption() 269 } 270 if sm2Opts, ok := opts.(*SM2SignerOption); ok { 271 // 传入的opts是SM2SignerOption类型时,根据设置决定是否进行ZA混合散列 272 if sm2Opts.ForceZA { 273 // 执行ZA混合散列 274 r, s, err = SignWithZA(rand, priv, sm2Opts.UID, digest) 275 } else { 276 // 不执行ZA混合散列 277 r, s, err = SignAfterZA(rand, priv, digest) 278 } 279 } else { 280 // 传入的opts不是SM2SignerOption类型时,执行ZA混合散列 281 r, s, err = SignWithZA(rand, priv, defaultUID, digest) 282 } 283 if err != nil { 284 return nil, err 285 } 286 // 将签名结果(r,s)转为asn1格式字节数组 287 var b cryptobyte.Builder 288 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { 289 b.AddASN1BigInt(r) 290 b.AddASN1BigInt(s) 291 }) 292 return b.Bytes() 293 } 294 295 // Sign Sign使用私钥priv对签名摘要hash进行签名,并将签名转为asn1格式字节数组。 296 // 297 // 会对hash做ZA混合散列。 298 func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { 299 r, s, err = SignWithZA(rand, priv, defaultUID, hash) 300 return 301 } 302 303 // Sm2Sign Sm2Sign使用私钥priv对签名摘要hash进行签名,并将签名转为asn1格式字节数组。 304 // 305 // 会对hash做ZA混合散列。 306 // 307 //goland:noinspection GoUnusedExportedFunction,GoNameStartsWithPackageName,GoUnusedParameter 308 func Sm2Sign(priv *PrivateKey, msg, uid []byte, random io.Reader) (r, s *big.Int, err error) { 309 r, s, err = SignWithZA(random, priv, defaultUID, msg) 310 return 311 } 312 313 // SignWithZA 对msg做ZA混合散列后再对得到的校验和进行签名。 314 // 315 // 混合散列使用sm3 316 // 317 // SignWithZA follow sm2 dsa standards for hash part, compliance with GB/T 32918.2-2016. 318 func SignWithZA(rand io.Reader, priv *PrivateKey, uid, msg []byte) (r, s *big.Int, err error) { 319 if len(uid) == 0 { 320 uid = defaultUID 321 } 322 // 计算ZA 323 za, err := calculateZA(&priv.PublicKey, uid) 324 if err != nil { 325 return nil, nil, err 326 } 327 // 混入ZA 328 md := sm3.New() 329 md.Write(za) 330 md.Write(msg) 331 // 对混入了ZA的签名内容做散列,对得到的校验和进行签名 332 return SignAfterZA(rand, priv, md.Sum(nil)) 333 } 334 335 // SignAfterZA sm2签名函数 336 // 337 // 1.内部不对签名内容hash进行混入ZA的散列处理。 338 // 2.内部会根据rand与hash使用aes生成一个后续签名生成随机数用的csprng,即本函数在签名时获取随机数时不是直接使用rand。 339 func SignAfterZA(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { 340 // 为避免获取相同的随机数? 341 maybeReadByte(rand) 342 343 // ↓↓↓↓↓ 计算 csprng 用于签名时的随机数获取 begin ↓↓↓↓↓ 344 // We use SDK's nouce generation implementation here. 345 // This implementation derives the nonce from an AES-CTR CSPRNG keyed by: 346 // SHA2-512(priv.D || entropy || hash)[:32] 347 // The CSPRNG key is indifferentiable from a random oracle as shown in 348 // [Coron], the AES-CTR stream is indifferentiable from a random oracle 349 // under standard cryptographic assumptions (see [Larsson] for examples). 350 // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf 351 // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf 352 // Get 256 bits of entropy from rand. 353 entropy := make([]byte, 32) 354 _, err = io.ReadFull(rand, entropy) 355 if err != nil { 356 return 357 } 358 // Initialize an SHA-512 hash context; digest ... 359 md := sha512.New() 360 md.Write(priv.D.Bytes()) // the private key, 361 md.Write(entropy) // the entropy, 362 md.Write(hash) // and the input hash; 363 key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), 364 // which is an indifferentiable MAC. 365 // Create an AES-CTR instance to use as a CSPRNG. 366 block, err := aes.NewCipher(key) 367 if err != nil { 368 return nil, nil, err 369 } 370 // Create a CSPRNG that xors a stream of zeros with 371 // the output of the AES-CTR instance. 372 csprng := cipher.StreamReader{ 373 R: zeroReader, 374 S: cipher.NewCTR(block, []byte(aesIV)), 375 } 376 // ↑↑↑↑↑ 计算 csprng 用于签名时的随机数获取 end ↑↑↑↑↑ 377 378 return signGeneric(priv, &csprng, hash) 379 } 380 381 // sm2签名的具体实现 382 func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, hash []byte) (r, s *big.Int, err error) { 383 // 获取私钥对应曲线 384 c := priv.PublicKey.Curve 385 N := c.Params().N 386 if N.Sign() == 0 { 387 return nil, nil, errZeroParam 388 } 389 var k *big.Int 390 e := hashToInt(hash, c) 391 for { 392 for { 393 // 1.生成随机数k,注意这里使用的不是random而是前面计算出来的csprng 394 k, err = randFieldElement(c, csprng) 395 if err != nil { 396 r = nil 397 return 398 } 399 // 2.计算P = k*G,即(x, y) = k*G,返回值的x座标赋予r 400 r, _ = priv.Curve.ScalarBaseMult(k.Bytes()) 401 // 3.计算 r = (e + P(x)) mod n 402 r.Add(r, e) // e + P(x) 403 r.Mod(r, N) // (e + P(x)) mod n 404 if r.Sign() != 0 { 405 t := new(big.Int).Add(r, k) 406 // 步骤1,2,3得到的 r 与 k 满足条件才能跳出循环 407 if t.Cmp(N) != 0 { // if r != 0 && (r + k) != N then ok 408 break 409 } 410 } 411 } 412 // 4. 计算 s = (((1 + d)^-1) (k-rd)) mod n 413 s = new(big.Int).Mul(priv.D, r) // r×d 414 s = new(big.Int).Sub(k, s) // k - rd 415 dp1 := new(big.Int).Add(priv.D, one) // 1 + d 416 var dp1Inv *big.Int // (1 + d)^-1 417 if in, ok := priv.Curve.(invertible); ok { 418 // fmt.Println("sm2hard/sm2.go signGeneric 利用硬件加速") 419 // 如果平台cpu是amd64或arm64架构,则利用cpu硬件实现快速的 (1 + d)^-1 运算 420 dp1Inv = in.Inverse(dp1) 421 } else { 422 // fmt.Println("sm2hard/sm2.go signGeneric 没有利用硬件加速") 423 // 纯软实现的 (1 + d)^-1 运算 424 dp1Inv = fermatInverse(dp1, N) // N != 0 425 } 426 s.Mul(s, dp1Inv) // ((1 + d)^-1) × (k-rd) 427 s.Mod(s, N) // (((1 + d)^-1) (k-rd)) mod n 428 if s.Sign() != 0 { 429 break 430 } 431 } 432 433 return 434 } 435 436 // Verify sm2公钥验签 437 // 438 // 对msg做ZA混合散列 439 func (pub *PublicKey) Verify(msg []byte, sig []byte) bool { 440 return VerifyASN1(pub, msg, sig) 441 } 442 443 // VerifyASN1 VerifyASN1将asn1格式字节数组的签名转为(r,s)在调用sm2的验签函数。 444 // 445 // 对msg做ZA混合散列 446 func VerifyASN1(pub *PublicKey, msg, sig []byte) bool { 447 var ( 448 r, s = &big.Int{}, &big.Int{} 449 inner cryptobyte.String 450 ) 451 input := cryptobyte.String(sig) 452 if !input.ReadASN1(&inner, asn1.SEQUENCE) || 453 !input.Empty() || 454 !inner.ReadASN1Integer(r) || 455 !inner.ReadASN1Integer(s) || 456 !inner.Empty() { 457 return false 458 } 459 return VerifyWithZA(pub, nil, msg, r, s) 460 } 461 462 // VerifyASN1WithoutZA 将asn1格式字节数组的签名转为(r,s),再做验签。 463 // 不对hash再做ZA混合散列。 464 // 465 //goland:noinspection GoUnusedExportedFunction 466 func VerifyASN1WithoutZA(pub *PublicKey, hash, sig []byte) bool { 467 var ( 468 r, s = &big.Int{}, &big.Int{} 469 inner cryptobyte.String 470 ) 471 input := cryptobyte.String(sig) 472 if !input.ReadASN1(&inner, asn1.SEQUENCE) || 473 !input.Empty() || 474 !inner.ReadASN1Integer(r) || 475 !inner.ReadASN1Integer(s) || 476 !inner.Empty() { 477 return false 478 } 479 return verifyGeneric(pub, hash, r, s) 480 } 481 482 // Verify sm2验签 483 // 484 // 对msg做ZA混合散列 485 // 486 //goland:noinspection GoUnusedExportedFunction 487 func Verify(pub *PublicKey, msg []byte, r, s *big.Int) bool { 488 return VerifyWithZA(pub, nil, msg, r, s) 489 } 490 491 // Sm2Verify sm2验签 492 // 493 // 对msg做ZA混合散列 494 // 495 //goland:noinspection GoUnusedExportedFunction,GoNameStartsWithPackageName 496 func Sm2Verify(pub *PublicKey, msg, uid []byte, r, s *big.Int) bool { 497 return VerifyWithZA(pub, uid, msg, r, s) 498 } 499 500 // VerifyWithZA 将对msg进行ZA混合散列后再进行验签。 501 func VerifyWithZA(pub *PublicKey, uid, msg []byte, r, s *big.Int) bool { 502 if len(uid) == 0 { 503 uid = defaultUID 504 } 505 // 对消息进行ZA混合散列 506 za, err := calculateZA(pub, uid) 507 if err != nil { 508 return false 509 } 510 md := sm3.New() 511 md.Write(za) 512 md.Write(msg) 513 return verifyGeneric(pub, md.Sum(nil), r, s) 514 } 515 516 // sm2验签的具体实现。 517 // 518 // 如果有ZA混合散列,则在调用该函数之前处理。 519 func verifyGeneric(pub *PublicKey, hash []byte, r, s *big.Int) bool { 520 // 获取公钥对应曲线及其参数N 521 c := pub.Curve 522 N := c.Params().N 523 // 检查签名(r,s)是否在(0, N)区间 524 if r.Sign() <= 0 || s.Sign() <= 0 { 525 return false 526 } 527 if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 { 528 return false 529 } 530 e := hashToInt(hash, c) 531 // 1.计算 t = (r + s) mod n 532 t := new(big.Int).Add(r, s) 533 t.Mod(t, N) 534 if t.Sign() == 0 { 535 return false 536 } 537 var x *big.Int 538 if opt, ok := c.(combinedMult); ok { 539 // fmt.Println("sm2hard/sm2.go verifyGeneric 利用硬件加速") 540 // 如果cpu是amd64或arm64架构,则使用快速计算实现步骤2~4 541 x, _ = opt.CombinedMult(pub.X, pub.Y, s.Bytes(), t.Bytes()) 542 } else { 543 // fmt.Println("sm2hard/sm2.go verifyGeneric 没有利用硬件加速") 544 // 2.计算 s*G 545 x1, y1 := c.ScalarBaseMult(s.Bytes()) 546 // 3.计算 t*pub 547 x2, y2 := c.ScalarMult(pub.X, pub.Y, t.Bytes()) 548 // 4.计算 s*G + t*pub 结果只要x轴座标 549 x, _ = c.Add(x1, y1, x2, y2) 550 } 551 // 计算 e + x 552 x.Add(x, e) 553 // 计算 R = (e + x) mod n 554 x.Mod(x, N) 555 // 判断 R == r 556 return x.Cmp(r) == 0 557 } 558 559 // CalculateZA ZA计算。 560 // 561 // SM2签名与验签之前,先对签名内容做一次混入ZA的散列。 562 // ZA的值是根据公钥与uid计算出来的。 563 // CalculateZA ZA = H256(ENTLA || IDA || a || b || xG || yG || xA || yA). 564 // Compliance with GB/T 32918.2-2016 5.5 565 // 566 //goland:noinspection GoUnusedExportedFunction 567 func CalculateZA(pub *PublicKey, uid []byte) ([]byte, error) { 568 return calculateZA(pub, uid) 569 } 570 571 // ZA计算。 572 // 573 // SM2签名与验签之前,先对签名内容做一次混入ZA的散列。 574 // ZA的值是根据公钥与uid计算出来的。 575 // calculateZA ZA = H256(ENTLA || IDA || a || b || xG || yG || xA || yA) 576 // Compliance with GB/T 32918.2-2016 5.5 577 func calculateZA(pub *PublicKey, uid []byte) ([]byte, error) { 578 uidLen := len(uid) 579 if uidLen >= 0x2000 { 580 return nil, errors.New("the uid is too long") 581 } 582 entla := uint16(uidLen) << 3 583 md := sm3.New() 584 md.Write([]byte{byte(entla >> 8), byte(entla)}) 585 if uidLen > 0 { 586 md.Write(uid) 587 } 588 a := new(big.Int).Sub(pub.Params().P, big.NewInt(3)) 589 md.Write(toBytes(pub.Curve, a)) 590 md.Write(toBytes(pub.Curve, pub.Params().B)) 591 md.Write(toBytes(pub.Curve, pub.Params().Gx)) 592 md.Write(toBytes(pub.Curve, pub.Params().Gy)) 593 md.Write(toBytes(pub.Curve, pub.X)) 594 md.Write(toBytes(pub.Curve, pub.Y)) 595 return md.Sum(nil), nil 596 } 597 598 // hashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4, 599 // we use the left-most bits of the hash to match the bit-length of the order of 600 // the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3. 601 func hashToInt(hash []byte, c elliptic.Curve) *big.Int { 602 orderBits := c.Params().N.BitLen() 603 orderBytes := (orderBits + 7) / 8 604 if len(hash) > orderBytes { 605 hash = hash[:orderBytes] 606 } 607 608 ret := new(big.Int).SetBytes(hash) 609 excess := len(hash)*8 - orderBits 610 if excess > 0 { 611 ret.Rsh(ret, uint(excess)) 612 } 613 return ret 614 } 615 616 type zr struct { 617 io.Reader 618 } 619 620 // Read replaces the contents of dst with zeros. 621 func (z *zr) Read(dst []byte) (n int, err error) { 622 for i := range dst { 623 dst[i] = 0 624 } 625 return len(dst), nil 626 } 627 628 var zeroReader = &zr{} 629 630 // A invertible implements fast inverse in GF(N). 631 type invertible interface { 632 // Inverse mod Params().N 的倒数运算 633 // Inverse returns the inverse of k mod Params().N. 634 Inverse(k *big.Int) *big.Int 635 } 636 637 // fermatInverse 使用费马方法(取幂模 P - 2,根据欧拉定理)计算 GF(P) 中 k 的倒数。 638 // 639 // fermatInverse calculates the inverse of k in GF(P) using Fermat's method 640 // (exponentiation modulo P - 2, per Euler's theorem). This has better 641 // constant-time properties than Euclid's method (implemented in 642 // math/big.Int.ModInverse and FIPS 186-4, Appendix C.1) although math/big 643 // itself isn't strictly constant-time so it's not perfect. 644 func fermatInverse(k, N *big.Int) *big.Int { 645 two := big.NewInt(2) 646 nMinus2 := new(big.Int).Sub(N, two) 647 return new(big.Int).Exp(k, nMinus2, N) 648 } 649 650 // combineMult 实现了快速组合乘法以进行验证。需要平台对应架构CPU的硬件支持。 651 // A combinedMult implements fast combined multiplication for verification. 652 type combinedMult interface { 653 // CombinedMult 返回 [s1]G + [s2]P,其中 G 是生成器。 654 // 需要平台对应架构CPU的硬件支持。 655 // CombinedMult returns [s1]G + [s2]P where G is the generator. 656 CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) 657 } 658 659 const ( 660 aesIV = "IV for ECDSA CTR" 661 ) 662 663 // ↑↑↑↑↑↑↑↑↑↑ 签名与验签 ↑↑↑↑↑↑↑↑↑↑ 664 665 // ↓↓↓↓↓↓↓↓↓↓ 非对称加解密 ↓↓↓↓↓↓↓↓↓↓ 666 667 // EncryptAsn1 sm2公钥加密, C1C3C2, C1不压缩, C3C2做ASN1转码 668 func (pub *PublicKey) EncryptAsn1(data []byte, random io.Reader) ([]byte, error) { 669 return EncryptAsn1(pub, data, random) 670 } 671 672 // DecryptAsn1 sm2私钥解密, C1C3C2, C1不压缩, C3C2做ASN1转码 673 func (priv *PrivateKey) DecryptAsn1(data []byte) ([]byte, error) { 674 return DecryptAsn1(priv, data) 675 } 676 677 // Encrypt sm2公钥加密 678 // 679 // opts传nil代表默认模式: C1C3C2, C1不压缩, C3C2不做ASN1转码 680 func (pub *PublicKey) Encrypt(rand io.Reader, msg []byte, opts *EncrypterOpts) (ciphertext []byte, err error) { 681 return encryptGeneric(rand, pub, msg, opts) 682 } 683 684 // Decrypt sm2私钥解密 685 // 686 // opts传nil代表C1C3C2模式 687 // 688 //goland:noinspection GoUnusedParameter 689 func (priv *PrivateKey) Decrypt(rand io.Reader, msg []byte, opts *DecrypterOpts) (plaintext []byte, err error) { 690 return decryptGeneric(priv, msg, opts) 691 } 692 693 // Encrypt sm2公钥加密 694 // 695 // opts传nil代表默认模式: C1C3C2, C1不压缩, C3C2不做ASN1转码 696 func Encrypt(pub *PublicKey, data []byte, random io.Reader, opts *EncrypterOpts) ([]byte, error) { 697 return encryptGeneric(random, pub, data, opts) 698 } 699 700 // Decrypt sm2私钥解密 701 // 702 // opts传nil代表C1C3C2模式 703 func Decrypt(priv *PrivateKey, data []byte, opts *DecrypterOpts) ([]byte, error) { 704 return decryptGeneric(priv, data, opts) 705 } 706 707 // EncryptDefault sm2公钥加密 708 // 709 // 默认模式: C1C3C2, C1不压缩, C3C2不做ASN1转码 710 // 711 //goland:noinspection GoUnusedExportedFunction 712 func EncryptDefault(pub *PublicKey, data []byte, random io.Reader) ([]byte, error) { 713 return encryptGeneric(random, pub, data, nil) 714 } 715 716 // EncryptAsn1 sm2公钥加密 717 // 718 // 默认模式: C1C3C2, C1不压缩, C3C2做ASN1转码 719 func EncryptAsn1(pub *PublicKey, data []byte, random io.Reader) ([]byte, error) { 720 return encryptGeneric(random, pub, data, ASN1EncrypterOpts) 721 } 722 723 // DecryptDefault sm2私钥解密, C1C3C2模式 724 // 725 //goland:noinspection GoUnusedExportedFunction 726 func DecryptDefault(priv *PrivateKey, ciphertext []byte) ([]byte, error) { 727 return decryptGeneric(priv, ciphertext, nil) 728 } 729 730 // DecryptAsn1 sm2私钥解密, C1C3C2, C3C2做ASN1转码 731 func DecryptAsn1(priv *PrivateKey, ciphertext []byte) ([]byte, error) { 732 return decryptGeneric(priv, ciphertext, ASN1DecrypterOpts) 733 } 734 735 // encryptGeneric sm2公钥加密实现 736 // 737 // opts传nil代表默认模式: C1C3C2, C1不压缩, C3C2不做ASN1转码 738 // 参考: GB/T 32918.4-2016 chapter 6 739 func encryptGeneric(random io.Reader, pub *PublicKey, msg []byte, opts *EncrypterOpts) ([]byte, error) { 740 // 获取公钥对应曲线 741 curve := pub.Curve 742 msgLen := len(msg) 743 if msgLen == 0 { 744 return nil, nil 745 } 746 if opts == nil { 747 // 默认C1C3C2, C1不压缩, C3C2不做ASN1转码 748 opts = defaultEncrypterOpts 749 } 750 // 检查公钥坐标 751 if pub.X.Sign() == 0 && pub.Y.Sign() == 0 { 752 return nil, errors.New("SM2: invalid public key") 753 } 754 for { 755 // 1.获取随机数k 756 k, err := randFieldElement(curve, random) 757 if err != nil { 758 return nil, err 759 } 760 // 2.计算C1 = k*G ,C1是曲线上的一个点,坐标为(x1, y1)。 761 // 因为k是随机数,所以C1每次加密都是随机的 762 x1, y1 := curve.ScalarBaseMult(k.Bytes()) 763 // 3.计算点(x2,y2) = k*pub,利用公钥计算出一个随机点(x2,y2) 764 x2, y2 := curve.ScalarMult(pub.X, pub.Y, k.Bytes()) 765 var kdfCount = 0 766 // 4.使用密钥派生函数kdf,基于P计算长度等于data长度的派生密钥 t=KDF(x2||y2, klen) 767 t, success := kdf(append(toBytes(curve, x2), toBytes(curve, y2)...), msgLen) 768 if !success { 769 kdfCount++ 770 if kdfCount > maxRetryLimit { 771 return nil, fmt.Errorf("SM2: A5, failed to calculate valid t, tried %v times", kdfCount) 772 } 773 continue 774 } 775 // 5.计算C2, 利用派生密钥t对data进行异或加密 776 c2 := make([]byte, msgLen) 777 for i := 0; i < msgLen; i++ { 778 c2[i] = msg[i] ^ t[i] 779 } 780 // 6.计算C3, 按照 (x2||msg||y2) 的顺序混合数据并做sm3摘要 781 c3 := calculateC3(curve, x2, y2, msg) 782 // 7.根据参数将C1,C2,C3拼接成加密结果 783 // c1字节数组 : 根据加密参数中的座标序列化模式,对c1进行序列化转为字节数组 784 c1 := opts.PointMarshalMode.mashal(curve, x1, y1) 785 // 如果C2C3不做ASN1转码,则直接在这里拼接加密结果 786 // 在 GB/T 32918.4-2016 中只看到直接拼接C2C3的,并没有对C3C2做ASN1转码的描述 787 if opts.CiphertextEncoding == ENCODING_PLAIN { 788 switch opts.CiphertextSplicingOrder { 789 case C1C3C2: 790 return append(append(c1, c3...), c2...), nil 791 case C1C2C3: 792 return append(append(c1, c2...), c3...), nil 793 } 794 } 795 // C2C3做ASN1转码时,只支持C1C3C2模式且C1不压缩 796 return mashalASN1Ciphertext(x1, y1, c2, c3) 797 } 798 } 799 800 // sm2私钥解密 801 // 802 // 参考: GB/T 32918.4-2016 chapter 7. 803 func decryptGeneric(priv *PrivateKey, ciphertext []byte, opts *DecrypterOpts) ([]byte, error) { 804 // 默认拼接顺序C1C3C2 805 splicingOrder := C1C3C2 806 if opts != nil { 807 // C3C2做了ASN1转码时,按照对应规则读取C1C3C2并做sm2私钥解密 808 if opts.CiphertextEncoding == ENCODING_ASN1 { 809 return decryptASN1(priv, ciphertext) 810 } 811 // 不是固定的ASN1模式时,设置传入的拼接模式 812 splicingOrder = opts.CipherTextSplicingOrder 813 } 814 // 判断密文是否做过ASN1转码 815 if ciphertext[0] == 0x30 { 816 return decryptASN1(priv, ciphertext) 817 } 818 ciphertextLen := len(ciphertext) 819 if ciphertextLen <= 1+(priv.Params().BitSize/8)+sm3.Size { 820 return nil, errors.New("SM2: invalid ciphertext length") 821 } 822 curve := priv.Curve 823 // 获取C1坐标,以及C1结束位置 824 x1, y1, c1End, err := bytes2Point(curve, ciphertext) 825 if err != nil { 826 return nil, err 827 } 828 829 // 根据拼接顺序取出C2C3 830 var c2, c3 []byte 831 if splicingOrder == C1C3C2 { 832 c2 = ciphertext[c1End+sm3.Size:] 833 c3 = ciphertext[c1End : c1End+sm3.Size] 834 } else { 835 c2 = ciphertext[c1End : ciphertextLen-sm3.Size] 836 c3 = ciphertext[ciphertextLen-sm3.Size:] 837 } 838 // 执行sm2私钥解密逻辑 839 return rawDecrypt(priv, x1, y1, c2, c3) 840 } 841 842 // 按照C1C3C2顺序, C1未压缩, C3C2做了ASN1转码的规则进行sm2私钥解密 843 func decryptASN1(priv *PrivateKey, ciphertext []byte) ([]byte, error) { 844 x1, y1, c2, c3, err := unmarshalASN1Ciphertext(ciphertext) 845 if err != nil { 846 return nil, err 847 } 848 return rawDecrypt(priv, x1, y1, c2, c3) 849 } 850 851 // 按照C1C3C2顺序, C1未压缩, C3C2做了ASN1转码的规则读取C1,C2,C3 852 func unmarshalASN1Ciphertext(ciphertext []byte) (*big.Int, *big.Int, []byte, []byte, error) { 853 var ( 854 x1, y1 = &big.Int{}, &big.Int{} 855 c2, c3 []byte 856 inner cryptobyte.String 857 ) 858 input := cryptobyte.String(ciphertext) 859 if !input.ReadASN1(&inner, asn1.SEQUENCE) || 860 !input.Empty() || 861 !inner.ReadASN1Integer(x1) || 862 !inner.ReadASN1Integer(y1) || 863 !inner.ReadASN1Bytes(&c3, asn1.OCTET_STRING) || 864 !inner.ReadASN1Bytes(&c2, asn1.OCTET_STRING) || 865 !inner.Empty() { 866 return nil, nil, nil, nil, errors.New("SM2: invalid asn1 format ciphertext") 867 } 868 return x1, y1, c2, c3, nil 869 } 870 871 // sm2私钥解密实现逻辑 872 func rawDecrypt(priv *PrivateKey, x1, y1 *big.Int, c2, c3 []byte) ([]byte, error) { 873 // 获取私钥对应曲线 874 curve := priv.Curve 875 // 根据C1计算随机点 (x2,y2) = c1 * D 876 x2, y2 := curve.ScalarMult(x1, y1, priv.D.Bytes()) 877 msgLen := len(c2) 878 // 派生密钥 879 t, success := kdf(append(toBytes(curve, x2), toBytes(curve, y2)...), msgLen) 880 if !success { 881 return nil, errors.New("SM2: invalid cipher text") 882 } 883 // 再对c2做异或运算,恢复msg 884 msg := make([]byte, msgLen) 885 for i := 0; i < msgLen; i++ { 886 msg[i] = c2[i] ^ t[i] 887 } 888 // 重新计算C3并比较 889 u := calculateC3(curve, x2, y2, msg) 890 for i := 0; i < sm3.Size; i++ { 891 if c3[i] != u[i] { 892 return nil, errors.New("SM2: invalid hash value") 893 } 894 } 895 return msg, nil 896 } 897 898 // ASN1Ciphertext2Plain sm2加密结果去除ASN1转码 899 // ASN1Ciphertext2Plain utility method to convert ASN.1 encoding ciphertext to plain encoding format 900 func ASN1Ciphertext2Plain(ciphertext []byte, opts *EncrypterOpts) ([]byte, error) { 901 if opts == nil { 902 opts = defaultEncrypterOpts 903 } 904 x1, y1, c2, c3, err := unmarshalASN1Ciphertext(ciphertext) 905 if err != nil { 906 return nil, err 907 } 908 curve := P256Sm2() 909 c1 := opts.PointMarshalMode.mashal(curve, x1, y1) 910 if opts.CiphertextSplicingOrder == C1C3C2 { 911 // c1 || c3 || c2 912 return append(append(c1, c3...), c2...), nil 913 } 914 // c1 || c2 || c3 915 return append(append(c1, c2...), c3...), nil 916 } 917 918 // PlainCiphertext2ASN1 sm2加密结果改为ASN1转码 919 // PlainCiphertext2ASN1 utility method to convert plain encoding ciphertext to ASN.1 encoding format 920 func PlainCiphertext2ASN1(ciphertext []byte, from ciphertextSplicingOrder) ([]byte, error) { 921 if ciphertext[0] == 0x30 { 922 return nil, errors.New("SM2: invalid plain encoding ciphertext") 923 } 924 curve := P256Sm2() 925 ciphertextLen := len(ciphertext) 926 if ciphertextLen <= 1+(curve.Params().BitSize/8)+sm3.Size { 927 return nil, errors.New("SM2: invalid ciphertext length") 928 } 929 // get C1, and check C1 930 x1, y1, c3Start, err := bytes2Point(curve, ciphertext) 931 if err != nil { 932 return nil, err 933 } 934 935 var c2, c3 []byte 936 937 if from == C1C3C2 { 938 c2 = ciphertext[c3Start+sm3.Size:] 939 c3 = ciphertext[c3Start : c3Start+sm3.Size] 940 } else { 941 c2 = ciphertext[c3Start : ciphertextLen-sm3.Size] 942 c3 = ciphertext[ciphertextLen-sm3.Size:] 943 } 944 return mashalASN1Ciphertext(x1, y1, c2, c3) 945 } 946 947 // AdjustCiphertextSplicingOrder 修改sm2加密结果的C2C3拼接顺序 948 // AdjustCiphertextSplicingOrder utility method to change c2 c3 order 949 func AdjustCiphertextSplicingOrder(ciphertext []byte, from, to ciphertextSplicingOrder) ([]byte, error) { 950 curve := P256Sm2() 951 if from == to { 952 return ciphertext, nil 953 } 954 ciphertextLen := len(ciphertext) 955 if ciphertextLen <= 1+(curve.Params().BitSize/8)+sm3.Size { 956 return nil, errors.New("SM2: invalid ciphertext length") 957 } 958 // 检查C1并获取C1结束位置 959 _, _, c1End, err := bytes2Point(curve, ciphertext) 960 if err != nil { 961 return nil, err 962 } 963 var c1, c2, c3 []byte 964 c1 = ciphertext[:c1End] 965 if from == C1C3C2 { 966 c2 = ciphertext[c1End+sm3.Size:] 967 c3 = ciphertext[c1End : c1End+sm3.Size] 968 } else { 969 c2 = ciphertext[c1End : ciphertextLen-sm3.Size] 970 c3 = ciphertext[ciphertextLen-sm3.Size:] 971 } 972 result := make([]byte, ciphertextLen) 973 copy(result, c1) 974 if to == C1C3C2 { 975 // c1 || c3 || c2 976 copy(result[c1End:], c3) 977 copy(result[c1End+sm3.Size:], c2) 978 } else { 979 // c1 || c2 || c3 980 copy(result[c1End:], c2) 981 copy(result[ciphertextLen-sm3.Size:], c3) 982 } 983 return result, nil 984 } 985 986 // 计算C3 : sm3hash(x2||msg||y2) 987 func calculateC3(curve elliptic.Curve, x2, y2 *big.Int, msg []byte) []byte { 988 md := sm3.New() 989 md.Write(toBytes(curve, x2)) 990 md.Write(msg) 991 md.Write(toBytes(curve, y2)) 992 return md.Sum(nil) 993 } 994 995 // 对C3C2做ASN1格式转码,并将加密啊结果拼接为C1C3C2模式,且C1不压缩 996 func mashalASN1Ciphertext(x1, y1 *big.Int, c2, c3 []byte) ([]byte, error) { 997 var b cryptobyte.Builder 998 b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { 999 b.AddASN1BigInt(x1) 1000 b.AddASN1BigInt(y1) 1001 b.AddASN1OctetString(c3) 1002 b.AddASN1OctetString(c2) 1003 }) 1004 return b.Bytes() 1005 } 1006 1007 // // EncryptASN1 sm2 encrypt and output ASN.1 result, compliance with GB/T 32918.4-2016. 1008 // func EncryptASN1(random io.Reader, pub *ecdsa.PublicKey, msg []byte) ([]byte, error) { 1009 // return Encrypt(random, pub, msg, ASN1EncrypterOpts) 1010 // } 1011 1012 const maxRetryLimit = 100 1013 1014 // 密钥派生函数 1015 // kdf key derivation function, compliance with GB/T 32918.4-2016 5.4.3. 1016 func kdf(z []byte, len int) ([]byte, bool) { 1017 // limit := (len + sm3.Size - 1) >> sm3.SizeBitSize 1018 limit := (len + sm3.Size - 1) >> 5 1019 hasher := sm3.New() 1020 var countBytes [4]byte 1021 var ct uint32 = 1 1022 k := make([]byte, len+sm3.Size-1) 1023 for i := 0; i < limit; i++ { 1024 binary.BigEndian.PutUint32(countBytes[:], ct) 1025 hasher.Write(z) 1026 hasher.Write(countBytes[:]) 1027 copy(k[i*sm3.Size:], hasher.Sum(nil)) 1028 ct++ 1029 hasher.Reset() 1030 } 1031 for i := 0; i < len; i++ { 1032 if k[i] != 0 { 1033 return k[:len], true 1034 } 1035 } 1036 return k, false 1037 } 1038 1039 const ( 1040 uncompressed byte = 0x04 1041 compressed02 byte = 0x02 1042 compressed03 byte = 0x03 1043 mixed06 byte = 0x06 1044 mixed07 byte = 0x07 1045 ) 1046 1047 // C1序列化模式 1048 type pointMarshalMode byte 1049 1050 const ( 1051 // MarshalUncompressed C1不压缩序列化 1052 // MarshalUncompressed uncompressed mashal mode 1053 MarshalUncompressed pointMarshalMode = iota 1054 // MarshalCompressed C1压缩序列化 1055 // MarshalCompressed compressed mashal mode 1056 MarshalCompressed 1057 // MarshalMixed C1混合序列化 1058 // MarshalMixed mixed mashal mode 1059 MarshalMixed 1060 ) 1061 1062 // sm2 C1C2C3拼接顺序 1063 type ciphertextSplicingOrder byte 1064 1065 const ( 1066 // C1C3C2 默认使用 C1C3C2 1067 C1C3C2 ciphertextSplicingOrder = iota 1068 C1C2C3 1069 ) 1070 1071 // sm2 C2C3转码规则 1072 type ciphertextEncoding byte 1073 1074 //goland:noinspection GoSnakeCaseUsage 1075 const ( 1076 // ENCODING_PLAIN 平文,即不对C2C3做ASN1转码 1077 ENCODING_PLAIN ciphertextEncoding = iota 1078 // ENCODING_ASN1 ASN1,即对C2C3做ASN1转码 1079 ENCODING_ASN1 1080 ) 1081 1082 // EncrypterOpts 加密参数 1083 // EncrypterOpts encryption options 1084 type EncrypterOpts struct { 1085 // C2C3转码规则 1086 CiphertextEncoding ciphertextEncoding 1087 // C1序列化模式 1088 PointMarshalMode pointMarshalMode 1089 // C1C2C3拼接模式 1090 CiphertextSplicingOrder ciphertextSplicingOrder 1091 } 1092 1093 // DecrypterOpts 解密参数 1094 // DecrypterOpts decryption options 1095 type DecrypterOpts struct { 1096 // 转码规则 1097 CiphertextEncoding ciphertextEncoding 1098 // 拼接模式 1099 CipherTextSplicingOrder ciphertextSplicingOrder 1100 } 1101 1102 // NewPlainEncrypterOpts 生成不做ASN1转码的sm2加密参数 1103 func NewPlainEncrypterOpts(marhsalMode pointMarshalMode, splicingOrder ciphertextSplicingOrder) *EncrypterOpts { 1104 return &EncrypterOpts{ENCODING_PLAIN, marhsalMode, splicingOrder} 1105 } 1106 1107 // NewPlainDecrypterOpts 生成不做ASN1转码的sm2解密参数 1108 func NewPlainDecrypterOpts(splicingOrder ciphertextSplicingOrder) *DecrypterOpts { 1109 return &DecrypterOpts{ENCODING_PLAIN, splicingOrder} 1110 } 1111 1112 // 曲线座标序列化, 用于C1的序列化计算 1113 func (mode pointMarshalMode) mashal(curve elliptic.Curve, x, y *big.Int) []byte { 1114 switch mode { 1115 case MarshalCompressed: 1116 // C1压缩序列化 1117 return point2CompressedBytes(curve, x, y) 1118 case MarshalMixed: 1119 // C1混合序列化 1120 return point2MixedBytes(curve, x, y) 1121 default: 1122 // C1完整序列化 1123 return point2UncompressedBytes(curve, x, y) 1124 } 1125 } 1126 1127 // 默认加密参数: C1C3C2, C1不压缩, C3C2不做ASN1转码 1128 var defaultEncrypterOpts = &EncrypterOpts{ENCODING_PLAIN, MarshalUncompressed, C1C3C2} 1129 1130 // ASN1EncrypterOpts ASN1转码加密参数: C1C3C2, C1不压缩, C3C2做ASN1转码 1131 var ASN1EncrypterOpts = &EncrypterOpts{ENCODING_ASN1, MarshalUncompressed, C1C3C2} 1132 1133 // ASN1DecrypterOpts ASN1转码解密参数: C1C3C2, C3C2做ASN1转码 1134 var ASN1DecrypterOpts = &DecrypterOpts{ENCODING_ASN1, C1C3C2} 1135 1136 // ↑↑↑↑↑↑↑↑↑↑ 非对称加解密 ↑↑↑↑↑↑↑↑↑↑