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  }