// // Copyright (c) SAS Institute Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // PKCS#8 is a specification for encoding private keys into an ASN.1 structure. // See RFC 5208 // // The Go standard library implements parsing PKCS#8 keys but does not support // marshalling them; this module provides that function. package pkcs8 import ( "crypto" "crypto/ecdsa" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" "errors" "github.com/sassoftware/relic/lib/x509tools" ) type privateKeyInfo struct { Version int PrivateKeyAlgorithm pkix.AlgorithmIdentifier PrivateKey []byte } // Marshal a RSA or ECDSA private key as an unencrypted PKCS#8 blob func MarshalPKCS8PrivateKey(priv crypto.PrivateKey) ([]byte, error) { switch pkey := priv.(type) { case *rsa.PrivateKey: return asn1.Marshal(privateKeyInfo{ Version: 0, PrivateKeyAlgorithm: pkix.AlgorithmIdentifier{ Algorithm: x509tools.OidPublicKeyRSA, Parameters: asn1.NullRawValue, }, PrivateKey: x509.MarshalPKCS1PrivateKey(pkey), }) case *ecdsa.PrivateKey: curve, err := x509tools.CurveByCurve(pkey.Curve) if err != nil { return nil, err } eckey, err := x509.MarshalECPrivateKey(pkey) if err != nil { return nil, err } return asn1.Marshal(privateKeyInfo{ Version: 0, PrivateKeyAlgorithm: pkix.AlgorithmIdentifier{ Algorithm: x509tools.OidPublicKeyECDSA, Parameters: asn1.RawValue{FullBytes: curve.ToDer()}, }, PrivateKey: eckey, }) default: return nil, errors.New("unsupported key type") } }