github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/crypto/ecies/ecies.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有(c)2013 Kyle Isom<kyle@tyrfingr.is> 10 //版权所有(c)2012 The Go作者。版权所有。 11 // 12 //以源和二进制形式重新分配和使用,有或无 13 //允许修改,前提是以下条件 14 //遇见: 15 // 16 //*源代码的再分配必须保留上述版权。 17 //注意,此条件列表和以下免责声明。 18 //*二进制形式的再分配必须复制上述内容 19 //版权声明、此条件列表和以下免责声明 20 //在提供的文件和/或其他材料中, 21 //分布。 22 //*无论是谷歌公司的名称还是其 23 //贡献者可用于支持或推广源自 24 //本软件未经事先明确书面许可。 25 // 26 //本软件由版权所有者和贡献者提供。 27 //“原样”和任何明示或暗示的保证,包括但不包括 28 //仅限于对适销性和适用性的暗示保证 29 //不承认特定目的。在任何情况下,版权 30 //所有人或出资人对任何直接、间接、附带的, 31 //特殊、惩戒性或后果性损害(包括但不包括 32 //仅限于采购替代货物或服务;使用损失, 33 //数据或利润;或业务中断),无论如何引起的 34 //责任理论,无论是合同责任、严格责任还是侵权责任。 35 //(包括疏忽或其他)因使用不当而引起的 36 //即使已告知此类损坏的可能性。 37 38 package ecies 39 40 import ( 41 "crypto/cipher" 42 "crypto/ecdsa" 43 "crypto/elliptic" 44 "crypto/hmac" 45 "crypto/subtle" 46 "fmt" 47 "hash" 48 "io" 49 "math/big" 50 ) 51 52 var ( 53 ErrImport = fmt.Errorf("ecies: failed to import key") 54 ErrInvalidCurve = fmt.Errorf("ecies: invalid elliptic curve") 55 ErrInvalidParams = fmt.Errorf("ecies: invalid ECIES parameters") 56 ErrInvalidPublicKey = fmt.Errorf("ecies: invalid public key") 57 ErrSharedKeyIsPointAtInfinity = fmt.Errorf("ecies: shared key is point at infinity") 58 ErrSharedKeyTooBig = fmt.Errorf("ecies: shared key params are too big") 59 ) 60 61 //公钥是椭圆曲线公钥的表示形式。 62 type PublicKey struct { 63 X *big.Int 64 Y *big.Int 65 elliptic.Curve 66 Params *ECIESParams 67 } 68 69 //将ECIES公钥导出为ECDSA公钥。 70 func (pub *PublicKey) ExportECDSA() *ecdsa.PublicKey { 71 return &ecdsa.PublicKey{Curve: pub.Curve, X: pub.X, Y: pub.Y} 72 } 73 74 //将ECDSA公钥导入为特定的公钥。 75 func ImportECDSAPublic(pub *ecdsa.PublicKey) *PublicKey { 76 return &PublicKey{ 77 X: pub.X, 78 Y: pub.Y, 79 Curve: pub.Curve, 80 Params: ParamsFromCurve(pub.Curve), 81 } 82 } 83 84 //private key是椭圆曲线私钥的表示。 85 type PrivateKey struct { 86 PublicKey 87 D *big.Int 88 } 89 90 //将ECIES私钥导出为ECDSA私钥。 91 func (prv *PrivateKey) ExportECDSA() *ecdsa.PrivateKey { 92 pub := &prv.PublicKey 93 pubECDSA := pub.ExportECDSA() 94 return &ecdsa.PrivateKey{PublicKey: *pubECDSA, D: prv.D} 95 } 96 97 //将ECDSA私钥导入为ECIES私钥。 98 func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey { 99 pub := ImportECDSAPublic(&prv.PublicKey) 100 return &PrivateKey{*pub, prv.D} 101 } 102 103 //生成椭圆曲线公钥/私钥对。如果参数为零, 104 //将选择该键的推荐默认参数。 105 func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) { 106 pb, x, y, err := elliptic.GenerateKey(curve, rand) 107 if err != nil { 108 return 109 } 110 prv = new(PrivateKey) 111 prv.PublicKey.X = x 112 prv.PublicKey.Y = y 113 prv.PublicKey.Curve = curve 114 prv.D = new(big.Int).SetBytes(pb) 115 if params == nil { 116 params = ParamsFromCurve(curve) 117 } 118 prv.PublicKey.Params = params 119 return 120 } 121 122 //MaxSharedKeyLength返回共享密钥的最大长度 123 //可以生成公钥。 124 func MaxSharedKeyLength(pub *PublicKey) int { 125 return (pub.Curve.Params().BitSize + 7) / 8 126 } 127 128 //用于建立加密密钥的ECDH密钥协议方法。 129 func (prv *PrivateKey) GenerateShared(pub *PublicKey, skLen, macLen int) (sk []byte, err error) { 130 if prv.PublicKey.Curve != pub.Curve { 131 return nil, ErrInvalidCurve 132 } 133 if skLen+macLen > MaxSharedKeyLength(pub) { 134 return nil, ErrSharedKeyTooBig 135 } 136 137 x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, prv.D.Bytes()) 138 if x == nil { 139 return nil, ErrSharedKeyIsPointAtInfinity 140 } 141 142 sk = make([]byte, skLen+macLen) 143 skBytes := x.Bytes() 144 copy(sk[len(sk)-len(skBytes):], skBytes) 145 return sk, nil 146 } 147 148 var ( 149 ErrKeyDataTooLong = fmt.Errorf("ecies: can't supply requested key data") 150 ErrSharedTooLong = fmt.Errorf("ecies: shared secret is too long") 151 ErrInvalidMessage = fmt.Errorf("ecies: invalid message") 152 ) 153 154 var ( 155 big2To32 = new(big.Int).Exp(big.NewInt(2), big.NewInt(32), nil) 156 big2To32M1 = new(big.Int).Sub(big2To32, big.NewInt(1)) 157 ) 158 159 func incCounter(ctr []byte) { 160 if ctr[3]++; ctr[3] != 0 { 161 return 162 } 163 if ctr[2]++; ctr[2] != 0 { 164 return 165 } 166 if ctr[1]++; ctr[1] != 0 { 167 return 168 } 169 if ctr[0]++; ctr[0] != 0 { 170 return 171 } 172 } 173 174 //NIST SP 800-56串联密钥派生函数(见第5.8.1节)。 175 func concatKDF(hash hash.Hash, z, s1 []byte, kdLen int) (k []byte, err error) { 176 if s1 == nil { 177 s1 = make([]byte, 0) 178 } 179 180 reps := ((kdLen + 7) * 8) / (hash.BlockSize() * 8) 181 if big.NewInt(int64(reps)).Cmp(big2To32M1) > 0 { 182 fmt.Println(big2To32M1) 183 return nil, ErrKeyDataTooLong 184 } 185 186 counter := []byte{0, 0, 0, 1} 187 k = make([]byte, 0) 188 189 for i := 0; i <= reps; i++ { 190 hash.Write(counter) 191 hash.Write(z) 192 hash.Write(s1) 193 k = append(k, hash.Sum(nil)...) 194 hash.Reset() 195 incCounter(counter) 196 } 197 198 k = k[:kdLen] 199 return 200 } 201 202 //message tag根据 203 //秒1,3.5。 204 func messageTag(hash func() hash.Hash, km, msg, shared []byte) []byte { 205 mac := hmac.New(hash, km) 206 mac.Write(msg) 207 mac.Write(shared) 208 tag := mac.Sum(nil) 209 return tag 210 } 211 212 //为ctr模式生成初始化向量。 213 func generateIV(params *ECIESParams, rand io.Reader) (iv []byte, err error) { 214 iv = make([]byte, params.BlockSize) 215 _, err = io.ReadFull(rand, iv) 216 return 217 } 218 219 //symeencrypt使用中指定的块密码执行ctr加密 220 //参数。 221 func symEncrypt(rand io.Reader, params *ECIESParams, key, m []byte) (ct []byte, err error) { 222 c, err := params.Cipher(key) 223 if err != nil { 224 return 225 } 226 227 iv, err := generateIV(params, rand) 228 if err != nil { 229 return 230 } 231 ctr := cipher.NewCTR(c, iv) 232 233 ct = make([]byte, len(m)+params.BlockSize) 234 copy(ct, iv) 235 ctr.XORKeyStream(ct[params.BlockSize:], m) 236 return 237 } 238 239 //symmdecrypt使用中指定的块密码执行ctr解密。 240 //参数 241 func symDecrypt(params *ECIESParams, key, ct []byte) (m []byte, err error) { 242 c, err := params.Cipher(key) 243 if err != nil { 244 return 245 } 246 247 ctr := cipher.NewCTR(c, ct[:params.BlockSize]) 248 249 m = make([]byte, len(ct)-params.BlockSize) 250 ctr.XORKeyStream(m, ct[params.BlockSize:]) 251 return 252 } 253 254 //Encrypt使用第1节5.1中指定的ECIES对消息进行加密。 255 // 256 //s1和s2包含不属于结果的共享信息 257 //密文。s1被输入到键派生中,s2被输入到mac中。如果 258 //未使用共享信息参数,它们应为零。 259 func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err error) { 260 params := pub.Params 261 if params == nil { 262 if params = ParamsFromCurve(pub.Curve); params == nil { 263 err = ErrUnsupportedECIESParameters 264 return 265 } 266 } 267 R, err := GenerateKey(rand, pub.Curve, params) 268 if err != nil { 269 return 270 } 271 272 hash := params.Hash() 273 z, err := R.GenerateShared(pub, params.KeyLen, params.KeyLen) 274 if err != nil { 275 return 276 } 277 K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen) 278 if err != nil { 279 return 280 } 281 Ke := K[:params.KeyLen] 282 Km := K[params.KeyLen:] 283 hash.Write(Km) 284 Km = hash.Sum(nil) 285 hash.Reset() 286 287 em, err := symEncrypt(rand, params, Ke, m) 288 if err != nil || len(em) <= params.BlockSize { 289 return 290 } 291 292 d := messageTag(params.Hash, Km, em, s2) 293 294 Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y) 295 ct = make([]byte, len(Rb)+len(em)+len(d)) 296 copy(ct, Rb) 297 copy(ct[len(Rb):], em) 298 copy(ct[len(Rb)+len(em):], d) 299 return 300 } 301 302 //解密-解密特定的密文。 303 func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) { 304 if len(c) == 0 { 305 return nil, ErrInvalidMessage 306 } 307 params := prv.PublicKey.Params 308 if params == nil { 309 if params = ParamsFromCurve(prv.PublicKey.Curve); params == nil { 310 err = ErrUnsupportedECIESParameters 311 return 312 } 313 } 314 hash := params.Hash() 315 316 var ( 317 rLen int 318 hLen int = hash.Size() 319 mStart int 320 mEnd int 321 ) 322 323 switch c[0] { 324 case 2, 3, 4: 325 rLen = (prv.PublicKey.Curve.Params().BitSize + 7) / 4 326 if len(c) < (rLen + hLen + 1) { 327 err = ErrInvalidMessage 328 return 329 } 330 default: 331 err = ErrInvalidPublicKey 332 return 333 } 334 335 mStart = rLen 336 mEnd = len(c) - hLen 337 338 R := new(PublicKey) 339 R.Curve = prv.PublicKey.Curve 340 R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen]) 341 if R.X == nil { 342 err = ErrInvalidPublicKey 343 return 344 } 345 if !R.Curve.IsOnCurve(R.X, R.Y) { 346 err = ErrInvalidCurve 347 return 348 } 349 350 z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen) 351 if err != nil { 352 return 353 } 354 355 K, err := concatKDF(hash, z, s1, params.KeyLen+params.KeyLen) 356 if err != nil { 357 return 358 } 359 360 Ke := K[:params.KeyLen] 361 Km := K[params.KeyLen:] 362 hash.Write(Km) 363 Km = hash.Sum(nil) 364 hash.Reset() 365 366 d := messageTag(params.Hash, Km, c[mStart:mEnd], s2) 367 if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 { 368 err = ErrInvalidMessage 369 return 370 } 371 372 m, err = symDecrypt(params, Ke, c[mStart:mEnd]) 373 return 374 }