github.com/emmansun/gmsm@v0.29.1/smx509/pkcs8.go (about) 1 package smx509 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/x509" 6 "crypto/x509/pkix" 7 "encoding/asn1" 8 "errors" 9 10 "github.com/emmansun/gmsm/ecdh" 11 "github.com/emmansun/gmsm/sm2" 12 "github.com/emmansun/gmsm/sm9" 13 ) 14 15 var ( 16 oidSM9 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 302} 17 oidSM9Sign = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 302, 1} 18 oidSM9Enc = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 302, 3} 19 ) 20 21 // pkcs8 reflects an ASN.1, PKCS #8 PrivateKey. See 22 // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn 23 // and RFC 5208. 24 type pkcs8 struct { 25 Version int 26 Algo pkix.AlgorithmIdentifier 27 PrivateKey []byte 28 // optional attributes omitted. 29 } 30 31 // ParsePKCS8PrivateKey parses an unencrypted private key in PKCS #8, ASN.1 DER form. 32 // 33 // It returns a *rsa.PrivateKey, a *ecdsa.PrivateKey, a *sm2.PrivateKey, a *sm9.SignMasterPrivateKey, 34 // a *sm9.SignPrivateKey, a *sm9.EncryptMasterPrivateKey, a *sm9.EncryptPrivateKey or a ed25519.PrivateKey. 35 // More types might be supported in the future. 36 // 37 // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". 38 func ParsePKCS8PrivateKey(der []byte) (key any, err error) { 39 var privKey pkcs8 40 if _, err := asn1.Unmarshal(der, &privKey); err != nil { 41 if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil { 42 return nil, errors.New("x509: failed to parse private key (use ParseECPrivateKey instead for this key format)") 43 } 44 if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil { 45 return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)") 46 } 47 return nil, err 48 } 49 switch { 50 case privKey.Algo.Algorithm.Equal(oidPublicKeySM2): 51 bytes := privKey.Algo.Parameters.FullBytes 52 namedCurveOID := new(asn1.ObjectIdentifier) 53 if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil { 54 namedCurveOID = nil 55 } 56 ecKey, err := parseECPrivateKey(namedCurveOID, privKey.PrivateKey) 57 if err != nil { 58 return nil, errors.New("x509: failed to parse SM2 private key embedded in PKCS#8: " + err.Error()) 59 } 60 if ecKey.Curve != sm2.P256() { 61 return nil, errors.New("x509: unsupported SM2 curve") 62 } 63 return new(sm2.PrivateKey).FromECPrivateKey(ecKey) 64 case privKey.Algo.Algorithm.Equal(oidSM9), privKey.Algo.Algorithm.Equal(oidSM9Sign), privKey.Algo.Algorithm.Equal(oidSM9Enc): 65 return parseSM9PrivateKey(privKey) 66 case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA): 67 bytes := privKey.Algo.Parameters.FullBytes 68 namedCurveOID := new(asn1.ObjectIdentifier) 69 if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil { 70 namedCurveOID = nil 71 } 72 ecKey, err := parseECPrivateKey(namedCurveOID, privKey.PrivateKey) 73 if err != nil { 74 return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error()) 75 } 76 // convert *ecdsa.PrivateKey to *sm2.PrivateKey 77 if ecKey.Curve == sm2.P256() { 78 return new(sm2.PrivateKey).FromECPrivateKey(ecKey) 79 } 80 return ecKey, err 81 default: 82 // fallback to golang sdk 83 return x509.ParsePKCS8PrivateKey(der) 84 } 85 } 86 87 func parseSM9PrivateKey(privKey pkcs8) (key any, err error) { 88 switch { 89 case privKey.Algo.Algorithm.Equal(oidSM9Sign): 90 sm9SignKey := new(sm9.SignPrivateKey) 91 err = sm9SignKey.UnmarshalASN1(privKey.PrivateKey) 92 if err != nil { 93 return 94 } 95 key = sm9SignKey 96 return 97 case privKey.Algo.Algorithm.Equal(oidSM9Enc): 98 sm9EncKey := new(sm9.EncryptPrivateKey) 99 err = sm9EncKey.UnmarshalASN1(privKey.PrivateKey) 100 if err != nil { 101 return 102 } 103 key = sm9EncKey 104 return 105 default: 106 bytes := privKey.Algo.Parameters.FullBytes 107 detailOID := new(asn1.ObjectIdentifier) 108 _, err = asn1.Unmarshal(bytes, detailOID) 109 if err != nil { 110 return 111 } 112 switch { 113 case oidSM9Sign.Equal(*detailOID): 114 sm9SignMasterKey := new(sm9.SignMasterPrivateKey) 115 err = sm9SignMasterKey.UnmarshalASN1(privKey.PrivateKey) 116 if err != nil { 117 return 118 } 119 key = sm9SignMasterKey 120 return 121 case oidSM9Enc.Equal(*detailOID): 122 sm9EncMasterKey := new(sm9.EncryptMasterPrivateKey) 123 err = sm9EncMasterKey.UnmarshalASN1(privKey.PrivateKey) 124 if err != nil { 125 return 126 } 127 key = sm9EncMasterKey 128 return 129 } 130 return nil, errors.New("not support yet") 131 } 132 } 133 134 // MarshalPKCS8PrivateKey converts a private key to PKCS #8, ASN.1 DER form. 135 // 136 // The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey, a *sm2.PrivateKey, a *ecdh.PrivateKey 137 // a *sm9.SignMasterPrivateKey, a *sm9.SignPrivateKey, a *sm9.EncryptMasterPrivateKey, a *sm9.EncryptPrivateKey 138 // and ed25519.PrivateKey. Unsupported key types result in an error. 139 // 140 // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". 141 func MarshalPKCS8PrivateKey(key any) ([]byte, error) { 142 switch k := key.(type) { 143 case *sm2.PrivateKey: 144 return marshalPKCS8ECPrivateKey(&k.PrivateKey) 145 case *ecdh.PrivateKey: 146 return marshalPKCS8ECDHPrivateKey(k) 147 case *sm9.SignPrivateKey: 148 return marshalPKCS8SM9SignPrivateKey(k) 149 case *sm9.EncryptPrivateKey: 150 return marshalPKCS8SM9EncPrivateKey(k) 151 case *sm9.SignMasterPrivateKey: 152 return marshalPKCS8SM9SignMasterPrivateKey(k) 153 case *sm9.EncryptMasterPrivateKey: 154 return marshalPKCS8SM9EncMasterPrivateKey(k) 155 } 156 return x509.MarshalPKCS8PrivateKey(key) 157 } 158 159 type sm9PrivateKey struct { 160 PrivateKey asn1.RawValue 161 PublicKey asn1.RawValue 162 } 163 164 func marshalPKCS8SM9SignPrivateKey(k *sm9.SignPrivateKey) ([]byte, error) { 165 var privKey pkcs8 166 privKey.Algo = pkix.AlgorithmIdentifier{ 167 Algorithm: oidSM9Sign, 168 Parameters: asn1.NullRawValue, 169 } 170 171 key := sm9PrivateKey{} 172 privans1, err := k.MarshalASN1() 173 if err != nil { 174 return nil, err 175 } 176 pubasn1, err := k.MasterPublic().MarshalASN1() 177 if err != nil { 178 return nil, err 179 } 180 key.PrivateKey.FullBytes = privans1 181 key.PublicKey.FullBytes = pubasn1 182 183 if privKey.PrivateKey, err = asn1.Marshal(key); err != nil { 184 return nil, errors.New("x509: failed to marshal sm9 sign private key while building PKCS#8: " + err.Error()) 185 } 186 return asn1.Marshal(privKey) 187 } 188 189 func marshalPKCS8SM9EncPrivateKey(k *sm9.EncryptPrivateKey) ([]byte, error) { 190 var privKey pkcs8 191 privKey.Algo = pkix.AlgorithmIdentifier{ 192 Algorithm: oidSM9Enc, 193 Parameters: asn1.NullRawValue, 194 } 195 key := sm9PrivateKey{} 196 privans1, err := k.MarshalASN1() 197 if err != nil { 198 return nil, err 199 } 200 pubasn1, err := k.MasterPublic().MarshalASN1() 201 if err != nil { 202 return nil, err 203 } 204 key.PrivateKey.FullBytes = privans1 205 key.PublicKey.FullBytes = pubasn1 206 207 if privKey.PrivateKey, err = asn1.Marshal(key); err != nil { 208 return nil, errors.New("x509: failed to marshal sm9 encrypt private key while building PKCS#8: " + err.Error()) 209 } 210 return asn1.Marshal(privKey) 211 } 212 213 func marshalPKCS8SM9SignMasterPrivateKey(k *sm9.SignMasterPrivateKey) ([]byte, error) { 214 var privKey pkcs8 215 oidBytes, err := asn1.Marshal(oidSM9Sign) 216 if err != nil { 217 return nil, errors.New("x509: failed to marshal SM9 OID: " + err.Error()) 218 } 219 220 privKey.Algo = pkix.AlgorithmIdentifier{ 221 Algorithm: oidSM9, 222 Parameters: asn1.RawValue{ 223 FullBytes: oidBytes, 224 }, 225 } 226 227 key := sm9PrivateKey{} 228 privans1, err := k.MarshalASN1() 229 if err != nil { 230 return nil, err 231 } 232 pubasn1, err := k.Public().MarshalASN1() 233 if err != nil { 234 return nil, err 235 } 236 key.PrivateKey.FullBytes = privans1 237 key.PublicKey.FullBytes = pubasn1 238 239 if privKey.PrivateKey, err = asn1.Marshal(key); err != nil { 240 return nil, errors.New("x509: failed to marshal sm9 sign master private key while building PKCS#8: " + err.Error()) 241 } 242 return asn1.Marshal(privKey) 243 } 244 245 func marshalPKCS8SM9EncMasterPrivateKey(k *sm9.EncryptMasterPrivateKey) ([]byte, error) { 246 var privKey pkcs8 247 oidBytes, err := asn1.Marshal(oidSM9Enc) 248 if err != nil { 249 return nil, errors.New("x509: failed to marshal SM9 OID: " + err.Error()) 250 } 251 252 privKey.Algo = pkix.AlgorithmIdentifier{ 253 Algorithm: oidSM9, 254 Parameters: asn1.RawValue{ 255 FullBytes: oidBytes, 256 }, 257 } 258 259 key := sm9PrivateKey{} 260 privans1, err := k.MarshalASN1() 261 if err != nil { 262 return nil, err 263 } 264 pubasn1, err := k.Public().MarshalASN1() 265 if err != nil { 266 return nil, err 267 } 268 key.PrivateKey.FullBytes = privans1 269 key.PublicKey.FullBytes = pubasn1 270 271 if privKey.PrivateKey, err = asn1.Marshal(key); err != nil { 272 return nil, errors.New("x509: failed to marshal sm9 encrypt master private key while building PKCS#8: " + err.Error()) 273 } 274 return asn1.Marshal(privKey) 275 } 276 277 func marshalPKCS8ECPrivateKey(k *ecdsa.PrivateKey) ([]byte, error) { 278 var privKey pkcs8 279 oid, ok := oidFromNamedCurve(k.Curve) 280 if !ok { 281 return nil, errors.New("x509: unknown curve while marshaling to PKCS#8") 282 } 283 284 oidBytes, err := asn1.Marshal(oid) 285 if err != nil { 286 return nil, errors.New("x509: failed to marshal curve OID: " + err.Error()) 287 } 288 289 privKey.Algo = pkix.AlgorithmIdentifier{ 290 Algorithm: oidPublicKeyECDSA, 291 Parameters: asn1.RawValue{ 292 FullBytes: oidBytes, 293 }, 294 } 295 296 if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil { 297 return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error()) 298 } 299 return asn1.Marshal(privKey) 300 } 301 302 func marshalPKCS8ECDHPrivateKey(k *ecdh.PrivateKey) ([]byte, error) { 303 var privKey pkcs8 304 oid, ok := oidFromECDHCurve(k.Curve()) 305 if !ok { 306 return nil, errors.New("x509: unknown curve while marshaling to PKCS#8") 307 } 308 oidBytes, err := asn1.Marshal(oid) 309 if err != nil { 310 return nil, errors.New("x509: failed to marshal curve OID: " + err.Error()) 311 } 312 privKey.Algo = pkix.AlgorithmIdentifier{ 313 Algorithm: oidPublicKeyECDSA, 314 Parameters: asn1.RawValue{ 315 FullBytes: oidBytes, 316 }, 317 } 318 if privKey.PrivateKey, err = marshalECDHPrivateKey(k); err != nil { 319 return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error()) 320 } 321 return asn1.Marshal(privKey) 322 }