github.com/karalabe/go-ethereum@v0.8.5/crypto/ecies/asn1.go (about) 1 package ecies 2 3 import ( 4 "bytes" 5 "crypto" 6 "crypto/elliptic" 7 "crypto/sha1" 8 "crypto/sha256" 9 "crypto/sha512" 10 "encoding/asn1" 11 "encoding/pem" 12 "fmt" 13 "hash" 14 "math/big" 15 ) 16 17 var ( 18 secgScheme = []int{1, 3, 132, 1} 19 shaScheme = []int{2, 16, 840, 1, 101, 3, 4, 2} 20 ansiX962Scheme = []int{1, 2, 840, 10045} 21 x963Scheme = []int{1, 2, 840, 63, 0} 22 ) 23 24 var ErrInvalidPrivateKey = fmt.Errorf("ecies: invalid private key") 25 26 func doScheme(base, v []int) asn1.ObjectIdentifier { 27 var oidInts asn1.ObjectIdentifier 28 oidInts = append(oidInts, base...) 29 return append(oidInts, v...) 30 } 31 32 // curve OID code taken from crypto/x509, including 33 // - oidNameCurve* 34 // - namedCurveFromOID 35 // - oidFromNamedCurve 36 // RFC 5480, 2.1.1.1. Named Curve 37 // 38 // secp224r1 OBJECT IDENTIFIER ::= { 39 // iso(1) identified-organization(3) certicom(132) curve(0) 33 } 40 // 41 // secp256r1 OBJECT IDENTIFIER ::= { 42 // iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) 43 // prime(1) 7 } 44 // 45 // secp384r1 OBJECT IDENTIFIER ::= { 46 // iso(1) identified-organization(3) certicom(132) curve(0) 34 } 47 // 48 // secp521r1 OBJECT IDENTIFIER ::= { 49 // iso(1) identified-organization(3) certicom(132) curve(0) 35 } 50 // 51 // NB: secp256r1 is equivalent to prime256v1 52 type secgNamedCurve asn1.ObjectIdentifier 53 54 var ( 55 secgNamedCurveP224 = secgNamedCurve{1, 3, 132, 0, 33} 56 secgNamedCurveP256 = secgNamedCurve{1, 2, 840, 10045, 3, 1, 7} 57 secgNamedCurveP384 = secgNamedCurve{1, 3, 132, 0, 34} 58 secgNamedCurveP521 = secgNamedCurve{1, 3, 132, 0, 35} 59 rawCurveP224 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 3} 60 rawCurveP256 = []byte{6, 8, 4, 2, 1, 3, 4, 7, 2, 2, 0, 6, 6, 1, 3, 1, 7} 61 rawCurveP384 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 4} 62 rawCurveP521 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 5} 63 ) 64 65 func rawCurve(curve elliptic.Curve) []byte { 66 switch curve { 67 case elliptic.P224(): 68 return rawCurveP224 69 case elliptic.P256(): 70 return rawCurveP256 71 case elliptic.P384(): 72 return rawCurveP384 73 case elliptic.P521(): 74 return rawCurveP521 75 default: 76 return nil 77 } 78 } 79 80 func (curve secgNamedCurve) Equal(curve2 secgNamedCurve) bool { 81 if len(curve) != len(curve2) { 82 return false 83 } 84 for i, _ := range curve { 85 if curve[i] != curve2[i] { 86 return false 87 } 88 } 89 return true 90 } 91 92 func namedCurveFromOID(curve secgNamedCurve) elliptic.Curve { 93 switch { 94 case curve.Equal(secgNamedCurveP224): 95 return elliptic.P224() 96 case curve.Equal(secgNamedCurveP256): 97 return elliptic.P256() 98 case curve.Equal(secgNamedCurveP384): 99 return elliptic.P384() 100 case curve.Equal(secgNamedCurveP521): 101 return elliptic.P521() 102 } 103 return nil 104 } 105 106 func oidFromNamedCurve(curve elliptic.Curve) (secgNamedCurve, bool) { 107 switch curve { 108 case elliptic.P224(): 109 return secgNamedCurveP224, true 110 case elliptic.P256(): 111 return secgNamedCurveP256, true 112 case elliptic.P384(): 113 return secgNamedCurveP384, true 114 case elliptic.P521(): 115 return secgNamedCurveP521, true 116 } 117 118 return nil, false 119 } 120 121 // asnAlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC 122 // 5280, section 4.1.1.2. 123 type asnAlgorithmIdentifier struct { 124 Algorithm asn1.ObjectIdentifier 125 Parameters asn1.RawValue `asn1:"optional"` 126 } 127 128 func (a asnAlgorithmIdentifier) Cmp(b asnAlgorithmIdentifier) bool { 129 if len(a.Algorithm) != len(b.Algorithm) { 130 return false 131 } 132 for i, _ := range a.Algorithm { 133 if a.Algorithm[i] != b.Algorithm[i] { 134 return false 135 } 136 } 137 return true 138 } 139 140 type asnHashFunction asnAlgorithmIdentifier 141 142 var ( 143 oidSHA1 = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26} 144 oidSHA224 = doScheme(shaScheme, []int{4}) 145 oidSHA256 = doScheme(shaScheme, []int{1}) 146 oidSHA384 = doScheme(shaScheme, []int{2}) 147 oidSHA512 = doScheme(shaScheme, []int{3}) 148 ) 149 150 func hashFromOID(oid asn1.ObjectIdentifier) func() hash.Hash { 151 switch { 152 case oid.Equal(oidSHA1): 153 return sha1.New 154 case oid.Equal(oidSHA224): 155 return sha256.New224 156 case oid.Equal(oidSHA256): 157 return sha256.New 158 case oid.Equal(oidSHA384): 159 return sha512.New384 160 case oid.Equal(oidSHA512): 161 return sha512.New 162 } 163 return nil 164 } 165 166 func oidFromHash(hash crypto.Hash) (asn1.ObjectIdentifier, bool) { 167 switch hash { 168 case crypto.SHA1: 169 return oidSHA1, true 170 case crypto.SHA224: 171 return oidSHA224, true 172 case crypto.SHA256: 173 return oidSHA256, true 174 case crypto.SHA384: 175 return oidSHA384, true 176 case crypto.SHA512: 177 return oidSHA512, true 178 default: 179 return nil, false 180 } 181 } 182 183 var ( 184 asnAlgoSHA1 = asnHashFunction{ 185 Algorithm: oidSHA1, 186 } 187 asnAlgoSHA224 = asnHashFunction{ 188 Algorithm: oidSHA224, 189 } 190 asnAlgoSHA256 = asnHashFunction{ 191 Algorithm: oidSHA256, 192 } 193 asnAlgoSHA384 = asnHashFunction{ 194 Algorithm: oidSHA384, 195 } 196 asnAlgoSHA512 = asnHashFunction{ 197 Algorithm: oidSHA512, 198 } 199 ) 200 201 // type ASNasnSubjectPublicKeyInfo struct { 202 // 203 // } 204 // 205 206 type asnSubjectPublicKeyInfo struct { 207 Algorithm asn1.ObjectIdentifier 208 PublicKey asn1.BitString 209 Supplements ecpksSupplements `asn1:"optional"` 210 } 211 212 type asnECPKAlgorithms struct { 213 Type asn1.ObjectIdentifier 214 } 215 216 var idPublicKeyType = doScheme(ansiX962Scheme, []int{2}) 217 var idEcPublicKey = doScheme(idPublicKeyType, []int{1}) 218 var idEcPublicKeySupplemented = doScheme(idPublicKeyType, []int{0}) 219 220 func curveToRaw(curve elliptic.Curve) (rv asn1.RawValue, ok bool) { 221 switch curve { 222 case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521(): 223 raw := rawCurve(curve) 224 return asn1.RawValue{ 225 Tag: 30, 226 Bytes: raw[2:], 227 FullBytes: raw, 228 }, true 229 default: 230 return rv, false 231 } 232 } 233 234 func asnECPublicKeyType(curve elliptic.Curve) (algo asnAlgorithmIdentifier, ok bool) { 235 raw, ok := curveToRaw(curve) 236 if !ok { 237 return 238 } else { 239 return asnAlgorithmIdentifier{Algorithm: idEcPublicKey, 240 Parameters: raw}, true 241 } 242 } 243 244 type asnECPrivKeyVer int 245 246 var asnECPrivKeyVer1 asnECPrivKeyVer = 1 247 248 type asnPrivateKey struct { 249 Version asnECPrivKeyVer 250 Private []byte 251 Curve secgNamedCurve `asn1:"optional"` 252 Public asn1.BitString 253 } 254 255 var asnECDH = doScheme(secgScheme, []int{12}) 256 257 type asnECDHAlgorithm asnAlgorithmIdentifier 258 259 var ( 260 dhSinglePass_stdDH_sha1kdf = asnECDHAlgorithm{ 261 Algorithm: doScheme(x963Scheme, []int{2}), 262 } 263 dhSinglePass_stdDH_sha256kdf = asnECDHAlgorithm{ 264 Algorithm: doScheme(secgScheme, []int{11, 1}), 265 } 266 dhSinglePass_stdDH_sha384kdf = asnECDHAlgorithm{ 267 Algorithm: doScheme(secgScheme, []int{11, 2}), 268 } 269 dhSinglePass_stdDH_sha224kdf = asnECDHAlgorithm{ 270 Algorithm: doScheme(secgScheme, []int{11, 0}), 271 } 272 dhSinglePass_stdDH_sha512kdf = asnECDHAlgorithm{ 273 Algorithm: doScheme(secgScheme, []int{11, 3}), 274 } 275 ) 276 277 func (a asnECDHAlgorithm) Cmp(b asnECDHAlgorithm) bool { 278 if len(a.Algorithm) != len(b.Algorithm) { 279 return false 280 } 281 for i, _ := range a.Algorithm { 282 if a.Algorithm[i] != b.Algorithm[i] { 283 return false 284 } 285 } 286 return true 287 } 288 289 // asnNISTConcatenation is the only supported KDF at this time. 290 type asnKeyDerivationFunction asnAlgorithmIdentifier 291 292 var asnNISTConcatenationKDF = asnKeyDerivationFunction{ 293 Algorithm: doScheme(secgScheme, []int{17, 1}), 294 } 295 296 func (a asnKeyDerivationFunction) Cmp(b asnKeyDerivationFunction) bool { 297 if len(a.Algorithm) != len(b.Algorithm) { 298 return false 299 } 300 for i, _ := range a.Algorithm { 301 if a.Algorithm[i] != b.Algorithm[i] { 302 return false 303 } 304 } 305 return true 306 } 307 308 var eciesRecommendedParameters = doScheme(secgScheme, []int{7}) 309 var eciesSpecifiedParameters = doScheme(secgScheme, []int{8}) 310 311 type asnECIESParameters struct { 312 KDF asnKeyDerivationFunction `asn1:"optional"` 313 Sym asnSymmetricEncryption `asn1:"optional"` 314 MAC asnMessageAuthenticationCode `asn1:"optional"` 315 } 316 317 type asnSymmetricEncryption asnAlgorithmIdentifier 318 319 var ( 320 aes128CTRinECIES = asnSymmetricEncryption{ 321 Algorithm: doScheme(secgScheme, []int{21, 0}), 322 } 323 aes192CTRinECIES = asnSymmetricEncryption{ 324 Algorithm: doScheme(secgScheme, []int{21, 1}), 325 } 326 aes256CTRinECIES = asnSymmetricEncryption{ 327 Algorithm: doScheme(secgScheme, []int{21, 2}), 328 } 329 ) 330 331 func (a asnSymmetricEncryption) Cmp(b asnSymmetricEncryption) bool { 332 if len(a.Algorithm) != len(b.Algorithm) { 333 return false 334 } 335 for i, _ := range a.Algorithm { 336 if a.Algorithm[i] != b.Algorithm[i] { 337 return false 338 } 339 } 340 return true 341 } 342 343 type asnMessageAuthenticationCode asnAlgorithmIdentifier 344 345 var ( 346 hmacFull = asnMessageAuthenticationCode{ 347 Algorithm: doScheme(secgScheme, []int{22}), 348 } 349 ) 350 351 func (a asnMessageAuthenticationCode) Cmp(b asnMessageAuthenticationCode) bool { 352 if len(a.Algorithm) != len(b.Algorithm) { 353 return false 354 } 355 for i, _ := range a.Algorithm { 356 if a.Algorithm[i] != b.Algorithm[i] { 357 return false 358 } 359 } 360 return true 361 } 362 363 type ecpksSupplements struct { 364 ECDomain secgNamedCurve 365 ECCAlgorithms eccAlgorithmSet 366 } 367 368 type eccAlgorithmSet struct { 369 ECDH asnECDHAlgorithm `asn1:"optional"` 370 ECIES asnECIESParameters `asn1:"optional"` 371 } 372 373 func marshalSubjectPublicKeyInfo(pub *PublicKey) (subj asnSubjectPublicKeyInfo, err error) { 374 subj.Algorithm = idEcPublicKeySupplemented 375 curve, ok := oidFromNamedCurve(pub.Curve) 376 if !ok { 377 err = ErrInvalidPublicKey 378 return 379 } 380 subj.Supplements.ECDomain = curve 381 if pub.Params != nil { 382 subj.Supplements.ECCAlgorithms.ECDH = paramsToASNECDH(pub.Params) 383 subj.Supplements.ECCAlgorithms.ECIES = paramsToASNECIES(pub.Params) 384 } 385 pubkey := elliptic.Marshal(pub.Curve, pub.X, pub.Y) 386 subj.PublicKey = asn1.BitString{ 387 BitLength: len(pubkey) * 8, 388 Bytes: pubkey, 389 } 390 return 391 } 392 393 // Encode a public key to DER format. 394 func MarshalPublic(pub *PublicKey) ([]byte, error) { 395 subj, err := marshalSubjectPublicKeyInfo(pub) 396 if err != nil { 397 return nil, err 398 } 399 return asn1.Marshal(subj) 400 } 401 402 // Decode a DER-encoded public key. 403 func UnmarshalPublic(in []byte) (pub *PublicKey, err error) { 404 var subj asnSubjectPublicKeyInfo 405 406 if _, err = asn1.Unmarshal(in, &subj); err != nil { 407 return 408 } 409 if !subj.Algorithm.Equal(idEcPublicKeySupplemented) { 410 err = ErrInvalidPublicKey 411 return 412 } 413 pub = new(PublicKey) 414 pub.Curve = namedCurveFromOID(subj.Supplements.ECDomain) 415 x, y := elliptic.Unmarshal(pub.Curve, subj.PublicKey.Bytes) 416 if x == nil { 417 err = ErrInvalidPublicKey 418 return 419 } 420 pub.X = x 421 pub.Y = y 422 pub.Params = new(ECIESParams) 423 asnECIEStoParams(subj.Supplements.ECCAlgorithms.ECIES, pub.Params) 424 asnECDHtoParams(subj.Supplements.ECCAlgorithms.ECDH, pub.Params) 425 if pub.Params == nil { 426 if pub.Params = ParamsFromCurve(pub.Curve); pub.Params == nil { 427 err = ErrInvalidPublicKey 428 } 429 } 430 return 431 } 432 433 func marshalPrivateKey(prv *PrivateKey) (ecprv asnPrivateKey, err error) { 434 ecprv.Version = asnECPrivKeyVer1 435 ecprv.Private = prv.D.Bytes() 436 437 var ok bool 438 ecprv.Curve, ok = oidFromNamedCurve(prv.PublicKey.Curve) 439 if !ok { 440 err = ErrInvalidPrivateKey 441 return 442 } 443 444 var pub []byte 445 if pub, err = MarshalPublic(&prv.PublicKey); err != nil { 446 return 447 } else { 448 ecprv.Public = asn1.BitString{ 449 BitLength: len(pub) * 8, 450 Bytes: pub, 451 } 452 } 453 return 454 } 455 456 // Encode a private key to DER format. 457 func MarshalPrivate(prv *PrivateKey) ([]byte, error) { 458 ecprv, err := marshalPrivateKey(prv) 459 if err != nil { 460 return nil, err 461 } 462 return asn1.Marshal(ecprv) 463 } 464 465 // Decode a private key from a DER-encoded format. 466 func UnmarshalPrivate(in []byte) (prv *PrivateKey, err error) { 467 var ecprv asnPrivateKey 468 469 if _, err = asn1.Unmarshal(in, &ecprv); err != nil { 470 return 471 } else if ecprv.Version != asnECPrivKeyVer1 { 472 err = ErrInvalidPrivateKey 473 return 474 } 475 476 privateCurve := namedCurveFromOID(ecprv.Curve) 477 if privateCurve == nil { 478 err = ErrInvalidPrivateKey 479 return 480 } 481 482 prv = new(PrivateKey) 483 prv.D = new(big.Int).SetBytes(ecprv.Private) 484 485 if pub, err := UnmarshalPublic(ecprv.Public.Bytes); err != nil { 486 return nil, err 487 } else { 488 prv.PublicKey = *pub 489 } 490 491 return 492 } 493 494 // Export a public key to PEM format. 495 func ExportPublicPEM(pub *PublicKey) (out []byte, err error) { 496 der, err := MarshalPublic(pub) 497 if err != nil { 498 return 499 } 500 501 var block pem.Block 502 block.Type = "ELLIPTIC CURVE PUBLIC KEY" 503 block.Bytes = der 504 505 buf := new(bytes.Buffer) 506 err = pem.Encode(buf, &block) 507 if err != nil { 508 return 509 } else { 510 out = buf.Bytes() 511 } 512 return 513 } 514 515 // Export a private key to PEM format. 516 func ExportPrivatePEM(prv *PrivateKey) (out []byte, err error) { 517 der, err := MarshalPrivate(prv) 518 if err != nil { 519 return 520 } 521 522 var block pem.Block 523 block.Type = "ELLIPTIC CURVE PRIVATE KEY" 524 block.Bytes = der 525 526 buf := new(bytes.Buffer) 527 err = pem.Encode(buf, &block) 528 if err != nil { 529 return 530 } else { 531 out = buf.Bytes() 532 } 533 return 534 } 535 536 // Import a PEM-encoded public key. 537 func ImportPublicPEM(in []byte) (pub *PublicKey, err error) { 538 p, _ := pem.Decode(in) 539 if p == nil || p.Type != "ELLIPTIC CURVE PUBLIC KEY" { 540 return nil, ErrInvalidPublicKey 541 } 542 543 pub, err = UnmarshalPublic(p.Bytes) 544 return 545 } 546 547 // Import a PEM-encoded private key. 548 func ImportPrivatePEM(in []byte) (prv *PrivateKey, err error) { 549 p, _ := pem.Decode(in) 550 if p == nil || p.Type != "ELLIPTIC CURVE PRIVATE KEY" { 551 return nil, ErrInvalidPrivateKey 552 } 553 554 prv, err = UnmarshalPrivate(p.Bytes) 555 return 556 }