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