doumao1887 2015-09-09 18:05
浏览 70
已采纳

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

Google App Engine's Go runtime has a SignBytes function, a PublicCertificates function, and a Certificate structure.

func SignBytes

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

SignBytes signs bytes using a private key unique to your application.

func PublicCertificates

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

PublicCertificates retrieves the public certificates for the app. They can be used to verify a signature returned by SignBytes.

type Certificate

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

Certificate represents a public certificate for the app.

It's clear that the application is expected to iterate through the public certificates to verify the signature. But it is not clear how the signature is generate or verified. Go's rsa package has two functions to verify signatures, VerifyPKCS1v15 and VerifyPSS, and each of those functions takes a crypto.Hash identifier as a parameter. Currently, there are 15 different hash identifiers (e.g., crypto.MD5, crypto.SHA256) giving 2x15=30 combinations of verification function and hash identifier.

How is the signature produced by SignBytes verified?

  • 写回答

1条回答 默认 最新

  • dqwh1119 2015-09-10 01:52
    关注

    VerifyPKCS1v15 using SHA256

    I discovered this by trying all combinations of verification scheme and hash type; I did not find documentation guaranteeing this is the signature scheme that will be used.

    But for the intrepid, below is a code sample that signs data and verifies the signature.

    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
    }
    

    I've also published the the verify step in a package on github.

    Update

    Google provides some sample code that verifies SignBytes. In it, there is a file app-identity-samples-read-only/python/app_identity_test.py has a method named buildjwt that creates a JWT signed by SignBytes, and the JWT alg is RS256, which is defined in RFC 7518 to be RSASSA-PKCS1-v1_5 using SHA-256.

    Note: I'm using Go App Engine for Managed VMs (see "google.golang.org/appengine" import) rather than the classic Go App Engine runtime, though there isn't really much different for the purposes of SignBytes.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog
  • ¥15 Excel发现不可读取的内容
  • ¥15 关于#stm32#的问题:CANOpen的PDO同步传输问题