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  }