github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/x509/pkcs8.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package x509 6 7 /* 8 x509/pkcs8.go PKCS#8标准DER字节数组与对应私钥之间的相互转换。 9 私钥支持: sm2, ecdsa, ed25519, rsa 10 11 ParsePKCS8PrivateKey : 将未加密的PKCS #8, ASN.1 DER格式字节数组转为对应的私钥 12 MarshalPKCS8PrivateKey : 将私钥转为PKCS #8, ASN.1 DER字节数组 13 14 PKCS#8 是私钥消息表示标准(Private-Key Information Syntax Standard). 15 reference to RFC5959 and RFC2898 16 */ 17 18 import ( 19 "crypto/ecdsa" 20 "crypto/ed25519" 21 "crypto/rsa" 22 "crypto/x509/pkix" 23 "encoding/asn1" 24 "errors" 25 "fmt" 26 27 "github.com/hxx258456/ccgo/sm2" 28 ) 29 30 // pkcs8 reflects an ASN.1, PKCS #8 PrivateKey. See 31 // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn 32 // and RFC 5208. 33 type pkcs8 struct { 34 Version int 35 Algo pkix.AlgorithmIdentifier 36 PrivateKey []byte 37 // optional attributes omitted. 38 } 39 40 // ParsePKCS8PrivateKey 将未加密的PKCS #8, ASN.1 DER格式字节数组转为对应的私钥。 41 // - 私钥支持: sm2, ecdsa, ed25519, rsa 42 // 43 // ParsePKCS8PrivateKey parses an unencrypted private key in PKCS #8, ASN.1 DER form. 44 // 45 // It returns a *rsa.PrivateKey, a *ecdsa.PrivateKey, or a ed25519.PrivateKey. 46 // More types might be supported in the future. 47 // 48 // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". 49 func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { 50 var privKey pkcs8 51 // 尝试将 der 反序列化到 privKey 52 if _, err := asn1.Unmarshal(der, &privKey); err != nil { 53 if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil { 54 return nil, errors.New("gmx509.ParsePKCS8PrivateKey: failed to parse private key (use ParseECPrivateKey instead for this key format)") 55 } 56 if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil { 57 return nil, errors.New("gmx509.ParsePKCS8PrivateKey: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)") 58 } 59 return nil, err 60 } 61 // 根据反序列化后的公钥算法标识生成对应的私钥 62 switch { 63 case privKey.Algo.Algorithm.Equal(oidPublicKeySM2): 64 bytes := privKey.Algo.Parameters.FullBytes 65 namedCurveOID := new(asn1.ObjectIdentifier) 66 // 尝试获取曲线oid 67 if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil { 68 namedCurveOID = nil 69 } 70 // 根据曲线oid获取对应曲线并生成对应私钥 71 key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey) 72 if err != nil { 73 return nil, fmt.Errorf("gmx509.ParsePKCS8PrivateKey: failed to parse EC private key embedded in PKCS#8: %s", err.Error()) 74 } 75 return key, nil 76 case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA): 77 key, err = ParsePKCS1PrivateKey(privKey.PrivateKey) 78 if err != nil { 79 return nil, fmt.Errorf("gmx509.ParsePKCS8PrivateKey: failed to parse RSA private key embedded in PKCS#8: %s", err.Error()) 80 } 81 return key, nil 82 case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA): 83 bytes := privKey.Algo.Parameters.FullBytes 84 namedCurveOID := new(asn1.ObjectIdentifier) 85 if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil { 86 namedCurveOID = nil 87 } 88 key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey) 89 if err != nil { 90 return nil, fmt.Errorf("gmx509.ParsePKCS8PrivateKey: failed to parse EC private key embedded in PKCS#8: %s", err.Error()) 91 } 92 return key, nil 93 case privKey.Algo.Algorithm.Equal(oidPublicKeyEd25519): 94 if l := len(privKey.Algo.Parameters.FullBytes); l != 0 { 95 return nil, errors.New("gmx509.ParsePKCS8PrivateKey: invalid Ed25519 private key parameters") 96 } 97 var curvePrivateKey []byte 98 if _, err := asn1.Unmarshal(privKey.PrivateKey, &curvePrivateKey); err != nil { 99 return nil, fmt.Errorf("gmx509.ParsePKCS8PrivateKey: invalid Ed25519 private key: %v", err) 100 } 101 if l := len(curvePrivateKey); l != ed25519.SeedSize { 102 return nil, fmt.Errorf("gmx509.ParsePKCS8PrivateKey: invalid Ed25519 private key length: %d", l) 103 } 104 return ed25519.NewKeyFromSeed(curvePrivateKey), nil 105 default: 106 return nil, fmt.Errorf("gmx509.ParsePKCS8PrivateKey: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm) 107 } 108 } 109 110 // MarshalPKCS8PrivateKey 将私钥转为PKCS #8, ASN.1 DER字节数组 111 // - 私钥支持: sm2, ecdsa, ed25519, rsa 112 // 113 // MarshalPKCS8PrivateKey converts a private key to PKCS #8, ASN.1 DER form. 114 // 115 // The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey 116 // and ed25519.PrivateKey. Unsupported key types result in an error. 117 // 118 // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". 119 func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) { 120 var privKey pkcs8 121 122 switch k := key.(type) { 123 case *sm2.PrivateKey: 124 oid, ok := oidFromNamedCurve(k.Curve) 125 if !ok { 126 return nil, fmt.Errorf("gmx509.MarshalPKCS8PrivateKey: unknown curve: [%s]", k.Curve.Params().Name) 127 } 128 oidBytes, err := asn1.Marshal(oid) 129 if err != nil { 130 return nil, fmt.Errorf("gmx509.MarshalPKCS8PrivateKey: failed to marshal curve OID: [%s]", err.Error()) 131 } 132 privKey.Algo = pkix.AlgorithmIdentifier{ 133 Algorithm: oidPublicKeySM2, 134 Parameters: asn1.RawValue{ 135 FullBytes: oidBytes, 136 }, 137 } 138 if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, oid); err != nil { 139 return nil, fmt.Errorf("gmx509.MarshalPKCS8PrivateKey: failed to marshal EC private key while building PKCS#8: " + err.Error()) 140 } 141 case *rsa.PrivateKey: 142 privKey.Algo = pkix.AlgorithmIdentifier{ 143 Algorithm: oidPublicKeyRSA, 144 Parameters: asn1.NullRawValue, 145 } 146 privKey.PrivateKey = MarshalPKCS1PrivateKey(k) 147 case *ecdsa.PrivateKey: 148 oid, ok := oidFromNamedCurve(k.Curve) 149 if !ok { 150 return nil, errors.New("gmx509.MarshalPKCS8PrivateKey: unknown curve while marshaling to PKCS#8") 151 } 152 oidBytes, err := asn1.Marshal(oid) 153 if err != nil { 154 return nil, errors.New("gmx509.MarshalPKCS8PrivateKey: failed to marshal curve OID: " + err.Error()) 155 } 156 privKey.Algo = pkix.AlgorithmIdentifier{ 157 Algorithm: oidPublicKeyECDSA, 158 Parameters: asn1.RawValue{ 159 FullBytes: oidBytes, 160 }, 161 } 162 // 注意, ecdsa并没有将曲线oid传入序列化结构中 163 // 大约是为了与openssl的结果对应 164 if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil { 165 return nil, errors.New("gmx509.MarshalPKCS8PrivateKey: failed to marshal EC private key while building PKCS#8: " + err.Error()) 166 } 167 case ed25519.PrivateKey: 168 privKey.Algo = pkix.AlgorithmIdentifier{ 169 Algorithm: oidPublicKeyEd25519, 170 } 171 curvePrivateKey, err := asn1.Marshal(k.Seed()) 172 if err != nil { 173 return nil, fmt.Errorf("gmx509.MarshalPKCS8PrivateKey: failed to marshal private key: %v", err) 174 } 175 privKey.PrivateKey = curvePrivateKey 176 default: 177 return nil, fmt.Errorf("gmx509.MarshalPKCS8PrivateKey: unknown key type while marshaling PKCS#8: %T", key) 178 } 179 return asn1.Marshal(privKey) 180 }