]> Cypherpunks repositories - gostls13.git/commitdiff
Ability to marshal PKCS#8 GOST keys
authorSergey Matveev <stargrave@rnd.stcnet.ru>
Mon, 25 Jan 2021 08:48:40 +0000 (11:48 +0300)
committerSergey Matveev <stargrave@rnd.stcnet.ru>
Mon, 25 Jan 2021 08:48:40 +0000 (11:48 +0300)
src/crypto/x509/pkcs8.go

index a5ee4cfbfeff14be4c8610671b51945f89b12b5c..fb83da81bfcc913abaad14837656fa448d95aba3 100644 (file)
@@ -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)
        }