//package ecc provides helpers for creating elliptic curve leys package ecc import ( "crypto/ecdsa" "crypto/elliptic" "crypto/x509" "encoding/pem" "errors" "math/big" ) // ReadPublic loads ecdsa.PublicKey from given PKCS1 X509 or PKIX blobs func ReadPublic(raw []byte) (key *ecdsa.PublicKey, err error) { var encoded *pem.Block if encoded, _ = pem.Decode(raw); encoded == nil { return nil, errors.New("Ecc.ReadPublic(): Key must be PEM encoded PKCS1 X509 certificate or PKIX EC public key") } var parsedKey interface{} var cert *x509.Certificate if parsedKey, err = x509.ParsePKIXPublicKey(encoded.Bytes); err != nil { if cert, err = x509.ParseCertificate(encoded.Bytes); err != nil { return nil, err } parsedKey = cert.PublicKey } var ok bool if key, ok = parsedKey.(*ecdsa.PublicKey); !ok { return nil, errors.New("Ecc.ReadPublic(): Key is not a valid *ecdsa.PublicKey") } return key, nil } // ReadPrivate loads ecdsa.PrivateKey from given PKCS1 or PKCS8 blobs func ReadPrivate(raw []byte) (key *ecdsa.PrivateKey, err error) { var encoded *pem.Block if encoded, _ = pem.Decode(raw); encoded == nil { return nil, errors.New("Ecc.ReadPrivate(): Key must be PEM encoded PKCS1 or PKCS8 EC private key") } var parsedKey interface{} if parsedKey, err = x509.ParseECPrivateKey(encoded.Bytes); err != nil { if parsedKey, err = x509.ParsePKCS8PrivateKey(encoded.Bytes); err != nil { return nil, err } } var ok bool if key, ok = parsedKey.(*ecdsa.PrivateKey); !ok { return nil, errors.New("Ecc.ReadPrivate(): Key is not valid *ecdsa.PrivateKey") } return key, nil } // NewPublic constructs ecdsa.PublicKey from given (X,Y) func NewPublic(x, y []byte) *ecdsa.PublicKey { return &ecdsa.PublicKey{Curve: curve(len(x)), X: new(big.Int).SetBytes(x), Y: new(big.Int).SetBytes(y)} } // NewPrivate constructs ecdsa.PrivateKey from given (X,Y) and D func NewPrivate(x, y, d []byte) *ecdsa.PrivateKey { return &ecdsa.PrivateKey{D: new(big.Int).SetBytes(d), PublicKey: ecdsa.PublicKey{Curve: curve(len(x)), X: new(big.Int).SetBytes(x), Y: new(big.Int).SetBytes(y)}} } func curve(size int) elliptic.Curve { switch size { case 31, 32: return elliptic.P256() case 48: return elliptic.P384() case 65, 66: return elliptic.P521() //adjust for P-521 curve, which can be 65 or 66 bytes default: return nil //unsupported curve } }