我try 使用Go的rsa和x509包生成一对PKCS8编码的私钥和相应的PKCS1编码的公钥.我希望具有与以下openssl命令相同的行为:
$ openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out rsa_key.p8 -nocrypt
$ openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub
我在下面添加了我的Go实现,归结为要点.
然而,当运行第二个openssl命令对由Go实现编码的私钥上的公钥进行编码时,公钥不同(我在下面提供了一个不同的示例).特别是,openssl输出似乎通过前缀扩展了Go实现的输出.
如果能解释一下差异(最好的情况是,我如何修复代码),我将不胜感激.非常感谢你!
我的Go代码如下所示:
package xyz
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
)
func GeneratePrivateKey(bitSize int) (*rsa.PrivateKey, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, bitSize)
if err != nil {
return nil, err
}
err = privateKey.Validate()
if err != nil {
return nil, err
}
return privateKey, nil
}
func EncodePrivateKeyToPEM(privateKey *rsa.PrivateKey) (string, error) {
privateDER, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
return "", err
}
privateBlock := pem.Block{
Type: "RSA PRIVATE KEY",
Headers: nil,
Bytes: privateDER,
}
privatePEM := pem.EncodeToMemory(&privateBlock)
return string(privatePEM), nil
}
func EncodePublicKeyToPEM(privateKey *rsa.PrivateKey) string {
publicRsaKey := x509.MarshalPKCS1PublicKey(&privateKey.PublicKey)
publicKeyBytes := pem.EncodeToMemory(
&pem.Block{
Type: "PUBLIC KEY",
Bytes: publicRsaKey,
})
return string(publicKeyBytes)
}
示例性私钥:
-----BEGIN RSA PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDnT3OOrKW+S2m4
3fMyl3BjCxnZ2n39wlnYqunYSor5S8wlynhPc72tY8xmTVGhxBYul9LAXyO1/LLU
4cNARmHtSSmeUeYLCU3PMKP795oL4k/YPLqnracIyieN5s8JnmWGtqZo7hyysvhu
Yp0LDmJcQRpB3BoDyTs++/amRP5fnRkkoFABqIejbJEgsjmfXlRnjLR8H4cK8Dmp
5tm2QzSAWos/E3LV/yhhe4b0oTqxGf+lHC5i4FgPd4Co/oaq47QOQkqarxFd57DH
yKNQF3vbGJmVucFnHC+7l4QflcP2Kp/6WJL7IDXA5FC1CFLC5YCmT1pxog/0iPJb
bOiMC1KHAgMBAAECggEBANrJru7j5L3zDOP8o/1VestkA6apYQS2YU9sklWwZHVb
OZUBRv0359Bqljqppa4SED0wA/tLwjZv+CMeDBXuvM+5pTEIHESSH1P7mRBKah4V
iRpqjs7tlRHeTL2O9IQPm85pU0vq9aAdYpjek9aSW30RYymqa7zrCSwRHYK1vblm
zbGUpz3PQp5Mp/CPPBGW2arK5Syo25AJ9YphaWAKub+NXPRZTIVZFylvDtONQmwt
D8YknEPB9eQcgL41egW+ViOs7WOpB6qM8nvbNa+lvdGawog0cZefeNw0PyHxQmhB
Mt/VzvbFaqG2aeH73Na+oFX9/DuQxrvns126R42VK4kCgYEA9lkqUWvVSq8MBb+h
QLZKlSlJiJ1R/nmYqd98r7DCZYwNTRF4LqK0DUbHJCF0WJ3G0UxuKNc98+k3JVz+
5YiZMj6S660XYgQR62GaGKLiVUQmFrKCYUmLrpgDse/pvnA6BfM6MMwR/eIlitGn
B65QarKMwRphCIRrVXnViFs/QNsCgYEA8F91NvVxk14cQPBzdeHK5Z1E+ekHLQHU
nvdWpuqF4n/UWrQg4JI9ACjZIbEd5oJRkQa7M8KXonaQwFlqTe9Ov7MrMon4/CmC
l+XxBLMIb5Pif+biNle3Jhdk6N7H16S9w4PpyaT4nSCU7HNHVIbb+yjr2awKzMSH
yKi51VYKXsUCgYBMGW1GK65+3KY1HGZezDEr9M4fYqHSn5N2XnBxAYR7xBDTzuK2
XVKLi2K3GZKMUWj6fMbG3P7pWxDK/PhMxa61Y7kVDqpbf/BdKxBkLeUG+/9cIZa/
IO4CaDkz/W3Sg26ZKfK+4jtolzSLtooHiGSVIUTz3gc9j1Js3C8HaVCX4wKBgA2b
eck4r8tF4peShRbBR3kkJAl5tZxIpD6zhcZBNH8T+XOBCvNrk+R0a4ZKvoSUEAYD
uYk+lNLvn1YkOa5bw7t6axGbWer8dpYewDwh3nJijsnqyheFc6rGXEIKiomcm9l7
mDqACkrq00NnazxPvhhDwsY5xQq+fWlQk+SN0Fx5AoGAKIMHfXkYrObD8NxE4kvs
Knx3/aH2vAAsDbC+mA2wZOSZ+hsD3SO62ypI3UW3Fxn5+55sQMsMCqaOJBXrLZMh
2iyTMk7V5Bx+//+pa5Hv3yPmDeGtlAT+gbwaqrh5KM1eaW1TVZ1HdUNmamh9Iq0O
KrEPYf2r8+IjAhctV08Mx7I=
-----END RSA PRIVATE KEY-----
由我的Go实现编码的公钥:
-----BEGIN PUBLIC KEY-----
MIIBCgKCAQEA509zjqylvktpuN3zMpdwYwsZ2dp9/cJZ2Krp2EqK+UvMJcp4T3O9
rWPMZk1RocQWLpfSwF8jtfyy1OHDQEZh7UkpnlHmCwlNzzCj+/eaC+JP2Dy6p62n
CMonjebPCZ5lhramaO4csrL4bmKdCw5iXEEaQdwaA8k7Pvv2pkT+X50ZJKBQAaiH
o2yRILI5n15UZ4y0fB+HCvA5qebZtkM0gFqLPxNy1f8oYXuG9KE6sRn/pRwuYuBY
D3eAqP6GquO0DkJKmq8RXeewx8ijUBd72xiZlbnBZxwvu5eEH5XD9iqf+liS+yA1
wORQtQhSwuWApk9acaIP9IjyW2zojAtShwIDAQAB
-----END PUBLIC KEY-----
由第二个openssl命令生成的公钥(请注意,它与前者的不同之处在于前缀MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
)
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA509zjqylvktpuN3zMpdw
YwsZ2dp9/cJZ2Krp2EqK+UvMJcp4T3O9rWPMZk1RocQWLpfSwF8jtfyy1OHDQEZh
7UkpnlHmCwlNzzCj+/eaC+JP2Dy6p62nCMonjebPCZ5lhramaO4csrL4bmKdCw5i
XEEaQdwaA8k7Pvv2pkT+X50ZJKBQAaiHo2yRILI5n15UZ4y0fB+HCvA5qebZtkM0
gFqLPxNy1f8oYXuG9KE6sRn/pRwuYuBYD3eAqP6GquO0DkJKmq8RXeewx8ijUBd7
2xiZlbnBZxwvu5eEH5XD9iqf+liS+yA1wORQtQhSwuWApk9acaIP9IjyW2zojAtS
hwIDAQAB
-----END PUBLIC KEY-----