Skip to content

Commit b2734b7

Browse files
committed
feat: update pkpSign test to use verify all signing schemes and remove extra validation leaving it as consumer responsibility
1 parent 341ea36 commit b2734b7

File tree

5 files changed

+92
-129
lines changed

5 files changed

+92
-129
lines changed

local-tests/tests/testUseEoaSessionSigsToPkpSign.ts

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1+
import { p256 } from '@noble/curves/p256';
2+
import { p384 } from '@noble/curves/p384';
3+
import { secp256k1 } from '@noble/curves/secp256k1';
14
import { hexToBytes } from '@noble/hashes/utils';
25

36
import { UnknownSignatureError } from '@lit-protocol/constants';
4-
import {
5-
curveFunctions,
6-
hashLitMessage,
7-
verifyLitSignature,
8-
} from '@lit-protocol/crypto';
7+
import { hashLitMessage } from '@lit-protocol/crypto';
98
import { log } from '@lit-protocol/misc';
10-
import { SigType } from '@lit-protocol/types';
9+
import { EcdsaSigType, SigType } from '@lit-protocol/types';
1110

1211
import { getEoaAuthContext } from 'local-tests/setup/session-sigs/get-eoa-session-sigs';
1312
import { TinnyEnvironment } from 'local-tests/setup/tinny-environment';
@@ -19,6 +18,13 @@ interface SigningSchemeConfig {
1918
signingScheme: SigType;
2019
}
2120

