为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕后森 2023-06-26 17:07:55
我们的想法是让这个简单的请求正常工作,然后发出更复杂的请求,例如上传资产。下面的代码从请求中返回错误。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}分别是:{}
查看完整描述

1 回答

?
呼唤远方

TA贡献1856条经验 获得超11个赞

如果有人需要它,这里是一个可行的解决方案。


package main


import (

    "bytes"

    "crypto/ecdsa"

    "crypto/rand"

    "crypto/sha256"

    "crypto/x509"

    "encoding/asn1"

    "encoding/base64"

    "encoding/pem"

    "fmt"

    "io/ioutil"

    "math/big"

    "net/http"

    "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 {

    R, S *big.Int

}


func main() {

    t0 := time.Now().UTC()

    t1 := time.Now().UTC()


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

    // 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")

    }


    private_key, err := x509.ParseECPrivateKey(privBlock.Bytes)

    if err != nil {

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

    }


    pubBlock, _ := pem.Decode([]byte(pubPEM))

    if pubBlock == nil {

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

    }


    var public_key *ecdsa.PublicKey

    public_k, err := x509.ParsePKIXPublicKey(pubBlock.Bytes)

    if err != nil {

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

    }

    switch public_k1 := public_k.(type) {

    case *ecdsa.PublicKey:

        public_key = public_k1

    default:

        //return false

    }

    //////////

    // Config

    //////////

    requestPath := "/database/" +

        version + "/" +

        container + "/" +

        environment + "/" +

        database + "/" +

        "records/query"


    requestBody := `{"query": {"recordType": "<your record type"}}`


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

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


    h := sha256.New()

    h.Write([]byte(requestBody))

    b := h.Sum(nil)

    hashedBody := base64.StdEncoding.EncodeToString(b)


    rawPayload := requestDate + ":" + hashedBody + ":" + requestPath


    signedSignature, err := SignMessage(private_key, []byte(rawPayload))

    if err != nil {

        fmt.Printf("SignMessage  error: %s\n", err.Error())

    }


    verify := VerifyMessage(public_key, []byte(rawPayload), signedSignature)

    fmt.Printf("signature verification result: %t\n", verify)


    requestSignature := base64.StdEncoding.EncodeToString(signedSignature)

    url := path + requestPath


    req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(requestBody)))


    req.Header.Add("content-type", "text/plain")

    req.Header.Add("X-Apple-CloudKit-Request-KeyID", authKeyID)


    req.Header.Add("X-Apple-CloudKit-Request-ISO8601Date", requestDate)


    req.Header.Add("X-Apple-CloudKit-Request-SignatureV1", requestSignature)


    resp, err := http.DefaultClient.Do(req)

    if err != nil {

        fmt.Printf("\nresp.err:%v\n", err.Error())


    }


    defer resp.Body.Close()

    rbody, err := ioutil.ReadAll(resp.Body)

    if err != nil {

        fmt.Printf("\nioutil.ReadAll.err:%v\n", err.Error())


    }

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


    curl := "curl -X POST -H \"content-type: text/plain\"" + " " +

        "-H X-Apple-CloudKit-Request-KeyID:" + authKeyID + " " +

        "-H X-Apple-CloudKit-Request-ISO8601Date:" + requestDate + " " +

        "-H X-Apple-CloudKit-Request-SignatureV1:" + base64.StdEncoding.EncodeToString(signedSignature) + " " +

        " -d " + "'" + requestBody + "'" + " " +

        url


    fmt.Printf("\n%s\n", curl)


}


func SignMessage(priv *ecdsa.PrivateKey, message []byte) ([]byte, error) {

    hashed := sha256.Sum256(message)

    r, s, err := ecdsa.Sign(rand.Reader, priv, hashed[:])

    if err != nil {

        return nil, err

    }


    return asn1.Marshal(ecdsaSignature{r, s})

}


func VerifyMessage(pub *ecdsa.PublicKey, message []byte, signature []byte) bool {

    var rs ecdsaSignature


    if _, err := asn1.Unmarshal(signature, &rs); err != nil {

        return false

    }


    hashed := sha256.Sum256(message)

    return ecdsa.Verify(pub, hashed[:], rs.R, rs.S)

}



查看完整回答
反对 回复 2023-06-26
  • 1 回答
  • 0 关注
  • 99 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信