@@ -5,15 +5,15 @@ import { ECDSASigValue } from "@peculiar/asn1-ecc";
5
5
import { AsnParser } from "@peculiar/asn1-schema" ;
6
6
import { bigintToBuf , bufToBigint } from "bigint-conversion" ;
7
7
import { assert , expect } from "chai" ;
8
+ import { randomBytes } from "crypto" ;
9
+ import { parseEther , ZeroAddress } from "ethers" ;
8
10
import * as hre from "hardhat" ;
11
+ import { encodeAbiParameters , Hex , hexToBytes , toHex } from "viem" ;
9
12
import { SmartAccount , Wallet } from "zksync-ethers" ;
13
+ import { base64UrlToUint8Array } from "zksync-sso/utils" ;
10
14
11
- import { SsoAccount__factory , WebAuthValidator , WebAuthValidator__factory } from "../typechain-types" ;
15
+ import { SsoAccount__factory , WebAuthValidator , WebAuthValidator__factory , WebAuthValidatorTest , WebAuthValidatorTest__factory } from "../typechain-types" ;
12
16
import { ContractFixtures , getProvider , getWallet , LOCAL_RICH_WALLETS , logInfo , RecordedResponse } from "./utils" ;
13
- import { base64UrlToUint8Array } from "zksync-sso/utils" ;
14
- import { encodeAbiParameters , Hex , hexToBytes , toHex } from "viem" ;
15
- import { randomBytes } from "crypto" ;
16
- import { parseEther , ZeroAddress } from "ethers" ;
17
17
18
18
/**
19
19
* Decode from a Base64URL-encoded string to an ArrayBuffer. Best used when converting a
@@ -36,6 +36,14 @@ async function deployValidator(wallet: Wallet): Promise<WebAuthValidator> {
36
36
return WebAuthValidator__factory . connect ( await validator . getAddress ( ) , wallet ) ;
37
37
}
38
38
39
+ async function deployP256Tester ( wallet : Wallet ) : Promise < WebAuthValidatorTest > {
40
+ const deployer : Deployer = new Deployer ( hre , wallet ) ;
41
+ const passkeyValidatorArtifact = await deployer . loadArtifact ( "WebAuthValidatorTest" ) ;
42
+
43
+ const validator = await deployer . deploy ( passkeyValidatorArtifact , [ ] ) ;
44
+ return WebAuthValidatorTest__factory . connect ( await validator . getAddress ( ) , wallet ) ;
45
+ }
46
+
39
47
/**
40
48
* COSE Keys
41
49
*
@@ -338,9 +346,6 @@ function encodeFatSignature(
338
346
clientDataJSON : string ;
339
347
signature : string ;
340
348
} ,
341
- contracts : {
342
- passkey : string ;
343
- } ,
344
349
) {
345
350
const signature = unwrapEC2Signature ( base64UrlToUint8Array ( passkeyResponse . signature ) ) ;
346
351
return encodeAbiParameters (
@@ -358,7 +363,7 @@ function encodeFatSignature(
358
363
}
359
364
360
365
async function rawVerify (
361
- passkeyValidator : WebAuthValidator ,
366
+ passkeyValidator : WebAuthValidatorTest ,
362
367
authenticatorData : string ,
363
368
clientData : string ,
364
369
b64SignedChallange : string ,
@@ -370,7 +375,7 @@ async function rawVerify(
370
375
const rs = unwrapEC2Signature ( toBuffer ( b64SignedChallange ) ) ;
371
376
const publicKeys = await getPublicKey ( publicKeyEs256Bytes ) ;
372
377
373
- return await passkeyValidator . rawVerify ( hashedData , rs , publicKeys ) ;
378
+ return await passkeyValidator . p256Verify ( hashedData , rs , publicKeys ) ;
374
379
}
375
380
376
381
async function verifyKeyStorage (
@@ -390,11 +395,11 @@ function encodeKeyFromHex(hexStrings: [Hex, Hex], domain: string) {
390
395
// the same as the ethers: new AbiCoder().encode(["bytes32[2]", "string"], [bytes, domain]);
391
396
return encodeAbiParameters (
392
397
[
393
- { name : ' publicKeys' , type : ' bytes32[2]' } ,
394
- { name : ' domain' , type : ' string' } ,
398
+ { name : " publicKeys" , type : " bytes32[2]" } ,
399
+ { name : " domain" , type : " string" } ,
395
400
] ,
396
- [ hexStrings , domain ]
397
- )
401
+ [ hexStrings , domain ] ,
402
+ ) ;
398
403
}
399
404
400
405
function encodeKeyFromBytes ( bytes : [ Uint8Array , Uint8Array ] , domain : string ) {
@@ -428,8 +433,8 @@ async function validateSignatureTest(
428
433
{ name : "clientDataJson" , type : "string" } ,
429
434
{ name : "rs" , type : "bytes32[2]" } ,
430
435
] ,
431
- [ toHex ( authData ) , sampleClientString , [ toHex ( rNormalization ( generatedSignature . r ) ) , toHex ( sNormalization ( generatedSignature . s ) ) ] ]
432
- )
436
+ [ toHex ( authData ) , sampleClientString , [ toHex ( rNormalization ( generatedSignature . r ) ) , toHex ( sNormalization ( generatedSignature . s ) ) ] ] ,
437
+ ) ;
433
438
return await passkeyValidator . validateSignature ( transactionHash , fatSignature ) ;
434
439
}
435
440
@@ -480,7 +485,7 @@ describe("Passkey validation", function () {
480
485
const receipt = await fundTx . wait ( ) ;
481
486
expect ( receipt . status ) . to . eq ( 1 , "send funds to proxy account" ) ;
482
487
483
- return { passKeyModuleContract, sampleDomain, proxyAccountAddress, generatedR1Key, passKeyModuleAddress }
488
+ return { passKeyModuleContract, sampleDomain, proxyAccountAddress, generatedR1Key, passKeyModuleAddress } ;
484
489
}
485
490
486
491
it ( "should deploy proxy account via factory" , async ( ) => {
@@ -523,16 +528,16 @@ describe("Passkey validation", function () {
523
528
] , [
524
529
toHex ( authData ) ,
525
530
sampleClientString ,
526
- [ toHex ( normalizeR ( generatedSignature . r ) ) , toHex ( normalizeS ( generatedSignature . s ) ) ]
527
- ] )
531
+ [ toHex ( normalizeR ( generatedSignature . r ) ) , toHex ( normalizeS ( generatedSignature . s ) ) ] ,
532
+ ] ) ;
528
533
529
534
const moduleSignature = encodeAbiParameters (
530
535
[ { name : "signature" , type : "bytes" } , { name : "moduleAddress" , type : "address" } , { name : "validatorData" , type : "bytes" } ] ,
531
536
[ fatSignature , passKeyModuleAddress , "0x" ] ) ;
532
537
return moduleSignature ;
533
538
} ,
534
539
address : proxyAccountAddress ,
535
- secret : wallet . privateKey , //generatedR1Key.privateKey,
540
+ secret : wallet . privateKey , // generatedR1Key.privateKey,
536
541
} , provider ) ;
537
542
538
543
const aaTransaction = {
@@ -653,7 +658,6 @@ describe("Passkey validation", function () {
653
658
clientDataJSON : ethersResponse . clientData ,
654
659
signature : ethersResponse . b64SignedChallenge ,
655
660
} ,
656
- { passkey : publicKeys [ 0 ] } ,
657
661
) ;
658
662
659
663
const initData = encodeKeyFromHex ( publicKeys , "http://localhost:5173" ) ;
@@ -671,14 +675,14 @@ describe("Passkey validation", function () {
671
675
// fully expand the raw validation to compare step by step
672
676
describe ( "P256 precompile comparison" , ( ) => {
673
677
it ( "should verify passkey" , async function ( ) {
674
- const passkeyValidator = await deployValidator ( wallet ) ;
678
+ const passkeyValidator = await deployP256Tester ( wallet ) ;
675
679
676
680
// 37 bytes
677
681
const authenticatorData = "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MFAAAABQ" ;
678
- const clientData =
679
- "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZFhPM3ctdWdycS00SkdkZUJLNDFsZFk1V2lNd0ZORDkiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUxNzMiLCJjcm9zc09yaWdpbiI6ZmFsc2UsIm90aGVyX2tleXNfY2FuX2JlX2FkZGVkX2hlcmUiOiJkbyBub3QgY29tcGFyZSBjbGllbnREYXRhSlNPTiBhZ2FpbnN0IGEgdGVtcGxhdGUuIFNlZSBodHRwczovL2dvby5nbC95YWJQZXgifQ" ;
680
- const b64SignedChallenge =
681
- "MEUCIQCYrSUCR_QUPAhvRNUVfYiJC2JlOKuqf4gx7i129n9QxgIgaY19A9vAAObuTQNs5_V9kZFizwRpUFpiRVW_dglpR2A" ;
682
+ const clientData
683
+ = "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZFhPM3ctdWdycS00SkdkZUJLNDFsZFk1V2lNd0ZORDkiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUxNzMiLCJjcm9zc09yaWdpbiI6ZmFsc2UsIm90aGVyX2tleXNfY2FuX2JlX2FkZGVkX2hlcmUiOiJkbyBub3QgY29tcGFyZSBjbGllbnREYXRhSlNPTiBhZ2FpbnN0IGEgdGVtcGxhdGUuIFNlZSBodHRwczovL2dvby5nbC95YWJQZXgifQ" ;
684
+ const b64SignedChallenge
685
+ = "MEUCIQCYrSUCR_QUPAhvRNUVfYiJC2JlOKuqf4gx7i129n9QxgIgaY19A9vAAObuTQNs5_V9kZFizwRpUFpiRVW_dglpR2A" ;
682
686
683
687
const verifyMessage = await rawVerify (
684
688
passkeyValidator ,
@@ -691,7 +695,7 @@ describe("Passkey validation", function () {
691
695
assert ( verifyMessage == true , "valid sig" ) ;
692
696
} ) ;
693
697
it ( "should sign with new data" , async function ( ) {
694
- const passkeyValidator = await deployValidator ( wallet ) ;
698
+ const passkeyValidator = await deployP256Tester ( wallet ) ;
695
699
// The precompile expects the fully hashed data
696
700
const preHashedData = await toHash (
697
701
concat ( [ toBuffer ( ethersResponse . authenticatorData ) , await toHash ( toBuffer ( ethersResponse . clientData ) ) ] ) ,
@@ -718,7 +722,7 @@ describe("Passkey validation", function () {
718
722
[ generatedSignature . r , generatedSignature . s ] ,
719
723
[ generatedX , generatedY ] ,
720
724
) ;
721
- const onChainGeneratedVerified = await passkeyValidator . rawVerify (
725
+ const onChainGeneratedVerified = await passkeyValidator . p256Verify (
722
726
preHashedData ,
723
727
[ generatedSignature . r , generatedSignature . s ] ,
724
728
[ generatedX , generatedY ] ,
@@ -728,7 +732,7 @@ describe("Passkey validation", function () {
728
732
[ recordedR , recordedS ] ,
729
733
[ recordedX , recordedY ] ,
730
734
) ;
731
- const onChainRecordedVerified = await passkeyValidator . rawVerify (
735
+ const onChainRecordedVerified = await passkeyValidator . p256Verify (
732
736
preHashedData ,
733
737
[ recordedR , recordedS ] ,
734
738
[ recordedX , recordedY ] ,
@@ -741,7 +745,7 @@ describe("Passkey validation", function () {
741
745
} ) ;
742
746
743
747
it ( "should verify other test passkey data" , async function ( ) {
744
- const passkeyValidator = await deployValidator ( wallet ) ;
748
+ const passkeyValidator = await deployP256Tester ( wallet ) ;
745
749
746
750
const verifyMessage = await rawVerify (
747
751
passkeyValidator ,
@@ -755,10 +759,10 @@ describe("Passkey validation", function () {
755
759
} ) ;
756
760
757
761
it ( "should fail when signature is bad" , async function ( ) {
758
- const passkeyValidator = await deployValidator ( wallet ) ;
762
+ const passkeyValidator = await deployP256Tester ( wallet ) ;
759
763
760
- const b64SignedChallenge =
761
- "MEUCIQCYrSUCR_QUPAhvRNUVfYiJC2JlOKuqf4gx7i129n9QxgIgaY19A9vAAObuTQNs5_V9kZFizwRpUFpiRVW_dglpR2A" ;
764
+ const b64SignedChallenge
765
+ = "MEUCIQCYrSUCR_QUPAhvRNUVfYiJC2JlOKuqf4gx7i129n9QxgIgaY19A9vAAObuTQNs5_V9kZFizwRpUFpiRVW_dglpR2A" ;
762
766
const verifyMessage = await rawVerify (
763
767
passkeyValidator ,
764
768
ethersResponse . authenticatorData ,
@@ -899,10 +903,10 @@ describe("Passkey validation", function () {
899
903
const partialClientObject = {
900
904
challenge : "jBBiiOGt1aSBy1WAuRGxqU7YzRM5oWpMA9g8MKydjPI" ,
901
905
} ;
902
- const duplicatedClientString =
903
- JSON . stringify ( sampleClientObject ) . slice ( 0 , - 1 ) +
904
- "," +
905
- JSON . stringify ( partialClientObject ) . slice ( 1 ) ;
906
+ const duplicatedClientString
907
+ = JSON . stringify ( sampleClientObject ) . slice ( 0 , - 1 )
908
+ + ","
909
+ + JSON . stringify ( partialClientObject ) . slice ( 1 ) ;
906
910
const authData = toBuffer ( ethersResponse . authenticatorData ) ;
907
911
const transactionHash = Buffer . from ( sampleClientObject . challenge , "base64url" ) ;
908
912
const isValidSignature = await validateSignatureTest (
0 commit comments