【问题标题】:GCP IoT core rejects this RSA_PEM public key with an errorGCP IoT 核心拒绝此 RSA_PEM 公钥并出现错误
【发布时间】:2019-06-15 15:51:25
【问题描述】:

我尝试开发一种自动化来使用公共 RSA pem 证书注册新的 IoT 设备,但我有一个问题,我不知道原因。

问题是生成了 RSA_PEM 公共 pem,我的自动化被 GCP IoT Server 拒绝并出现错误。该错误是“位置 1 的设备凭据的密钥数据无效。确保格式正确:无效的 RS256 公钥”

当我调试我的代码时,pem 公共证书看起来不错。但我不确定。

我正在共享生成成对的私有和公共证书的 go 代码。

package cert

import (
    "bytes"
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/pem"

    "io"
)

type CertificateRSA struct {
    Private io.Reader
    Public  io.Reader
}

func Create() (*CertificateRSA, error) {

    bitSize := 2048
    key, err := rsa.GenerateKey(rand.Reader, bitSize)
    if err != nil {
        return nil, err
    }

    var privateKey = &pem.Block{
        Type:  "RSA PRIVATE KEY",
        Bytes: x509.MarshalPKCS1PrivateKey(key),
    }

    var priBuff bytes.Buffer
    err = pem.Encode(&priBuff, privateKey)
    if err != nil {
        return nil, err
    }

    // asn1Bytes := x509.MarshalPKCS1PublicKey(&key.PublicKey)
    asn1Bytes := x509.MarshalPKCS1PublicKey(&key.PublicKey)

    var publicKey = &pem.Block{
        Type:  "PUBLIC KEY",
        Bytes: asn1Bytes,
    }

    var pubBuff bytes.Buffer

    err = pem.Encode(&pubBuff, publicKey)
    return &CertificateRSA{
        Private: &priBuff,
        Public:  &pubBuff,
    }, err
}

你能看出我的代码有什么问题吗?

这段代码可以生成如下证书:

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA0FGWENPInhIfCLDTqCFKFsyrvmzKsEjJtHEL0Tqh0LtHDWG5
Sh7MT7/x/xNAFc00zmgGG+PPaJDP/7gkGJitRAXcJOlKwlowgmVTf+QGwH81pq3o
ZNRd0mEXbF0EuPBRNt/9TzkZPAlPDGruMCiMq9LWsoIflx+u/3UmXgsyMQTs5vSM
z4T5VCELHGCtfZfBrDAP19KzwjFEUTEzX+Llotp0mO6+cRCslVvSK3xd8KIk2cOm
AXEmCavZnwuVsqCVmNZFoQZvFszisMf5cXZRDstKCGsqDgqIGM5dMMrBS92CqZ4u
j6h9zbMG7J9oXsVmVFiQ++hS0TLJdWwMD+uhWQIDAQABAoIBAAbKIfH6dRdxz8Eg
wkVAkIGduhtCwHhuZuSSqqfvGUcMU4yEGt3nkxEmWGTP487SGV6A1XIjQqdN0Pms
rsB+eWc2Ka6qS915wwr88nPAotezTbRZBrICmew5beICRh0g+ASp2D+0xLXIN+NX
uNuo9qzC+mxnAVCTn8iDsPRvuPsP9vJSy5zIzPWURdPBQ3Ny1pbj+odqwDdUw8q7
FfUmGHC7a5oKex3vxDhDL8OPc3KjynFJdm1YqUagLzppDHMZtI2rNAYfWrkrJVB7
zlX3m0hUDDrvHbQBiqGUj2qI2MqgrFlcK0HSryJdCz4tVdYY3qBi/tZrwOAvnSkv
zNFT6AECgYEA9veJpGwUYdRhWyo05xsatDJ+KvBpizi66Iu2Lu+fRQUuwYaC0DSV
BMr1ktbJzbgbu4XDNrJ8GKrqka06vGjaYVhw1C56LU83hHsckTx+K3fpb9wkFamE
gCZG3uAqflLsEPZ6xPHLe1U+SDZfghLrH90JYi7tTULReAVy5zVs8iECgYEA1/Aq
6ls9kPtJWLEU299WdNGYy5Fx1N8oUj5sjYTfPf/27OeBXWg+CKBIhXk534z9pwqq
LUs7NbmqhuocuxFtE7oxdwqXqUR7qYUdpVuRZ8EmVvBuUGxI1MG6MMKxHxSSpTs5
3tTDAd2WlwPX3jbqAj2WOiL2T97cXNjYyKxiuDkCgYBbI0RnKf9njtGSrAOz2XvE
TfHjdK7uUrQfBxfnQER9WwlDH5l8rjrj9uYjFyKHyU5qqFU/BSTokYJY2h2X0/Xr
AJE6rCAoQliRikEjk7hX4DuELTAf0lv0UqvKqdzkm0NEi0EJFtXpoK6IRZB/Vu3v
50kEM58c6PCWIyShEEUxIQKBgQCg63qf0UTNMWaUcMqxm/sq7TNnqMjisTa0K47r
27Qd2Q1juJZATLnF5eSFizSkssYoYJs3S9QhEm7RQdANXEwkImJQaxVgcAeT6f6Q
xu9SGa9/pIcg6cFQw9oEEmK6XbN27O8Qbw+v6Tka6yNIlzXGW60DQCC8nsErc/IB
ge3DiQKBgA3183wzRLj7oZD/KJHW+BY0Y6ljZ8EQQ5anc3RFsQrJ48MdPtRNvC49
Oe0T2lRznVdiPcGY8DKlBMYXQ4jiXZxpWmM8jNkJYPBhx9rq8zBDESo8DKSFd1Jo
lNADlBGDEPYgxG29hnSOrBf5TI1Fkj15RVZOJ79uaefp98ACIgkl
-----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIIBCgKCAQEA0FGWENPInhIfCLDTqCFKFsyrvmzKsEjJtHEL0Tqh0LtHDWG5Sh7M
T7/x/xNAFc00zmgGG+PPaJDP/7gkGJitRAXcJOlKwlowgmVTf+QGwH81pq3oZNRd
0mEXbF0EuPBRNt/9TzkZPAlPDGruMCiMq9LWsoIflx+u/3UmXgsyMQTs5vSMz4T5
VCELHGCtfZfBrDAP19KzwjFEUTEzX+Llotp0mO6+cRCslVvSK3xd8KIk2cOmAXEm
CavZnwuVsqCVmNZFoQZvFszisMf5cXZRDstKCGsqDgqIGM5dMMrBS92CqZ4uj6h9
zbMG7J9oXsVmVFiQ++hS0TLJdWwMD+uhWQIDAQAB
-----END PUBLIC KEY-----

