Skip to content

crypto/x509: ParsePKCS1PrivateKey is not complaint with PKCS#1 standard #14512

Description

@wpc

According to https://tools.ietf.org/html/rfc3447#section-3.2: a RSA private key may have either
of two representations: The first representation consists of a pair of n(modulus) and d(privateExponent); The second representation is made of primary factors (p, q) and CRT factors (dp, dq, qInv...). Both representation should be valid.

Go's current pkcs#1 implementation can not parse the first representation form of RSA private key. In https://github.com/golang/go/blob/release-branch.go1.6/src/crypto/x509/pkcs1.go#L39, line 54 checks n, d, p, q are all not zero.

if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
    return nil, errors.New("x509: private key contains zero or negative value")
}

This check makes crypto/x509.ParsePKCS1PrivateKey can only parse keys with mixture of first and second representation, such as keys generated by openssl.

I generate a key with Java bouncycastle's org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPrivateKey, which use the first representation. It can not be parse it by go.

package main

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

var privateKeyStr = `
-----BEGIN RSA PRIVATE KEY-----
MIICHgIBAAKCAQEAkvro39f9TwktskxcxiDB4fzHE4AXDYe2FkWVVMGjlxGUVag3
vK9WPlIKgoGQJvoBnKXbgoM+544+F13JdYTivU9ym90SuBn4KpnZcntLitZWbCs1
zoMS6L1Xp3E6yjgg0fheYTQ1Ux2GZ92EL8eTQtxHijtZSDVRSEShzUlmD4hErYuz
O9qKmbRxBXR0BSec1PyFIrp64oj2HEPcKUijgmHy1LUtAkc3Jy7f8jmxoaJKzecb
RTv4WsV8iDQMD+OOCDa3ZZ6DRJknXsZWqHtfjtoJz0wo7O+E5xa/mkBjyEMeQQm8
VHzcuNu6DslCrUQTpZ2sRJL8c90m/Knp56rVbwIBAAKCAQAFzLTHsGQkbD5LXMwE
XWKJIkpQsKs4M3Sx6Ej+MS3dVio+PwcEAP8sMlyLzcT8ZL0Pi1PgEIG47Vnx3heG
9Zlk0u+4yr5kWVH7jFqSM99FOTPrzMCwx2dFm8MLrmIdfJ1+64f92euIvg+BpbID
mKJs7vg7sh/Rw5jTezHPQegvEKgWPGaJIfCeyeSZsOiWmfypzjfOPZEaHRo99h46
96T4YmG12Rm0TL6O3s3+EW0T20jrwoddoG8yrWKXSgjbliK4yknmR7ZZR+F5atJd
7fxm0tBl+XaqBBUIu2QQV3262ll3QQPFXPjJ5SpXIC+SIG/Mk0FH9ngKpuM0g+Mi
20OxAgEAAgEAAgEAAgEAAgEA
-----END RSA PRIVATE KEY-----
`

func main() {
    decodedPEM, _ := pem.Decode([]byte(privateKeyStr))

    if key, err := x509.ParsePKCS1PrivateKey(decodedPEM.Bytes); err == nil {
        fmt.Println(key)
    } else {
        panic(err)
    }
}
% go run go-pkcs1-issue.go
panic: x509: private key contains zero or negative value

But openssl can read it fine

% openssl rsa -noout -text -in rsa.pem
Private-Key: (2048 bit)
modulus:
    00:92:fa:e8:df:d7:fd:4f:09:2d:b2:4c:5c:c6:20:
    c1:e1:fc:c7:13:80:17:0d:87:b6:16:45:95:54:c1:
    a3:97:11:94:55:a8:37:bc:af:56:3e:52:0a:82:81:
    90:26:fa:01:9c:a5:db:82:83:3e:e7:8e:3e:17:5d:
    c9:75:84:e2:bd:4f:72:9b:dd:12:b8:19:f8:2a:99:
    d9:72:7b:4b:8a:d6:56:6c:2b:35:ce:83:12:e8:bd:
    57:a7:71:3a:ca:38:20:d1:f8:5e:61:34:35:53:1d:
    86:67:dd:84:2f:c7:93:42:dc:47:8a:3b:59:48:35:
    51:48:44:a1:cd:49:66:0f:88:44:ad:8b:b3:3b:da:
    8a:99:b4:71:05:74:74:05:27:9c:d4:fc:85:22:ba:
    7a:e2:88:f6:1c:43:dc:29:48:a3:82:61:f2:d4:b5:
    2d:02:47:37:27:2e:df:f2:39:b1:a1:a2:4a:cd:e7:
    1b:45:3b:f8:5a:c5:7c:88:34:0c:0f:e3:8e:08:36:
    b7:65:9e:83:44:99:27:5e:c6:56:a8:7b:5f:8e:da:
    09:cf:4c:28:ec:ef:84:e7:16:bf:9a:40:63:c8:43:
    1e:41:09:bc:54:7c:dc:b8:db:ba:0e:c9:42:ad:44:
    13:a5:9d:ac:44:92:fc:73:dd:26:fc:a9:e9:e7:aa:
    d5:6f
publicExponent: 0
privateExponent:
    05:cc:b4:c7:b0:64:24:6c:3e:4b:5c:cc:04:5d:62:
    89:22:4a:50:b0:ab:38:33:74:b1:e8:48:fe:31:2d:
    dd:56:2a:3e:3f:07:04:00:ff:2c:32:5c:8b:cd:c4:
    fc:64:bd:0f:8b:53:e0:10:81:b8:ed:59:f1:de:17:
    86:f5:99:64:d2:ef:b8:ca:be:64:59:51:fb:8c:5a:
    92:33:df:45:39:33:eb:cc:c0:b0:c7:67:45:9b:c3:
    0b:ae:62:1d:7c:9d:7e:eb:87:fd:d9:eb:88:be:0f:
    81:a5:b2:03:98:a2:6c:ee:f8:3b:b2:1f:d1:c3:98:
    d3:7b:31:cf:41:e8:2f:10:a8:16:3c:66:89:21:f0:
    9e:c9:e4:99:b0:e8:96:99:fc:a9:ce:37:ce:3d:91:
    1a:1d:1a:3d:f6:1e:3a:f7:a4:f8:62:61:b5:d9:19:
    b4:4c:be:8e:de:cd:fe:11:6d:13:db:48:eb:c2:87:
    5d:a0:6f:32:ad:62:97:4a:08:db:96:22:b8:ca:49:
    e6:47:b6:59:47:e1:79:6a:d2:5d:ed:fc:66:d2:d0:
    65:f9:76:aa:04:15:08:bb:64:10:57:7d:ba:da:59:
    77:41:03:c5:5c:f8:c9:e5:2a:57:20:2f:92:20:6f:
    cc:93:41:47:f6:78:0a:a6:e3:34:83:e3:22:db:43:
    b1
prime1: 0
prime2: 0
exponent1: 0
exponent2: 0
coefficient: 0

Go version: go1.6 darwin/amd64
OS: Mac OSX 10.11.1
Openssl version: 0.9.8zg 14 July 2015

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions