1package plc
2
3import (
4 "bytes"
5 "crypto/ecdsa"
6 "encoding/base64"
7 "encoding/json"
8 "fmt"
9 "testing"
10
11 "github.com/lestrrat-go/jwx/v2/jwk"
12 did "github.com/whyrusleeping/go-did"
13)
14
15type testVector struct {
16 Jwk string
17 Did string
18 Op string
19 SignedOp string
20 EncodedOp string
21 Sig string
22}
23
24func TestPLCCreateVector(t *testing.T) {
25
26 tv := testVector{
27 Jwk: `{
28 "key_ops": [
29 "sign"
30 ],
31 "ext": true,
32 "kty": "EC",
33 "x": "DwHtAjFHuhYWf9RKnE4XgMImEUKA40G0PR8Cbz-GTMY",
34 "y": "pqny0WfZnm2jHEimqEwg21wvHsWWnqV3E_ofMW_jWuw",
35 "crv": "P-256",
36 "d": "elqCGEYj8NB1jXd-I7y4qyy35yZ2PhCOqPW3fM2ToM0"
37 }`,
38 Did: "did:key:zDnaeRSYs7c2NpcNA5NRAUqS8DCkLWDyNLnATi28D6w7no7hX",
39 Op: `{
40 "type": "create",
41 "signingKey": "did:key:zDnaeRSYs7c2NpcNA5NRAUqS8DCkLWDyNLnATi28D6w7no7hX",
42 "recoveryKey": "did:key:zDnaeRSYs7c2NpcNA5NRAUqS8DCkLWDyNLnATi28D6w7no7hX",
43 "handle": "why.bsky.social",
44 "service": "bsky.social",
45 "prev": null
46 }`,
47 SignedOp: `{
48 "type": "create",
49 "signingKey": "did:key:zDnaeRSYs7c2NpcNA5NRAUqS8DCkLWDyNLnATi28D6w7no7hX",
50 "recoveryKey": "did:key:zDnaeRSYs7c2NpcNA5NRAUqS8DCkLWDyNLnATi28D6w7no7hX",
51 "handle": "why.bsky.social",
52 "service": "bsky.social",
53 "prev": null,
54 "sig": "e8h6dCx405Z_95cZWWkZtfLgDPvfdXDG9pCZQi1NhduooZgb4d1w-CzahA3J-iNGCCgP3D0O5l997G3vQfxKOA"
55 }`,
56 EncodedOp: "pmRwcmV29mR0eXBlZmNyZWF0ZWZoYW5kbGVvd2h5LmJza3kuc29jaWFsZ3NlcnZpY2VrYnNreS5zb2NpYWxqc2lnbmluZ0tleXg5ZGlkOmtleTp6RG5hZVJTWXM3YzJOcGNOQTVOUkFVcVM4RENrTFdEeU5MbkFUaTI4RDZ3N25vN2hYa3JlY292ZXJ5S2V5eDlkaWQ6a2V5OnpEbmFlUlNZczdjMk5wY05BNU5SQVVxUzhEQ2tMV0R5TkxuQVRpMjhENnc3bm83aFg",
57 Sig: "e8h6dCx405Z_95cZWWkZtfLgDPvfdXDG9pCZQi1NhduooZgb4d1w-CzahA3J-iNGCCgP3D0O5l997G3vQfxKOA",
58 }
59
60 var op CreateOp
61 if err := json.Unmarshal([]byte(tv.Op), &op); err != nil {
62 t.Fatal(err)
63 }
64
65 buf := new(bytes.Buffer)
66 if err := op.MarshalCBOR(buf); err != nil {
67 t.Fatal(err)
68 }
69
70 exp, err := base64.RawURLEncoding.DecodeString(tv.EncodedOp)
71 if err != nil {
72 t.Fatal(err)
73 }
74
75 if !bytes.Equal(buf.Bytes(), exp) {
76 fmt.Printf("%x\n", buf.Bytes())
77 fmt.Printf("%x\n", exp)
78 t.Fatal("encoding mismatched")
79 }
80
81 k, err := jwk.ParseKey([]byte(tv.Jwk))
82 if err != nil {
83 t.Fatal(err)
84 }
85
86 var spk ecdsa.PrivateKey
87 if err := k.Raw(&spk); err != nil {
88 t.Fatal(err)
89 }
90
91 mk := did.PrivKey{
92 Raw: &spk,
93 Type: did.KeyTypeP256,
94 }
95
96 if mk.Public().DID() != tv.Did {
97 t.Fatal("keys generated different DIDs")
98 }
99
100 mysig, err := mk.Sign(buf.Bytes())
101 if err != nil {
102 t.Fatal(err)
103 }
104
105 fmt.Println(base64.RawURLEncoding.DecodeString(tv.Sig))
106 fmt.Println(base64.RawURLEncoding.EncodeToString(mysig))
107 fmt.Println(tv.Sig)
108
109}