【问题讨论】:

  • 公钥格式无效。标头建议使用 base64 编码的 SubjectPublicKeyInfo 结构,但内容实际上是 RSAPublicKey 结构。 RSAPublicKey 结构应该以“BEGIN RSA PUBLIC KEY”开头。
  • @JamesKPolk 谢谢你的评论。但是使用您推荐的标题而不是“PUBLIC KEY”是行不通的。 GCP IoT Core API 遇到同样的错误。我认为我的 go 代码无法像 openssl 命令那样生成 RSA 密钥。例如,此命令openssl genrsa -out rsa_private.pem 2048 && openssl rsa -in rsa_private.pem -pubout -out rsa_public.pem 的输出由 GCP IoT Core API 验证。
  • 我想不出任何方法来通过上面的代码生成有效的 pem 文件。所以我在ssh 命令上写了一个包装器。

标签: go google-cloud-platform rsa iot google-cloud-iot


【解决方案1】:

如果你得到:

Error: 7 PERMISSION_DENIED: The signature of device credential in position 0 could not be verified against any registry certificate.

错误并且您的系统曾经正常工作,请检查根 CA 证书的到期日期。如果超过日期,它将返回此错误。

【讨论】:

    【解决方案2】:

    编码头和编码方法不匹配。如果你想使用

    asn1Bytes := x509.MarshalPKCS1PublicKey(&key.PublicKey)
    

    那么pem.Block 类型应该是Type: "RSA PUBLIC KEY",

    如果您想要其他通用公钥格式,即 SubjectPublicKeyInfo ASN.1 结构,请保留 pem.Block 并改为使用

    asn1Bytes, err := x509.MarshalPKIXPublicKey(&key.PublicKey)
    

    我不知道 GCP 期待什么,但几乎可以肯定是其中之一。

    【讨论】:

    • @JohnHanley:谢谢。您是否碰巧有指向正确文档的链接,还是您通过反复试验发现的?
    • 这更像是与云供应商的约定,因为 PKCS #1 更容易解码。但是,我只是查找了 IoT 证书创建命令:openssl req -x509 -newkey rsa:2048 -keyout rsa_private.pem -nodes -out rsa_cert.pem -subj "/CN=unused",该命令生成 PKCS #8。 cloud.google.com/iot/docs/how-tos/credentials/keys
    • @JamesKPolk 使用 RSA PUBLIC KEY 作为 TYPE 不起作用。
    【解决方案3】:

    我遇到了同样的问题。 我可以用下面的代码解决这个问题。

    package cloudIotCore
    
    import (
        "crypto/rand"
        "crypto/rsa"
        "crypto/x509"
        "encoding/pem"
        "os"
    )
    
    func create() {
    
        //
        // Create key
        //
        reader := rand.Reader
        bitSize := 2048
    
        key, err := rsa.GenerateKey(reader, bitSize)
        if err != nil {
            panic(err)
        }
    
        publicKeyAsc1Bytes, err := x509.MarshalPKIXPublicKey(&(key.PublicKey))
        if err != nil {
            panic(err)
        }
    
        publicPemKey := &pem.Block{
            Type:  "PUBLIC KEY",
            Bytes: publicKeyAsc1Bytes,
        }
    
        privatePemKey := &pem.Block{
            Type:  "RSA PRIVATE KEY",
            Bytes: x509.MarshalPKCS1PrivateKey(key),
        }
    
        //
        // Create Device with publicPemKey
        //
    
        :
    
        //
        // Save pem files
        //
    
        publicPemFile, err := os.Create(PATH_TO_PUBLICKEY)
        if err != nil {
            panic(err)
        }
        defer publicPemFile.Close()
    
        err = pem.Encode(publicPemFile, publicPemKey)
        if err != nil {
            panic(err)
        }
    
        privatePemFile, err := os.Create(PATH_TO_PRIVATEKEY)
        if err != nil {
            panic(err)
        }
        defer privatePemFile.Close()
    
        err = pem.Encode(privatePemFile, privatePemKey)
        if err != nil {
            panic(err)
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      预期的密钥格式与密钥类型 RSA_PEM 与 RSA_X509_PEM 不匹配。切换解决了问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-09
        • 1970-01-01
        • 2019-12-29
        • 2020-10-06
        • 2011-03-29
        • 2021-10-18
        • 2015-03-25
        • 1970-01-01
        相关资源
        最近更新 更多