@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/index.mjs CHANGED
@@ -1,7 +1,6 @@
1
1
  import { bech32 } from '@scure/base';
2
2
  import { Buffer } from 'buffer';
3
- import { Verifier } from 'bip322-js';
4
- import * as bitcoinMessage from 'bitcoinjs-message';
3
+ import { verifySignature as verifySignature$1 } from '@orangecheck/bip322';
5
4
  import { schnorr } from '@noble/curves/secp256k1.js';
6
5
  import { sha256 } from '@noble/hashes/sha2.js';
7
6
 
@@ -861,87 +860,79 @@ async function verifySignature({
861
860
  sig,
862
861
  scheme
863
862
  }) {
864
- try {
865
- const detectedScheme = scheme || detectSignatureScheme(addr, sig);
863
+ const detectedScheme = scheme || detectSignatureScheme(addr, sig);
864
+ log4.debug(
865
+ { addr, msgLength: msg.length, sigLength: sig.length, scheme: detectedScheme },
866
+ "Verifying signature"
867
+ );
868
+ if (detectedScheme === "bip322") {
869
+ const sigBase64 = toBase64Maybe(sig);
866
870
  log4.debug(
867
- { addr, msgLength: msg.length, sigLength: sig.length, scheme: detectedScheme },
868
- "Verifying signature"
871
+ { sigBase64: sigBase64.substring(0, 50) + "..." },
872
+ "Signature converted to base64"
869
873
  );
870
- if (detectedScheme === "bip322") {
871
- const sigBase64 = toBase64Maybe(sig);
872
- log4.debug(
873
- { sigBase64: sigBase64.substring(0, 50) + "..." },
874
- "Signature converted to base64"
875
- );
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 = Verifier.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 {
895
- log4.error(
896
- {
897
- addr,
898
- sigLength: sigBase64.length,
899
- msgLength: msg.length,
900
- msgPreview: msg.substring(0, 200)
901
- },
902
- "BIP-322 verification failed - signature does not match message"
903
- );
904
- }
905
- }
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"
922
- );
923
- const ok = bitcoinMessage.verify(msg, addr, sigBase64);
924
- log4.info({ addr, ok, sigBase64Length: sigBase64.length }, "Legacy verification result");
925
- if (!ok) {
874
+ log4.debug(
875
+ {
876
+ msgFull: msg,
877
+ msgLines: msg.split("\n").length,
878
+ msgFirstLine: msg.split("\n")[0],
879
+ msgLastLine: msg.split("\n")[msg.split("\n").length - 1]
880
+ },
881
+ "Message being verified"
882
+ );
883
+ const ok = verifySignature$1(addr, msg, sigBase64);
884
+ log4.info({ addr, ok }, "BIP-322 verification result");
885
+ if (!ok) {
886
+ const isSegWit = addr.startsWith("bc1") || addr.startsWith("tb1");
887
+ if (isSegWit && sigBase64.length === 88) {
888
+ log4.warn(
889
+ { addr, wallet: "possibly Electrum", sigLength: sigBase64.length },
890
+ "BIP-322 verification failed - likely Electrum wallet (does not support BIP-322 for SegWit)"
891
+ );
892
+ } else {
926
893
  log4.error(
927
894
  {
928
895
  addr,
929
- msgFirstLine: msg.split("\n")[0],
930
- sigFormat: sigBase64.substring(0, 10)
896
+ sigLength: sigBase64.length,
897
+ msgLength: msg.length,
898
+ msgPreview: msg.substring(0, 200)
931
899
  },
932
- "Legacy signature verification failed - check message format and signature"
900
+ "BIP-322 verification failed - signature does not match message"
933
901
  );
934
902
  }
935
- return ok ? "sig_ok_legacy" : "sig_invalid";
936
903
  }
937
- return "invalid_scheme";
938
- } catch (err) {
939
- log4.error(
940
- { addr, error: err instanceof Error ? err.message : String(err) },
941
- "Signature verification error"
904
+ return ok ? "sig_ok_bip322" : "sig_invalid";
905
+ }
906
+ if (detectedScheme === "legacy") {
907
+ const sigBase64 = toBase64Maybe(sig);
908
+ if (!addr.startsWith("1") && !addr.startsWith("m") && !addr.startsWith("n")) {
909
+ log4.warn({ addr }, "Legacy signature attempted on non-P2PKH address");
910
+ return "sig_unsupported_script";
911
+ }
912
+ log4.debug(
913
+ {
914
+ addr,
915
+ sigBase64: sigBase64.substring(0, 50) + "...",
916
+ msgPreview: msg.substring(0, 100) + "...",
917
+ msgLength: msg.length
918
+ },
919
+ "Verifying legacy signature"
942
920
  );
943
- return "sig_invalid";
921
+ const ok = verifySignature$1(addr, msg, sigBase64);
922
+ log4.info({ addr, ok, sigBase64Length: sigBase64.length }, "Legacy verification result");
923
+ if (!ok) {
924
+ log4.error(
925
+ {
926
+ addr,
927
+ msgFirstLine: msg.split("\n")[0],
928
+ sigFormat: sigBase64.substring(0, 10)
929
+ },
930
+ "Legacy signature verification failed - check message format and signature"
931
+ );
932
+ }
933
+ return ok ? "sig_ok_legacy" : "sig_invalid";
944
934
  }
935
+ return "invalid_scheme";
945
936
  }
946
937
  function parseCanonicalMessage(msg) {
947
938
  const lines = msg.split("\n").map((l) => l.trim());
@@ -1072,7 +1063,7 @@ function computeMetrics(utxos, bondAmount) {
1072
1063
  const days_unspent = Math.max(0, Math.floor((Date.now() / 1e3 - oldestTime) / (24 * 60 * 60)));
1073
1064
  return { sats_bonded, days_unspent, confirmed_balance };
1074
1065
  }
1075
- async function verify2(input, opts = {}) {
1066
+ async function verify(input, opts = {}) {
1076
1067
  const codes = [];
1077
1068
  let network = "mainnet";
1078
1069
  try {
@@ -1227,7 +1218,7 @@ async function check(params) {
1227
1218
  return { ok: false, sats: 0, days: 0, score: 0, reasons: ["not_found"] };
1228
1219
  }
1229
1220
  const shared = identity ? await backsOtherIdentity(env, identity, relays) : false;
1230
- const outcome = await verify2(
1221
+ const outcome = await verify(
1231
1222
  {
1232
1223
  addr: env.address,
1233
1224
  msg: env.message,
@@ -1415,21 +1406,17 @@ async function verifyChallenge(opts) {
1415
1406
  return { ok: false, reason: "purpose_mismatch" };
1416
1407
  }
1417
1408
  const scheme = opts.scheme ?? "bip322";
1418
- let sigValid = false;
1419
- try {
1420
- if (scheme === "bip322") {
1421
- const sigBase64 = /^[0-9a-fA-F]+$/.test(opts.signature) && opts.signature.length % 2 === 0 ? Buffer.from(opts.signature, "hex").toString("base64") : opts.signature;
1422
- sigValid = Verifier.verifySignature(address, opts.message, sigBase64);
1423
- } else if (scheme === "legacy") {
1424
- if (!/^[1m][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(address)) {
1425
- return { ok: false, reason: "sig_unsupported_scheme" };
1426
- }
1427
- sigValid = bitcoinMessage.verify(opts.message, address, opts.signature);
1428
- } else {
1409
+ let sigValid;
1410
+ if (scheme === "bip322") {
1411
+ const sigBase64 = /^[0-9a-fA-F]+$/.test(opts.signature) && opts.signature.length % 2 === 0 ? Buffer.from(opts.signature, "hex").toString("base64") : opts.signature;
1412
+ sigValid = verifySignature$1(address, opts.message, sigBase64);
1413
+ } else if (scheme === "legacy") {
1414
+ if (!/^[1m][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(address)) {
1429
1415
  return { ok: false, reason: "sig_unsupported_scheme" };
1430
1416
  }
1431
- } catch {
1432
- sigValid = false;
1417
+ sigValid = verifySignature$1(address, opts.message, opts.signature);
1418
+ } else {
1419
+ return { ok: false, reason: "sig_unsupported_scheme" };
1433
1420
  }
1434
1421
  if (!sigValid) return { ok: false, reason: "sig_invalid" };
1435
1422
  return {
@@ -1595,11 +1582,14 @@ function isValidDomain(domain) {
1595
1582
  const domainPattern = /^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,}$/i;
1596
1583
  return domainPattern.test(cleanDomain);
1597
1584
  }
1598
- function isDnsIdentityVerified(attestationId, _domain, cachedContent) {
1599
- if (!cachedContent) {
1585
+ function isDnsIdentityVerified(attestationId, domain, cachedContent) {
1586
+ if (!cachedContent || !cachedContent.includes(attestationId)) {
1600
1587
  return false;
1601
1588
  }
1602
- return cachedContent.includes(attestationId);
1589
+ const named = /^Domain:\s*(\S+)\s*$/im.exec(cachedContent);
1590
+ if (!named) return true;
1591
+ const cleanDomain = domain.replace(/^https?:\/\//, "").replace(/\/$/, "").toLowerCase();
1592
+ return named[1].toLowerCase() === cleanDomain;
1603
1593
  }
1604
1594
 
1605
1595
  // src/identity/github.ts
@@ -1743,8 +1733,10 @@ This gist proves that I control both:
1743
1733
  Learn more about OrangeCheck: https://ochk.io
1744
1734
  `;
1745
1735
  }
1746
- function isGitHubIdentityVerified(attestationId, _username, cachedGists) {
1736
+ function isGitHubIdentityVerified(attestationId, username, cachedGists) {
1737
+ const login = username.replace(/^@/, "").toLowerCase();
1747
1738
  return cachedGists.some((gist) => {
1739
+ if (gist.owner?.login?.toLowerCase() !== login) return false;
1748
1740
  if (gist.description?.includes(attestationId)) {
1749
1741
  return true;
1750
1742
  }
@@ -1843,6 +1835,9 @@ async function queryNostrEvents(options) {
1843
1835
  return events;
1844
1836
  }
1845
1837
  async function verifyNostrEventSignature(event) {
1838
+ return nostrEventSignatureValid(event);
1839
+ }
1840
+ function nostrEventSignatureValid(event) {
1846
1841
  try {
1847
1842
  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)) {
1848
1843
  return false;
@@ -1929,7 +1924,7 @@ The verification will search Nostr relays for your note and confirm you control
1929
1924
  function isNostrIdentityVerified(attestationId, npub, cachedEvents) {
1930
1925
  const pubkeyHex = npubToHex(npub);
1931
1926
  return cachedEvents.some(
1932
- (event) => event.pubkey === pubkeyHex && event.kind === 1 && event.content.includes(attestationId)
1927
+ (event) => event.pubkey === pubkeyHex && event.kind === 1 && event.content.includes(attestationId) && nostrEventSignatureValid(event)
1933
1928
  );
1934
1929
  }
1935
1930
 
@@ -2223,6 +2218,6 @@ var STATUS_META = {
2223
2218
  }
2224
2219
  };
2225
2220
 
2226
- export { DEFAULT_RELAYS, FANOUT_DEADLINE_MS, STATUS_META, buildCanonicalMessage, check, computeAllScores, computeScore, createAttestation, createAttestationEnvelope, createAttestationEvent, discoverAttestations, extractAttestationIdFromUrl, formatIdentities, formatIdentitiesForDisplay, generateAttestationId, generateGistTemplate, generateTweetText, generateWellKnownContent, getAttestationsForAddress, getAttestationsForIdentity, getDnsVerificationInstructions, getGistCreationUrl, getGitHubVerificationInstructions, getManualVerificationInstructions, getNip07Info, getNostrPublicKey, getNostrVerificationInstructions, getTweetUrl, getTwitterComposeUrl, getTwitterVerificationInstructions, getVerificationInstructions, getVerificationSummary, getVerificationUrl, getWellKnownUrl, isDnsIdentityVerified, isGitHubIdentityVerified, isNip07Available, isNostrIdentityVerified, isValidDomain, isValidTweetUrl, issueChallenge, nostrIdentifierForms, nostrPubkeyToHex, parseAttestationFromEvent, parseIdentities, publishAttestation, publishToRelays, queryByAddress, queryByAttestationId, queryByIdentity, queryRecent, requiresManualVerification, signNostrEvent, supportsAutomaticVerification, verify2 as verify, verifyAllIdentities, verifyAttestationById, verifyChallenge, verifyDnsIdentity, verifyGitHubIdentity, verifyIdentity, verifyNostrIdentity, verifyTwitterIdentity };
2221
+ export { DEFAULT_RELAYS, FANOUT_DEADLINE_MS, STATUS_META, buildCanonicalMessage, check, computeAllScores, computeScore, createAttestation, createAttestationEnvelope, createAttestationEvent, discoverAttestations, extractAttestationIdFromUrl, formatIdentities, formatIdentitiesForDisplay, generateAttestationId, generateGistTemplate, generateTweetText, generateWellKnownContent, getAttestationsForAddress, getAttestationsForIdentity, getDnsVerificationInstructions, getGistCreationUrl, getGitHubVerificationInstructions, getManualVerificationInstructions, getNip07Info, getNostrPublicKey, getNostrVerificationInstructions, getTweetUrl, getTwitterComposeUrl, getTwitterVerificationInstructions, getVerificationInstructions, getVerificationSummary, getVerificationUrl, getWellKnownUrl, isDnsIdentityVerified, isGitHubIdentityVerified, isNip07Available, isNostrIdentityVerified, isValidDomain, isValidTweetUrl, issueChallenge, nostrIdentifierForms, nostrPubkeyToHex, parseAttestationFromEvent, parseIdentities, publishAttestation, publishToRelays, queryByAddress, queryByAttestationId, queryByIdentity, queryRecent, requiresManualVerification, signNostrEvent, supportsAutomaticVerification, verify, verifyAllIdentities, verifyAttestationById, verifyChallenge, verifyDnsIdentity, verifyGitHubIdentity, verifyIdentity, verifyNostrIdentity, verifyTwitterIdentity };
2227
2222
  //# sourceMappingURL=index.mjs.map
2228
2223
  //# sourceMappingURL=index.mjs.map