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
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.
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.
But openssl can read it fine
Go version: go1.6 darwin/amd64
OS: Mac OSX 10.11.1
Openssl version: 0.9.8zg 14 July 2015