+111
-7
scripts/setup.js
+111
-7
scripts/setup.js
···
48
48
return opts
49
49
}
50
50
51
+
// === KEY GENERATION ===
52
+
53
+
async function generateP256Keypair() {
54
+
const keyPair = await webcrypto.subtle.generateKey(
55
+
{ name: 'ECDSA', namedCurve: 'P-256' },
56
+
true,
57
+
['sign', 'verify']
58
+
)
59
+
60
+
// Export private key as raw 32 bytes
61
+
const privateJwk = await webcrypto.subtle.exportKey('jwk', keyPair.privateKey)
62
+
const privateBytes = base64UrlDecode(privateJwk.d)
63
+
64
+
// Export public key as uncompressed point (65 bytes)
65
+
const publicRaw = await webcrypto.subtle.exportKey('raw', keyPair.publicKey)
66
+
const publicBytes = new Uint8Array(publicRaw)
67
+
68
+
// Compress public key to 33 bytes
69
+
const compressedPublic = compressPublicKey(publicBytes)
70
+
71
+
return {
72
+
privateKey: privateBytes,
73
+
publicKey: compressedPublic,
74
+
cryptoKey: keyPair.privateKey
75
+
}
76
+
}
77
+
78
+
function compressPublicKey(uncompressed) {
79
+
// uncompressed is 65 bytes: 0x04 + x(32) + y(32)
80
+
const x = uncompressed.slice(1, 33)
81
+
const y = uncompressed.slice(33, 65)
82
+
const prefix = (y[31] & 1) === 0 ? 0x02 : 0x03
83
+
const compressed = new Uint8Array(33)
84
+
compressed[0] = prefix
85
+
compressed.set(x, 1)
86
+
return compressed
87
+
}
88
+
89
+
function base64UrlDecode(str) {
90
+
const base64 = str.replace(/-/g, '+').replace(/_/g, '/')
91
+
const binary = atob(base64)
92
+
const bytes = new Uint8Array(binary.length)
93
+
for (let i = 0; i < binary.length; i++) {
94
+
bytes[i] = binary.charCodeAt(i)
95
+
}
96
+
return bytes
97
+
}
98
+
99
+
function bytesToHex(bytes) {
100
+
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('')
101
+
}
102
+
103
+
// === DID:KEY ENCODING ===
104
+
105
+
// Multicodec prefix for P-256 public key (0x1200)
106
+
const P256_MULTICODEC = new Uint8Array([0x80, 0x24])
107
+
108
+
function publicKeyToDidKey(compressedPublicKey) {
109
+
// did:key format: "did:key:" + multibase(base58btc) of multicodec + key
110
+
const keyWithCodec = new Uint8Array(P256_MULTICODEC.length + compressedPublicKey.length)
111
+
keyWithCodec.set(P256_MULTICODEC)
112
+
keyWithCodec.set(compressedPublicKey, P256_MULTICODEC.length)
113
+
114
+
return 'did:key:z' + base58btcEncode(keyWithCodec)
115
+
}
116
+
117
+
function base58btcEncode(bytes) {
118
+
const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
119
+
120
+
// Count leading zeros
121
+
let zeros = 0
122
+
for (const b of bytes) {
123
+
if (b === 0) zeros++
124
+
else break
125
+
}
126
+
127
+
// Convert to base58
128
+
const digits = [0]
129
+
for (const byte of bytes) {
130
+
let carry = byte
131
+
for (let i = 0; i < digits.length; i++) {
132
+
carry += digits[i] << 8
133
+
digits[i] = carry % 58
134
+
carry = (carry / 58) | 0
135
+
}
136
+
while (carry > 0) {
137
+
digits.push(carry % 58)
138
+
carry = (carry / 58) | 0
139
+
}
140
+
}
141
+
142
+
// Convert to string
143
+
let result = '1'.repeat(zeros)
144
+
for (let i = digits.length - 1; i >= 0; i--) {
145
+
result += ALPHABET[digits[i]]
146
+
}
147
+
148
+
return result
149
+
}
150
+
51
151
// === MAIN ===
52
152
53
153
async function main() {
···
57
157
console.log('====================')
58
158
console.log(`Handle: ${opts.handle}`)
59
159
console.log(`PDS: ${opts.pds}`)
60
-
console.log(`PLC: ${opts.plcUrl}`)
61
-
console.log(`Relay: ${opts.relayUrl}`)
160
+
console.log('')
161
+
162
+
// Step 1: Generate keypair
163
+
console.log('Generating P-256 keypair...')
164
+
const keyPair = await generateP256Keypair()
165
+
const didKey = publicKeyToDidKey(keyPair.publicKey)
166
+
console.log(` did:key: ${didKey}`)
167
+
console.log(` Private key: ${bytesToHex(keyPair.privateKey)}`)
62
168
console.log('')
63
169
64
-
// TODO: Implement in subsequent tasks
65
-
console.log('TODO: Generate keypair')
66
-
console.log('TODO: Register DID:PLC')
67
-
console.log('TODO: Initialize PDS')
68
-
console.log('TODO: Notify relay')
170
+
// TODO: Register DID:PLC
171
+
// TODO: Initialize PDS
172
+
// TODO: Notify relay
69
173
}
70
174
71
175
main().catch(err => {