src/crypto/x509/pkcs8.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++-- diff --git a/src/crypto/x509/pkcs8.go b/src/crypto/x509/pkcs8.go index a5ee4cfbfeff14be4c8610671b51945f89b12b5c..fb83da81bfcc913abaad14837656fa448d95aba3 100644 --- a/src/crypto/x509/pkcs8.go +++ b/src/crypto/x509/pkcs8.go @@ -12,6 +12,11 @@ "crypto/x509/pkix" "encoding/asn1" "errors" "fmt" + + "golang.org/x/crypto/cryptobyte" + cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" + + "crypto/go.cypherpunks.ru/gogost/v5/gost3410" ) // pkcs8 reflects an ASN.1, PKCS #8 PrivateKey. See @@ -81,8 +86,8 @@ } // MarshalPKCS8PrivateKey converts a private key to PKCS #8, ASN.1 DER form. // -// The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey -// and ed25519.PrivateKey. Unsupported key types result in an error. +// The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey, +// GOST R 34.10-2012 and ed25519.PrivateKey. Unsupported key types result in an error. // // This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) { @@ -127,6 +132,57 @@ if err != nil { return nil, fmt.Errorf("x509: failed to marshal private key: %v", err) } privKey.PrivateKey = curvePrivateKey + + case *gost3410.PrivateKey: + builder := cryptobyte.NewBuilder(nil) + switch k.C.Name { + case "id-tc26-gost-3410-2012-256-paramSetA": + privKey.Algo.Algorithm = oidTc26Gost34102012256 + builder.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1ObjectIdentifier(oidTc26Gost34102012256ParamSetA) + }) + case "id-tc26-gost-3410-2012-256-paramSetB": + privKey.Algo.Algorithm = oidTc26Gost34102012256 + builder.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1ObjectIdentifier(oidTc26Gost34102012256ParamSetB) + }) + case "id-tc26-gost-3410-2012-256-paramSetC": + privKey.Algo.Algorithm = oidTc26Gost34102012256 + builder.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1ObjectIdentifier(oidTc26Gost34102012256ParamSetC) + }) + case "id-tc26-gost-3410-2012-256-paramSetD": + privKey.Algo.Algorithm = oidTc26Gost34102012256 + builder.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1ObjectIdentifier(oidTc26Gost34102012256ParamSetD) + }) + case "id-tc26-gost-3410-12-512-paramSetA": + privKey.Algo.Algorithm = oidTc26Gost34102012512 + builder.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1ObjectIdentifier(oidTc26Gost34102012512ParamSetA) + }) + case "id-tc26-gost-3410-12-512-paramSetB": + privKey.Algo.Algorithm = oidTc26Gost34102012512 + builder.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1ObjectIdentifier(oidTc26Gost34102012512ParamSetB) + }) + case "id-tc26-gost-3410-2012-512-paramSetC": + privKey.Algo.Algorithm = oidTc26Gost34102012512 + builder.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1ObjectIdentifier(oidTc26Gost34102012512ParamSetC) + }) + } + var err error + privKey.Algo.Parameters.FullBytes, err = builder.Bytes() + if err != nil { + return nil, err + } + builder = cryptobyte.NewBuilder(nil) + builder.AddASN1OctetString(k.Raw()) + privKey.PrivateKey, err = builder.Bytes() + if err != nil { + return nil, err + } default: return nil, fmt.Errorf("x509: unknown key type while marshaling PKCS#8: %T", key)