ox 0.10.2 → 0.10.4
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/CHANGELOG.md +14 -0
- package/_cjs/tempo/SignatureEnvelope.js +66 -7
- package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/tempo/SignatureEnvelope.js +169 -6
- package/_esm/tempo/SignatureEnvelope.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/tempo/SignatureEnvelope.d.ts +132 -3
- package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/package.json +2 -2
- package/tempo/SignatureEnvelope.test.ts +554 -1
- package/tempo/SignatureEnvelope.ts +205 -3
- package/version.ts +1 -1
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Address,
|
|
3
|
+
Hex,
|
|
4
|
+
P256,
|
|
5
|
+
PublicKey,
|
|
6
|
+
Secp256k1,
|
|
7
|
+
Signature,
|
|
8
|
+
WebAuthnP256,
|
|
9
|
+
WebCryptoP256,
|
|
10
|
+
} from 'ox'
|
|
2
11
|
import { describe, expect, test } from 'vitest'
|
|
3
12
|
import * as SignatureEnvelope from './SignatureEnvelope.js'
|
|
4
13
|
|
|
@@ -477,6 +486,24 @@ describe('deserialize', () => {
|
|
|
477
486
|
})
|
|
478
487
|
})
|
|
479
488
|
|
|
489
|
+
test('behavior: deserializes signature with magic identifier', () => {
|
|
490
|
+
const serialized = SignatureEnvelope.serialize(
|
|
491
|
+
{ signature: signature_secp256k1, type: 'secp256k1' },
|
|
492
|
+
{ magic: true },
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
const envelope = SignatureEnvelope.deserialize(serialized)
|
|
496
|
+
|
|
497
|
+
expect(envelope).toMatchObject({
|
|
498
|
+
signature: {
|
|
499
|
+
r: signature_secp256k1.r,
|
|
500
|
+
s: signature_secp256k1.s,
|
|
501
|
+
yParity: signature_secp256k1.yParity,
|
|
502
|
+
},
|
|
503
|
+
type: 'secp256k1',
|
|
504
|
+
})
|
|
505
|
+
})
|
|
506
|
+
|
|
480
507
|
test('error: throws on invalid size', () => {
|
|
481
508
|
expect(() =>
|
|
482
509
|
SignatureEnvelope.deserialize('0xdeadbeef'),
|
|
@@ -520,6 +547,26 @@ describe('deserialize', () => {
|
|
|
520
547
|
})
|
|
521
548
|
})
|
|
522
549
|
|
|
550
|
+
test('behavior: deserializes P256 signature with magic identifier', () => {
|
|
551
|
+
const serialized = SignatureEnvelope.serialize(signature_p256, {
|
|
552
|
+
magic: true,
|
|
553
|
+
})
|
|
554
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
555
|
+
|
|
556
|
+
expect(deserialized).toMatchObject({
|
|
557
|
+
signature: {
|
|
558
|
+
r: signature_p256.signature.r,
|
|
559
|
+
s: signature_p256.signature.s,
|
|
560
|
+
},
|
|
561
|
+
publicKey: {
|
|
562
|
+
x: signature_p256.publicKey.x,
|
|
563
|
+
y: signature_p256.publicKey.y,
|
|
564
|
+
},
|
|
565
|
+
prehash: signature_p256.prehash,
|
|
566
|
+
type: 'p256',
|
|
567
|
+
})
|
|
568
|
+
})
|
|
569
|
+
|
|
523
570
|
test('error: throws on invalid P256 signature length', () => {
|
|
524
571
|
// P256 signature with wrong length (should be 130 bytes total, but only 100)
|
|
525
572
|
const invalidSig = `0x01${'00'.repeat(100)}` as `0x${string}`
|
|
@@ -557,6 +604,29 @@ describe('deserialize', () => {
|
|
|
557
604
|
})
|
|
558
605
|
})
|
|
559
606
|
|
|
607
|
+
test('behavior: deserializes WebAuthn signature with magic identifier', () => {
|
|
608
|
+
const serialized = SignatureEnvelope.serialize(signature_webauthn, {
|
|
609
|
+
magic: true,
|
|
610
|
+
})
|
|
611
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
612
|
+
|
|
613
|
+
expect(deserialized).toMatchObject({
|
|
614
|
+
signature: {
|
|
615
|
+
r: signature_webauthn.signature.r,
|
|
616
|
+
s: signature_webauthn.signature.s,
|
|
617
|
+
},
|
|
618
|
+
publicKey: {
|
|
619
|
+
x: signature_webauthn.publicKey.x,
|
|
620
|
+
y: signature_webauthn.publicKey.y,
|
|
621
|
+
},
|
|
622
|
+
metadata: {
|
|
623
|
+
authenticatorData: signature_webauthn.metadata.authenticatorData,
|
|
624
|
+
clientDataJSON: signature_webauthn.metadata.clientDataJSON,
|
|
625
|
+
},
|
|
626
|
+
type: 'webAuthn',
|
|
627
|
+
})
|
|
628
|
+
})
|
|
629
|
+
|
|
560
630
|
test('error: throws on invalid WebAuthn signature length', () => {
|
|
561
631
|
// WebAuthn signature too short (must be at least 129 bytes: 1 type + 128 signature data)
|
|
562
632
|
const invalidSig = `0x02${'00'.repeat(100)}` as const
|
|
@@ -676,6 +746,20 @@ describe('deserialize', () => {
|
|
|
676
746
|
`)
|
|
677
747
|
})
|
|
678
748
|
|
|
749
|
+
test('behavior: deserializes keychain signature with magic identifier', () => {
|
|
750
|
+
const serialized = SignatureEnvelope.serialize(
|
|
751
|
+
signature_keychain_secp256k1,
|
|
752
|
+
{ magic: true },
|
|
753
|
+
)
|
|
754
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
755
|
+
|
|
756
|
+
expect(deserialized).toMatchObject({
|
|
757
|
+
userAddress: signature_keychain_secp256k1.userAddress,
|
|
758
|
+
inner: SignatureEnvelope.from(signature_secp256k1),
|
|
759
|
+
type: 'keychain',
|
|
760
|
+
})
|
|
761
|
+
})
|
|
762
|
+
|
|
679
763
|
test('error: throws on invalid keychain signature length', () => {
|
|
680
764
|
// Keychain signature too short (must be at least 21 bytes: 1 type + 20 address)
|
|
681
765
|
const invalidSig = `0x03${'00'.repeat(10)}` as const
|
|
@@ -916,6 +1000,20 @@ describe('serialize', () => {
|
|
|
916
1000
|
|
|
917
1001
|
expect(serialized).toBe(Signature.toHex(signature_secp256k1))
|
|
918
1002
|
})
|
|
1003
|
+
|
|
1004
|
+
test('behavior: serializes with magic identifier', () => {
|
|
1005
|
+
const envelope: SignatureEnvelope.SignatureEnvelope = {
|
|
1006
|
+
signature: signature_secp256k1,
|
|
1007
|
+
type: 'secp256k1',
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
const serialized = SignatureEnvelope.serialize(envelope, { magic: true })
|
|
1011
|
+
|
|
1012
|
+
expect(serialized.endsWith(SignatureEnvelope.magicBytes.slice(2))).toBe(
|
|
1013
|
+
true,
|
|
1014
|
+
)
|
|
1015
|
+
expect(Hex.size(serialized)).toBe(65 + 32) // signature + magic identifier
|
|
1016
|
+
})
|
|
919
1017
|
})
|
|
920
1018
|
|
|
921
1019
|
describe('p256', () => {
|
|
@@ -936,6 +1034,17 @@ describe('serialize', () => {
|
|
|
936
1034
|
// Last byte should be 0x00 for false
|
|
937
1035
|
expect(serialized.slice(-2)).toBe('00')
|
|
938
1036
|
})
|
|
1037
|
+
|
|
1038
|
+
test('behavior: serializes with magic identifier', () => {
|
|
1039
|
+
const serialized = SignatureEnvelope.serialize(signature_p256, {
|
|
1040
|
+
magic: true,
|
|
1041
|
+
})
|
|
1042
|
+
|
|
1043
|
+
expect(serialized.endsWith(SignatureEnvelope.magicBytes.slice(2))).toBe(
|
|
1044
|
+
true,
|
|
1045
|
+
)
|
|
1046
|
+
expect(Hex.size(serialized)).toBe(130 + 32) // signature + magic identifier
|
|
1047
|
+
})
|
|
939
1048
|
})
|
|
940
1049
|
|
|
941
1050
|
describe('webAuthn', () => {
|
|
@@ -966,6 +1075,23 @@ describe('serialize', () => {
|
|
|
966
1075
|
signature_webauthn.metadata.clientDataJSON,
|
|
967
1076
|
)
|
|
968
1077
|
})
|
|
1078
|
+
|
|
1079
|
+
test('behavior: serializes with magic identifier', () => {
|
|
1080
|
+
const serialized = SignatureEnvelope.serialize(signature_webauthn, {
|
|
1081
|
+
magic: true,
|
|
1082
|
+
})
|
|
1083
|
+
|
|
1084
|
+
expect(serialized.endsWith(SignatureEnvelope.magicBytes.slice(2))).toBe(
|
|
1085
|
+
true,
|
|
1086
|
+
)
|
|
1087
|
+
|
|
1088
|
+
const authDataLength =
|
|
1089
|
+
(signature_webauthn.metadata.authenticatorData.length - 2) / 2
|
|
1090
|
+
const clientDataLength = signature_webauthn.metadata.clientDataJSON.length
|
|
1091
|
+
const expectedSize = 1 + authDataLength + clientDataLength + 128 + 32 // type + data + signature components + magic
|
|
1092
|
+
|
|
1093
|
+
expect(Hex.size(serialized)).toBe(expectedSize)
|
|
1094
|
+
})
|
|
969
1095
|
})
|
|
970
1096
|
|
|
971
1097
|
describe('keychain', () => {
|
|
@@ -1043,6 +1169,18 @@ describe('serialize', () => {
|
|
|
1043
1169
|
},
|
|
1044
1170
|
})
|
|
1045
1171
|
})
|
|
1172
|
+
|
|
1173
|
+
test('behavior: serializes with magic identifier', () => {
|
|
1174
|
+
const serialized = SignatureEnvelope.serialize(
|
|
1175
|
+
signature_keychain_secp256k1,
|
|
1176
|
+
{ magic: true },
|
|
1177
|
+
)
|
|
1178
|
+
|
|
1179
|
+
expect(serialized.endsWith(SignatureEnvelope.magicBytes.slice(2))).toBe(
|
|
1180
|
+
true,
|
|
1181
|
+
)
|
|
1182
|
+
expect(Hex.size(serialized)).toBe(1 + 20 + 65 + 32) // type + address + secp256k1 + magic
|
|
1183
|
+
})
|
|
1046
1184
|
})
|
|
1047
1185
|
|
|
1048
1186
|
describe('roundtrip', () => {
|
|
@@ -1065,6 +1203,27 @@ describe('serialize', () => {
|
|
|
1065
1203
|
type: 'secp256k1',
|
|
1066
1204
|
})
|
|
1067
1205
|
})
|
|
1206
|
+
|
|
1207
|
+
test('behavior: roundtrips serialize with magic -> deserialize', () => {
|
|
1208
|
+
const envelope: SignatureEnvelope.Secp256k1 = {
|
|
1209
|
+
signature: signature_secp256k1,
|
|
1210
|
+
type: 'secp256k1',
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
const serialized = SignatureEnvelope.serialize(envelope, {
|
|
1214
|
+
magic: true,
|
|
1215
|
+
})
|
|
1216
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
1217
|
+
|
|
1218
|
+
expect(deserialized).toMatchObject({
|
|
1219
|
+
signature: {
|
|
1220
|
+
r: signature_secp256k1.r,
|
|
1221
|
+
s: signature_secp256k1.s,
|
|
1222
|
+
yParity: signature_secp256k1.yParity,
|
|
1223
|
+
},
|
|
1224
|
+
type: 'secp256k1',
|
|
1225
|
+
})
|
|
1226
|
+
})
|
|
1068
1227
|
})
|
|
1069
1228
|
|
|
1070
1229
|
describe('p256', () => {
|
|
@@ -1093,6 +1252,26 @@ describe('serialize', () => {
|
|
|
1093
1252
|
|
|
1094
1253
|
expect(deserialized.prehash).toBe(false)
|
|
1095
1254
|
})
|
|
1255
|
+
|
|
1256
|
+
test('behavior: roundtrips serialize with magic -> deserialize', () => {
|
|
1257
|
+
const serialized = SignatureEnvelope.serialize(signature_p256, {
|
|
1258
|
+
magic: true,
|
|
1259
|
+
})
|
|
1260
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
1261
|
+
|
|
1262
|
+
expect(deserialized).toMatchObject({
|
|
1263
|
+
signature: {
|
|
1264
|
+
r: signature_p256.signature.r,
|
|
1265
|
+
s: signature_p256.signature.s,
|
|
1266
|
+
},
|
|
1267
|
+
publicKey: {
|
|
1268
|
+
x: signature_p256.publicKey.x,
|
|
1269
|
+
y: signature_p256.publicKey.y,
|
|
1270
|
+
},
|
|
1271
|
+
prehash: signature_p256.prehash,
|
|
1272
|
+
type: 'p256',
|
|
1273
|
+
})
|
|
1274
|
+
})
|
|
1096
1275
|
})
|
|
1097
1276
|
|
|
1098
1277
|
describe('webAuthn', () => {
|
|
@@ -1137,6 +1316,29 @@ describe('serialize', () => {
|
|
|
1137
1316
|
|
|
1138
1317
|
expect(deserialized.metadata?.clientDataJSON).toBe(longClientData)
|
|
1139
1318
|
})
|
|
1319
|
+
|
|
1320
|
+
test('behavior: roundtrips serialize with magic -> deserialize', () => {
|
|
1321
|
+
const serialized = SignatureEnvelope.serialize(signature_webauthn, {
|
|
1322
|
+
magic: true,
|
|
1323
|
+
})
|
|
1324
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
1325
|
+
|
|
1326
|
+
expect(deserialized).toMatchObject({
|
|
1327
|
+
signature: {
|
|
1328
|
+
r: signature_webauthn.signature.r,
|
|
1329
|
+
s: signature_webauthn.signature.s,
|
|
1330
|
+
},
|
|
1331
|
+
publicKey: {
|
|
1332
|
+
x: signature_webauthn.publicKey.x,
|
|
1333
|
+
y: signature_webauthn.publicKey.y,
|
|
1334
|
+
},
|
|
1335
|
+
metadata: {
|
|
1336
|
+
authenticatorData: signature_webauthn.metadata.authenticatorData,
|
|
1337
|
+
clientDataJSON: signature_webauthn.metadata.clientDataJSON,
|
|
1338
|
+
},
|
|
1339
|
+
type: 'webAuthn',
|
|
1340
|
+
})
|
|
1341
|
+
})
|
|
1140
1342
|
})
|
|
1141
1343
|
|
|
1142
1344
|
describe('keychain', () => {
|
|
@@ -1203,6 +1405,69 @@ describe('serialize', () => {
|
|
|
1203
1405
|
}
|
|
1204
1406
|
`)
|
|
1205
1407
|
})
|
|
1408
|
+
|
|
1409
|
+
test('behavior: roundtrips serialize with magic -> deserialize with secp256k1 inner', () => {
|
|
1410
|
+
const serialized = SignatureEnvelope.serialize(
|
|
1411
|
+
signature_keychain_secp256k1,
|
|
1412
|
+
{ magic: true },
|
|
1413
|
+
)
|
|
1414
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
1415
|
+
|
|
1416
|
+
expect(deserialized).toMatchObject(signature_keychain_secp256k1)
|
|
1417
|
+
})
|
|
1418
|
+
|
|
1419
|
+
test('behavior: roundtrips serialize with magic -> deserialize with p256 inner', () => {
|
|
1420
|
+
const serialized = SignatureEnvelope.serialize(
|
|
1421
|
+
signature_keychain_p256,
|
|
1422
|
+
{ magic: true },
|
|
1423
|
+
)
|
|
1424
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
1425
|
+
|
|
1426
|
+
expect(deserialized).toMatchObject({
|
|
1427
|
+
type: 'keychain',
|
|
1428
|
+
userAddress: signature_keychain_p256.userAddress,
|
|
1429
|
+
inner: {
|
|
1430
|
+
type: 'p256',
|
|
1431
|
+
prehash: signature_p256.prehash,
|
|
1432
|
+
publicKey: {
|
|
1433
|
+
x: signature_p256.publicKey.x,
|
|
1434
|
+
y: signature_p256.publicKey.y,
|
|
1435
|
+
},
|
|
1436
|
+
signature: {
|
|
1437
|
+
r: signature_p256.signature.r,
|
|
1438
|
+
s: signature_p256.signature.s,
|
|
1439
|
+
},
|
|
1440
|
+
},
|
|
1441
|
+
})
|
|
1442
|
+
})
|
|
1443
|
+
|
|
1444
|
+
test('behavior: roundtrips serialize with magic -> deserialize with webAuthn inner', () => {
|
|
1445
|
+
const serialized = SignatureEnvelope.serialize(
|
|
1446
|
+
signature_keychain_webauthn,
|
|
1447
|
+
{ magic: true },
|
|
1448
|
+
)
|
|
1449
|
+
const deserialized = SignatureEnvelope.deserialize(serialized)
|
|
1450
|
+
|
|
1451
|
+
expect(deserialized).toMatchObject({
|
|
1452
|
+
type: 'keychain',
|
|
1453
|
+
userAddress: signature_keychain_webauthn.userAddress,
|
|
1454
|
+
inner: {
|
|
1455
|
+
type: 'webAuthn',
|
|
1456
|
+
metadata: {
|
|
1457
|
+
authenticatorData: signature_webauthn.metadata.authenticatorData,
|
|
1458
|
+
clientDataJSON: signature_webauthn.metadata.clientDataJSON,
|
|
1459
|
+
},
|
|
1460
|
+
publicKey: {
|
|
1461
|
+
x: signature_webauthn.publicKey.x,
|
|
1462
|
+
y: signature_webauthn.publicKey.y,
|
|
1463
|
+
},
|
|
1464
|
+
signature: {
|
|
1465
|
+
r: signature_webauthn.signature.r,
|
|
1466
|
+
s: signature_webauthn.signature.s,
|
|
1467
|
+
},
|
|
1468
|
+
},
|
|
1469
|
+
})
|
|
1470
|
+
})
|
|
1206
1471
|
})
|
|
1207
1472
|
})
|
|
1208
1473
|
|
|
@@ -1326,6 +1591,294 @@ describe('validate', () => {
|
|
|
1326
1591
|
})
|
|
1327
1592
|
})
|
|
1328
1593
|
|
|
1594
|
+
describe('verify', () => {
|
|
1595
|
+
describe('secp256k1', () => {
|
|
1596
|
+
test('behavior: verifies valid signature with publicKey', () => {
|
|
1597
|
+
const privateKey = Secp256k1.randomPrivateKey()
|
|
1598
|
+
const publicKey = Secp256k1.getPublicKey({ privateKey })
|
|
1599
|
+
const payload = '0xdeadbeef' as const
|
|
1600
|
+
|
|
1601
|
+
const signature = Secp256k1.sign({ payload, privateKey })
|
|
1602
|
+
const envelope = SignatureEnvelope.from(signature)
|
|
1603
|
+
|
|
1604
|
+
expect(
|
|
1605
|
+
SignatureEnvelope.verify(envelope, {
|
|
1606
|
+
payload,
|
|
1607
|
+
publicKey,
|
|
1608
|
+
}),
|
|
1609
|
+
).toBe(true)
|
|
1610
|
+
})
|
|
1611
|
+
|
|
1612
|
+
test('behavior: verifies valid signature with address', () => {
|
|
1613
|
+
const privateKey = Secp256k1.randomPrivateKey()
|
|
1614
|
+
const publicKey = Secp256k1.getPublicKey({ privateKey })
|
|
1615
|
+
const address = Address.fromPublicKey(publicKey)
|
|
1616
|
+
const payload = '0xdeadbeef' as const
|
|
1617
|
+
|
|
1618
|
+
const signature = Secp256k1.sign({ payload, privateKey })
|
|
1619
|
+
const envelope = SignatureEnvelope.from(signature)
|
|
1620
|
+
|
|
1621
|
+
expect(
|
|
1622
|
+
SignatureEnvelope.verify(envelope, {
|
|
1623
|
+
payload,
|
|
1624
|
+
address,
|
|
1625
|
+
}),
|
|
1626
|
+
).toBe(true)
|
|
1627
|
+
})
|
|
1628
|
+
|
|
1629
|
+
test('behavior: returns false for wrong publicKey', () => {
|
|
1630
|
+
const privateKey = Secp256k1.randomPrivateKey()
|
|
1631
|
+
const wrongPrivateKey = Secp256k1.randomPrivateKey()
|
|
1632
|
+
const wrongPublicKey = Secp256k1.getPublicKey({
|
|
1633
|
+
privateKey: wrongPrivateKey,
|
|
1634
|
+
})
|
|
1635
|
+
const payload = '0xdeadbeef' as const
|
|
1636
|
+
|
|
1637
|
+
const signature = Secp256k1.sign({ payload, privateKey })
|
|
1638
|
+
const envelope = SignatureEnvelope.from(signature)
|
|
1639
|
+
|
|
1640
|
+
expect(
|
|
1641
|
+
SignatureEnvelope.verify(envelope, {
|
|
1642
|
+
payload,
|
|
1643
|
+
publicKey: wrongPublicKey,
|
|
1644
|
+
}),
|
|
1645
|
+
).toBe(false)
|
|
1646
|
+
})
|
|
1647
|
+
|
|
1648
|
+
test('behavior: returns false for wrong payload', () => {
|
|
1649
|
+
const privateKey = Secp256k1.randomPrivateKey()
|
|
1650
|
+
const publicKey = Secp256k1.getPublicKey({ privateKey })
|
|
1651
|
+
const payload = '0xdeadbeef' as const
|
|
1652
|
+
|
|
1653
|
+
const signature = Secp256k1.sign({ payload, privateKey })
|
|
1654
|
+
const envelope = SignatureEnvelope.from(signature)
|
|
1655
|
+
|
|
1656
|
+
expect(
|
|
1657
|
+
SignatureEnvelope.verify(envelope, {
|
|
1658
|
+
payload: '0xcafebabe',
|
|
1659
|
+
publicKey,
|
|
1660
|
+
}),
|
|
1661
|
+
).toBe(false)
|
|
1662
|
+
})
|
|
1663
|
+
})
|
|
1664
|
+
|
|
1665
|
+
describe('p256', () => {
|
|
1666
|
+
test('behavior: verifies valid signature with publicKey', () => {
|
|
1667
|
+
const privateKey = P256.randomPrivateKey()
|
|
1668
|
+
const publicKey = P256.getPublicKey({ privateKey })
|
|
1669
|
+
const payload = '0xdeadbeef' as const
|
|
1670
|
+
|
|
1671
|
+
const signature = P256.sign({ payload, privateKey })
|
|
1672
|
+
const envelope = SignatureEnvelope.from({
|
|
1673
|
+
prehash: false,
|
|
1674
|
+
publicKey,
|
|
1675
|
+
signature,
|
|
1676
|
+
})
|
|
1677
|
+
|
|
1678
|
+
expect(
|
|
1679
|
+
SignatureEnvelope.verify(envelope, {
|
|
1680
|
+
payload,
|
|
1681
|
+
publicKey,
|
|
1682
|
+
}),
|
|
1683
|
+
).toBe(true)
|
|
1684
|
+
})
|
|
1685
|
+
|
|
1686
|
+
test('behavior: verifies valid signature with address', () => {
|
|
1687
|
+
const privateKey = P256.randomPrivateKey()
|
|
1688
|
+
const publicKey = P256.getPublicKey({ privateKey })
|
|
1689
|
+
const address = Address.fromPublicKey(publicKey)
|
|
1690
|
+
const payload = '0xdeadbeef' as const
|
|
1691
|
+
|
|
1692
|
+
const signature = P256.sign({ payload, privateKey })
|
|
1693
|
+
const envelope = SignatureEnvelope.from({
|
|
1694
|
+
prehash: false,
|
|
1695
|
+
publicKey,
|
|
1696
|
+
signature,
|
|
1697
|
+
})
|
|
1698
|
+
|
|
1699
|
+
expect(
|
|
1700
|
+
SignatureEnvelope.verify(envelope, {
|
|
1701
|
+
payload,
|
|
1702
|
+
address,
|
|
1703
|
+
}),
|
|
1704
|
+
).toBe(true)
|
|
1705
|
+
})
|
|
1706
|
+
|
|
1707
|
+
test('behavior: returns false for mismatched publicKey', () => {
|
|
1708
|
+
const privateKey = P256.randomPrivateKey()
|
|
1709
|
+
const publicKey = P256.getPublicKey({ privateKey })
|
|
1710
|
+
const wrongPrivateKey = P256.randomPrivateKey()
|
|
1711
|
+
const wrongPublicKey = P256.getPublicKey({ privateKey: wrongPrivateKey })
|
|
1712
|
+
const payload = '0xdeadbeef' as const
|
|
1713
|
+
|
|
1714
|
+
const signature = P256.sign({ payload, privateKey })
|
|
1715
|
+
const envelope = SignatureEnvelope.from({
|
|
1716
|
+
prehash: false,
|
|
1717
|
+
publicKey,
|
|
1718
|
+
signature,
|
|
1719
|
+
})
|
|
1720
|
+
|
|
1721
|
+
expect(
|
|
1722
|
+
SignatureEnvelope.verify(envelope, {
|
|
1723
|
+
payload,
|
|
1724
|
+
publicKey: wrongPublicKey,
|
|
1725
|
+
}),
|
|
1726
|
+
).toBe(false)
|
|
1727
|
+
})
|
|
1728
|
+
|
|
1729
|
+
test('behavior: returns false for wrong payload', () => {
|
|
1730
|
+
const privateKey = P256.randomPrivateKey()
|
|
1731
|
+
const publicKey = P256.getPublicKey({ privateKey })
|
|
1732
|
+
const payload = '0xdeadbeef' as const
|
|
1733
|
+
|
|
1734
|
+
const signature = P256.sign({ payload, privateKey })
|
|
1735
|
+
const envelope = SignatureEnvelope.from({
|
|
1736
|
+
prehash: false,
|
|
1737
|
+
publicKey,
|
|
1738
|
+
signature,
|
|
1739
|
+
})
|
|
1740
|
+
|
|
1741
|
+
expect(
|
|
1742
|
+
SignatureEnvelope.verify(envelope, {
|
|
1743
|
+
payload: '0xcafebabe',
|
|
1744
|
+
publicKey,
|
|
1745
|
+
}),
|
|
1746
|
+
).toBe(false)
|
|
1747
|
+
})
|
|
1748
|
+
})
|
|
1749
|
+
|
|
1750
|
+
describe('webCryptoP256', () => {
|
|
1751
|
+
test('behavior: verifies valid signature with publicKey', async () => {
|
|
1752
|
+
const { privateKey, publicKey } = await WebCryptoP256.createKeyPair()
|
|
1753
|
+
const payload = '0xdeadbeef' as const
|
|
1754
|
+
|
|
1755
|
+
const signature = await WebCryptoP256.sign({ payload, privateKey })
|
|
1756
|
+
const envelope = SignatureEnvelope.from({
|
|
1757
|
+
prehash: true,
|
|
1758
|
+
publicKey,
|
|
1759
|
+
signature,
|
|
1760
|
+
})
|
|
1761
|
+
|
|
1762
|
+
expect(
|
|
1763
|
+
SignatureEnvelope.verify(envelope, {
|
|
1764
|
+
payload,
|
|
1765
|
+
publicKey,
|
|
1766
|
+
}),
|
|
1767
|
+
).toBe(true)
|
|
1768
|
+
})
|
|
1769
|
+
|
|
1770
|
+
test('behavior: verifies valid signature with address', async () => {
|
|
1771
|
+
const { privateKey, publicKey } = await WebCryptoP256.createKeyPair()
|
|
1772
|
+
const address = Address.fromPublicKey(publicKey)
|
|
1773
|
+
const payload = '0xdeadbeef' as const
|
|
1774
|
+
|
|
1775
|
+
const signature = await WebCryptoP256.sign({ payload, privateKey })
|
|
1776
|
+
const envelope = SignatureEnvelope.from({
|
|
1777
|
+
prehash: true,
|
|
1778
|
+
publicKey,
|
|
1779
|
+
signature,
|
|
1780
|
+
})
|
|
1781
|
+
|
|
1782
|
+
expect(
|
|
1783
|
+
SignatureEnvelope.verify(envelope, {
|
|
1784
|
+
payload,
|
|
1785
|
+
address,
|
|
1786
|
+
}),
|
|
1787
|
+
).toBe(true)
|
|
1788
|
+
})
|
|
1789
|
+
|
|
1790
|
+
test('behavior: returns false for mismatched publicKey', async () => {
|
|
1791
|
+
const { privateKey, publicKey } = await WebCryptoP256.createKeyPair()
|
|
1792
|
+
const { publicKey: wrongPublicKey } = await WebCryptoP256.createKeyPair()
|
|
1793
|
+
const payload = '0xdeadbeef' as const
|
|
1794
|
+
|
|
1795
|
+
const signature = await WebCryptoP256.sign({ payload, privateKey })
|
|
1796
|
+
const envelope = SignatureEnvelope.from({
|
|
1797
|
+
prehash: true,
|
|
1798
|
+
publicKey,
|
|
1799
|
+
signature,
|
|
1800
|
+
})
|
|
1801
|
+
|
|
1802
|
+
expect(
|
|
1803
|
+
SignatureEnvelope.verify(envelope, {
|
|
1804
|
+
payload,
|
|
1805
|
+
publicKey: wrongPublicKey,
|
|
1806
|
+
}),
|
|
1807
|
+
).toBe(false)
|
|
1808
|
+
})
|
|
1809
|
+
|
|
1810
|
+
test('behavior: returns false for wrong payload', async () => {
|
|
1811
|
+
const { privateKey, publicKey } = await WebCryptoP256.createKeyPair()
|
|
1812
|
+
const payload = '0xdeadbeef' as const
|
|
1813
|
+
|
|
1814
|
+
const signature = await WebCryptoP256.sign({ payload, privateKey })
|
|
1815
|
+
const envelope = SignatureEnvelope.from({
|
|
1816
|
+
prehash: true,
|
|
1817
|
+
publicKey,
|
|
1818
|
+
signature,
|
|
1819
|
+
})
|
|
1820
|
+
|
|
1821
|
+
expect(
|
|
1822
|
+
SignatureEnvelope.verify(envelope, {
|
|
1823
|
+
payload: '0xcafebabe',
|
|
1824
|
+
publicKey,
|
|
1825
|
+
}),
|
|
1826
|
+
).toBe(false)
|
|
1827
|
+
})
|
|
1828
|
+
})
|
|
1829
|
+
|
|
1830
|
+
describe('webAuthn', () => {
|
|
1831
|
+
test('behavior: returns false for mismatched publicKey', () => {
|
|
1832
|
+
const wrongPrivateKey = P256.randomPrivateKey()
|
|
1833
|
+
const wrongPublicKey = P256.getPublicKey({ privateKey: wrongPrivateKey })
|
|
1834
|
+
const payload = '0xdeadbeef' as const
|
|
1835
|
+
|
|
1836
|
+
expect(
|
|
1837
|
+
SignatureEnvelope.verify(signature_webauthn, {
|
|
1838
|
+
payload,
|
|
1839
|
+
publicKey: wrongPublicKey,
|
|
1840
|
+
}),
|
|
1841
|
+
).toBe(false)
|
|
1842
|
+
})
|
|
1843
|
+
|
|
1844
|
+
test('behavior: returns false for mismatched address', () => {
|
|
1845
|
+
const wrongPrivateKey = P256.randomPrivateKey()
|
|
1846
|
+
const wrongPublicKey = P256.getPublicKey({ privateKey: wrongPrivateKey })
|
|
1847
|
+
const wrongAddress = Address.fromPublicKey(wrongPublicKey)
|
|
1848
|
+
const payload = '0xdeadbeef' as const
|
|
1849
|
+
|
|
1850
|
+
expect(
|
|
1851
|
+
SignatureEnvelope.verify(signature_webauthn, {
|
|
1852
|
+
payload,
|
|
1853
|
+
address: wrongAddress,
|
|
1854
|
+
}),
|
|
1855
|
+
).toBe(false)
|
|
1856
|
+
})
|
|
1857
|
+
})
|
|
1858
|
+
|
|
1859
|
+
describe('keychain', () => {
|
|
1860
|
+
test('behavior: returns false for keychain signatures', () => {
|
|
1861
|
+
const privateKey = Secp256k1.randomPrivateKey()
|
|
1862
|
+
const secp256k1PublicKey = Secp256k1.getPublicKey({ privateKey })
|
|
1863
|
+
const payload = '0xdeadbeef' as const
|
|
1864
|
+
|
|
1865
|
+
const signature = Secp256k1.sign({ payload, privateKey })
|
|
1866
|
+
const innerEnvelope = SignatureEnvelope.from(signature)
|
|
1867
|
+
const envelope = SignatureEnvelope.from({
|
|
1868
|
+
userAddress: '0x1234567890123456789012345678901234567890',
|
|
1869
|
+
inner: innerEnvelope,
|
|
1870
|
+
})
|
|
1871
|
+
|
|
1872
|
+
expect(
|
|
1873
|
+
SignatureEnvelope.verify(envelope, {
|
|
1874
|
+
payload,
|
|
1875
|
+
publicKey: secp256k1PublicKey,
|
|
1876
|
+
}),
|
|
1877
|
+
).toBe(false)
|
|
1878
|
+
})
|
|
1879
|
+
})
|
|
1880
|
+
})
|
|
1881
|
+
|
|
1329
1882
|
describe('fromRpc', () => {
|
|
1330
1883
|
describe('secp256k1', () => {
|
|
1331
1884
|
test('behavior: converts RPC secp256k1 signature', () => {
|