21+
// Map the right curve function per signing scheme
22+
export const ecdsaCurveFunctions: Record<EcdsaSigType, any> = {
23+
EcdsaK256Sha256: secp256k1,
24+
EcdsaP256Sha256: p256,
25+
EcdsaP384Sha384: p384,
26+
} as const;
27+
2228
/**
2329
* Test Commands:
2430
* ✅ NETWORK=naga-dev yarn test:local --filter=testUseEoaSessionSigsToPkpSign
@@ -32,9 +38,13 @@ export const testUseEoaSessionSigsToPkpSign = async (
3238
const signingSchemeConfigs: SigningSchemeConfig[] = [
3339
// BLS
3440
// {
35-
// signingScheme: 'Bls12381G1ProofOfPossession', // TODO pkpSignature.signature: '{ProofOfPossession:984ffb9ef7a0e6225dd074bade4b9494fab3487ff543f25a90d86f794cbf190ed20179df6eb6dd3eb9a285838d3cf4980e5e7028688e0461bd1cb95c075046fcafa343d3702e7edff70fb8eb8ada130f58fa45140ab2d90f24b1309b026d98d6}'
41+
// signingScheme: 'Bls12381', // TODO nodes accept this signing scheme but they throw an unexpected error
3642
// hashesMessage: false,
3743
// },
44+
{
45+
signingScheme: 'Bls12381G1ProofOfPossession',
46+
hashesMessage: false,
47+
},
3848
// ECDSA
3949
{
4050
hasRecoveryId: true,
@@ -59,49 +69,48 @@ export const testUseEoaSessionSigsToPkpSign = async (
5969
signingScheme: 'SchnorrEd25519Sha512',
6070
hashesMessage: false,
6171
},
62-
// {
63-
// signingScheme: 'SchnorrK256Sha256', // TODO signature of length 64 expected, got 65
64-
// hashesMessage: false,
65-
// },
66-
// {
67-
// signingScheme: 'SchnorrP256Sha256', // TODO Expected pkpSignature to consistently verify its components
68-
// hashesMessage: false,
69-
// },
70-
// {
71-
// signingScheme: 'SchnorrP384Sha384', // TODO Expected pkpSignature to consistently verify its components
72-
// hashesMessage: false,
73-
// },
74-
// {
75-
// signingScheme: 'SchnorrRistretto25519Sha512', // TODO curve.verify is not a function
76-
// hashesMessage: false,
77-
// },
72+
{
73+
signingScheme: 'SchnorrK256Sha256',
74+
hashesMessage: false,
75+
},
76+
{
77+
signingScheme: 'SchnorrP256Sha256',
78+
hashesMessage: false,
79+
},
80+
{
81+
signingScheme: 'SchnorrP384Sha384',
82+
hashesMessage: false,
83+
},
84+
{
85+
signingScheme: 'SchnorrRistretto25519Sha512',
86+
hashesMessage: false,
87+
},
7888
{
7989
signingScheme: 'SchnorrEd448Shake256',
8090
hashesMessage: false,
8191
},
82-
// {
83-
// signingScheme: 'SchnorrRedJubjubBlake2b512', // TODO Expected pkpSignature to consistently verify its components
84-
// hashesMessage: false,
85-
// },
86-
// {
87-
// signingScheme: 'SchnorrK256Taproot', // TODO Expected pkpSignature to consistently verify its components
88-
// hashesMessage: false,
89-
// },
90-
// {
91-
// signingScheme: 'SchnorrRedDecaf377Blake2b512', // TODO Expected pkpSignature to consistently verify its components
92-
// hashesMessage: false,
93-
// },
94-
// {
95-
// signingScheme: 'SchnorrkelSubstrate', // TODO Expected pkpSignature to consistently verify its components
96-
// hashesMessage: false,
97-
// },
92+
{
93+
signingScheme: 'SchnorrRedJubjubBlake2b512',
94+
hashesMessage: false,
95+
},
96+
{
97+
signingScheme: 'SchnorrK256Taproot',
98+
hashesMessage: false,
99+
},
100+
{
101+
signingScheme: 'SchnorrRedDecaf377Blake2b512',
102+
hashesMessage: false,
103+
},
104+
{
105+
signingScheme: 'SchnorrkelSubstrate',
106+
hashesMessage: false,
107+
},
98108
];
99109

100110
for (const signingSchemeConfig of signingSchemeConfigs) {
101111
try {
102112
const signingScheme = signingSchemeConfig.signingScheme;
103113
log(`Checking testUseEoaSessionSigsToPkpSign for ${signingSchemeConfig}`);
104-
// const eoaSessionSigs = await getEoaSessionSigs(devEnv, alice);
105114

106115
const pkpSignature = await devEnv.litNodeClient.pkpSign({
107116
pubKey: alice.pkp.publicKey,
@@ -119,6 +128,15 @@ export const testUseEoaSessionSigsToPkpSign = async (
119128
'signedData',
120129
'publicKey',
121130
]) {
131+
// Bls12381G1ProofOfPossession signature is a json string with ProofOfPossession, not an hex signature
132+
if (
133+
signingScheme === 'Bls12381G1ProofOfPossession' &&
134+
hexString === 'signature' &&
135+
pkpSignature.signature.startsWith('{')
136+
) {
137+
continue;
138+
}
139+
122140
if (
123141
!pkpSignature[hexString] ||
124142
!pkpSignature[hexString].startsWith('0x')
@@ -139,21 +157,8 @@ export const testUseEoaSessionSigsToPkpSign = async (
139157
);
140158
}
141159

142-
// Signature, public key and signed data verification
143-
const signatureVerification = verifyLitSignature(
144-
signingSchemeConfig.signingScheme,
145-
pkpSignature.publicKey.replace('0x', ''),
146-
pkpSignature.signedData.replace('0x', ''),
147-
pkpSignature.signature.replace('0x', '')
148-
);
149-
if (!signatureVerification) {
150-
throw new Error(
151-
`Expected pkpSignature to consistently verify its components. Signing Scheme: ${signingScheme}`
152-
);
153-
}
154-
155160
if (signingSchemeConfig.recoversPublicKey) {
156-
const curve = curveFunctions[signingScheme];
161+
const curve = ecdsaCurveFunctions[signingScheme];
157162
const signatureBytes = hexToBytes(
158163
pkpSignature.signature.replace(/^0x/, '')
159164
);
@@ -182,7 +187,7 @@ export const testUseEoaSessionSigsToPkpSign = async (
182187
}
183188

184189
const messageHash = signingSchemeConfig.hashesMessage
185-
? hashLitMessage(signingScheme, alice.loveLetter)
190+
? hashLitMessage(signingScheme as EcdsaSigType, alice.loveLetter)
186191
: alice.loveLetter;
187192
const messageHashHex = Buffer.from(messageHash).toString('hex');
188193
if (pkpSignature.signedData.replace('0x', '') !== messageHashHex) {

packages/constants/src/lib/constants/curves.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ export const LIT_CURVE = {
4646
...LIT_ECDSA_VARIANT,
4747
};
4848

49-
export type LIT_CURVE_TYPE = keyof typeof LIT_CURVE; // Identical to Sig
50-
// This should replicate SigShare.sigType in types package
49+
export type LIT_CURVE_TYPE = keyof typeof LIT_CURVE; // Identical to SigType = BlsSigType | EcdsaSigType | FrostSigType;
5150
export type LIT_CURVE_VALUES = (typeof LIT_CURVE)[keyof typeof LIT_CURVE];
5251

5352
export const CURVE_GROUPS = ['BLS', 'ECDSA', 'FROST'] as const;

packages/crypto/src/lib/crypto.ts

Lines changed: 8 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
1-
import { bls12_381 } from '@noble/curves/bls12-381';
2-
import { ed25519, RistrettoPoint } from '@noble/curves/ed25519';
3-
import { ed448 } from '@noble/curves/ed448';
4-
import { jubjub } from '@noble/curves/jubjub';
5-
import { p256 } from '@noble/curves/p256';
6-
import { p384 } from '@noble/curves/p384';
7-
import { schnorr as schnorrK256, secp256k1 } from '@noble/curves/secp256k1';
8-
import { blake2b } from '@noble/hashes/blake2b';
91
import { sha256 } from '@noble/hashes/sha256';
10-
import { shake256 } from '@noble/hashes/sha3';
11-
import { sha384, sha512 } from '@noble/hashes/sha512';
2+
import { sha384 } from '@noble/hashes/sha512';
123

134
import {
145
CurveTypeNotFoundError,
@@ -30,11 +21,11 @@ import { nacl } from '@lit-protocol/nacl';
3021
import {
3122
CleanLitNodeSignature,
3223
CombinedLitNodeSignature,
24+
EcdsaSigType,
3325
LitActionSignedData,
3426
NodeAttestation,
3527
PKPSignEndpointResponse,
3628
SessionKeyPair,
37-
SigType,
3829
} from '@lit-protocol/types';
3930
import {
4031
uint8arrayFromString,
@@ -489,48 +480,20 @@ export const checkSevSnpAttestation = async (
489480
};
490481

491482
// Map the right hash function per signing scheme
492-
export const hashFunctions: Record<SigType, any> = {
493-
Bls12381G1ProofOfPossession: sha256, // TODO needed here? Which hash?
483+
export const ecdsaHashFunctions: Record<
484+
EcdsaSigType,
485+
(arg0: Uint8Array) => Uint8Array
486+
> = {
494487
EcdsaK256Sha256: sha256,
495488
EcdsaP256Sha256: sha256,
496489
EcdsaP384Sha384: sha384,
497-
SchnorrEd25519Sha512: sha512,
498-
SchnorrK256Sha256: sha256,
499-
SchnorrP256Sha256: sha256,
500-
SchnorrP384Sha384: sha384,
501-
SchnorrRistretto25519Sha512: sha512,
502-
SchnorrEd448Shake256: (msg: Uint8Array) => shake256(msg, 114),
503-
SchnorrRedJubjubBlake2b512: (msg: Uint8Array) => blake2b(msg, { dkLen: 64 }),
504-
SchnorrK256Taproot: sha256,
505-
SchnorrRedDecaf377Blake2b512: (msg: Uint8Array) =>
506-
blake2b(msg, { dkLen: 64 }),
507-
SchnorrkelSubstrate: (msg: Uint8Array) => blake2b(msg, { dkLen: 64 }),
508-
} as const;
509-
510-
// Map the right curve function per signing scheme
511-
export const curveFunctions: Record<SigType, any> = {
512-
Bls12381G1ProofOfPossession: bls12_381,
513-
EcdsaK256Sha256: secp256k1,
514-
EcdsaP256Sha256: p256,
515-
EcdsaP384Sha384: p384,
516-
SchnorrEd25519Sha512: ed25519,
517-
SchnorrK256Sha256: schnorrK256,
518-
SchnorrP256Sha256: p256,
519-
SchnorrP384Sha384: p384,
520-
SchnorrRistretto25519Sha512: (msg: Uint8Array) =>
521-
RistrettoPoint.hashToCurve(sha512(msg)).toHex(),
522-
SchnorrEd448Shake256: ed448,
523-
SchnorrRedJubjubBlake2b512: jubjub,
524-
SchnorrK256Taproot: secp256k1,
525-
SchnorrRedDecaf377Blake2b512: p256, // TODO check curve function
526-
SchnorrkelSubstrate: ed25519, // TODO check curve function
527490
} as const;
528491

529492
export function hashLitMessage(
530-
signingScheme: SigType,
493+
signingScheme: EcdsaSigType,
531494
message: Uint8Array
532495
): Uint8Array {
533-
const hashFn = hashFunctions[signingScheme];
496+
const hashFn = ecdsaHashFunctions[signingScheme];
534497

535498
if (!hashFn) {
536499
throw new CurveTypeNotFoundError(
@@ -545,25 +508,3 @@ export function hashLitMessage(
545508

546509
return hashFn(message);
547510
}
548-
549-
export function verifyLitSignature(
550-
signingScheme: SigType,
551-
publicKey: string,
552-
message: string,
553-
signature: string
554-
) {
555-
const curve = curveFunctions[signingScheme];
556-
if (!curve) {
557-
throw new CurveTypeNotFoundError(
558-
{
559-
info: {
560-
signingScheme,
561-
},
562-
},
563-
`No known curve function for specified signing scheme ${signingScheme}`
564-
);
565-
}
566-
567-
// TODO call correct verification on all curve functions
568-
return curve.verify(signature, message, publicKey);
569-
}

packages/lit-node-client-nodejs/src/lib/lit-node-client-nodejs.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
PRODUCT_IDS_TYPE,
3838
SIWE_URI_PREFIX,
3939
UnknownError,
40+
UnknownSignatureError,
4041
UnsupportedMethodError,
4142
WalletSignatureNotFoundError,
4243
} from '@lit-protocol/constants';
@@ -72,6 +73,7 @@ import {
7273
import { nacl } from '@lit-protocol/nacl';
7374
import {
7475
AuthMethod,
76+
EcdsaSigType,
7577
ExecuteJsValueResponse,
7678
LitNodeSignature,
7779
} from '@lit-protocol/types';
@@ -899,7 +901,10 @@ export class LitNodeClientNodeJs extends LitCore implements ILitNodeClient {
899901
const toSign =
900902
CURVE_GROUP_BY_CURVE_TYPE[params.signingScheme] !== 'ECDSA'
901903
? params.messageToSign!
902-
: hashLitMessage(params.signingScheme, params.messageToSign!);
904+
: hashLitMessage(
905+
params.signingScheme as EcdsaSigType,
906+
params.messageToSign!
907+
);
903908

904909
const reqBody: JsonPkpSignRequest = {
905910
toSign: normalizeArray(toSign),
@@ -958,9 +963,17 @@ export class LitNodeClientNodeJs extends LitCore implements ILitNodeClient {
958963

959964
return signatures;
960965
} catch (e) {
961-
// TODO remove log and re throw pattern. Wrap in LitError
962-
console.error('Error getting signature', e);
963-
throw e;
966+
throw new UnknownSignatureError(
967+
{
968+
info: {
969+
responseData,
970+
requestId,
971+
threshold: this._getThreshold(),
972+
},
973+
cause: e,
974+
},
975+
'Could not combine pkp signature shares'
976+
);
964977
}
965978
};
966979

packages/types/src/lib/interfaces.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,12 @@ export interface FormattedMultipleAccs {
629629
formattedUnifiedAccessControlConditions: any;
630630
}
631631

632-
// BLS TODO
632+
// BLS
633+
// ================== unifiedSignature: {
634+
// "signature":"{\"ProofOfPossession\":\"abff2ed7e23d0e7c01880e76fd66c84b23427842447ec5474a842ca729d5f21b675342aac3fe94386ffd02c6726b14740c4571efcf45fb86342fd806b6557bcfb32c225f006d7870eea0980810c26606779667786c1a875d563b5731c65da21f\"}",
635+
// "verifying_key":"\"af93eb21b135d6a95d46f03662168f34e0ea8a749d0579ac46aa7aff721c1259991997c0598aad6838678a2f17dd85e2\"",
636+
// "signed_data":"0102030405",
637+
// "recovery_id":null}
633638
// ECDSA
634639
// ================== unifiedSignature: {
635640
// "signature":"\"F0E7A72197D93FFF7A5A22B2A865511C6A117DE75E08519A2298061485169A2B6EE44425E45AD3A7455720C5D786EFFFBB24D94DD4E8F2143CDBF777BBCA6FE1\"",

0 commit comments

Comments
 (0)