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

时间:2015-09-09 18:05:19

标签: google-app-engine go rsa

Google App Engine的Go运行时具有SignBytes函数,PublicCertificates函数和Certificate结构。

  

func SignBytes

func SignBytes(c Context, bytes []byte) (keyName string, signature []byte, err error) 
     

SignBytes使用您的应用程序独有的私钥来标记字节。

     

func PublicCertificates

func PublicCertificates(c Context) ([]Certificate, error) 
     

PublicCertificates检索应用程序的公共证书。他们   可用于验证SignBytes返回的签名。

     

输入证书

type Certificate struct {
    KeyName string
    Data    []byte // PEM-encoded X.509 certificate
}
     

证书代表该应用的公共证书。

很明显,应用程序应该遍历公共证书以验证签名。但目前尚不清楚如何生成或验证签名。 Go rsa package有两个功能来验证签名,VerifyPKCS1v15VerifyPSS,每个函数都使用crypto.Hash标识符作为参数。目前,有15种不同的散列标识符(例如,crypto.MD5,crypto.SHA256),提供2x15 = 30种验证功能和散列标识符组合。

SignBytes如何验证签名?

1 个答案:

答案 0 :(得分:4)

使用SHA256

VerifyPKCS1v15

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

但是对于无畏者,下面是一个代码示例,用于签署数据并验证签名。

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上的package发布了验证步骤。

更新

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

注意:我正在使用Go App Engine for Managed VMs(请参阅“google.golang.org/appengine”导入)而不是经典的Go App Engine运行时,尽管目的并没有太大差异SignBytes。