@orangecheck/sdk 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -68
- package/dist/index.d.ts +1 -68
- package/dist/index.js +5 -251
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9 -249
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -33,73 +33,6 @@ interface CheckResult {
|
|
|
33
33
|
}
|
|
34
34
|
declare function check(params: CheckParams): Promise<CheckResult>;
|
|
35
35
|
|
|
36
|
-
declare const BINDING_KIND = 30079;
|
|
37
|
-
interface BindingInput {
|
|
38
|
-
principal: string;
|
|
39
|
-
btc: string;
|
|
40
|
-
nostr: string;
|
|
41
|
-
nonce: string;
|
|
42
|
-
issued_at: string;
|
|
43
|
-
extensions?: Record<string, string>;
|
|
44
|
-
}
|
|
45
|
-
interface BindingNostrEvent {
|
|
46
|
-
id: string;
|
|
47
|
-
pubkey: string;
|
|
48
|
-
kind: number;
|
|
49
|
-
created_at: number;
|
|
50
|
-
tags: string[][];
|
|
51
|
-
content: string;
|
|
52
|
-
sig: string;
|
|
53
|
-
}
|
|
54
|
-
interface BindingEnvelope {
|
|
55
|
-
binding_id?: string;
|
|
56
|
-
v?: number;
|
|
57
|
-
principal?: string;
|
|
58
|
-
btc?: string;
|
|
59
|
-
nostr?: string;
|
|
60
|
-
message: string;
|
|
61
|
-
message_b64url?: string;
|
|
62
|
-
btc_signature?: string;
|
|
63
|
-
btc_scheme?: 'bip322' | 'legacy';
|
|
64
|
-
nostr_event?: BindingNostrEvent;
|
|
65
|
-
}
|
|
66
|
-
type BindingStatus = 'binding_ok' | 'malformed' | 'bad_header' | 'bad_ack' | 'bad_principal' | 'ext_unsorted' | 'id_mismatch' | 'field_mismatch' | 'expired' | 'network' | 'bad_scheme' | 'btc_sig_invalid' | 'nostr_id_invalid' | 'nostr_sig_invalid' | 'nostr_key_mismatch' | 'message_mismatch';
|
|
67
|
-
type BindingVerifyResult = {
|
|
68
|
-
valid: true;
|
|
69
|
-
status: 'binding_ok';
|
|
70
|
-
binding_id: string;
|
|
71
|
-
principal: string;
|
|
72
|
-
btc: string;
|
|
73
|
-
nostr: string;
|
|
74
|
-
} | {
|
|
75
|
-
valid: false;
|
|
76
|
-
status: Exclude<BindingStatus, 'binding_ok'>;
|
|
77
|
-
};
|
|
78
|
-
declare function buildBindingMessage(input: BindingInput): string;
|
|
79
|
-
declare function bindingId(message: string): string;
|
|
80
|
-
declare function verifyBinding(envelope: BindingEnvelope): BindingVerifyResult;
|
|
81
|
-
declare function xOnlyHexToNpub(hex: string): string;
|
|
82
|
-
interface BindingEventTemplate {
|
|
83
|
-
kind: typeof BINDING_KIND;
|
|
84
|
-
pubkey: string;
|
|
85
|
-
created_at: number;
|
|
86
|
-
tags: string[][];
|
|
87
|
-
content: string;
|
|
88
|
-
}
|
|
89
|
-
declare function buildBindingEventTemplate(params: {
|
|
90
|
-
message: string;
|
|
91
|
-
btcSignature: string;
|
|
92
|
-
nostrPubkeyHex: string;
|
|
93
|
-
btc: string;
|
|
94
|
-
createdAt?: number;
|
|
95
|
-
}): BindingEventTemplate;
|
|
96
|
-
declare function assembleBindingEnvelope(params: {
|
|
97
|
-
message: string;
|
|
98
|
-
btcSignature: string;
|
|
99
|
-
btcScheme?: 'bip322' | 'legacy';
|
|
100
|
-
nostrEvent: BindingNostrEvent;
|
|
101
|
-
}): BindingEnvelope;
|
|
102
|
-
|
|
103
36
|
declare function isNip07Available(): boolean;
|
|
104
37
|
declare function getNostrPublicKey(): Promise<string | null>;
|
|
105
38
|
declare function signNostrEvent(event: Omit<NostrEvent, 'id' | 'sig'>): Promise<NostrEvent | null>;
|
|
@@ -117,4 +50,4 @@ interface StatusMeta {
|
|
|
117
50
|
}
|
|
118
51
|
declare const STATUS_META: Record<StatusCode, StatusMeta>;
|
|
119
52
|
|
|
120
|
-
export { type
|
|
53
|
+
export { type CheckParams, type CheckResult, IdentityBinding, Network, NostrEvent, STATUS_META, type Severity, StatusCode, type StatusMeta, VerifyOptions, check, getNip07Info, getNostrPublicKey, isNip07Available, signNostrEvent };
|
package/dist/index.d.ts
CHANGED
|
@@ -33,73 +33,6 @@ interface CheckResult {
|
|
|
33
33
|
}
|
|
34
34
|
declare function check(params: CheckParams): Promise<CheckResult>;
|
|
35
35
|
|
|
36
|
-
declare const BINDING_KIND = 30079;
|
|
37
|
-
interface BindingInput {
|
|
38
|
-
principal: string;
|
|
39
|
-
btc: string;
|
|
40
|
-
nostr: string;
|
|
41
|
-
nonce: string;
|
|
42
|
-
issued_at: string;
|
|
43
|
-
extensions?: Record<string, string>;
|
|
44
|
-
}
|
|
45
|
-
interface BindingNostrEvent {
|
|
46
|
-
id: string;
|
|
47
|
-
pubkey: string;
|
|
48
|
-
kind: number;
|
|
49
|
-
created_at: number;
|
|
50
|
-
tags: string[][];
|
|
51
|
-
content: string;
|
|
52
|
-
sig: string;
|
|
53
|
-
}
|
|
54
|
-
interface BindingEnvelope {
|
|
55
|
-
binding_id?: string;
|
|
56
|
-
v?: number;
|
|
57
|
-
principal?: string;
|
|
58
|
-
btc?: string;
|
|
59
|
-
nostr?: string;
|
|
60
|
-
message: string;
|
|
61
|
-
message_b64url?: string;
|
|
62
|
-
btc_signature?: string;
|
|
63
|
-
btc_scheme?: 'bip322' | 'legacy';
|
|
64
|
-
nostr_event?: BindingNostrEvent;
|
|
65
|
-
}
|
|
66
|
-
type BindingStatus = 'binding_ok' | 'malformed' | 'bad_header' | 'bad_ack' | 'bad_principal' | 'ext_unsorted' | 'id_mismatch' | 'field_mismatch' | 'expired' | 'network' | 'bad_scheme' | 'btc_sig_invalid' | 'nostr_id_invalid' | 'nostr_sig_invalid' | 'nostr_key_mismatch' | 'message_mismatch';
|
|
67
|
-
type BindingVerifyResult = {
|
|
68
|
-
valid: true;
|
|
69
|
-
status: 'binding_ok';
|
|
70
|
-
binding_id: string;
|
|
71
|
-
principal: string;
|
|
72
|
-
btc: string;
|
|
73
|
-
nostr: string;
|
|
74
|
-
} | {
|
|
75
|
-
valid: false;
|
|
76
|
-
status: Exclude<BindingStatus, 'binding_ok'>;
|
|
77
|
-
};
|
|
78
|
-
declare function buildBindingMessage(input: BindingInput): string;
|
|
79
|
-
declare function bindingId(message: string): string;
|
|
80
|
-
declare function verifyBinding(envelope: BindingEnvelope): BindingVerifyResult;
|
|
81
|
-
declare function xOnlyHexToNpub(hex: string): string;
|
|
82
|
-
interface BindingEventTemplate {
|
|
83
|
-
kind: typeof BINDING_KIND;
|
|
84
|
-
pubkey: string;
|
|
85
|
-
created_at: number;
|
|
86
|
-
tags: string[][];
|
|
87
|
-
content: string;
|
|
88
|
-
}
|
|
89
|
-
declare function buildBindingEventTemplate(params: {
|
|
90
|
-
message: string;
|
|
91
|
-
btcSignature: string;
|
|
92
|
-
nostrPubkeyHex: string;
|
|
93
|
-
btc: string;
|
|
94
|
-
createdAt?: number;
|
|
95
|
-
}): BindingEventTemplate;
|
|
96
|
-
declare function assembleBindingEnvelope(params: {
|
|
97
|
-
message: string;
|
|
98
|
-
btcSignature: string;
|
|
99
|
-
btcScheme?: 'bip322' | 'legacy';
|
|
100
|
-
nostrEvent: BindingNostrEvent;
|
|
101
|
-
}): BindingEnvelope;
|
|
102
|
-
|
|
103
36
|
declare function isNip07Available(): boolean;
|
|
104
37
|
declare function getNostrPublicKey(): Promise<string | null>;
|
|
105
38
|
declare function signNostrEvent(event: Omit<NostrEvent, 'id' | 'sig'>): Promise<NostrEvent | null>;
|
|
@@ -117,4 +50,4 @@ interface StatusMeta {
|
|
|
117
50
|
}
|
|
118
51
|
declare const STATUS_META: Record<StatusCode, StatusMeta>;
|
|
119
52
|
|
|
120
|
-
export { type
|
|
53
|
+
export { type CheckParams, type CheckResult, IdentityBinding, Network, NostrEvent, STATUS_META, type Severity, StatusCode, type StatusMeta, VerifyOptions, check, getNip07Info, getNostrPublicKey, isNip07Available, signNostrEvent };
|
package/dist/index.js
CHANGED
|
@@ -1177,246 +1177,6 @@ async function check(params) {
|
|
|
1177
1177
|
...reasons.length ? { reasons } : {}
|
|
1178
1178
|
};
|
|
1179
1179
|
}
|
|
1180
|
-
var HEADER = "orangecheck-binding";
|
|
1181
|
-
var ACK = "I attest the keys named in this message are one principal.";
|
|
1182
|
-
var BINDING_KIND = 30079;
|
|
1183
|
-
function toHex(bytes) {
|
|
1184
|
-
let out = "";
|
|
1185
|
-
for (const b of bytes) out += b.toString(16).padStart(2, "0");
|
|
1186
|
-
return out;
|
|
1187
|
-
}
|
|
1188
|
-
function fromHex(hex) {
|
|
1189
|
-
const clean = hex.toLowerCase();
|
|
1190
|
-
if (clean.length % 2 !== 0 || /[^0-9a-f]/.test(clean)) {
|
|
1191
|
-
throw new Error("invalid hex");
|
|
1192
|
-
}
|
|
1193
|
-
const out = new Uint8Array(clean.length / 2);
|
|
1194
|
-
for (let i = 0; i < out.length; i++) out[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
1195
|
-
return out;
|
|
1196
|
-
}
|
|
1197
|
-
function assertPrintableAscii(field, value) {
|
|
1198
|
-
for (let i = 0; i < value.length; i++) {
|
|
1199
|
-
const c = value.charCodeAt(i);
|
|
1200
|
-
if (c < 32 || c > 126) {
|
|
1201
|
-
throw new Error(
|
|
1202
|
-
`binding ${field} contains an unsafe character (0x${c.toString(16)}) \u2014 line-smuggling defense (SPEC-BINDING \xA73.5)`
|
|
1203
|
-
);
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
function buildBindingMessage(input) {
|
|
1208
|
-
assertPrintableAscii("principal", input.principal);
|
|
1209
|
-
assertPrintableAscii("btc", input.btc);
|
|
1210
|
-
assertPrintableAscii("nostr", input.nostr);
|
|
1211
|
-
assertPrintableAscii("nonce", input.nonce);
|
|
1212
|
-
assertPrintableAscii("issued_at", input.issued_at);
|
|
1213
|
-
const core = [
|
|
1214
|
-
HEADER,
|
|
1215
|
-
"v: 1",
|
|
1216
|
-
`principal: ${input.principal}`,
|
|
1217
|
-
`btc: ${input.btc}`,
|
|
1218
|
-
`nostr: ${input.nostr}`,
|
|
1219
|
-
`nonce: ${input.nonce}`,
|
|
1220
|
-
`issued_at: ${input.issued_at}`,
|
|
1221
|
-
`ack: ${ACK}`
|
|
1222
|
-
];
|
|
1223
|
-
const ext = [];
|
|
1224
|
-
if (input.extensions) {
|
|
1225
|
-
for (const key of Object.keys(input.extensions).sort()) {
|
|
1226
|
-
const value = input.extensions[key];
|
|
1227
|
-
if (value == null) continue;
|
|
1228
|
-
if (!/^[a-z]+$/.test(key)) {
|
|
1229
|
-
throw new Error(`binding extension key "${key}" must be lowercase ASCII`);
|
|
1230
|
-
}
|
|
1231
|
-
assertPrintableAscii(`extension ${key}`, value);
|
|
1232
|
-
ext.push(`${key}: ${value}`);
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
return [...core, ...ext].join("\n") + "\n";
|
|
1236
|
-
}
|
|
1237
|
-
function bindingId(message) {
|
|
1238
|
-
return toHex(sha2_js.sha256(new TextEncoder().encode(message)));
|
|
1239
|
-
}
|
|
1240
|
-
function linePrefix(line, prefix) {
|
|
1241
|
-
if (typeof line !== "string" || !line.startsWith(prefix)) return null;
|
|
1242
|
-
return line.slice(prefix.length);
|
|
1243
|
-
}
|
|
1244
|
-
function nostrEventId(ev) {
|
|
1245
|
-
const serialized = JSON.stringify([
|
|
1246
|
-
0,
|
|
1247
|
-
ev.pubkey,
|
|
1248
|
-
ev.created_at,
|
|
1249
|
-
ev.kind,
|
|
1250
|
-
ev.tags,
|
|
1251
|
-
ev.content
|
|
1252
|
-
]);
|
|
1253
|
-
return toHex(sha2_js.sha256(new TextEncoder().encode(serialized)));
|
|
1254
|
-
}
|
|
1255
|
-
function npubToXOnlyHex(npub) {
|
|
1256
|
-
const decoded = base.bech32.decode(npub, 90);
|
|
1257
|
-
if (decoded.prefix !== "npub") throw new Error("not an npub");
|
|
1258
|
-
const bytes = Uint8Array.from(base.bech32.fromWords(decoded.words));
|
|
1259
|
-
if (bytes.length !== 32) throw new Error("npub payload is not 32 bytes");
|
|
1260
|
-
return toHex(bytes);
|
|
1261
|
-
}
|
|
1262
|
-
function verifyBinding(envelope) {
|
|
1263
|
-
const fail = (status) => ({
|
|
1264
|
-
valid: false,
|
|
1265
|
-
status
|
|
1266
|
-
});
|
|
1267
|
-
try {
|
|
1268
|
-
const msg = envelope.message;
|
|
1269
|
-
if (typeof msg !== "string" || msg.length === 0) return fail("malformed");
|
|
1270
|
-
const lines = msg.split("\n");
|
|
1271
|
-
if ((lines[0] ?? "") !== HEADER) return fail("bad_header");
|
|
1272
|
-
if (lines.length < 9 || lines[lines.length - 1] !== "") return fail("malformed");
|
|
1273
|
-
const body = lines.slice(0, -1);
|
|
1274
|
-
if (body.length < 8) return fail("malformed");
|
|
1275
|
-
if (body[1] !== "v: 1") return fail("malformed");
|
|
1276
|
-
if (body[7] !== `ack: ${ACK}`) return fail("bad_ack");
|
|
1277
|
-
const principal = linePrefix(body[2], "principal: ");
|
|
1278
|
-
const btc = linePrefix(body[3], "btc: ");
|
|
1279
|
-
const nostr = linePrefix(body[4], "nostr: ");
|
|
1280
|
-
const nonce = linePrefix(body[5], "nonce: ");
|
|
1281
|
-
const issuedAt = linePrefix(body[6], "issued_at: ");
|
|
1282
|
-
if (principal == null || btc == null || nostr == null || nonce == null || issuedAt == null) {
|
|
1283
|
-
return fail("malformed");
|
|
1284
|
-
}
|
|
1285
|
-
for (const value of [principal, btc, nostr, nonce, issuedAt]) {
|
|
1286
|
-
for (let i = 0; i < value.length; i++) {
|
|
1287
|
-
const c = value.charCodeAt(i);
|
|
1288
|
-
if (c < 32 || c > 126) return fail("malformed");
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
if (!/^did:oc:[0-9a-f]{32}$/.test(principal)) return fail("bad_principal");
|
|
1292
|
-
if (!/^[0-9a-f]{32}$/.test(nonce)) return fail("malformed");
|
|
1293
|
-
const ext = {};
|
|
1294
|
-
let prevKey = "";
|
|
1295
|
-
for (const line of body.slice(8)) {
|
|
1296
|
-
const idx = line.indexOf(": ");
|
|
1297
|
-
if (idx <= 0) return fail("malformed");
|
|
1298
|
-
const key = line.slice(0, idx);
|
|
1299
|
-
const value = line.slice(idx + 2);
|
|
1300
|
-
if (!/^[a-z]+$/.test(key)) return fail("malformed");
|
|
1301
|
-
if (key <= prevKey) return fail("ext_unsorted");
|
|
1302
|
-
prevKey = key;
|
|
1303
|
-
ext[key] = value;
|
|
1304
|
-
}
|
|
1305
|
-
const bid = bindingId(msg);
|
|
1306
|
-
if (envelope.binding_id && envelope.binding_id.toLowerCase() !== bid) {
|
|
1307
|
-
return fail("id_mismatch");
|
|
1308
|
-
}
|
|
1309
|
-
if (envelope.btc && envelope.btc !== btc) return fail("field_mismatch");
|
|
1310
|
-
if (envelope.nostr && envelope.nostr !== nostr) return fail("field_mismatch");
|
|
1311
|
-
if (envelope.principal && envelope.principal !== principal) return fail("field_mismatch");
|
|
1312
|
-
if (ext.expires) {
|
|
1313
|
-
const t = Date.parse(ext.expires);
|
|
1314
|
-
if (!Number.isNaN(t) && Date.now() > t) return fail("expired");
|
|
1315
|
-
}
|
|
1316
|
-
if (typeof envelope.btc_signature !== "string" || !envelope.btc_signature) {
|
|
1317
|
-
return fail("btc_sig_invalid");
|
|
1318
|
-
}
|
|
1319
|
-
const scheme = envelope.btc_scheme ?? "bip322";
|
|
1320
|
-
let btcOk = false;
|
|
1321
|
-
try {
|
|
1322
|
-
if (scheme === "bip322") {
|
|
1323
|
-
btcOk = bip322Js.Verifier.verifySignature(btc, msg, envelope.btc_signature);
|
|
1324
|
-
} else if (scheme === "legacy") {
|
|
1325
|
-
btcOk = bitcoinMessage__namespace.verify(msg, btc, envelope.btc_signature);
|
|
1326
|
-
} else {
|
|
1327
|
-
return fail("bad_scheme");
|
|
1328
|
-
}
|
|
1329
|
-
} catch {
|
|
1330
|
-
btcOk = false;
|
|
1331
|
-
}
|
|
1332
|
-
if (!btcOk) return fail("btc_sig_invalid");
|
|
1333
|
-
const ev = envelope.nostr_event;
|
|
1334
|
-
if (!ev || ev.kind !== BINDING_KIND || typeof ev.id !== "string") return fail("malformed");
|
|
1335
|
-
if (nostrEventId(ev) !== ev.id.toLowerCase()) return fail("nostr_id_invalid");
|
|
1336
|
-
let nostrSigOk = false;
|
|
1337
|
-
try {
|
|
1338
|
-
nostrSigOk = secp256k1_js.schnorr.verify(fromHex(ev.sig), fromHex(ev.id), fromHex(ev.pubkey));
|
|
1339
|
-
} catch {
|
|
1340
|
-
nostrSigOk = false;
|
|
1341
|
-
}
|
|
1342
|
-
if (!nostrSigOk) return fail("nostr_sig_invalid");
|
|
1343
|
-
let nostrXOnly;
|
|
1344
|
-
try {
|
|
1345
|
-
nostrXOnly = npubToXOnlyHex(nostr);
|
|
1346
|
-
} catch {
|
|
1347
|
-
return fail("nostr_key_mismatch");
|
|
1348
|
-
}
|
|
1349
|
-
if (nostrXOnly !== ev.pubkey.toLowerCase()) return fail("nostr_key_mismatch");
|
|
1350
|
-
let content;
|
|
1351
|
-
try {
|
|
1352
|
-
content = JSON.parse(ev.content);
|
|
1353
|
-
} catch {
|
|
1354
|
-
return fail("message_mismatch");
|
|
1355
|
-
}
|
|
1356
|
-
if (content.message !== msg) return fail("message_mismatch");
|
|
1357
|
-
if (content.btc_signature !== envelope.btc_signature) return fail("message_mismatch");
|
|
1358
|
-
return { valid: true, status: "binding_ok", binding_id: bid, principal, btc, nostr };
|
|
1359
|
-
} catch {
|
|
1360
|
-
return fail("malformed");
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
function xOnlyHexToNpub(hex) {
|
|
1364
|
-
const bytes = fromHex(hex);
|
|
1365
|
-
if (bytes.length !== 32) throw new Error("x-only Nostr key must be 32 bytes");
|
|
1366
|
-
return base.bech32.encode("npub", base.bech32.toWords(bytes), 90);
|
|
1367
|
-
}
|
|
1368
|
-
function buildBindingEventTemplate(params) {
|
|
1369
|
-
const id = bindingId(params.message);
|
|
1370
|
-
return {
|
|
1371
|
-
kind: BINDING_KIND,
|
|
1372
|
-
pubkey: params.nostrPubkeyHex.toLowerCase(),
|
|
1373
|
-
created_at: params.createdAt ?? Math.floor(Date.now() / 1e3),
|
|
1374
|
-
tags: [
|
|
1375
|
-
["d", `oc-attest-binding:${id}`],
|
|
1376
|
-
["btc", params.btc],
|
|
1377
|
-
["oc", "binding-attestation"],
|
|
1378
|
-
["v", "1"]
|
|
1379
|
-
],
|
|
1380
|
-
content: JSON.stringify({ message: params.message, btc_signature: params.btcSignature })
|
|
1381
|
-
};
|
|
1382
|
-
}
|
|
1383
|
-
function parseBindingFields(message) {
|
|
1384
|
-
const body = message.split("\n");
|
|
1385
|
-
const at = (i, prefix) => {
|
|
1386
|
-
const line = body[i];
|
|
1387
|
-
if (typeof line !== "string" || !line.startsWith(prefix)) {
|
|
1388
|
-
throw new Error(`binding message line ${i + 1} is malformed`);
|
|
1389
|
-
}
|
|
1390
|
-
return line.slice(prefix.length);
|
|
1391
|
-
};
|
|
1392
|
-
return {
|
|
1393
|
-
principal: at(2, "principal: "),
|
|
1394
|
-
btc: at(3, "btc: "),
|
|
1395
|
-
nostr: at(4, "nostr: ")
|
|
1396
|
-
};
|
|
1397
|
-
}
|
|
1398
|
-
function toBase64Url(s) {
|
|
1399
|
-
const bytes = new TextEncoder().encode(s);
|
|
1400
|
-
let bin = "";
|
|
1401
|
-
for (const b of bytes) bin += String.fromCharCode(b);
|
|
1402
|
-
const b64 = typeof btoa !== "undefined" ? btoa(bin) : Buffer.from(bytes).toString("base64");
|
|
1403
|
-
return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1404
|
-
}
|
|
1405
|
-
function assembleBindingEnvelope(params) {
|
|
1406
|
-
const { principal, btc, nostr } = parseBindingFields(params.message);
|
|
1407
|
-
return {
|
|
1408
|
-
binding_id: bindingId(params.message),
|
|
1409
|
-
v: 1,
|
|
1410
|
-
principal,
|
|
1411
|
-
btc,
|
|
1412
|
-
nostr,
|
|
1413
|
-
message: params.message,
|
|
1414
|
-
message_b64url: toBase64Url(params.message),
|
|
1415
|
-
btc_signature: params.btcSignature,
|
|
1416
|
-
btc_scheme: params.btcScheme ?? "bip322",
|
|
1417
|
-
nostr_event: params.nostrEvent
|
|
1418
|
-
};
|
|
1419
|
-
}
|
|
1420
1180
|
var AUTH_HEADER = "orangecheck-auth";
|
|
1421
1181
|
var AUTH_ACK = "I authorize this session under the OrangeCheck auth challenge.";
|
|
1422
1182
|
function randomNonce() {
|
|
@@ -1872,12 +1632,12 @@ function getGistCreationUrl() {
|
|
|
1872
1632
|
}
|
|
1873
1633
|
var log7 = createLogger("identity-verification/nostr");
|
|
1874
1634
|
var HEX_64_RE = /^[0-9a-f]{64}$/;
|
|
1875
|
-
function
|
|
1635
|
+
function toHex(bytes) {
|
|
1876
1636
|
let out = "";
|
|
1877
1637
|
for (const b of bytes) out += b.toString(16).padStart(2, "0");
|
|
1878
1638
|
return out;
|
|
1879
1639
|
}
|
|
1880
|
-
function
|
|
1640
|
+
function fromHex(hex) {
|
|
1881
1641
|
if (hex.length % 2 !== 0) throw new Error("odd-length hex");
|
|
1882
1642
|
const out = new Uint8Array(hex.length / 2);
|
|
1883
1643
|
for (let i = 0; i < out.length; i++) {
|
|
@@ -1901,7 +1661,7 @@ function npubToHex(npub) {
|
|
|
1901
1661
|
if (bytes.length !== 32) {
|
|
1902
1662
|
throw new Error(`invalid npub payload length: ${bytes.length}`);
|
|
1903
1663
|
}
|
|
1904
|
-
return
|
|
1664
|
+
return toHex(Uint8Array.from(bytes));
|
|
1905
1665
|
}
|
|
1906
1666
|
async function queryNostrEvents(options) {
|
|
1907
1667
|
const { authors, kinds, search, relays = DEFAULT_RELAYS, limit = 100 } = options;
|
|
@@ -1984,7 +1744,7 @@ async function verifyNostrEventSignature(event) {
|
|
|
1984
1744
|
event.tags ?? [],
|
|
1985
1745
|
event.content ?? ""
|
|
1986
1746
|
]);
|
|
1987
|
-
const computedId =
|
|
1747
|
+
const computedId = toHex(sha2_js.sha256(new TextEncoder().encode(preimage)));
|
|
1988
1748
|
if (computedId !== event.id.toLowerCase()) {
|
|
1989
1749
|
log7.warn(
|
|
1990
1750
|
{ eventId: event.id, computedId },
|
|
@@ -1992,7 +1752,7 @@ async function verifyNostrEventSignature(event) {
|
|
|
1992
1752
|
);
|
|
1993
1753
|
return false;
|
|
1994
1754
|
}
|
|
1995
|
-
return secp256k1_js.schnorr.verify(
|
|
1755
|
+
return secp256k1_js.schnorr.verify(fromHex(event.sig), fromHex(event.id), fromHex(event.pubkey));
|
|
1996
1756
|
} catch (err) {
|
|
1997
1757
|
log7.warn({ err }, "schnorr verify threw");
|
|
1998
1758
|
return false;
|
|
@@ -2354,10 +2114,6 @@ var STATUS_META = {
|
|
|
2354
2114
|
|
|
2355
2115
|
exports.DEFAULT_RELAYS = DEFAULT_RELAYS;
|
|
2356
2116
|
exports.STATUS_META = STATUS_META;
|
|
2357
|
-
exports.assembleBindingEnvelope = assembleBindingEnvelope;
|
|
2358
|
-
exports.bindingId = bindingId;
|
|
2359
|
-
exports.buildBindingEventTemplate = buildBindingEventTemplate;
|
|
2360
|
-
exports.buildBindingMessage = buildBindingMessage;
|
|
2361
2117
|
exports.buildCanonicalMessage = buildCanonicalMessage;
|
|
2362
2118
|
exports.check = check;
|
|
2363
2119
|
exports.computeAllScores = computeAllScores;
|
|
@@ -2409,13 +2165,11 @@ exports.supportsAutomaticVerification = supportsAutomaticVerification;
|
|
|
2409
2165
|
exports.verify = verify2;
|
|
2410
2166
|
exports.verifyAllIdentities = verifyAllIdentities;
|
|
2411
2167
|
exports.verifyAttestationById = verifyAttestationById;
|
|
2412
|
-
exports.verifyBinding = verifyBinding;
|
|
2413
2168
|
exports.verifyChallenge = verifyChallenge;
|
|
2414
2169
|
exports.verifyDnsIdentity = verifyDnsIdentity;
|
|
2415
2170
|
exports.verifyGitHubIdentity = verifyGitHubIdentity;
|
|
2416
2171
|
exports.verifyIdentity = verifyIdentity;
|
|
2417
2172
|
exports.verifyNostrIdentity = verifyNostrIdentity;
|
|
2418
2173
|
exports.verifyTwitterIdentity = verifyTwitterIdentity;
|
|
2419
|
-
exports.xOnlyHexToNpub = xOnlyHexToNpub;
|
|
2420
2174
|
//# sourceMappingURL=index.js.map
|
|
2421
2175
|
//# sourceMappingURL=index.js.map
|