From e4e7780c7f62f8d2c7ba9a09d0af810835a66a03 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Mon, 25 Jan 2021 11:48:40 +0300 Subject: [PATCH] Ability to marshal PKCS#8 GOST keys --- src/crypto/x509/pkcs8.go | 60 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/src/crypto/x509/pkcs8.go b/src/crypto/x509/pkcs8.go index a5ee4cfbfe..fb83da81bf 100644 --- a/src/crypto/x509/pkcs8.go +++ b/src/crypto/x509/pkcs8.go @@ -12,6 +12,11 @@ import ( "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 @@ func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { // 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) { @@ -128,6 +133,57 @@ func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) { } 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) } -- 2.50.0