如何执行 CloudKit 服务器到服务器身份验证

我们的想法是让这个简单的请求正常工作,然后发出更复杂的请求,例如上传资产。

下面的代码从请求中返回错误。

import (

    "bytes"

    "crypto/ecdsa"

    "crypto/rand"

    "crypto/sha256"

    "crypto/x509"

    "encoding/base64"

    "encoding/pem"

    "fmt"

    "math/big"

    "net/http"

    "time"

    //...

)


func main() {


    fmt.Printf("\nprivate key:\n")


    const privPEM = `-----BEGIN EC PRIVATE KEY-----

MyProvateKey

-----END EC PRIVATE KEY-----`


    // https://golang.org/pkg/crypto/x509/#example_ParsePKIXPublicKey

    privBlock, _ := pem.Decode([]byte(privPEM))

    if privBlock == nil {

        panic("failed to parse PEM block containing the public key")

    }


    requestPathStr := "/database/1/iCloud.<MyContainer>/development/public/users/discover"


    var requestPath []byte

    requestPath = []byte(requestPathStr)

    fmt.Printf("requestPath: %s\n", requestPath)


    requestBody := ""

    var jsonStr = []byte(requestBody)

    //

    h := sha256.New()

    h.Write([]byte(requestBody))

    b := h.Sum(nil)

    hashedBody := base64.StdEncoding.EncodeToString(b)

    //


    f := "2006-01-02T15:04:05Z"

    requestDate := time.Now().UTC().Format(f)

    fmt.Println(requestDate)


    rawPayload := []byte(requestDate + ":" + hashedBody + ":" + requestPathStr)


    r, s, err := pkSign(rawPayload, privBlock)

    if err != nil {

        fmt.Printf("signing hash error: %s\n", err)

    }

    fmt.Printf("r: %v\n", r)

    fmt.Printf("s: %v\n", s)


    fmt.Printf("\npublic key:\n")


    const pubPEM = `-----BEGIN PUBLIC KEY-----



我得到的错误如下:

resp:&{503 服务不可用 503 HTTP/1.1 1 1 映射[Access-Control-Expose-Headers:[X-Apple-Request-UUID Via] 连接:[keep-alive] 内容长度:[0] 内容类型:[text/plain] 日期:[2019 年 6 月 24 日星期一 07:47:52 GMT] 重试后:[30] 服务器:[AppleHttpServer/70a91026] 通过:[icloudedge:mi01p00ic-zteu02110401:7401:19RC207:迈阿密] X-Apple-Cache:[false] X-Apple-Request-Uuid:[ddeb0fa3-ea16-40e9-a15b-c2e68cb5fe78]] {} 0 [] false false 地图[] 0xc00015c000 0xc0000ce2c0}

分别是:{}


慕后森
浏览 105回答 1
1回答

呼唤远方

如果有人需要它,这里是一个可行的解决方案。package mainimport (&nbsp; &nbsp; "bytes"&nbsp; &nbsp; "crypto/ecdsa"&nbsp; &nbsp; "crypto/rand"&nbsp; &nbsp; "crypto/sha256"&nbsp; &nbsp; "crypto/x509"&nbsp; &nbsp; "encoding/asn1"&nbsp; &nbsp; "encoding/base64"&nbsp; &nbsp; "encoding/pem"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "io/ioutil"&nbsp; &nbsp; "math/big"&nbsp; &nbsp; "net/http"&nbsp; &nbsp; "time")const projectID = "<your ID>"//const authKeyID = "your ID"const path = "https://api.apple-cloudkit.com"const version = "1"const container = "your container"const environment = "development"const database = "public"const privPEM = `-----BEGIN EC PRIVATE KEY-----your privste key-----END EC PRIVATE KEY-----`const pubPEM = `-----BEGIN PUBLIC KEY-----your public key-----END PUBLIC KEY-----`type ecdsaSignature struct {&nbsp; &nbsp; R, S *big.Int}func main() {&nbsp; &nbsp; t0 := time.Now().UTC()&nbsp; &nbsp; t1 := time.Now().UTC()&nbsp; &nbsp; // fmt.Printf("\nprivate key:\n")&nbsp; &nbsp; // https://golang.org/pkg/crypto/x509/#example_ParsePKIXPublicKey&nbsp; &nbsp; privBlock, _ := pem.Decode([]byte(privPEM))&nbsp; &nbsp; if privBlock == nil {&nbsp; &nbsp; &nbsp; &nbsp; panic("failed to parse PEM block containing the public key")&nbsp; &nbsp; }&nbsp; &nbsp; private_key, err := x509.ParseECPrivateKey(privBlock.Bytes)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic("failed to parse PEM block containing the public key")&nbsp; &nbsp; }&nbsp; &nbsp; pubBlock, _ := pem.Decode([]byte(pubPEM))&nbsp; &nbsp; if pubBlock == nil {&nbsp; &nbsp; &nbsp; &nbsp; panic("failed to parse PEM block containing the public key")&nbsp; &nbsp; }&nbsp; &nbsp; var public_key *ecdsa.PublicKey&nbsp; &nbsp; public_k, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic("failed to parse PEM block containing the public key")&nbsp; &nbsp; }&nbsp; &nbsp; switch public_k1 := public_k.(type) {&nbsp; &nbsp; case *ecdsa.PublicKey:&nbsp; &nbsp; &nbsp; &nbsp; public_key = public_k1&nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; //return false&nbsp; &nbsp; }&nbsp; &nbsp; //////////&nbsp; &nbsp; // Config&nbsp; &nbsp; //////////&nbsp; &nbsp; requestPath := "/database/" +&nbsp; &nbsp; &nbsp; &nbsp; version + "/" +&nbsp; &nbsp; &nbsp; &nbsp; container + "/" +&nbsp; &nbsp; &nbsp; &nbsp; environment + "/" +&nbsp; &nbsp; &nbsp; &nbsp; database + "/" +&nbsp; &nbsp; &nbsp; &nbsp; "records/query"&nbsp; &nbsp; requestBody := `{"query": {"recordType": "<your record type"}}`&nbsp; &nbsp; f := "2006-01-02T15:04:05Z"&nbsp; &nbsp; requestDate := time.Now().UTC().Format(f)&nbsp; &nbsp; h := sha256.New()&nbsp; &nbsp; h.Write([]byte(requestBody))&nbsp; &nbsp; b := h.Sum(nil)&nbsp; &nbsp; hashedBody := base64.StdEncoding.EncodeToString(b)&nbsp; &nbsp; rawPayload := requestDate + ":" + hashedBody + ":" + requestPath&nbsp; &nbsp; signedSignature, err := SignMessage(private_key, []byte(rawPayload))&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("SignMessage&nbsp; error: %s\n", err.Error())&nbsp; &nbsp; }&nbsp; &nbsp; verify := VerifyMessage(public_key, []byte(rawPayload), signedSignature)&nbsp; &nbsp; fmt.Printf("signature verification result: %t\n", verify)&nbsp; &nbsp; requestSignature := base64.StdEncoding.EncodeToString(signedSignature)&nbsp; &nbsp; url := path + requestPath&nbsp; &nbsp; req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(requestBody)))&nbsp; &nbsp; req.Header.Add("content-type", "text/plain")&nbsp; &nbsp; req.Header.Add("X-Apple-CloudKit-Request-KeyID", authKeyID)&nbsp; &nbsp; req.Header.Add("X-Apple-CloudKit-Request-ISO8601Date", requestDate)&nbsp; &nbsp; req.Header.Add("X-Apple-CloudKit-Request-SignatureV1", requestSignature)&nbsp; &nbsp; resp, err := http.DefaultClient.Do(req)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("\nresp.err:%v\n", err.Error())&nbsp; &nbsp; }&nbsp; &nbsp; defer resp.Body.Close()&nbsp; &nbsp; rbody, err := ioutil.ReadAll(resp.Body)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("\nioutil.ReadAll.err:%v\n", err.Error())&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Printf("\nrbody:%s\n", rbody)&nbsp; &nbsp; curl := "curl -X POST -H \"content-type: text/plain\"" + " " +&nbsp; &nbsp; &nbsp; &nbsp; "-H X-Apple-CloudKit-Request-KeyID:" + authKeyID + " " +&nbsp; &nbsp; &nbsp; &nbsp; "-H X-Apple-CloudKit-Request-ISO8601Date:" + requestDate + " " +&nbsp; &nbsp; &nbsp; &nbsp; "-H X-Apple-CloudKit-Request-SignatureV1:" + base64.StdEncoding.EncodeToString(signedSignature) + " " +&nbsp; &nbsp; &nbsp; &nbsp; " -d " + "'" + requestBody + "'" + " " +&nbsp; &nbsp; &nbsp; &nbsp; url&nbsp; &nbsp; fmt.Printf("\n%s\n", curl)}func SignMessage(priv *ecdsa.PrivateKey, message []byte) ([]byte, error) {&nbsp; &nbsp; hashed := sha256.Sum256(message)&nbsp; &nbsp; r, s, err := ecdsa.Sign(rand.Reader, priv, hashed[:])&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return nil, err&nbsp; &nbsp; }&nbsp; &nbsp; return asn1.Marshal(ecdsaSignature{r, s})}func VerifyMessage(pub *ecdsa.PublicKey, message []byte, signature []byte) bool {&nbsp; &nbsp; var rs ecdsaSignature&nbsp; &nbsp; if _, err := asn1.Unmarshal(signature, &rs); err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; }&nbsp; &nbsp; hashed := sha256.Sum256(message)&nbsp; &nbsp; return ecdsa.Verify(pub, hashed[:], rs.R, rs.S)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go