@orangecheck/sdk 1.9.0 → 1.11.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/challenge.js +10 -35
- package/dist/challenge.js.map +1 -1
- package/dist/challenge.mjs +10 -15
- package/dist/challenge.mjs.map +1 -1
- package/dist/identity.d.mts +5 -2
- package/dist/identity.d.ts +5 -2
- package/dist/identity.js +13 -5
- package/dist/identity.js.map +1 -1
- package/dist/identity.mjs +13 -5
- package/dist/identity.mjs.map +1 -1
- package/dist/index.js +88 -113
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +88 -93
- package/dist/index.mjs.map +1 -1
- package/dist/verify.js +65 -94
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +65 -74
- package/dist/verify.mjs.map +1 -1
- package/package.json +2 -4
package/dist/index.js
CHANGED
|
@@ -2,31 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
var base = require('@scure/base');
|
|
4
4
|
var buffer = require('buffer');
|
|
5
|
-
var
|
|
6
|
-
var bitcoinMessage = require('bitcoinjs-message');
|
|
5
|
+
var bip322 = require('@orangecheck/bip322');
|
|
7
6
|
var secp256k1_js = require('@noble/curves/secp256k1.js');
|
|
8
7
|
var sha2_js = require('@noble/hashes/sha2.js');
|
|
9
8
|
|
|
10
|
-
function _interopNamespace(e) {
|
|
11
|
-
if (e && e.__esModule) return e;
|
|
12
|
-
var n = Object.create(null);
|
|
13
|
-
if (e) {
|
|
14
|
-
Object.keys(e).forEach(function (k) {
|
|
15
|
-
if (k !== 'default') {
|
|
16
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
-
enumerable: true,
|
|
19
|
-
get: function () { return e[k]; }
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
n.default = e;
|
|
25
|
-
return Object.freeze(n);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
var bitcoinMessage__namespace = /*#__PURE__*/_interopNamespace(bitcoinMessage);
|
|
29
|
-
|
|
30
9
|
// src/canonical.ts
|
|
31
10
|
function toLowerHex(bytes) {
|
|
32
11
|
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
@@ -883,87 +862,79 @@ async function verifySignature({
|
|
|
883
862
|
sig,
|
|
884
863
|
scheme
|
|
885
864
|
}) {
|
|
886
|
-
|
|
887
|
-
|
|
865
|
+
const detectedScheme = scheme || detectSignatureScheme(addr, sig);
|
|
866
|
+
log4.debug(
|
|
867
|
+
{ addr, msgLength: msg.length, sigLength: sig.length, scheme: detectedScheme },
|
|
868
|
+
"Verifying signature"
|
|
869
|
+
);
|
|
870
|
+
if (detectedScheme === "bip322") {
|
|
871
|
+
const sigBase64 = toBase64Maybe(sig);
|
|
888
872
|
log4.debug(
|
|
889
|
-
{
|
|
890
|
-
"
|
|
873
|
+
{ sigBase64: sigBase64.substring(0, 50) + "..." },
|
|
874
|
+
"Signature converted to base64"
|
|
891
875
|
);
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
if (isSegWit && sigBase64.length === 88) {
|
|
912
|
-
log4.warn(
|
|
913
|
-
{ addr, wallet: "possibly Electrum", sigLength: sigBase64.length },
|
|
914
|
-
"BIP-322 verification failed - likely Electrum wallet (does not support BIP-322 for SegWit)"
|
|
915
|
-
);
|
|
916
|
-
} else {
|
|
917
|
-
log4.error(
|
|
918
|
-
{
|
|
919
|
-
addr,
|
|
920
|
-
sigLength: sigBase64.length,
|
|
921
|
-
msgLength: msg.length,
|
|
922
|
-
msgPreview: msg.substring(0, 200)
|
|
923
|
-
},
|
|
924
|
-
"BIP-322 verification failed - signature does not match message"
|
|
925
|
-
);
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
return ok ? "sig_ok_bip322" : "sig_invalid";
|
|
929
|
-
}
|
|
930
|
-
if (detectedScheme === "legacy") {
|
|
931
|
-
const sigBase64 = toBase64Maybe(sig);
|
|
932
|
-
if (!addr.startsWith("1") && !addr.startsWith("m") && !addr.startsWith("n")) {
|
|
933
|
-
log4.warn({ addr }, "Legacy signature attempted on non-P2PKH address");
|
|
934
|
-
return "sig_unsupported_script";
|
|
935
|
-
}
|
|
936
|
-
log4.debug(
|
|
937
|
-
{
|
|
938
|
-
addr,
|
|
939
|
-
sigBase64: sigBase64.substring(0, 50) + "...",
|
|
940
|
-
msgPreview: msg.substring(0, 100) + "...",
|
|
941
|
-
msgLength: msg.length
|
|
942
|
-
},
|
|
943
|
-
"Verifying legacy signature"
|
|
944
|
-
);
|
|
945
|
-
const ok = bitcoinMessage__namespace.verify(msg, addr, sigBase64);
|
|
946
|
-
log4.info({ addr, ok, sigBase64Length: sigBase64.length }, "Legacy verification result");
|
|
947
|
-
if (!ok) {
|
|
876
|
+
log4.debug(
|
|
877
|
+
{
|
|
878
|
+
msgFull: msg,
|
|
879
|
+
msgLines: msg.split("\n").length,
|
|
880
|
+
msgFirstLine: msg.split("\n")[0],
|
|
881
|
+
msgLastLine: msg.split("\n")[msg.split("\n").length - 1]
|
|
882
|
+
},
|
|
883
|
+
"Message being verified"
|
|
884
|
+
);
|
|
885
|
+
const ok = bip322.verifySignature(addr, msg, sigBase64);
|
|
886
|
+
log4.info({ addr, ok }, "BIP-322 verification result");
|
|
887
|
+
if (!ok) {
|
|
888
|
+
const isSegWit = addr.startsWith("bc1") || addr.startsWith("tb1");
|
|
889
|
+
if (isSegWit && sigBase64.length === 88) {
|
|
890
|
+
log4.warn(
|
|
891
|
+
{ addr, wallet: "possibly Electrum", sigLength: sigBase64.length },
|
|
892
|
+
"BIP-322 verification failed - likely Electrum wallet (does not support BIP-322 for SegWit)"
|
|
893
|
+
);
|
|
894
|
+
} else {
|
|
948
895
|
log4.error(
|
|
949
896
|
{
|
|
950
897
|
addr,
|
|
951
|
-
|
|
952
|
-
|
|
898
|
+
sigLength: sigBase64.length,
|
|
899
|
+
msgLength: msg.length,
|
|
900
|
+
msgPreview: msg.substring(0, 200)
|
|
953
901
|
},
|
|
954
|
-
"
|
|
902
|
+
"BIP-322 verification failed - signature does not match message"
|
|
955
903
|
);
|
|
956
904
|
}
|
|
957
|
-
return ok ? "sig_ok_legacy" : "sig_invalid";
|
|
958
905
|
}
|
|
959
|
-
return "
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
906
|
+
return ok ? "sig_ok_bip322" : "sig_invalid";
|
|
907
|
+
}
|
|
908
|
+
if (detectedScheme === "legacy") {
|
|
909
|
+
const sigBase64 = toBase64Maybe(sig);
|
|
910
|
+
if (!addr.startsWith("1") && !addr.startsWith("m") && !addr.startsWith("n")) {
|
|
911
|
+
log4.warn({ addr }, "Legacy signature attempted on non-P2PKH address");
|
|
912
|
+
return "sig_unsupported_script";
|
|
913
|
+
}
|
|
914
|
+
log4.debug(
|
|
915
|
+
{
|
|
916
|
+
addr,
|
|
917
|
+
sigBase64: sigBase64.substring(0, 50) + "...",
|
|
918
|
+
msgPreview: msg.substring(0, 100) + "...",
|
|
919
|
+
msgLength: msg.length
|
|
920
|
+
},
|
|
921
|
+
"Verifying legacy signature"
|
|
964
922
|
);
|
|
965
|
-
|
|
923
|
+
const ok = bip322.verifySignature(addr, msg, sigBase64);
|
|
924
|
+
log4.info({ addr, ok, sigBase64Length: sigBase64.length }, "Legacy verification result");
|
|
925
|
+
if (!ok) {
|
|
926
|
+
log4.error(
|
|
927
|
+
{
|
|
928
|
+
addr,
|
|
929
|
+
msgFirstLine: msg.split("\n")[0],
|
|
930
|
+
sigFormat: sigBase64.substring(0, 10)
|
|
931
|
+
},
|
|
932
|
+
"Legacy signature verification failed - check message format and signature"
|
|
933
|
+
);
|
|
934
|
+
}
|
|
935
|
+
return ok ? "sig_ok_legacy" : "sig_invalid";
|
|
966
936
|
}
|
|
937
|
+
return "invalid_scheme";
|
|
967
938
|
}
|
|
968
939
|
function parseCanonicalMessage(msg) {
|
|
969
940
|
const lines = msg.split("\n").map((l) => l.trim());
|
|
@@ -1094,7 +1065,7 @@ function computeMetrics(utxos, bondAmount) {
|
|
|
1094
1065
|
const days_unspent = Math.max(0, Math.floor((Date.now() / 1e3 - oldestTime) / (24 * 60 * 60)));
|
|
1095
1066
|
return { sats_bonded, days_unspent, confirmed_balance };
|
|
1096
1067
|
}
|
|
1097
|
-
async function
|
|
1068
|
+
async function verify(input, opts = {}) {
|
|
1098
1069
|
const codes = [];
|
|
1099
1070
|
let network = "mainnet";
|
|
1100
1071
|
try {
|
|
@@ -1249,7 +1220,7 @@ async function check(params) {
|
|
|
1249
1220
|
return { ok: false, sats: 0, days: 0, score: 0, reasons: ["not_found"] };
|
|
1250
1221
|
}
|
|
1251
1222
|
const shared = identity ? await backsOtherIdentity(env, identity, relays) : false;
|
|
1252
|
-
const outcome = await
|
|
1223
|
+
const outcome = await verify(
|
|
1253
1224
|
{
|
|
1254
1225
|
addr: env.address,
|
|
1255
1226
|
msg: env.message,
|
|
@@ -1437,21 +1408,17 @@ async function verifyChallenge(opts) {
|
|
|
1437
1408
|
return { ok: false, reason: "purpose_mismatch" };
|
|
1438
1409
|
}
|
|
1439
1410
|
const scheme = opts.scheme ?? "bip322";
|
|
1440
|
-
let sigValid
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
if (!/^[1m][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(address)) {
|
|
1447
|
-
return { ok: false, reason: "sig_unsupported_scheme" };
|
|
1448
|
-
}
|
|
1449
|
-
sigValid = bitcoinMessage__namespace.verify(opts.message, address, opts.signature);
|
|
1450
|
-
} else {
|
|
1411
|
+
let sigValid;
|
|
1412
|
+
if (scheme === "bip322") {
|
|
1413
|
+
const sigBase64 = /^[0-9a-fA-F]+$/.test(opts.signature) && opts.signature.length % 2 === 0 ? buffer.Buffer.from(opts.signature, "hex").toString("base64") : opts.signature;
|
|
1414
|
+
sigValid = bip322.verifySignature(address, opts.message, sigBase64);
|
|
1415
|
+
} else if (scheme === "legacy") {
|
|
1416
|
+
if (!/^[1m][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(address)) {
|
|
1451
1417
|
return { ok: false, reason: "sig_unsupported_scheme" };
|
|
1452
1418
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
1419
|
+
sigValid = bip322.verifySignature(address, opts.message, opts.signature);
|
|
1420
|
+
} else {
|
|
1421
|
+
return { ok: false, reason: "sig_unsupported_scheme" };
|
|
1455
1422
|
}
|
|
1456
1423
|
if (!sigValid) return { ok: false, reason: "sig_invalid" };
|
|
1457
1424
|
return {
|
|
@@ -1617,11 +1584,14 @@ function isValidDomain(domain) {
|
|
|
1617
1584
|
const domainPattern = /^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,}$/i;
|
|
1618
1585
|
return domainPattern.test(cleanDomain);
|
|
1619
1586
|
}
|
|
1620
|
-
function isDnsIdentityVerified(attestationId,
|
|
1621
|
-
if (!cachedContent) {
|
|
1587
|
+
function isDnsIdentityVerified(attestationId, domain, cachedContent) {
|
|
1588
|
+
if (!cachedContent || !cachedContent.includes(attestationId)) {
|
|
1622
1589
|
return false;
|
|
1623
1590
|
}
|
|
1624
|
-
|
|
1591
|
+
const named = /^Domain:\s*(\S+)\s*$/im.exec(cachedContent);
|
|
1592
|
+
if (!named) return true;
|
|
1593
|
+
const cleanDomain = domain.replace(/^https?:\/\//, "").replace(/\/$/, "").toLowerCase();
|
|
1594
|
+
return named[1].toLowerCase() === cleanDomain;
|
|
1625
1595
|
}
|
|
1626
1596
|
|
|
1627
1597
|
// src/identity/github.ts
|
|
@@ -1765,8 +1735,10 @@ This gist proves that I control both:
|
|
|
1765
1735
|
Learn more about OrangeCheck: https://ochk.io
|
|
1766
1736
|
`;
|
|
1767
1737
|
}
|
|
1768
|
-
function isGitHubIdentityVerified(attestationId,
|
|
1738
|
+
function isGitHubIdentityVerified(attestationId, username, cachedGists) {
|
|
1739
|
+
const login = username.replace(/^@/, "").toLowerCase();
|
|
1769
1740
|
return cachedGists.some((gist) => {
|
|
1741
|
+
if (gist.owner?.login?.toLowerCase() !== login) return false;
|
|
1770
1742
|
if (gist.description?.includes(attestationId)) {
|
|
1771
1743
|
return true;
|
|
1772
1744
|
}
|
|
@@ -1865,6 +1837,9 @@ async function queryNostrEvents(options) {
|
|
|
1865
1837
|
return events;
|
|
1866
1838
|
}
|
|
1867
1839
|
async function verifyNostrEventSignature(event) {
|
|
1840
|
+
return nostrEventSignatureValid(event);
|
|
1841
|
+
}
|
|
1842
|
+
function nostrEventSignatureValid(event) {
|
|
1868
1843
|
try {
|
|
1869
1844
|
if (!event.id || !event.sig || !event.pubkey || typeof event.id !== "string" || typeof event.sig !== "string" || typeof event.pubkey !== "string" || event.sig.length !== 128 || !HEX_64_RE2.test(event.id) || !HEX_64_RE2.test(event.pubkey)) {
|
|
1870
1845
|
return false;
|
|
@@ -1951,7 +1926,7 @@ The verification will search Nostr relays for your note and confirm you control
|
|
|
1951
1926
|
function isNostrIdentityVerified(attestationId, npub, cachedEvents) {
|
|
1952
1927
|
const pubkeyHex = npubToHex(npub);
|
|
1953
1928
|
return cachedEvents.some(
|
|
1954
|
-
(event) => event.pubkey === pubkeyHex && event.kind === 1 && event.content.includes(attestationId)
|
|
1929
|
+
(event) => event.pubkey === pubkeyHex && event.kind === 1 && event.content.includes(attestationId) && nostrEventSignatureValid(event)
|
|
1955
1930
|
);
|
|
1956
1931
|
}
|
|
1957
1932
|
|
|
@@ -2299,7 +2274,7 @@ exports.queryRecent = queryRecent;
|
|
|
2299
2274
|
exports.requiresManualVerification = requiresManualVerification;
|
|
2300
2275
|
exports.signNostrEvent = signNostrEvent;
|
|
2301
2276
|
exports.supportsAutomaticVerification = supportsAutomaticVerification;
|
|
2302
|
-
exports.verify =
|
|
2277
|
+
exports.verify = verify;
|
|
2303
2278
|
exports.verifyAllIdentities = verifyAllIdentities;
|
|
2304
2279
|
exports.verifyAttestationById = verifyAttestationById;
|
|
2305
2280
|
exports.verifyChallenge = verifyChallenge;
|