in pkcs8.go [189:261]
func MarshalPrivateKey(priv interface{}, password []byte, opts *Opts) ([]byte, error) {
if len(password) == 0 {
return x509.MarshalPKCS8PrivateKey(priv)
}
if opts == nil {
opts = DefaultOpts
}
// Convert private key into PKCS8 format
pkey, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
return nil, err
}
encAlg := opts.Cipher
salt := make([]byte, opts.KDFOpts.GetSaltSize())
_, err = rand.Read(salt)
if err != nil {
return nil, err
}
iv := make([]byte, encAlg.IVSize())
_, err = rand.Read(iv)
if err != nil {
return nil, err
}
key, kdfParams, err := opts.KDFOpts.DeriveKey(password, salt, encAlg.KeySize())
if err != nil {
return nil, err
}
encryptedKey, err := encAlg.Encrypt(key, iv, pkey)
if err != nil {
return nil, err
}
marshalledParams, err := asn1.Marshal(kdfParams)
if err != nil {
return nil, err
}
keyDerivationFunc := pkix.AlgorithmIdentifier{
Algorithm: opts.KDFOpts.OID(),
Parameters: asn1.RawValue{FullBytes: marshalledParams},
}
marshalledIV, err := asn1.Marshal(iv)
if err != nil {
return nil, err
}
encryptionScheme := pkix.AlgorithmIdentifier{
Algorithm: encAlg.OID(),
Parameters: asn1.RawValue{FullBytes: marshalledIV},
}
encryptionAlgorithmParams := pbes2Params{
EncryptionScheme: encryptionScheme,
KeyDerivationFunc: keyDerivationFunc,
}
marshalledEncryptionAlgorithmParams, err := asn1.Marshal(encryptionAlgorithmParams)
if err != nil {
return nil, err
}
encryptionAlgorithm := pkix.AlgorithmIdentifier{
Algorithm: oidPBES2,
Parameters: asn1.RawValue{FullBytes: marshalledEncryptionAlgorithmParams},
}
encryptedPkey := encryptedPrivateKeyInfo{
EncryptionAlgorithm: encryptionAlgorithm,
EncryptedData: encryptedKey,
}
return asn1.Marshal(encryptedPkey)
}