代码生成的RSA公钥无法上传CloudFront,如何修复?
问题描述
尝试生成RSA公私钥对,公钥用于上传至AWS CloudFront。参考示例代码后做了两处修改:
- 密钥位数设为
2048,符合CloudFront文档要求; - 公钥PEM类型设为
PUBLIC KEY,匹配CloudFront所需的-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----格式。
使用的代码如下:
package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "io/ioutil" ) func main() { filename := "key" bitSize := 2048 // Generate RSA key. key, err := rsa.GenerateKey(rand.Reader, bitSize) if err != nil { panic(err) } // Extract public component. pub := key.Public() // Encode private key to PKCS#1 ASN.1 PEM. keyPEM := pem.EncodeToMemory( &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key), }, ) // Encode public key to PKCS#1 ASN.1 PEM. pubPEM := pem.EncodeToMemory( &pem.Block{ Type: "PUBLIC KEY", Bytes: x509.MarshalPKCS1PublicKey(pub.(*rsa.PublicKey)), }, ) // Write private key to file. if err := ioutil.WriteFile(filename+".rsa", keyPEM, 0700); err != nil { panic(err) } // Write public key to file. if err := ioutil.WriteFile(filename+".rsa.pub", pubPEM, 0755); err != nil { panic(err) } }
上传公钥至CloudFront时收到错误:
Your request contains empty/invalid/out of limits RSA Encoded Key
本地通过openssl genrsa和openssl rsa命令生成的公钥可正常被CloudFront接受,该代码需在Lambda中运行并轮换SecretsManager中的密钥,请问代码生成的公钥不被接受的原因是什么,该如何修复?
原因分析
问题出在公钥编码格式与PEM头的不匹配:
- 代码中用
x509.MarshalPKCS1PublicKey生成的是PKCS#1格式的公钥内容,但给PEM块指定的Type是PUBLIC KEY——这是矛盾的。 PUBLIC KEY类型的PEM头,对应的必须是PKIX(X.509 SubjectPublicKeyInfo)格式的公钥;而PKCS#1格式的公钥,对应的PEM Type应该是RSA PUBLIC KEY。- CloudFront要求的
-----BEGIN PUBLIC KEY-----格式,只接受PKIX编码的公钥,不兼容PKCS#1编码。
本地openssl生成的公钥能正常工作,是因为openssl rsa -pubout默认生成的就是PKIX格式的公钥,正好匹配CloudFront的要求。
修复方案
将公钥的编码方式从x509.MarshalPKCS1PublicKey替换为x509.MarshalPKIXPublicKey,同时保留PEM块的Type为PUBLIC KEY即可。
修复后的代码如下:
package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "io/ioutil" ) func main() { filename := "key" bitSize := 2048 // Generate RSA key. key, err := rsa.GenerateKey(rand.Reader, bitSize) if err != nil { panic(err) } // Extract public component. pub := key.Public() // Encode private key to PKCS#1 ASN.1 PEM. keyPEM := pem.EncodeToMemory( &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key), }, ) // Encode public key to PKIX (X.509) format instead of PKCS#1 pubASN1, err := x509.MarshalPKIXPublicKey(pub.(*rsa.PublicKey)) if err != nil { panic(err) } pubPEM := pem.EncodeToMemory( &pem.Block{ Type: "PUBLIC KEY", Bytes: pubASN1, }, ) // Write private key to file. if err := ioutil.WriteFile(filename+".rsa", keyPEM, 0700); err != nil { panic(err) } // Write public key to file. if err := ioutil.WriteFile(filename+".rsa.pub", pubPEM, 0755); err != nil { panic(err) } }
验证方式
生成公钥后,可通过以下openssl命令验证格式是否正确:
openssl rsa -in key.rsa.pub -pubin -text -noout
如果能正常输出公钥的模数、指数等信息,说明格式符合要求,可正常上传至CloudFront。
内容的提问来源于stack exchange,提问作者user246392
相关产品推荐
相关产品推荐

