验证和签署 JSON Web Tokens(JWT)从 Node.js 到 Golang,以及反之,使用 RSA。

huangapple go评论72阅读模式
英文:

Verify and Sign JSON Web Tokens from NodeJS to Golang and vice-versa using RSA?

问题

我已经在Golang中生成了一个私钥,该私钥应该用于对以NodeJS编写的其他服务发出的JSON Web Tokens进行签名。

在交换令牌之前,NodeJS服务应该存储Golang客户端的公钥。

我的问题是,我不知道如何将rsa.PublicKey导出为与NodeJS的npmjs.com/package/jsonwebtoken兼容的格式,并在另一个方向上执行相同的操作;也就是为Golang客户端提供NodeJS服务的公钥以验证传入的令牌。

编辑:

相关代码请参考https://github.com/zarkones/XENA
请查看文件/xena-apep/main.go的第16行和第36行。

编辑2:

以下是相关的代码:

var privateIdentificationKey = generatePrivateKey() // 生成私钥。

identify(id.String(), privateIdentificationKey.publicKey) // 由于类型不匹配,无法工作。

/* 生成私钥。 */
func generatePrivateKey() *rsa.PrivateKey {
    secret, err := rsa.GenerateKey(rand.Reader, 4096)
    if err != nil {
	    fmt.Println(err)
    }
    return secret
}

/* 使Xena-Atila意识到自己的存在。 */
func identify(id string, identificationKey string) {
    insertionPayload := []byte(`{"id":"` + id + `","identificationKey":"` + identificationKey + `","status":"ALIVE"}`)

    request, err := http.NewRequest("POST", centralizedHost+"/v1/clients", bytes.NewBuffer(insertionPayload))
    request.Header.Set("Content-Type", "application/json")
    if err != nil {
	    fmt.Println("无法连接到集中主机。")
    }

    client := &http.Client{}
    response, err := client.Do(request)
    defer response.Body.Close()
}
英文:

I've generated a private key in Golang, which should be used to sign JSON Web Tokens issued to the other service coded in NodeJS.

Prior to any exchange of the tokens, NodeJS service should store the public key of the Golang client.

My problem is, I don't know how to export a rsa.PublicKey into a format which is working with NodeJS' npmjs.com/package/jsonwebtoken and do the same in the other direction; meaning providing the Golang client with a public key of the NodeJS service to verify incoming tokens.

Edit:

Code in question https://github.com/zarkones/XENA
Look under the file /xena-apep/main.go lines 16 and 36.

Edit2:

Here is the code in question:

var privateIdentificationKey = generatePrivateKey() // Generating the private key.

identify(id.String(), privateIdentificationKey.publicKey) // Won't work because of the type miss-match.

/* Generates a private key. */
func generatePrivateKey() *rsa.PrivateKey {
    secret, err := rsa.GenerateKey(rand.Reader, 4096)
    if err != nil {
	    fmt.Println(err)
    }
    return secret
}

/* Makes Xena-Atila aware of its existence. */
func identify(id string, identificationKey string) {
    insertionPayload := []byte(`{"id":"` + id + `","identificationKey":"` + identificationKey + `","status":"ALIVE"}`)

    request, err := http.NewRequest("POST", centralizedHost+"/v1/clients", bytes.NewBuffer(insertionPayload))
    request.Header.Set("Content-Type", "application/json")
    if err != nil {
	    fmt.Println("Unable to connect to the centralized host.")
    }

    client := &http.Client{}
    response, err := client.Do(request)
    defer response.Body.Close()
}

答案1

得分: 1

jwt.sign()jwt.verify()方法来自node-jsonwebtoken库,它们期望使用PEM编码的密钥。因此,NodeJS端将提供PEM编码的公钥或期望一个PEM编码的密钥(可以是X.509/SPKI格式或PKCS#1格式)。

在Go中,密钥的导出和导入是在crypto/x509包中实现的,PEM编码在encoding/pem包中实现,RSA在crypto/rsa包中实现。

使用Go中发布的GeneratePrivateKey()方法生成私钥和公钥的示例代码如下:

privateKey := GeneratePrivateKey()
publicKey := &privateKey.PublicKey

在Go中,可以使用以下代码将以X.509/SPKI格式导出的PEM编码的公钥:

func ExportSPKIPublicKeyPEM(pubkey *rsa.PublicKey) string {
    spkiDER, _ := x509.MarshalPKIXPublicKey(pubkey)
    spkiPEM := pem.EncodeToMemory(
        &pem.Block{
            Type:  "PUBLIC KEY",
            Bytes: spkiDER,
        },
    )
    return string(spkiPEM)
}

另外,可以使用MarshalPKCS1PublicKey()方法将以PKCS#1格式导出的PEM编码的公钥。在这种情况下,需要指定TypeRSA PUBLIC KEY

可以使用ASN.1解析器检查导出的密钥,例如在线工具:https://lapo.it/asn1js/

在Go中,可以使用以下代码导入以X.509/SPKI格式编码的PEM公钥:

func ImportSPKIPublicKeyPEM(spkiPEM string) *rsa.PublicKey {
    body, _ := pem.Decode([]byte(spkiPEM))
    publicKey, _ := x509.ParsePKIXPublicKey(body.Bytes)
    if publicKey, ok := publicKey.(*rsa.PublicKey); ok {
        return publicKey
    } else {
        return nil
    }
}

使用ParsePKCS1PublicKey()方法可以导入以PKCS#1格式编码的PEM公钥。

英文:

The jwt.sign() and and jwt.verify() method from node-jsonwebtoken expect PEM encoded keys. Therefore, the NodeJS side will provide the public key PEM encoded or expects a PEM encoded key (either in X.509/SPKI format or PKCS#1 format).

Key export and import is implemented in Go in the crypto/x509 package, PEM encoding in the encoding/pem package, RSA in the crypto/rsa package.

The generation of a private and public key using the posted GeneratePrivateKey() method in Go is:

<!-- language: lang-go -->
privateKey := GeneratePrivateKey()
publicKey := &privateKey.PublicKey

Exporting a PEM encoded public key in X.509/SPKI format in Go is possible e.g. with:

<!-- language: lang-go -->
func ExportSPKIPublicKeyPEM(pubkey *rsa.PublicKey) (string){
spkiDER, _ := x509.MarshalPKIXPublicKey(pubkey)
spkiPEM := pem.EncodeToMemory(
&pem.Block{
Type: "PUBLIC KEY",
Bytes: spkiDER,
},
)
return string(spkiPEM)
}

Alternatively, a PEM encoded public key in PKCS#1 format can be exported with MarshalPKCS1PublicKey(). For this as Type RSA PUBLIC KEY must be specified.

The exported key can be checked with an ASN.1 parser, e.g. online with: https://lapo.it/asn1js/

The import of a PEM encoded public key in X.509/SPKI format is possible in Go e.g. with:

<!-- language: lang-go -->
func ImportSPKIPublicKeyPEM(spkiPEM string) (*rsa.PublicKey) {
body, _ := pem.Decode([]byte(spkiPEM ))
publicKey, _ := x509.ParsePKIXPublicKey(body.Bytes)
if publicKey, ok := publicKey.(*rsa.PublicKey); ok {
return publicKey
} else {
return nil
}
}

With ParsePKCS1PublicKey() a PEM encoded public key in PKCS#1 format can be imported.

huangapple
  • 本文由 发表于 2021年6月27日 03:30:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/68145666.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定