@notabene/verify-proof 1.11.1-next.1 → 1.12.0-next.12
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/{bitcoin-3CW4MNAW.cjs → cjs/bitcoin-UIEQV3IM.cjs} +105 -16
- package/dist/cjs/bitcoin-UIEQV3IM.cjs.map +1 -0
- package/dist/{cardano-DYBYEAAF.cjs → cjs/cardano-QG2S452K.cjs} +5 -22
- package/dist/cjs/cardano-QG2S452K.cjs.map +1 -0
- package/dist/cjs/concordium-4B33UJJ5.cjs +44 -0
- package/dist/cjs/concordium-4B33UJJ5.cjs.map +1 -0
- package/dist/cjs/cosmos-JTT3AZCF.cjs +92 -0
- package/dist/cjs/cosmos-JTT3AZCF.cjs.map +1 -0
- package/dist/{eth-3DX3PXDU.cjs → cjs/eth-BVXX47HH.cjs} +2 -3
- package/dist/cjs/eth-BVXX47HH.cjs.map +1 -0
- package/dist/{index.cjs → cjs/index.cjs} +10 -12
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/{solana-PQ5K4NGO.cjs → cjs/solana-4WNBEQSU.cjs} +6 -23
- package/dist/cjs/solana-4WNBEQSU.cjs.map +1 -0
- package/dist/{tron-F5AARBY4.cjs → cjs/tron-IM2O2VLM.cjs} +2 -3
- package/dist/cjs/tron-IM2O2VLM.cjs.map +1 -0
- package/dist/{xlm-5GODWWL2.cjs → cjs/xlm-CHT7RN4Z.cjs} +2 -3
- package/dist/cjs/xlm-CHT7RN4Z.cjs.map +1 -0
- package/dist/cjs/xrpl-HJ2XWSOO.cjs +74 -0
- package/dist/cjs/xrpl-HJ2XWSOO.cjs.map +1 -0
- package/dist/{bitcoin-QK53ILBF.js → esm/bitcoin-BTZ4TXEK.js} +105 -16
- package/dist/esm/bitcoin-BTZ4TXEK.js.map +1 -0
- package/dist/{cardano-WE6YXYLW.js → esm/cardano-OMGAPH5N.js} +4 -5
- package/dist/esm/cardano-OMGAPH5N.js.map +1 -0
- package/dist/esm/concordium-JJ5VEIOA.js +42 -0
- package/dist/esm/concordium-JJ5VEIOA.js.map +1 -0
- package/dist/esm/cosmos-AVIWAIX7.js +90 -0
- package/dist/esm/cosmos-AVIWAIX7.js.map +1 -0
- package/dist/{eth-ICLGRJE5.js → esm/eth-GI4Z5V4T.js} +2 -3
- package/dist/esm/eth-GI4Z5V4T.js.map +1 -0
- package/dist/{index.js → esm/index.js} +10 -12
- package/dist/esm/index.js.map +1 -0
- package/dist/{solana-4KQFLZUC.js → esm/solana-ZARDAF6O.js} +3 -4
- package/dist/esm/solana-ZARDAF6O.js.map +1 -0
- package/dist/{tron-OBLPB2LN.js → esm/tron-FI2B6DRS.js} +2 -3
- package/dist/esm/tron-FI2B6DRS.js.map +1 -0
- package/dist/{xlm-GX2QGFLI.js → esm/xlm-TNRZ5CFC.js} +2 -3
- package/dist/esm/xlm-TNRZ5CFC.js.map +1 -0
- package/dist/esm/xrpl-52IBJ4EW.js +69 -0
- package/dist/esm/xrpl-52IBJ4EW.js.map +1 -0
- package/package.json +21 -9
- package/src/bitcoin.ts +43 -19
- package/src/cardano.ts +2 -2
- package/src/cashaddr.ts +157 -0
- package/src/concordium.ts +34 -283
- package/src/cosmos.ts +44 -6
- package/src/index.ts +0 -1
- package/src/solana.ts +1 -1
- package/src/tests/bitcoin.test.ts +527 -16
- package/src/tests/concordium.test.ts +96 -134
- package/src/tests/cosmos.test.ts +139 -0
- package/src/tests/index.test.ts +7 -7
- package/src/tests/xrpl.test.ts +8 -6
- package/dist/bitcoin-3CW4MNAW.cjs.map +0 -1
- package/dist/bitcoin-QK53ILBF.js.map +0 -1
- package/dist/cardano-DYBYEAAF.cjs.map +0 -1
- package/dist/cardano-WE6YXYLW.js.map +0 -1
- package/dist/chunk-E3V5ATTC.js +0 -38
- package/dist/chunk-E3V5ATTC.js.map +0 -1
- package/dist/chunk-OAXNH5XR.cjs +0 -42
- package/dist/chunk-OAXNH5XR.cjs.map +0 -1
- package/dist/concordium-HQC37GCK.cjs +0 -188
- package/dist/concordium-HQC37GCK.cjs.map +0 -1
- package/dist/concordium-XX4XYLLU.js +0 -186
- package/dist/concordium-XX4XYLLU.js.map +0 -1
- package/dist/cosmos-64MKE5FJ.cjs +0 -683
- package/dist/cosmos-64MKE5FJ.cjs.map +0 -1
- package/dist/cosmos-QMH7BK7S.js +0 -681
- package/dist/cosmos-QMH7BK7S.js.map +0 -1
- package/dist/eth-3DX3PXDU.cjs.map +0 -1
- package/dist/eth-ICLGRJE5.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/solana-4KQFLZUC.js.map +0 -1
- package/dist/solana-PQ5K4NGO.cjs.map +0 -1
- package/dist/tron-F5AARBY4.cjs.map +0 -1
- package/dist/tron-OBLPB2LN.js.map +0 -1
- package/dist/xlm-5GODWWL2.cjs.map +0 -1
- package/dist/xlm-GX2QGFLI.js.map +0 -1
- package/dist/xrpl-7HQLIDAK.cjs +0 -1174
- package/dist/xrpl-7HQLIDAK.cjs.map +0 -1
- package/dist/xrpl-YCDFXBGQ.js +0 -1169
- package/dist/xrpl-YCDFXBGQ.js.map +0 -1
- /package/dist/{index.d.cts → cjs/index.d.cts} +0 -0
- /package/dist/{index.d.ts → esm/index.d.ts} +0 -0
|
@@ -7,216 +7,178 @@ import {
|
|
|
7
7
|
} from "@notabene/javascript-sdk";
|
|
8
8
|
|
|
9
9
|
describe("verifyConcordiumSignature", () => {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
it("returns verified proof when valid presentation on testnet", async () => {
|
|
11
|
+
const proof: SignatureProof = {
|
|
12
|
+
"address": "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3Soqc3mEU5WC4R9Qho9fxm4CJ1157q6qsJbPvtGV8iT8FbQdv2",
|
|
13
|
+
"attestation": "b74a8e64f1568f1fb22a57b033bc8ef2b8f6ba23ff8e831e7abfbb671927fda1",
|
|
14
|
+
"type": ProofTypes.CONCORDIUM,
|
|
15
|
+
"did": "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3Soqc3mEU5WC4R9Qho9fxm4CJ1157q6qsJbPvtGV8iT8FbQdv2",
|
|
16
|
+
"proof": "{\"presentationContext\":\"b74a8e64f1568f1fb22a57b033bc8ef2b8f6ba23ff8e831e7abfbb671927fda1\",\"proof\":{\"created\":\"2025-12-10T10:39:14.395Z\",\"proofValue\":[],\"type\":\"ConcordiumWeakLinkingProofV1\"},\"type\":\"VerifiablePresentation\",\"verifiableCredential\":[{\"credentialSubject\":{\"id\":\"did:ccd:mainnet:cred:91a1f28bc42222096856a54fb157f7c80b9827457d4ece682b9592bca964948f01dce51a7deb392ea9bd0c1e1630d17b\",\"proof\":{\"created\":\"2025-12-10T10:39:14.395Z\",\"proofValue\":[{\"proof\":\"988f08d03bc8adaac4d51986dfaafe70874ab3bb22e8c09c32da5bfcd0ff0407203770533220e74ba4386acb36f7b7288e38c461279f7edf6f41b8b285d629280a5ca297e7fc42155222c5b1ad3cc74f770d5c87addbba6935ade425460b1616a587d9c45a4676f7fc751b31110cd37b25998c61d7d85c84e4db155491665e556778a9784e557799f06531bafe6b4b8ca2ce386d66f7759079eaff74b1e519550c9d137a13851c0987ee434feb6dae0ca659d67661b27e92d7cca9567a1a6ecd2175c574f5a6c2f4691597cbf3680f65abab72633d050746211c56961277064d694a31c2a93ef3b64c4957ff8261978a53d8b65d40ff23ddc7ee65d0ea0817702be58fbaec3954322e00667c6c94736eba8d3aa3f2686b89f257ca34c90ae1200000000785c57df969a45b25b1d39bdb388d33a756147e98f285891e83ce58eab3bb1f466c25a0946fc62513b16f3f02397b15418ebc131b5e1a8c0f05d6983cd3c44cc40ab8364c1aa209c2e8c0e8e84694587053542fd5cbb918f025723a5a0c200f08875728874571f50cb8b54d1c8629a10c76f0a982ad667efcfa280943f7c8753d3fa859a8d5d9837e6bdd5026d54546a3ae5918055208b5d2f77e0206d7861b4c472c634ec4cece107aeb14c42fe3d801aba38aa38e15785152e7c061561a5594a6cabb34f469b3121c15437df5d6ba0638ba3a192f2106d07e2f7bfd73310f669d3e8bdeb1b43244455d7bd7fa5917a1af2b23dc3433dac68ee4571bea2b0c22ce2ed665e22cee5676b9c3de0169926e72c847f7e3f2caa671e55ab5c4530205845b08ee12bba954f4a41e5638b05043a93ed212f402273c2b477f95f7b82ddbe4621f1758f80fcec726df755a76d0f585eda201dff2b91147cca5eae5d5319b7e1438c0f4af42b9fe4f7e845d0c643328ddd5dead96bfd345ae972312650a9ab6e6d7fa3d3f5d1fe68e5ff513095e3caa5bb21bec64dae007e62b4494986ac40b9e14b61255a84ea51780b8439adaeeae0b83a8bcee382491dd8e7b2f1921e8eeffe39a45bffd470b5a8f74d82ccdb8ccda651c387844f61704cc04f51d65fb9069900cb1febfc0b2ba02ffc857c45c12a7b306440e6627995d67353e9f6327b6f6cfa6ad0b859ea904f087a5b29a888043ba21ccb3e36da0a2da797310c2f2ce56c275d6fc48b60aade4b4e6bb6ff62d5f5be1a529c8d71cab2b0904fa306cb779a897872f5f047df7c7bee150ca6be6f3ad840a862ecc0793bb27f0594ff8741a4ab426b53d72acbdbde6c20a7c4399ca181d81a4b0ac437c23220f52ff8e9095ae35a53f8cd58913c4999a8153b656fabb162feafe8fc8708eaeb2b5ce0d347e5733cd685783271eaf564e05efce61996686ee9f50663204841ff30416061721a5cab8e1c80708809b58d2bc9c402da453e486ce08e0ec6c72c1f0e9dc15\",\"type\":\"AttributeInRange\"}],\"type\":\"ConcordiumZKProofV3\"},\"statement\":[{\"attributeTag\":\"dob\",\"lower\":\"19300101\",\"type\":\"AttributeInRange\",\"upper\":\"99990101\"}]},\"issuer\":\"did:ccd:mainnet:idp:1\",\"type\":[\"VerifiableCredential\",\"ConcordiumVerifiableCredential\"]}]}",
|
|
17
|
+
"wallet_provider": "Concordium Browser",
|
|
18
|
+
"status": ProofStatus.PENDING
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const result = await verifyConcordiumSignature(proof);
|
|
22
|
+
|
|
23
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
|
24
|
+
}, 15000);
|
|
25
|
+
|
|
26
|
+
it("returns failed proof when proof field contains invalid JSON", async () => {
|
|
12
27
|
const proof: SignatureProof = {
|
|
13
28
|
address:
|
|
14
29
|
"ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
15
30
|
attestation:
|
|
16
|
-
"
|
|
31
|
+
"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
|
|
17
32
|
type: ProofTypes.CONCORDIUM,
|
|
18
|
-
did: "did:
|
|
19
|
-
proof:
|
|
20
|
-
|
|
33
|
+
did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
34
|
+
proof: "invalid json string",
|
|
35
|
+
wallet_provider: "Concordium Browser",
|
|
21
36
|
status: ProofStatus.PENDING,
|
|
22
|
-
wallet_provider: "Concordium Wallet",
|
|
23
37
|
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// This should either be VERIFIED (if account exists and signature is valid)
|
|
33
|
-
// or FAILED (if account doesn't exist or signature is invalid)
|
|
34
|
-
expect([ProofStatus.VERIFIED, ProofStatus.FAILED]).toContain(result.status);
|
|
35
|
-
}, 15000); // 15 second test timeout
|
|
36
|
-
|
|
37
|
-
// Test with valid signature against testnet (makes network calls)
|
|
38
|
-
it("returns verified proof when valid message and address on testnet", async () => {
|
|
38
|
+
|
|
39
|
+
const result = await verifyConcordiumSignature(proof);
|
|
40
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("returns failed proof when proof field is empty string", async () => {
|
|
39
44
|
const proof: SignatureProof = {
|
|
40
45
|
address:
|
|
41
|
-
"ccd:
|
|
46
|
+
"ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
42
47
|
attestation:
|
|
43
|
-
"
|
|
48
|
+
"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
|
|
44
49
|
type: ProofTypes.CONCORDIUM,
|
|
45
|
-
did: "did:
|
|
46
|
-
proof:
|
|
47
|
-
|
|
50
|
+
did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
51
|
+
proof: "",
|
|
52
|
+
wallet_provider: "Concordium Browser",
|
|
48
53
|
status: ProofStatus.PENDING,
|
|
49
|
-
wallet_provider: "Concordium Wallet",
|
|
50
54
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// This should either be VERIFIED (if account exists and signature is valid)
|
|
60
|
-
// or FAILED (if account doesn't exist or signature is invalid)
|
|
61
|
-
expect([ProofStatus.VERIFIED, ProofStatus.FAILED]).toContain(result.status);
|
|
62
|
-
}, 15000); // 15 second test timeout
|
|
63
|
-
|
|
64
|
-
// Test with non-existent account on mainnet (should fail but make network calls)
|
|
65
|
-
it("returns failed proof when account is not found on mainnet", async () => {
|
|
55
|
+
|
|
56
|
+
const result = await verifyConcordiumSignature(proof);
|
|
57
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("returns failed proof when proof field is empty object", async () => {
|
|
66
61
|
const proof: SignatureProof = {
|
|
67
62
|
address:
|
|
68
63
|
"ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
69
64
|
attestation:
|
|
70
|
-
"
|
|
65
|
+
"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
|
|
71
66
|
type: ProofTypes.CONCORDIUM,
|
|
72
|
-
did: "did:
|
|
73
|
-
proof:
|
|
74
|
-
|
|
67
|
+
did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
68
|
+
proof: "{}",
|
|
69
|
+
wallet_provider: "Concordium Browser",
|
|
75
70
|
status: ProofStatus.PENDING,
|
|
76
|
-
wallet_provider: "Concordium Wallet",
|
|
77
71
|
};
|
|
78
|
-
|
|
79
|
-
// Test against mainnet (makes network calls, calls isValidSignature)
|
|
80
|
-
const result = await verifyConcordiumSignature(proof, {
|
|
81
|
-
network: "mainnet",
|
|
82
|
-
testMode: false,
|
|
83
|
-
timeout: 10000
|
|
84
|
-
});
|
|
85
72
|
|
|
73
|
+
const result = await verifyConcordiumSignature(proof);
|
|
86
74
|
expect(result.status).toBe(ProofStatus.FAILED);
|
|
87
|
-
}
|
|
75
|
+
});
|
|
88
76
|
|
|
89
|
-
|
|
90
|
-
it("returns failed proof when account is not found on testnet", async () => {
|
|
77
|
+
it("returns failed proof when presentation is missing verifiableCredential", async () => {
|
|
91
78
|
const proof: SignatureProof = {
|
|
92
79
|
address:
|
|
93
|
-
"ccd:
|
|
80
|
+
"ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
94
81
|
attestation:
|
|
95
|
-
"
|
|
82
|
+
"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
|
|
96
83
|
type: ProofTypes.CONCORDIUM,
|
|
97
|
-
did: "did:
|
|
84
|
+
did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
98
85
|
proof:
|
|
99
|
-
'{"
|
|
86
|
+
'{"presentationContext":"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation"}',
|
|
87
|
+
wallet_provider: "Concordium Browser",
|
|
100
88
|
status: ProofStatus.PENDING,
|
|
101
|
-
wallet_provider: "Concordium Wallet",
|
|
102
89
|
};
|
|
103
|
-
|
|
104
|
-
// Test against testnet (makes network calls, calls isValidSignature)
|
|
105
|
-
const result = await verifyConcordiumSignature(proof, {
|
|
106
|
-
network: "testnet",
|
|
107
|
-
testMode: true,
|
|
108
|
-
timeout: 10000
|
|
109
|
-
});
|
|
110
90
|
|
|
111
|
-
|
|
112
|
-
|
|
91
|
+
const result = await verifyConcordiumSignature(proof);
|
|
92
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
|
93
|
+
});
|
|
113
94
|
|
|
114
|
-
|
|
115
|
-
it("handles network timeouts gracefully", async () => {
|
|
95
|
+
it("returns failed proof when presentation has empty verifiableCredential array", async () => {
|
|
116
96
|
const proof: SignatureProof = {
|
|
117
97
|
address:
|
|
118
98
|
"ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
119
99
|
attestation:
|
|
120
|
-
"
|
|
100
|
+
"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
|
|
121
101
|
type: ProofTypes.CONCORDIUM,
|
|
122
|
-
did: "did:
|
|
102
|
+
did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
123
103
|
proof:
|
|
124
|
-
'{"
|
|
104
|
+
'{"presentationContext":"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[]}',
|
|
105
|
+
wallet_provider: "Concordium Browser",
|
|
125
106
|
status: ProofStatus.PENDING,
|
|
126
|
-
wallet_provider: "Concordium Wallet",
|
|
127
107
|
};
|
|
128
|
-
|
|
129
|
-
// Test with very short timeout to trigger timeout handling
|
|
130
|
-
const result = await verifyConcordiumSignature(proof, {
|
|
131
|
-
network: "mainnet",
|
|
132
|
-
testMode: false,
|
|
133
|
-
timeout: 1, // 1ms timeout to force timeout
|
|
134
|
-
retries: 1
|
|
135
|
-
});
|
|
136
108
|
|
|
109
|
+
const result = await verifyConcordiumSignature(proof);
|
|
137
110
|
expect(result.status).toBe(ProofStatus.FAILED);
|
|
138
|
-
}
|
|
111
|
+
});
|
|
139
112
|
|
|
140
|
-
|
|
141
|
-
it("returns failed proof when invalid message and address in test mode", async () => {
|
|
113
|
+
it("returns failed proof when presentation is missing presentationContext", async () => {
|
|
142
114
|
const proof: SignatureProof = {
|
|
143
115
|
address:
|
|
144
116
|
"ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
145
117
|
attestation:
|
|
146
|
-
"
|
|
147
|
-
proof: '{}',
|
|
148
|
-
did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
|
|
149
|
-
status: ProofStatus.PENDING,
|
|
150
|
-
wallet_provider: "Concordium Wallet",
|
|
118
|
+
"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
|
|
151
119
|
type: ProofTypes.CONCORDIUM,
|
|
120
|
+
did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
121
|
+
proof:
|
|
122
|
+
'{"proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"credentialSubject":{"id":"did:ccd:testnet:cred:8f73851550a5d2c2ed4df215731cf9e3f33614d4be6c1c336f0f8858522c94afa34a759258a2b3281f9bacd0a8a3cd09","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[{"proof":"test","type":"AttributeInRange"}],"type":"ConcordiumZKProofV3"},"statement":[{"attributeTag":"dob","lower":"19300101","type":"AttributeInRange","upper":"99990101"}]},"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}',
|
|
123
|
+
wallet_provider: "Concordium Browser",
|
|
124
|
+
status: ProofStatus.PENDING,
|
|
152
125
|
};
|
|
153
126
|
|
|
154
|
-
|
|
155
|
-
const result = await verifyConcordiumSignature(proof, { testMode: true });
|
|
156
|
-
|
|
127
|
+
const result = await verifyConcordiumSignature(proof);
|
|
157
128
|
expect(result.status).toBe(ProofStatus.FAILED);
|
|
158
129
|
});
|
|
159
130
|
|
|
160
|
-
it("
|
|
131
|
+
it("returns failed proof when credential is missing credentialSubject", async () => {
|
|
161
132
|
const proof: SignatureProof = {
|
|
162
133
|
address:
|
|
163
134
|
"ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
164
135
|
attestation:
|
|
165
|
-
"
|
|
166
|
-
proof: 'invalid json',
|
|
167
|
-
did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
|
|
168
|
-
status: ProofStatus.PENDING,
|
|
169
|
-
wallet_provider: "Concordium Wallet",
|
|
136
|
+
"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
|
|
170
137
|
type: ProofTypes.CONCORDIUM,
|
|
138
|
+
did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
139
|
+
proof:
|
|
140
|
+
'{"presentationContext":"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}',
|
|
141
|
+
wallet_provider: "Concordium Browser",
|
|
142
|
+
status: ProofStatus.PENDING,
|
|
171
143
|
};
|
|
172
144
|
|
|
173
|
-
|
|
174
|
-
const result = await verifyConcordiumSignature(proof, { testMode: true });
|
|
175
|
-
|
|
145
|
+
const result = await verifyConcordiumSignature(proof);
|
|
176
146
|
expect(result.status).toBe(ProofStatus.FAILED);
|
|
177
147
|
});
|
|
178
148
|
|
|
179
|
-
it("
|
|
149
|
+
it("returns failed proof with tampered proof signature", async () => {
|
|
180
150
|
const proof: SignatureProof = {
|
|
181
|
-
address:
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
status: ProofStatus.PENDING,
|
|
186
|
-
wallet_provider: "Test Wallet",
|
|
151
|
+
address:
|
|
152
|
+
"ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
153
|
+
attestation:
|
|
154
|
+
"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
|
|
187
155
|
type: ProofTypes.CONCORDIUM,
|
|
156
|
+
did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
157
|
+
proof:
|
|
158
|
+
'{"presentationContext":"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"credentialSubject":{"id":"did:ccd:testnet:cred:8f73851550a5d2c2ed4df215731cf9e3f33614d4be6c1c336f0f8858522c94afa34a759258a2b3281f9bacd0a8a3cd09","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[{"proof":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","type":"AttributeInRange"}],"type":"ConcordiumZKProofV3"},"statement":[{"attributeTag":"dob","lower":"19300101","type":"AttributeInRange","upper":"99990101"}]},"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}',
|
|
159
|
+
wallet_provider: "Concordium Browser",
|
|
160
|
+
status: ProofStatus.PENDING,
|
|
188
161
|
};
|
|
189
162
|
|
|
190
|
-
const result = await verifyConcordiumSignature(proof
|
|
191
|
-
|
|
163
|
+
const result = await verifyConcordiumSignature(proof);
|
|
192
164
|
expect(result.status).toBe(ProofStatus.FAILED);
|
|
193
|
-
});
|
|
165
|
+
}, 15000);
|
|
194
166
|
|
|
195
|
-
|
|
196
|
-
it("tests with known valid mainnet account", async () => {
|
|
197
|
-
// This test uses a potentially valid account address for testing
|
|
198
|
-
// In a real scenario, you'd want to use an account that actually exists
|
|
167
|
+
it("returns failed proof with mismatched presentationContext and attestation", async () => {
|
|
199
168
|
const proof: SignatureProof = {
|
|
200
169
|
address:
|
|
201
|
-
"ccd:9dd9ca4d19e9393877d2c44b70f89acb:
|
|
170
|
+
"ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
202
171
|
attestation:
|
|
203
|
-
"
|
|
172
|
+
"0000000000000000000000000000000000000000000000000000000000000000",
|
|
204
173
|
type: ProofTypes.CONCORDIUM,
|
|
205
|
-
did: "did:
|
|
174
|
+
did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
|
|
206
175
|
proof:
|
|
207
|
-
'{"
|
|
176
|
+
'{"presentationContext":"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"credentialSubject":{"id":"did:ccd:testnet:cred:8f73851550a5d2c2ed4df215731cf9e3f33614d4be6c1c336f0f8858522c94afa34a759258a2b3281f9bacd0a8a3cd09","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[{"proof":"a9f68ef2cb10cfe4b7734ab0464e6af952e9ebeb7d8701c00d6894ee64ee9f110d6dfbbdfd7de737ebaf0d3e85512ae98e7047e9db92d7d8bf5c4414f30443e13461bda7da17bd7a1e95d65add4e6fdc2d2da7338b9e2b71359a834df422d90682d490d1dc266806981c48cc39c1d7dfad0c86364cc1607d15dffe36a5f67b229f34567adcd9bbe249e9b3e521ecc4ccb260512d37da8cc7e61b224be723140b00412dfb57deb54ed8f0cd74e1cf31f64b50e649b7c262433f167c9e490cb06f4b12a3da45d25c45a76cfb94e21bf1b5950bb4edc83730ef882ecc376ff0e83957ef73535557ea865be9391f7948b6b34f5778025fcc681b469b9d1922e7605f1e768c0fd4280b6c1f338d7922a545536d5fb3c0e88b1da8b17020c9c26b544c00000007b15c3faa19a2f749f762be0f87820a299de52ccbea2e38dcc2c1275eca95e808bda09bffc4afdc0affca5e40308b2b00a1bf346359c0effc8c0cafbb17eb217cee0ac4239e053b5e058cd14fe8b687259255c5c9c110f11926f31760cf8ce4d2ae8fa37bdf19efaf35661fd2d31d45c535735e5af7871afbe8bea0783b01c1e66f62df3fce23309a7f743ebc7e27d9a5951821b5031c443310bb777ad4a04c3111ec017b18cdecab0a107f1a086bbfa513a2ed61e72665b8332e9f4809b04595a6bf76ed0ea0b38ca897aa5811a17df35bdab1a0a02ab6a8379acde4c9c01908de128821739028359e5173e7222fca0b8cad1206e0e6ca938a7bae3864445ca22ee60f7de2aceecb98d1f40a0c7a0519af09df4d7c536017c0236b7e579c73ea8aeb20762d31b3daa5a966f4f5824eb51ea037b3686cbd8a9d8daa0927fbe26ac1d9d41f0d96ce1896e6eaa69cfa88a09682079406a50718a47539999be699d4bfe2a414a13dc39d96a911e5113fab61a09b66346c74bc67c2bdbace3dcc74eca8e30bf2e64b2f577b0a4a9d484ff7696771e8e347bf870f51a9ef2d88b2bac8f53a0ae5ba2a537121b26977a57d585d8ef41596a8663ebada0626fcc4a919c115c8f766216abb76355970c5431152087d8e727aea7b245912ee35ca169bdf43ab89f1d2c857038faf337b7f0cfe16162fb43339a879159290116b95d64379d2a927b4b99e5aa50e784aa0b0ee930b17b31c778e09d3dd8879578179dc17e70f92252d0cc2226da0e70a0c1d6a375cca572818034242443f5f5e3d7bacff47d380e2698afc0e67fefc66fbb4e336744bde829f68ede5e4fac6315fd005471045fdee23a6f9c43ff69a2adddc597372f8acd2f02507ed99e195396412f181b207a3711ec68ce5b0811c46fe1be324fb64e8866d2850c16c33bb953a6ddf1bd8650f26db28333a7e2fd69f32e64778efd02c60730a96adad0fb12fa872d2c48268075c5335724f03d118b1e32593dc71e4141a5febcd078c1a85f21dd36d35af77","type":"AttributeInRange"}],"type":"ConcordiumZKProofV3"},"statement":[{"attributeTag":"dob","lower":"19300101","type":"AttributeInRange","upper":"99990101"}]},"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}',
|
|
177
|
+
wallet_provider: "Concordium Browser",
|
|
208
178
|
status: ProofStatus.PENDING,
|
|
209
|
-
wallet_provider: "Concordium Wallet",
|
|
210
179
|
};
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const result = await verifyConcordiumSignature(proof, {
|
|
214
|
-
network: "mainnet",
|
|
215
|
-
testMode: false,
|
|
216
|
-
timeout: 10000
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
// Should fail because this account likely doesn't exist, but the network call should be made
|
|
180
|
+
|
|
181
|
+
const result = await verifyConcordiumSignature(proof);
|
|
220
182
|
expect(result.status).toBe(ProofStatus.FAILED);
|
|
221
183
|
}, 15000);
|
|
222
184
|
});
|
package/src/tests/cosmos.test.ts
CHANGED
|
@@ -5,6 +5,10 @@ import {
|
|
|
5
5
|
SignatureProof,
|
|
6
6
|
} from "@notabene/javascript-sdk";
|
|
7
7
|
import { verifyCosmosSignature } from "../cosmos";
|
|
8
|
+
import { bech32 } from "bech32";
|
|
9
|
+
import { serializeSignDoc } from "@cosmjs/amino";
|
|
10
|
+
import { secp256k1 } from "@noble/curves/secp256k1";
|
|
11
|
+
import { keccak_256 } from "@noble/hashes/sha3";
|
|
8
12
|
|
|
9
13
|
describe("verifyCosmosSignature", () => {
|
|
10
14
|
it("returns verified proof when valid message and address", async () => {
|
|
@@ -48,4 +52,139 @@ describe("verifyCosmosSignature", () => {
|
|
|
48
52
|
|
|
49
53
|
expect(result.status).toBe(ProofStatus.FAILED);
|
|
50
54
|
});
|
|
55
|
+
|
|
56
|
+
// Signed with Keplr mobile on Celestia (PAY-1209). Every Cosmos SDK chain has its own
|
|
57
|
+
// bech32 prefix, so the address must be derived under the prefix the proof carries.
|
|
58
|
+
const celestiaProof: SignatureProof = {
|
|
59
|
+
type: ProofTypes.COSMOS,
|
|
60
|
+
did: "did:pkh:cosmos:celestia:celestia15f22nghu889nxwxgfak2th3z7fjq9atqvfw0vk",
|
|
61
|
+
status: ProofStatus.PENDING,
|
|
62
|
+
attestation:
|
|
63
|
+
"I certify that\n\ncosmos:celestia account celestia15f22nghu889nxwxgfak2th3z7fjq9atqvfw0vk\n\nbelonged to undefined\n\non Wed, 16 Sep 2026 15:34:35 GMT",
|
|
64
|
+
address:
|
|
65
|
+
"cosmos:celestia:celestia15f22nghu889nxwxgfak2th3z7fjq9atqvfw0vk",
|
|
66
|
+
proof:
|
|
67
|
+
"oI0CC9GVzR8rLrwXkXoMHnZWaGSL6GYq9G469p5OCKUB49WwAzVCqhTY8+mfkyFn//mIe6lEXfqjka8TWKkkag==",
|
|
68
|
+
wallet_provider: "Keplr (Wallet Connect)",
|
|
69
|
+
chainSpecificData: {
|
|
70
|
+
pub_key: {
|
|
71
|
+
type: "tendermint/PubKeySecp256k1",
|
|
72
|
+
value: "AqijUvgyDbKc0qm9M0M371FMiu384gJxXd67avWYEX1e",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
it("verifies a proof from a cosmos chain with a non-cosmos bech32 prefix", async () => {
|
|
78
|
+
const result = await verifyCosmosSignature(celestiaProof);
|
|
79
|
+
|
|
80
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("fails when the public key does not derive to the signed address under its own prefix", async () => {
|
|
84
|
+
const result = await verifyCosmosSignature({
|
|
85
|
+
...celestiaProof,
|
|
86
|
+
chainSpecificData: {
|
|
87
|
+
pub_key: {
|
|
88
|
+
type: "tendermint/PubKeySecp256k1",
|
|
89
|
+
// the cosmoshub-4 key from the first test
|
|
90
|
+
value: "Ak8k3jYgH4srYi1ygG0GWLrdbF7VwQgjiLqjifuJSsmU",
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Injective (and other ethermint-style chains) use eth-secp256k1 keys: the address is
|
|
99
|
+
// keccak256 of the uncompressed key, and ADR-036 signs a keccak256 digest (PAY-1210).
|
|
100
|
+
// Keplr's own verifier: @keplr-wallet/cosmos verifyADR36AminoSignDoc, algo "ethsecp256k1".
|
|
101
|
+
describe("eth-secp256k1 chains", () => {
|
|
102
|
+
const privateKey = Uint8Array.from({ length: 32 }, (_, i) => i + 1);
|
|
103
|
+
const pubKey = secp256k1.getPublicKey(privateKey, true);
|
|
104
|
+
const uncompressed = secp256k1.getPublicKey(privateKey, false).slice(1);
|
|
105
|
+
const injAddress = bech32.encode(
|
|
106
|
+
"inj",
|
|
107
|
+
bech32.toWords(keccak_256(uncompressed).slice(-20))
|
|
108
|
+
);
|
|
109
|
+
const attestation = `I certify that\n\ncosmos:injective-1 account ${injAddress}\n\nbelonged to did:key:test\n\non Wed, 16 Sep 2026 16:00:00 GMT`;
|
|
110
|
+
const signDoc = {
|
|
111
|
+
chain_id: "",
|
|
112
|
+
account_number: "0",
|
|
113
|
+
sequence: "0",
|
|
114
|
+
fee: { amount: [], gas: "0" },
|
|
115
|
+
msgs: [
|
|
116
|
+
{
|
|
117
|
+
type: "sign/MsgSignData",
|
|
118
|
+
value: {
|
|
119
|
+
signer: injAddress,
|
|
120
|
+
data: Buffer.from(attestation).toString("base64"),
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
memo: "",
|
|
125
|
+
};
|
|
126
|
+
const sign = (digest: Uint8Array) =>
|
|
127
|
+
Buffer.from(
|
|
128
|
+
secp256k1.sign(digest, privateKey).toCompactRawBytes()
|
|
129
|
+
).toString("base64");
|
|
130
|
+
|
|
131
|
+
const injectiveProof = (proof: string): SignatureProof => ({
|
|
132
|
+
type: ProofTypes.COSMOS,
|
|
133
|
+
did: `did:pkh:cosmos:injective-1:${injAddress}`,
|
|
134
|
+
status: ProofStatus.PENDING,
|
|
135
|
+
attestation,
|
|
136
|
+
address: `cosmos:injective-1:${injAddress}`,
|
|
137
|
+
proof,
|
|
138
|
+
wallet_provider: "Keplr (Wallet Connect)",
|
|
139
|
+
chainSpecificData: {
|
|
140
|
+
pub_key: {
|
|
141
|
+
type: "ethsecp256k1/PubKey",
|
|
142
|
+
value: Buffer.from(pubKey).toString("base64"),
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("verifies an inj1 address signed over a keccak256 digest", async () => {
|
|
148
|
+
const proof = injectiveProof(sign(keccak_256(serializeSignDoc(signDoc))));
|
|
149
|
+
|
|
150
|
+
const result = await verifyCosmosSignature(proof);
|
|
151
|
+
|
|
152
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Signed with Keplr mobile on Injective via WalletConnect. Keplr labels the key
|
|
156
|
+
// "tendermint/PubKeySecp256k1" even though it is eth-secp256k1, which is why the
|
|
157
|
+
// verifier picks the algorithm from the address rather than from pub_key.type.
|
|
158
|
+
it("verifies a real Keplr proof from injective-1", async () => {
|
|
159
|
+
const result = await verifyCosmosSignature({
|
|
160
|
+
type: ProofTypes.COSMOS,
|
|
161
|
+
did: "did:pkh:cosmos:injective-1:inj1jnk39fazhpf36kpmp6848cz7w2w9mnk8yvt7hj",
|
|
162
|
+
status: ProofStatus.PENDING,
|
|
163
|
+
attestation:
|
|
164
|
+
"I certify that\n\ncosmos:injective-1 account inj1jnk39fazhpf36kpmp6848cz7w2w9mnk8yvt7hj\n\nbelonged to undefined\n\non Wed, 16 Sep 2026 16:30:22 GMT",
|
|
165
|
+
address:
|
|
166
|
+
"cosmos:injective-1:inj1jnk39fazhpf36kpmp6848cz7w2w9mnk8yvt7hj",
|
|
167
|
+
proof:
|
|
168
|
+
"7aOueGwF+KrmBpx61+kjjUQq9qzqcIDA4xgG2lWtjtx8nqXIN++2u2kN6vfti1U9freaxxWgZF8zCPsr/TInoA==",
|
|
169
|
+
wallet_provider: "Keplr (Wallet Connect)",
|
|
170
|
+
chainSpecificData: {
|
|
171
|
+
pub_key: {
|
|
172
|
+
type: "tendermint/PubKeySecp256k1",
|
|
173
|
+
value: "AsEu8nenas+bG7oo+oNXET6nTV+dSSOutCD7SttV34HT",
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
expect(result.status).toBe(ProofStatus.VERIFIED);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it("fails an inj1 address signed over a sha256 digest", async () => {
|
|
182
|
+
const { sha256 } = await import("@noble/hashes/sha2");
|
|
183
|
+
const proof = injectiveProof(sign(sha256(serializeSignDoc(signDoc))));
|
|
184
|
+
|
|
185
|
+
const result = await verifyCosmosSignature(proof);
|
|
186
|
+
|
|
187
|
+
expect(result.status).toBe(ProofStatus.FAILED);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
51
190
|
});
|
package/src/tests/index.test.ts
CHANGED
|
@@ -328,13 +328,13 @@ describe("verifyProof", () => {
|
|
|
328
328
|
|
|
329
329
|
describe("Concordium", () => {
|
|
330
330
|
const proof: SignatureProof = {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
331
|
+
"address": "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3Soqc3mEU5WC4R9Qho9fxm4CJ1157q6qsJbPvtGV8iT8FbQdv2",
|
|
332
|
+
"attestation": "b74a8e64f1568f1fb22a57b033bc8ef2b8f6ba23ff8e831e7abfbb671927fda1",
|
|
333
|
+
"type": ProofTypes.CONCORDIUM,
|
|
334
|
+
"did": "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3Soqc3mEU5WC4R9Qho9fxm4CJ1157q6qsJbPvtGV8iT8FbQdv2",
|
|
335
|
+
"proof": "{\"presentationContext\":\"b74a8e64f1568f1fb22a57b033bc8ef2b8f6ba23ff8e831e7abfbb671927fda1\",\"proof\":{\"created\":\"2025-12-10T10:39:14.395Z\",\"proofValue\":[],\"type\":\"ConcordiumWeakLinkingProofV1\"},\"type\":\"VerifiablePresentation\",\"verifiableCredential\":[{\"credentialSubject\":{\"id\":\"did:ccd:mainnet:cred:91a1f28bc42222096856a54fb157f7c80b9827457d4ece682b9592bca964948f01dce51a7deb392ea9bd0c1e1630d17b\",\"proof\":{\"created\":\"2025-12-10T10:39:14.395Z\",\"proofValue\":[{\"proof\":\"988f08d03bc8adaac4d51986dfaafe70874ab3bb22e8c09c32da5bfcd0ff0407203770533220e74ba4386acb36f7b7288e38c461279f7edf6f41b8b285d629280a5ca297e7fc42155222c5b1ad3cc74f770d5c87addbba6935ade425460b1616a587d9c45a4676f7fc751b31110cd37b25998c61d7d85c84e4db155491665e556778a9784e557799f06531bafe6b4b8ca2ce386d66f7759079eaff74b1e519550c9d137a13851c0987ee434feb6dae0ca659d67661b27e92d7cca9567a1a6ecd2175c574f5a6c2f4691597cbf3680f65abab72633d050746211c56961277064d694a31c2a93ef3b64c4957ff8261978a53d8b65d40ff23ddc7ee65d0ea0817702be58fbaec3954322e00667c6c94736eba8d3aa3f2686b89f257ca34c90ae1200000000785c57df969a45b25b1d39bdb388d33a756147e98f285891e83ce58eab3bb1f466c25a0946fc62513b16f3f02397b15418ebc131b5e1a8c0f05d6983cd3c44cc40ab8364c1aa209c2e8c0e8e84694587053542fd5cbb918f025723a5a0c200f08875728874571f50cb8b54d1c8629a10c76f0a982ad667efcfa280943f7c8753d3fa859a8d5d9837e6bdd5026d54546a3ae5918055208b5d2f77e0206d7861b4c472c634ec4cece107aeb14c42fe3d801aba38aa38e15785152e7c061561a5594a6cabb34f469b3121c15437df5d6ba0638ba3a192f2106d07e2f7bfd73310f669d3e8bdeb1b43244455d7bd7fa5917a1af2b23dc3433dac68ee4571bea2b0c22ce2ed665e22cee5676b9c3de0169926e72c847f7e3f2caa671e55ab5c4530205845b08ee12bba954f4a41e5638b05043a93ed212f402273c2b477f95f7b82ddbe4621f1758f80fcec726df755a76d0f585eda201dff2b91147cca5eae5d5319b7e1438c0f4af42b9fe4f7e845d0c643328ddd5dead96bfd345ae972312650a9ab6e6d7fa3d3f5d1fe68e5ff513095e3caa5bb21bec64dae007e62b4494986ac40b9e14b61255a84ea51780b8439adaeeae0b83a8bcee382491dd8e7b2f1921e8eeffe39a45bffd470b5a8f74d82ccdb8ccda651c387844f61704cc04f51d65fb9069900cb1febfc0b2ba02ffc857c45c12a7b306440e6627995d67353e9f6327b6f6cfa6ad0b859ea904f087a5b29a888043ba21ccb3e36da0a2da797310c2f2ce56c275d6fc48b60aade4b4e6bb6ff62d5f5be1a529c8d71cab2b0904fa306cb779a897872f5f047df7c7bee150ca6be6f3ad840a862ecc0793bb27f0594ff8741a4ab426b53d72acbdbde6c20a7c4399ca181d81a4b0ac437c23220f52ff8e9095ae35a53f8cd58913c4999a8153b656fabb162feafe8fc8708eaeb2b5ce0d347e5733cd685783271eaf564e05efce61996686ee9f50663204841ff30416061721a5cab8e1c80708809b58d2bc9c402da453e486ce08e0ec6c72c1f0e9dc15\",\"type\":\"AttributeInRange\"}],\"type\":\"ConcordiumZKProofV3\"},\"statement\":[{\"attributeTag\":\"dob\",\"lower\":\"19300101\",\"type\":\"AttributeInRange\",\"upper\":\"99990101\"}]},\"issuer\":\"did:ccd:mainnet:idp:1\",\"type\":[\"VerifiableCredential\",\"ConcordiumVerifiableCredential\"]}]}",
|
|
336
|
+
"wallet_provider": "Concordium Browser",
|
|
337
|
+
"status": ProofStatus.PENDING
|
|
338
338
|
};
|
|
339
339
|
|
|
340
340
|
it("should verify proof", async () => {
|
package/src/tests/xrpl.test.ts
CHANGED
|
@@ -28,21 +28,23 @@ describe("verifyPersonalSignXRPL", async () => {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
const existingXRPLPublicKey = 'ED33CE53E97678D4C9016377B944716D80833098E666BB2BE160C5BE84C310E1D7';
|
|
32
|
+
|
|
33
|
+
function existingXRPLProof(): SignatureProof {
|
|
32
34
|
return {
|
|
33
35
|
type: ProofTypes.XRP_ED25519,
|
|
34
|
-
proof: '
|
|
35
|
-
address: `xrpl:1:
|
|
36
|
-
did: `did:pkh:xrpl:1:
|
|
36
|
+
proof: '30DC5E837D23A408414E270C9E79E7BEE4450D4FD89E1A42B94BA5C36728011A0D47BF6036464BDDE842F90F72BFD0F521504EF8F181F41421B1748EAA8DBC04',
|
|
37
|
+
address: `xrpl:1:rUe11XPvngHVzwS61wDwj98unworBbRDNc`,
|
|
38
|
+
did: `did:pkh:xrpl:1:rUe11XPvngHVzwS61wDwj98unworBbRDNc`,
|
|
37
39
|
status: ProofStatus.PENDING,
|
|
38
40
|
wallet_provider: "XRPL",
|
|
39
|
-
attestation: "I certify that\n\nxrpl:1 account
|
|
41
|
+
attestation: "I certify that\n\nxrpl:1 account rUe11XPvngHVzwS61wDwj98unworBbRDNc\n\nbelonged to did:key:z6Mkq3vnQfZFLVe2UXBUTgonfEhzYr9QF7xvkSSpdt9LXeY6\n\non Thu, 06 Mar 2025 10:34:43 GMT"
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
it("returns verified proof when valid existing XRPL proof", async () => {
|
|
44
46
|
const proof = existingXRPLProof();
|
|
45
|
-
const result = await verifyPersonalSignXRPL(proof,
|
|
47
|
+
const result = await verifyPersonalSignXRPL(proof, existingXRPLPublicKey);
|
|
46
48
|
expect(result.status).toBe(ProofStatus.VERIFIED);
|
|
47
49
|
});
|
|
48
50
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bitcoin.ts"],"names":["ProofStatus","ProofTypes","Verifier","base64","secp256k1","createBase58check","Hash","encodeLength","bech32"],"mappings":"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","file":"bitcoin-3CW4MNAW.cjs","sourcesContent":["import {\n ProofStatus,\n ProofTypes,\n SignatureProof,\n} from \"@notabene/javascript-sdk\";\n\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { base64, bech32, createBase58check } from \"@scure/base\";\nimport { Hash } from \"ox\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { SignatureType } from \"@noble/curves/abstract/weierstrass\";\nimport { Verifier } from \"bip322-js\";\n\nenum SEGWIT_TYPES {\n P2WPKH = \"p2wpkh\",\n P2SH_P2WPKH = \"p2sh(p2wpkh)\",\n}\n\ninterface ChainConfig {\n messagePrefix: string;\n pubKeyHashVersion: number | Uint8Array;\n scriptHashVersion: number | Uint8Array;\n bech32Prefix?: string;\n isTestnet?: boolean;\n}\n\nconst CHAIN_CONFIGS: Record<string, ChainConfig> = {\n bitcoin: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n bitcoincash: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n litecoin: {\n messagePrefix: \"\\u0019Litecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x30, // L... or M...\n scriptHashVersion: 0x32, // 3... or M...\n bech32Prefix: \"ltc\",\n isTestnet: false,\n },\n dogecoin: {\n messagePrefix: \"\\u0019Dogecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x1e, // D...\n scriptHashVersion: 0x16, // A...\n isTestnet: false,\n },\n dash: {\n messagePrefix: \"\\u0019DarkCoin Signed Message:\\n\",\n pubKeyHashVersion: 0x4c, // X...\n scriptHashVersion: 0x10, // 7...\n isTestnet: false,\n },\n zcash: {\n messagePrefix: \"\\u0018Zcash Signed Message:\\n\",\n pubKeyHashVersion: Uint8Array.from([0x1c, 0xb8]), // <-- FIXED\n scriptHashVersion: Uint8Array.from([0x1c, 0xbd]),\n isTestnet: false,\n },\n\n testnet: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x6f, // m or n\n scriptHashVersion: 0xc4, // 2\n bech32Prefix: \"tb\",\n isTestnet: true,\n },\n};\n\nenum DerivationMode {\n LEGACY = \"Legacy\",\n NATIVE = \"Native SegWit\",\n SEGWIT = \"SegWit\",\n P2SH_SEGWIT = \"p2sh\",\n BCH = \"Bitcoin Cash\",\n ETHEREUM = \"Ethereum\",\n DOGECOIN = \"Dogecoin\",\n UNKNOWN = \"Unknown\",\n}\n\nexport async function verifyBTCSignature(\n proof: SignatureProof\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"bip122\") return { ...proof, status: ProofStatus.FAILED };\n\n // Map chainId to our chain configuration\n const chainConfig = getChainConfig(address);\n if (!chainConfig) return { ...proof, status: ProofStatus.FAILED };\n\n const isZcash = address.startsWith(\"t1\") || address.startsWith(\"t3\");\n if (isZcash) {\n return verifyBIP137(address, proof, chainConfig);\n }\n\n // Use BIP322 for testnet addresses\n if (chainConfig.isTestnet) {\n return verifyBIP322(address, proof);\n }\n\n // Check if this is a Taproot address (bc1p or tb1p)\n const isTaproot = address.startsWith(\"bc1p\") || address.startsWith(\"tb1p\");\n\n // For Taproot addresses with BIP-137 proof type, use BIP-322 verification\n // since BIP-137 doesn't officially support Taproot\n if (isTaproot && proof.type === ProofTypes.BIP137) {\n return verifyBIP322(address, proof);\n }\n\n try {\n switch (proof.type) {\n case ProofTypes.BIP137:\n return verifyBIP137(address, proof, chainConfig);\n case ProofTypes.BIP322:\n return verifyBIP322(address, proof);\n default:\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n } catch {\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n}\n\nfunction getChainConfig(address: string): ChainConfig {\n if (\n address.startsWith(\"1\") ||\n address.startsWith(\"3\") ||\n address.startsWith(\"bc1\")\n ) {\n return CHAIN_CONFIGS[\"bitcoin\"];\n }\n if (address.startsWith(\"t1\") || address.startsWith(\"t3\")) {\n return CHAIN_CONFIGS[\"zcash\"];\n }\n if (\n address.startsWith(\"L\") ||\n address.startsWith(\"M\") ||\n address.startsWith(\"ltc1\")\n ) {\n return CHAIN_CONFIGS[\"litecoin\"];\n }\n if (address.startsWith(\"D\") || address.startsWith(\"A\")) {\n return CHAIN_CONFIGS[\"dogecoin\"];\n }\n if (address.startsWith(\"X\") || address.startsWith(\"7\")) {\n return CHAIN_CONFIGS[\"dash\"];\n }\n if (address.startsWith(\"q\")) {\n return CHAIN_CONFIGS[\"bitcoincash\"];\n }\n if (address.startsWith(\"tb1\")) {\n return CHAIN_CONFIGS[\"testnet\"];\n }\n\n return CHAIN_CONFIGS[\"bitcoin\"];\n}\n\nfunction verifyBIP322(address: string, proof: SignatureProof) {\n const { attestation, proof: signatureProof } = proof;\n const verified = Verifier.verifySignature(\n address,\n attestation,\n signatureProof\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction verifyBIP137(\n address: string,\n proof: SignatureProof,\n chainConfig: ChainConfig\n) {\n const derivationMode = getDerivationMode(address);\n\n // For legacy addresses (starting with \"1\"), never use SegWit encoding\n // For P2SH addresses (starting with \"3\"), use SegWit encoding if they have bech32 support\n // For native SegWit addresses (bc1, tb1, ltc1), always use SegWit encoding\n const useSegwitEncoding = Boolean(\n chainConfig.bech32Prefix &&\n (derivationMode === DerivationMode.NATIVE ||\n (derivationMode === DerivationMode.SEGWIT && !address.startsWith(\"1\")))\n );\n\n const verified = verify(\n proof.attestation,\n address,\n proof.proof,\n useSegwitEncoding,\n chainConfig\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction getDerivationMode(address: string) {\n if (address.match(\"^(bc1|tb1|ltc1).*\")) {\n return DerivationMode.NATIVE;\n } else if (address.match(\"^[32M].*\")) {\n return DerivationMode.SEGWIT;\n } else if (address.match(\"^[1nmL].*\")) {\n return DerivationMode.LEGACY;\n } else if (address.match(\"^(D).*\")) {\n return DerivationMode.DOGECOIN;\n } else if (address.match(\"^(q).*\")) {\n return DerivationMode.BCH;\n } else if (address.match(\"^(t1|t3).*\")) {\n return DerivationMode.LEGACY; // Zcash addresses\n } else if (address.match(\"^[X7].*\")) {\n return DerivationMode.LEGACY; // Dash addresses\n } else {\n throw new Error(\n \"INVALID ADDRESS: \"\n .concat(address)\n .concat(\" is not a valid or a supported address\")\n );\n }\n}\n\ntype DecodedSignature = {\n compressed: boolean;\n segwitType?: SEGWIT_TYPES;\n signature: SignatureType;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const sigbytes = base64.decode(proof);\n if (sigbytes.length !== 65) throw new Error(\"Invalid signature length\");\n const flagByte = sigbytes[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n const compressed = !!(flagByte & 12); // Are there cases that aren't compressed?\n const recovery = flagByte & 3;\n const signature = secp256k1.Signature.fromCompact(sigbytes.slice(1));\n\n return {\n compressed,\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n signature: signature.addRecoveryBit(recovery),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n chainConfig: ChainConfig\n) {\n const { compressed, segwitType, signature } = decodeSignature(proof);\n if (checkSegwitAlways && !compressed) {\n throw new Error(\n \"checkSegwitAlways can only be used with a compressed pubkey signature flagbyte\"\n );\n }\n const hash = magicHash(attestation, chainConfig.messagePrefix);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyBytes = publicKey.toRawBytes(compressed);\n const publicKeyHash = hash160(publicKeyBytes);\n let actual: string = \"\";\n\n // Special handling for Bitcoin Cash addresses\n if (address.startsWith(\"q\")) {\n // For BCH, we'll compare the public key hash directly since we're getting a CashAddr\n // Convert the CashAddr to legacy format for comparison\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n // Legacy P2PKH addresses in BCH start with '1' just like BTC\n // Source: https://reference.cash/protocol/blockchain/encoding/cashaddr#legacy-address-format\n return actual.startsWith(\"1\");\n }\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n // Fallback to legacy if bech32 not supported\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n }\n } else {\n // For addresses starting with \"3\" (P2SH), try both P2SH-P2WPKH and legacy P2SH encodings if segwitType is undefined\n if (address.startsWith(\"3\") && !segwitType) {\n // P2SH-P2WPKH: script hash of the redeem script (OP_0 <pubkeyhash>)\n const redeemScript = new Uint8Array(22);\n redeemScript[0] = 0x00; // OP_0\n redeemScript[1] = 0x14; // push 20 bytes\n redeemScript.set(publicKeyHash, 2);\n const redeemScriptHash = hash160(redeemScript);\n const p2shP2wpkh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n redeemScriptHash\n );\n // Legacy P2SH: script hash of the public key\n const legacyP2sh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n if (address === p2shP2wpkh || address === legacyP2sh) {\n return true;\n }\n actual = legacyP2sh; // fallback for error reporting\n } else if (address.startsWith(\"bc1q\") || address.startsWith(\"tb1q\") || address.startsWith(\"ltc1q\")) {\n // For native SegWit P2WPKH addresses (bc1q/tb1q/ltc1q), always encode as bech32\n // This handles Ledger wallets that sign without segwit flags\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n } else if (checkSegwitAlways && chainConfig.bech32Prefix) {\n try {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n // if address is bech32 it is not p2sh\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (e) {\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(\n version: number | Uint8Array,\n publicKeyHash: Uint8Array\n) {\n const prefixBytes =\n typeof version === \"number\" ? Uint8Array.of(version) : version; // Accept raw Uint8Array for Zcash\n\n const payload = new Uint8Array(prefixBytes.length + publicKeyHash.length);\n payload.set(prefixBytes);\n payload.set(publicKeyHash, prefixBytes.length);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: string, messagePrefix: string) {\n const prefix = new TextEncoder().encode(messagePrefix);\n const message = new TextEncoder().encode(attestation);\n const length = encodeLength(message.length).buffer;\n const buffer = new Uint8Array(\n prefix.length + length.byteLength + message.length\n );\n buffer.set(prefix);\n buffer.set(new Uint8Array(length), prefix.length);\n buffer.set(message, prefix.length + length.byteLength);\n return hash256(buffer);\n}\n\nfunction encodeBech32Address(\n publicKeyHash: Uint8Array,\n prefix: string = \"bc\"\n): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(prefix, bwords);\n}\n\nfunction hash256(buffer: Uint8Array): Uint8Array {\n return Hash.sha256(Hash.sha256(buffer));\n}\n\nfunction hash160(buffer: Uint8Array): Uint8Array {\n return Hash.ripemd160(Hash.sha256(buffer));\n}\n"]}
|