Search code examples
gorsaprivate-keypkcs#8

ParsePKCS8PrivateKey isn't parsing my PKCS8 encoded key


Here's my code:

package main

import (
    "encoding/pem"
    "encoding/base64"
    "crypto/x509"
    "crypto/rsa"
    "fmt"
)

func main() {
    key := `-----BEGIN PRIVATE KEY-----
MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqPfgaTEWEP3S9w0t
gsicURfo+nLW09/0KfOPinhYZ4ouzU+3xC4pSlEp8Ut9FgL0AgqNslNaK34Kq+NZ
jO9DAQIDAQABAkAgkuLEHLaqkWhLgNKagSajeobLS3rPT0Agm0f7k55FXVt743hw
Ngkp98bMNrzy9AQ1mJGbQZGrpr4c8ZAx3aRNAiEAoxK/MgGeeLui385KJ7ZOYktj
hLBNAB69fKwTZFsUNh0CIQEJQRpFCcydunv2bENcN/oBTRw39E8GNv2pIcNxZkcb
NQIgbYSzn3Py6AasNj6nEtCfB+i1p3F35TK/87DlPSrmAgkCIQDJLhFoj1gbwRbH
/bDRPrtlRUDDx44wHoEhSDRdy77eiQIgE6z/k6I+ChN1LLttwX0galITxmAYrOBh
BVl433tgTTQ=
-----END PRIVATE KEY-----`
    var ciphertext = "L812/9Y8TSpwErlLR6Bz4J3uR/T5YaqtTtB5jxtD1qazGPI5t15V9drWi58colGOZFeCnGKpCrtQWKk4HWRocQ==";

    keyBytes := []byte(key)
    decodedKey, _ := pem.Decode(keyBytes)
    privateKey, err := x509.ParsePKCS8PrivateKey(decodedKey.Bytes)
    if err != nil {
        panic(err)
    }

    ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertext)
    if err != nil {
        panic(err)
    }

    plaintextBytes, err := privateKey.Decrypt(nil, ciphertextBytes, &rsa.PKCS1v15DecryptOptions{})
    if err != nil {
        panic(err)
    }

    plaintext := string(plaintextBytes[:])

    fmt.Println(plaintext)
}

When I run it I get privateKey.Decrypt undefined (type any has no field or method Decrypt).

Superficially it seems like this could be caused by an invalid PKCS8 key but I believe the key to be valid. Unfortunately, I am unaware of a way to test it's validity with OpenSSL's pkcs8 tool. With OpenSSL's rsa tool and with OpenSSL's x509 tool you can use the -text option but the pkcs8 tool has no such option. In lieu of that here's the output from asn1parse:

    0:d=0  hl=4 l= 340 cons: SEQUENCE
    4:d=1  hl=2 l=   1 prim:  INTEGER           :00
    7:d=1  hl=2 l=  13 cons:  SEQUENCE
    9:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
   20:d=2  hl=2 l=   0 prim:   NULL
   22:d=1  hl=4 l= 318 prim:  OCTET STRING

Solution

  • ParsePKCS8PrivateKey returns an any as key type, which is an alias of interface{}, see here. The background is that PKCS#8 can contain different key types, e.g. RSA, EC key etc.
    The concrete key type must therefore be determined via a type assertion, in the case of RSA, which applies here: privateKey.(*rsa.PrivateKey).

    Possible fix:

    plaintextBytes, err := privateKey.(*rsa.PrivateKey).Decrypt(nil, ciphertextBytes, &rsa.PKCS1v15DecryptOptions{})
    

    or alternatively:

    plaintextBytes, err := rsa.DecryptPKCS1v15(nil, privateKey.(*rsa.PrivateKey), ciphertextBytes)