Go Verion : go version go1.16.7 linux/amd64
Imports:
import (
"crypto/ecdsa"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
"encoding/asn1"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"math/big"
"net/http"
"time"
"github.com/gin-gonic/gin"
uuid "github.com/satori/go.uuid"
"go.mongodb.org/mongo-driver/mongo"
)
Code I'm using
var (
// the id and private key below is got from here:
// https://developer.apple.com/documentation/storekit/in-app_purchase/generating_a_subscription_offer_signature_using_node_js
AppleKeyId = "mykeyid"
ApplePrivateKey = `-----BEGIN PRIVATE KEY-----
MyKey
-----END PRIVATE KEY-----`
privateKey, _ = AuthKeyFromBytes([]byte(ApplePrivateKey))
sep = "\u2063"
AppBundleID = "mybundlename"
)
func AuthKeyFromBytes(key []byte) (*ecdsa.PrivateKey, error) {
var err error
// Parse PEM block
var block *pem.Block
if block, _ = pem.Decode(key); block == nil {
return nil, errors.New("token: AuthKey must be a valid .p8 PEM file")
}
// Parse the key
var parsedKey interface{}
if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
return nil, err
}
var pkey *ecdsa.PrivateKey
var ok bool
if pkey, ok = parsedKey.(*ecdsa.PrivateKey); !ok {
return nil, errors.New("token: AuthKey must be of type ecdsa.privateKey")
}
return pkey, nil
}
type SignParams struct {
ProductIdentifier string `json:"productIdentifier"`
OfferID string `json:"offerID"`
ApplicationUsername string `json:"applicationUsername"`
}
type SignResult struct {
KeyID string `json:"keyID"`
Nonce string `json:"nonce"`
Timestamp int64 `json:"timestamp"`
Signature string `json:"signature"`
}
func Sign(params *SignParams) (SignResult, error) {
nonce := uuid.NewV4().String()
timestamp := time.Now().UnixNano() / 1000000
payload := AppBundleID + sep +
AppleKeyId + sep +
params.ProductIdentifier + sep +
params.OfferID + sep +
params.ApplicationUsername + sep +
nonce + sep +
fmt.Sprintf("%v", timestamp)
hash := sha256.Sum256([]byte(payload))
sig, err := privateKey.Sign(rand.Reader, hash[:], nil) Error Here
if err != nil {
return SignResult{}, err
}
return SignResult{
KeyID: AppleKeyId,
Nonce: nonce,
Timestamp: timestamp,
Signature: base64.StdEncoding.EncodeToString(sig),
}, nil
}
Issue at: sig, err := privateKey.Sign(rand.Reader, hash[:], nil) in Sign Function
Error on the console:
2021/09/13 09:47:59 [Recovery] 2021/09/13 - 09:47:59 panic recovered:
POST /signatures HTTP/1.1
Host: localhost:5000
Accept: */*
Accept-Encoding: gzip, deflate, br
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 114
Content-Type: application/json
Postman-Token: 12f5ac0a-3379-40ad-826e-78dc63579cbb
User-Agent: PostmanRuntime/7.28.4
runtime error: invalid memory address or nil pointer dereference
/usr/local/go/src/runtime/panic.go:212 (0x435cda)
panicmem: panic(memoryError)
/usr/local/go/src/runtime/signal_unix.go:734 (0x44e852)
sigpanic: panicmem()
/usr/local/go/src/crypto/ecdsa/ecdsa.go:204 (0x5652b8)
Sign: entropylen := (priv.Curve.Params().BitSize + 7) / 16
/usr/local/go/src/crypto/ecdsa/ecdsa.go:116 (0x564ba4)
(*PrivateKey).Sign: r, s, err := Sign(rand, priv, digest)
/usr/local/go/src/crypto/ecdsa/ecdsa.go:286 (0xd8fd0f)
SignASN1: return priv.Sign(rand, hash, nil)
/home/zainkhan/GolandProjects/kotc-server/controllers/signature.go:121 (0xd8fcc1)
Sign: sig, err := ecdsa.SignASN1(rand.Reader, privateKey, hash[:])
/home/zainkhan/GolandProjects/kotc-server/controllers/signature.go:39 (0xd8f284)
(*signaturesController).post: final, err := Sign(req)
/home/zainkhan/GolandProjects/pkg/mod/github.com/gin-gonic/gin@v1.7.3/context.go:165 (0x992c99)
(*Context).Next: c.handlers[c.index](c)
/home/zainkhan/GolandProjects/pkg/mod/github.com/gin-gonic/gin@v1.7.3/recovery.go:99 (0x992c80)
CustomRecoveryWithWriter.func1: c.Next()
/home/zainkhan/GolandProjects/pkg/mod/github.com/gin-gonic/gin@v1.7.3/context.go:165 (0x991d73)
(*Context).Next: c.handlers[c.index](c)
/home/zainkhan/GolandProjects/pkg/mod/github.com/gin-gonic/gin@v1.7.3/logger.go:241 (0x991d32)
LoggerWithConfig.func1: c.Next()
/home/zainkhan/GolandProjects/pkg/mod/github.com/gin-gonic/gin@v1.7.3/context.go:165 (0x988109)
(*Context).Next: c.handlers[c.index](c)
/home/zainkhan/GolandProjects/pkg/mod/github.com/gin-gonic/gin@v1.7.3/gin.go:489 (0x9880ef)
(*Engine).handleHTTPRequest: c.Next()
/home/zainkhan/GolandProjects/pkg/mod/github.com/gin-gonic/gin@v1.7.3/gin.go:445 (0x987bdb)
(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/local/go/src/net/http/server.go:2867 (0x6e2462)
serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/local/go/src/net/http/server.go:1932 (0x6dd88c)
(*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/local/go/src/runtime/asm_amd64.s:1371 (0x46e5a0)
goexit: BYTE $0x90 // NOP
I don't know why its coming, ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////