最近,一个新的 API Look Up Order ID被添加到应用商店服务器 API 中。以及此 API 响应的JWSTransaction由 App Store 签名,采用 JSON Web 签名格式。我们想用 go 来验证它。
我们尝试过的
- 使用了jwt-go ,我们尝试根据这个问题从 pem 文件中提取公钥。同样根据此链接,应通过从私钥中提取公钥来解码响应
type JWSTransaction struct {
BundleID string `json:"bundleId"`
InAppOwnershipType string `json:"inAppOwnershipType"`
TransactionID string `json:"transactionId"`
ProductID string `json:"productId"`
PurchaseDate int64 `json:"purchaseDate"`
Type string `json:"type"`
OriginalPurchaseDate int64 `json:"originalPurchaseDate"`
}
func (ac *JWSTransaction) Valid() error {
return nil
}
func (a *AppStore) readPrivateKeyFromFile(keyFile string) (*ecdsa.PrivateKey, error) {
bytes, err := ioutil.ReadFile(keyFile)
if err != nil {
return nil, err
}
block, _ := pem.Decode(bytes)
if block == nil {
return nil, errors.New("appstore private key must be a valid .p8 PEM file")
}
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
switch pk := key.(type) {
case *ecdsa.PrivateKey:
return pk, nil
default:
return nil, errors.New("appstore private key must be of type ecdsa.PrivateKey")
}
}
func (a *AppStore) ExtractClaims(tokenStr string) (*JWSTransaction, error) {
privateKey, err := a.readPrivateKeyFromFile()
if err != nil {
return nil, err
}
publicKey, err := x509.MarshalPKIXPublicKey(privateKey.Public())
if err != nil {
return nil, err
}
fmt.Println(publicKey)
tran := JWSTransaction{}
token, err := jwt.ParseWithClaims(tokenStr, &tran, func(token *jwt.Token) (interface{}, error) {
fmt.Println(token.Claims)
fmt.Println(token.Method.Alg())
return publicKey, nil
})
if err != nil {
fmt.Println(err)
}
但是,错误key is of invalid type
来自jwt.ParseWithClaims
.
- 通过此链接的 jwt-go 和 jwk 包验证它的另一种方法
token, err := jwt.ParseWithClaims(tokenStr, &tran, func(token *jwt.Token) (interface{}, error) {
fmt.Println(token.Claims)
fmt.Println(token.Method.Alg())
kid, ok := token.Header["kid"].(string)
if !ok {
return nil, errors.New("failed to find kid from headers")
}
key, found := keySet.LookupKeyID(kid)
if !found {
return nil, errors.New("failed to find kid from key set")
}
return publicKey, nil
})
但是,我们未能在应用商店服务器 API 文档中找到公钥 URL。此外,kid
JWSTransaction 的标头中也没有。
我们想知道如何在 Go 中验证应用商店服务器 api 的 JWS 事务?我有什么遗漏吗?