// Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the Golang LICENSE file. package main import ( "crypto/ecdsa" "crypto/elliptic" "encoding/asn1" "errors" ) // ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure. // References: // RFC5915 // SEC1 - http://www.secg.org/download/aid-780/sec1-v2.pdf // Per RFC5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in // most cases it is not. type ecPrivateKey struct { Version int PrivateKey []byte NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"` PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"` } var ( oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} ) func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) { switch curve { case elliptic.P224(): return oidNamedCurveP224, true case elliptic.P256(): return oidNamedCurveP256, true case elliptic.P384(): return oidNamedCurveP384, true case elliptic.P521(): return oidNamedCurveP521, true } return nil, false } func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) { oid, ok := oidFromNamedCurve(key.Curve) if !ok { return nil, errors.New("x509: unknown elliptic curve") } return asn1.Marshal(ecPrivateKey{ Version: 1, PrivateKey: key.D.Bytes(), NamedCurveOID: oid, PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}, }) }