github.com/emmansun/gmsm@v0.29.1/pkcs8/pkcs8.go (about) 1 // Package pkcs8 implements functions to parse and convert private keys in PKCS#8 format with ShangMi(SM) support, as defined in RFC5208 and RFC5958. 2 package pkcs8 3 4 import ( 5 "crypto/ecdsa" 6 "crypto/rand" 7 "crypto/rsa" 8 "crypto/x509/pkix" 9 "encoding/asn1" 10 "encoding/pem" 11 "errors" 12 13 "github.com/emmansun/gmsm/pkcs" 14 "github.com/emmansun/gmsm/sm2" 15 "github.com/emmansun/gmsm/sm9" 16 "github.com/emmansun/gmsm/smx509" 17 ) 18 19 type Opts = pkcs.PBES2Opts 20 type PBKDF2Opts = pkcs.PBKDF2Opts 21 type ScryptOpts = pkcs.ScryptOpts 22 23 var DefaultOpts = pkcs.DefaultOpts 24 var SM3 = pkcs.SM3 25 var SHA1 = pkcs.SHA1 26 var SHA224 = pkcs.SHA224 27 var SHA256 = pkcs.SHA256 28 var SHA384 = pkcs.SHA384 29 var SHA512 = pkcs.SHA512 30 var SHA512_224 = pkcs.SHA512_224 31 var SHA512_256 = pkcs.SHA512_256 32 33 // for encrypted private-key information 34 type encryptedPrivateKeyInfo struct { 35 EncryptionAlgorithm pkix.AlgorithmIdentifier 36 EncryptedData []byte 37 } 38 39 var ( 40 ErrUnsupportedPBES = errors.New("pkcs8: only part of PBES1/PBES2 supported") 41 ErrUnexpectedKeyType = errors.New("pkcs8: unexpected key type") 42 ) 43 44 // ParsePrivateKey parses a DER-encoded PKCS#8 private key. 45 // Password can be nil. 46 // This is equivalent to ParsePKCS8PrivateKey. 47 func ParsePrivateKey(der []byte, password []byte) (any, pkcs.KDFParameters, error) { 48 // No password provided, assume the private key is unencrypted 49 if len(password) == 0 { 50 privateKey, err := smx509.ParsePKCS8PrivateKey(der) 51 return privateKey, nil, err 52 } 53 54 // Use the password provided to decrypt the private key 55 var privKey encryptedPrivateKeyInfo 56 if _, err := asn1.Unmarshal(der, &privKey); err != nil { 57 if block, _ := pem.Decode(der); block != nil { 58 return nil, nil, errors.New("pkcs8: this method just supports DER-encoded key") 59 } 60 return nil, nil, errors.New("pkcs8: only PKCS #5 v2.0 supported") 61 } 62 63 var kdfParams pkcs.KDFParameters 64 var decryptedKey []byte 65 var err error 66 switch { 67 case pkcs.IsPBES2(privKey.EncryptionAlgorithm) || pkcs.IsSMPBES(privKey.EncryptionAlgorithm): 68 var params pkcs.PBES2Params 69 if _, err := asn1.Unmarshal(privKey.EncryptionAlgorithm.Parameters.FullBytes, ¶ms); err != nil { 70 return nil, nil, errors.New("pkcs8: invalid PBES2 parameters") 71 } 72 decryptedKey, kdfParams, err = params.Decrypt(password, privKey.EncryptedData) 73 case pkcs.IsPBES1(privKey.EncryptionAlgorithm): 74 pbes1 := &pkcs.PBES1{Algorithm: privKey.EncryptionAlgorithm} 75 decryptedKey, kdfParams, err = pbes1.Decrypt(password, privKey.EncryptedData) 76 default: 77 return nil, nil, ErrUnsupportedPBES 78 } 79 if err != nil { 80 return nil, nil, err 81 } 82 key, err := smx509.ParsePKCS8PrivateKey(decryptedKey) 83 if err != nil { 84 return nil, nil, err 85 } 86 return key, kdfParams, nil 87 } 88 89 // MarshalPrivateKey encodes a private key into DER-encoded PKCS#8 with the given options. 90 // Password can be nil. 91 func MarshalPrivateKey(priv any, password []byte, encrypter pkcs.PBESEncrypter) ([]byte, error) { 92 if len(password) == 0 { 93 return smx509.MarshalPKCS8PrivateKey(priv) 94 } 95 96 if encrypter == nil { 97 encrypter = DefaultOpts 98 } 99 100 // Convert private key into PKCS8 format 101 pkey, err := smx509.MarshalPKCS8PrivateKey(priv) 102 if err != nil { 103 return nil, err 104 } 105 106 encryptionAlgorithm, encryptedKey, err := encrypter.Encrypt(rand.Reader, password, pkey) 107 if err != nil { 108 return nil, err 109 } 110 111 encryptedPkey := encryptedPrivateKeyInfo{ 112 EncryptionAlgorithm: *encryptionAlgorithm, 113 EncryptedData: encryptedKey, 114 } 115 116 return asn1.Marshal(encryptedPkey) 117 } 118 119 // ParsePKCS8PrivateKey parses encrypted/unencrypted private keys in PKCS#8 format. 120 // To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. 121 func ParsePKCS8PrivateKey(der []byte, v ...[]byte) (any, error) { 122 var password []byte 123 if len(v) > 0 { 124 password = v[0] 125 } 126 privateKey, _, err := ParsePrivateKey(der, password) 127 return privateKey, err 128 } 129 130 // ParsePKCS8PrivateKeyRSA parses encrypted/unencrypted private keys in PKCS#8 format. 131 // To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. 132 func ParsePKCS8PrivateKeyRSA(der []byte, v ...[]byte) (*rsa.PrivateKey, error) { 133 key, err := ParsePKCS8PrivateKey(der, v...) 134 if err != nil { 135 return nil, err 136 } 137 typedKey, ok := key.(*rsa.PrivateKey) 138 if !ok { 139 return nil, ErrUnexpectedKeyType 140 } 141 return typedKey, nil 142 } 143 144 // ParsePKCS8PrivateKeyECDSA parses encrypted/unencrypted private keys in PKCS#8 format. 145 // To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. 146 func ParsePKCS8PrivateKeyECDSA(der []byte, v ...[]byte) (*ecdsa.PrivateKey, error) { 147 key, err := ParsePKCS8PrivateKey(der, v...) 148 if err != nil { 149 return nil, err 150 } 151 typedKey, ok := key.(*ecdsa.PrivateKey) 152 if !ok { 153 return nil, ErrUnexpectedKeyType 154 } 155 return typedKey, nil 156 } 157 158 // ParsePKCS8PrivateKeySM2 parses encrypted/unencrypted SM2 private key in PKCS#8 format. 159 // To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. 160 func ParsePKCS8PrivateKeySM2(der []byte, v ...[]byte) (*sm2.PrivateKey, error) { 161 key, err := ParsePKCS8PrivateKey(der, v...) 162 if err != nil { 163 return nil, err 164 } 165 typedKey, ok := key.(*sm2.PrivateKey) 166 if !ok { 167 return nil, ErrUnexpectedKeyType 168 } 169 return typedKey, nil 170 } 171 172 // ParseSM9SignMasterPrivateKey parses encrypted/unencrypted SM9 sign master private key in PKCS#8 format. 173 // To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. 174 func ParseSM9SignMasterPrivateKey(der []byte, v ...[]byte) (*sm9.SignMasterPrivateKey, error) { 175 key, err := ParsePKCS8PrivateKey(der, v...) 176 if err != nil { 177 return nil, err 178 } 179 typedKey, ok := key.(*sm9.SignMasterPrivateKey) 180 if !ok { 181 return nil, ErrUnexpectedKeyType 182 } 183 return typedKey, nil 184 } 185 186 // ParseSM9SignPrivateKey parses encrypted/unencrypted SM9 sign private key in PKCS#8 format. 187 // To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. 188 func ParseSM9SignPrivateKey(der []byte, v ...[]byte) (*sm9.SignPrivateKey, error) { 189 key, err := ParsePKCS8PrivateKey(der, v...) 190 if err != nil { 191 return nil, err 192 } 193 typedKey, ok := key.(*sm9.SignPrivateKey) 194 if !ok { 195 return nil, ErrUnexpectedKeyType 196 } 197 return typedKey, nil 198 } 199 200 // ParseSM9EncryptMasterPrivateKey parses encrypted/unencrypted SM9 encrypt master private key in PKCS#8 format. 201 // To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. 202 func ParseSM9EncryptMasterPrivateKey(der []byte, v ...[]byte) (*sm9.EncryptMasterPrivateKey, error) { 203 key, err := ParsePKCS8PrivateKey(der, v...) 204 if err != nil { 205 return nil, err 206 } 207 typedKey, ok := key.(*sm9.EncryptMasterPrivateKey) 208 if !ok { 209 return nil, ErrUnexpectedKeyType 210 } 211 return typedKey, nil 212 } 213 214 // ParseSM9EncryptPrivateKey parses encrypted/unencrypted SM9 encrypt private key in PKCS#8 format. 215 // To parse encrypted private keys, a password of []byte type should be provided to the function as the second parameter. 216 func ParseSM9EncryptPrivateKey(der []byte, v ...[]byte) (*sm9.EncryptPrivateKey, error) { 217 key, err := ParsePKCS8PrivateKey(der, v...) 218 if err != nil { 219 return nil, err 220 } 221 typedKey, ok := key.(*sm9.EncryptPrivateKey) 222 if !ok { 223 return nil, ErrUnexpectedKeyType 224 } 225 return typedKey, nil 226 } 227 228 // ConvertPrivateKeyToPKCS8 converts the private key into PKCS#8 format. 229 // To encrypt the private key, the password of []byte type should be provided as the second parameter. 230 func ConvertPrivateKeyToPKCS8(priv any, v ...[]byte) ([]byte, error) { 231 var password []byte 232 if len(v) > 0 { 233 password = v[0] 234 } 235 return MarshalPrivateKey(priv, password, nil) 236 }