为了账号安全,请及时绑定邮箱和手机立即绑定

如何验证 appengine.SignBytes 返回的签名?

如何验证 appengine.SignBytes 返回的签名?

Go
慕哥6287543 2021-11-08 14:34:20
Google App Engine 的 Go 运行时具有SignBytes函数、PublicCertificates函数和证书结构。功能符号字节func SignBytes(c Context, bytes []byte) (keyName string, signature []byte, err error) SignBytes 使用您的应用程序唯一的私钥对字节进行签名。func 公共证书func PublicCertificates(c Context) ([]Certificate, error) PublicCertificates 检索应用程序的公共证书。它们可用于验证 SignBytes 返回的签名。类型证书type Certificate struct {    KeyName string    Data    []byte // PEM-encoded X.509 certificate}Certificate 代表应用程序的公共证书。很明显,应用程序需要遍历公共证书以验证签名。但尚不清楚签名是如何生成或验证的。Go 的rsa 包有两个函数来验证签名,VerifyPKCS1v15和VerifyPSS,每个函数都以一个crypto.Hash标识符作为参数。目前,有 15 种不同的哈希标识符(例如,crypto.MD5、crypto.SHA256)给出验证函数和哈希标识符的 2x15=30 组合。SignBytes 生成的签名是如何验证的?
查看完整描述

1 回答

?
catspeake

TA贡献1111条经验 获得超0个赞

使用 SHA256 验证 PKCS1v15

我通过尝试验证方案和哈希类型的所有组合发现了这一点;我没有找到保证这是将使用的签名方案的文档。


但是对于无畏者来说,下面是一个对数据进行签名并验证签名的代码示例。


package yourpackage


import (

    "crypto"

    "crypto/rsa"

    "crypto/x509"

    "encoding/pem"

    "errors"

    "google.golang.org/appengine"

    "net/http"

)


func signAndVerify(request *http.Request) error {

    c := appengine.NewContext(request)

    data := []byte("test data to sign")

    _, sig, err := appengine.SignBytes(c, data)

    if err != nil {

        return err

    }


    certs, err := appengine.PublicCertificates(c)

    if err != nil {

        return err

    }


    lastErr := errors.New("ErrNoPublicCertificates")


    for _, cert := range certs {

        block, _ := pem.Decode(cert.Data)

        if block == nil {

            lastErr = errors.New("ErrPemDecodeFailure")

            continue

        }

        x509Cert, err := x509.ParseCertificate(block.Bytes)

        if err != nil {

            lastErr = err

            continue

        }

        pubkey, ok := x509Cert.PublicKey.(*rsa.PublicKey)

        if !ok {

            lastErr = errors.New("ErrNotRSAPublicKey")

            continue

        }


        signBytesHash := crypto.SHA256

        h := signBytesHash.New()

        h.Write(data)

        hashed := h.Sum(nil)

        err = rsa.VerifyPKCS1v15(pubkey, signBytesHash, hashed, sig)

        if err != nil {

            lastErr = err

            continue

        }


        return nil

    }


    return lastErr

}

我还在github 上的一个包中发布了验证步骤。


更新

Google 提供了一些验证 SignBytes 的示例代码。其中,有一个文件app-identity-samples-read-only/python/app_identity_test.py有一个名为buildjwt创建由 SignBytes 签名的 JWT 的方法,并且 JWT 算法是 RS256,它在RFC 7518 中定义为使用 SHA-256 的 RSASSA-PKCS1-v1_5。


注意:我将Go App Engine 用于托管 VM(请参阅“google.golang.org/appengine”导入)而不是经典的 Go App Engine 运行时,尽管对于 SignBytes 的目的来说并没有太大的不同。


查看完整回答
反对 回复 2021-11-08
  • 1 回答
  • 0 关注
  • 196 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信