tangled
alpha
login
or
join now
willdot.net
/
cocoon
forked from
hailey.at/cocoon
0
fork
atom
An atproto PDS written in Go
0
fork
atom
overview
issues
pulls
pipelines
cleanup plc operation stuff
hailey.at
11 months ago
b9831175
4cb0fad5
+89
-61
2 changed files
expand all
collapse all
unified
split
plc
client.go
types.go
+42
-61
plc/client.go
···
14
14
"strings"
15
15
16
16
"github.com/bluesky-social/indigo/atproto/crypto"
17
17
-
"github.com/bluesky-social/indigo/atproto/data"
18
17
"github.com/bluesky-social/indigo/util"
19
18
)
20
19
21
20
type Client struct {
22
22
-
h *http.Client
23
23
-
21
21
+
h *http.Client
24
22
service string
23
23
+
pdsHostname string
25
24
rotationKey *crypto.PrivateKeyK256
26
26
-
recoveryKey string
27
27
-
pdsHostname string
28
25
}
29
26
30
27
type ClientArgs struct {
31
28
Service string
32
29
RotationKey []byte
33
33
-
RecoveryKey string
34
30
PdsHostname string
35
31
}
36
32
···
48
44
h: util.RobustHTTPClient(),
49
45
service: args.Service,
50
46
rotationKey: rk,
51
51
-
recoveryKey: args.RecoveryKey,
52
47
pdsHostname: args.PdsHostname,
53
48
}, nil
54
49
}
55
50
56
56
-
func (c *Client) CreateDID(ctx context.Context, sigkey *crypto.PrivateKeyK256, recovery string, handle string) (string, map[string]any, error) {
51
51
+
func (c *Client) CreateDID(ctx context.Context, sigkey *crypto.PrivateKeyK256, recovery string, handle string) (string, *PlcOperation, error) {
52
52
+
pubsigkey, err := sigkey.PublicKey()
53
53
+
if err != nil {
54
54
+
return "", nil, err
55
55
+
}
56
56
+
57
57
pubrotkey, err := c.rotationKey.PublicKey()
58
58
if err != nil {
59
59
return "", nil, err
···
61
61
62
62
// todo
63
63
rotationKeys := []string{pubrotkey.DIDKey()}
64
64
-
if c.recoveryKey != "" {
65
65
-
rotationKeys = []string{c.recoveryKey, rotationKeys[0]}
66
66
-
}
67
64
if recovery != "" {
68
65
rotationKeys = func(recovery string) []string {
69
66
newRotationKeys := []string{recovery}
···
74
71
}(recovery)
75
72
}
76
73
77
77
-
op, err := c.FormatAndSignAtprotoOp(sigkey, handle, rotationKeys, nil)
74
74
+
op := PlcOperation{
75
75
+
Type: "plc_operation",
76
76
+
VerificationMethods: map[string]string{
77
77
+
"atproto": pubsigkey.DIDKey(),
78
78
+
},
79
79
+
RotationKeys: rotationKeys,
80
80
+
AlsoKnownAs: []string{
81
81
+
"at://" + handle,
82
82
+
},
83
83
+
Services: map[string]PlcOperationService{
84
84
+
"atproto_pds": {
85
85
+
Type: "AtprotoPersonalDataServer",
86
86
+
Endpoint: "https://" + c.pdsHostname,
87
87
+
},
88
88
+
},
89
89
+
Prev: nil,
90
90
+
}
91
91
+
92
92
+
signed, err := c.FormatAndSignAtprotoOp(sigkey, op)
78
93
if err != nil {
79
94
return "", nil, err
80
95
}
81
96
82
82
-
did, err := didForCreateOp(op)
97
97
+
did, err := didFromOp(signed)
83
98
if err != nil {
84
99
return "", nil, err
85
100
}
86
101
87
87
-
return did, op, nil
102
102
+
return did, &op, nil
88
103
}
89
104
90
90
-
func (c *Client) UpdateUserHandle(ctx context.Context, didstr string, nhandle string) error {
91
91
-
return nil
92
92
-
}
93
93
-
94
94
-
func (c *Client) FormatAndSignAtprotoOp(sigkey *crypto.PrivateKeyK256, handle string, rotationKeys []string, prev *string) (map[string]any, error) {
95
95
-
pubsigkey, err := sigkey.PublicKey()
105
105
+
func didFromOp(op *PlcOperation) (string, error) {
106
106
+
b, err := op.MarshalCBOR()
96
107
if err != nil {
97
97
-
return nil, err
108
108
+
return "", err
98
109
}
99
99
-
100
100
-
op := map[string]any{
101
101
-
"type": "plc_operation",
102
102
-
"verificationMethods": map[string]string{
103
103
-
"atproto": pubsigkey.DIDKey(),
104
104
-
},
105
105
-
"rotationKeys": rotationKeys,
106
106
-
"alsoKnownAs": []string{"at://" + handle},
107
107
-
"services": map[string]any{
108
108
-
"atproto_pds": map[string]string{
109
109
-
"type": "AtprotoPersonalDataServer",
110
110
-
"endpoint": "https://" + c.pdsHostname,
111
111
-
},
112
112
-
},
113
113
-
"prev": prev,
114
114
-
}
110
110
+
s := sha256.Sum256(b)
111
111
+
b32 := strings.ToLower(base32.StdEncoding.EncodeToString(s[:]))
112
112
+
return "did:plc:" + b32[0:24], nil
113
113
+
}
115
114
116
116
-
b, err := data.MarshalCBOR(op)
115
115
+
func (c *Client) FormatAndSignAtprotoOp(sigkey *crypto.PrivateKeyK256, op PlcOperation) (*PlcOperation, error) {
116
116
+
b, err := op.MarshalCBOR()
117
117
if err != nil {
118
118
return nil, err
119
119
}
···
123
123
return nil, err
124
124
}
125
125
126
126
-
op["sig"] = base64.RawURLEncoding.EncodeToString(sig)
126
126
+
op.Sig = base64.RawURLEncoding.EncodeToString(sig)
127
127
128
128
-
return op, nil
128
128
+
return &op, nil
129
129
}
130
130
131
131
-
func didForCreateOp(op map[string]any) (string, error) {
132
132
-
b, err := data.MarshalCBOR(op)
133
133
-
if err != nil {
134
134
-
return "", err
135
135
-
}
136
136
-
137
137
-
h := sha256.New()
138
138
-
h.Write(b)
139
139
-
bs := h.Sum(nil)
140
140
-
141
141
-
b32 := strings.ToLower(base32.StdEncoding.EncodeToString(bs))
142
142
-
143
143
-
return "did:plc:" + b32[0:24], nil
144
144
-
}
145
145
-
146
146
-
func (c *Client) SendOperation(ctx context.Context, did string, op any) error {
131
131
+
func (c *Client) SendOperation(ctx context.Context, did string, op *PlcOperation) error {
147
132
b, err := json.Marshal(op)
148
133
if err != nil {
149
134
return err
···
162
147
}
163
148
defer resp.Body.Close()
164
149
165
165
-
fmt.Println(resp.StatusCode)
166
166
-
167
150
b, err = io.ReadAll(resp.Body)
168
151
if err != nil {
169
169
-
return err
152
152
+
return fmt.Errorf("error sending operation. status code: %d, response: %s", resp.StatusCode, string(b))
170
153
}
171
171
-
172
172
-
fmt.Println(string(b))
173
154
174
155
return nil
175
156
}
+47
plc/types.go
···
1
1
+
package plc
2
2
+
3
3
+
import (
4
4
+
"encoding/json"
5
5
+
6
6
+
"github.com/bluesky-social/indigo/atproto/data"
7
7
+
cbg "github.com/whyrusleeping/cbor-gen"
8
8
+
)
9
9
+
10
10
+
type PlcOperation struct {
11
11
+
Type string `json:"type"`
12
12
+
VerificationMethods map[string]string `json:"verificationMethods"`
13
13
+
RotationKeys []string `json:"rotationKeys"`
14
14
+
AlsoKnownAs []string `json:"alsoKnownAs"`
15
15
+
Services map[string]PlcOperationService `json:"services"`
16
16
+
Prev *string `json:"prev"`
17
17
+
Sig string `json:"sig,omitempty"`
18
18
+
}
19
19
+
20
20
+
type PlcOperationService struct {
21
21
+
Type string `json:"type"`
22
22
+
Endpoint string `json:"endpoint"`
23
23
+
}
24
24
+
25
25
+
// This is kinda gross. We could just use cborgen i suppose?
26
26
+
func (po *PlcOperation) MarshalCBOR() ([]byte, error) {
27
27
+
if po == nil {
28
28
+
return cbg.CborNull, nil
29
29
+
}
30
30
+
31
31
+
b, err := json.Marshal(po)
32
32
+
if err != nil {
33
33
+
return nil, err
34
34
+
}
35
35
+
36
36
+
var m map[string]any
37
37
+
if err := json.Unmarshal(b, &m); err != nil {
38
38
+
return nil, err
39
39
+
}
40
40
+
41
41
+
b, err = data.MarshalCBOR(m)
42
42
+
if err != nil {
43
43
+
return nil, err
44
44
+
}
45
45
+
46
46
+
return b, nil
47
47
+
}