@mentaproject/signer-react-native 0.0.1

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.
@@ -0,0 +1,296 @@
1
+ import { encodeAbiParameters, keccak256 } from "viem";
2
+ import { base64UrlToBytes, base64UrlToHex, bytesToHex, hexToBase64Url, padHex, } from "./base64url.js";
3
+ /**
4
+ * Error thrown when signature parsing or encoding fails.
5
+ */
6
+ export class SignatureError extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = "SignatureError";
10
+ }
11
+ }
12
+ /**
13
+ * Parses the authenticator data from a WebAuthn assertion.
14
+ *
15
+ * @param authenticatorDataB64 - Base64URL encoded authenticator data
16
+ * @returns Parsed authenticator data structure
17
+ */
18
+ export function parseAuthenticatorDataFromAssertion(authenticatorDataB64) {
19
+ const bytes = base64UrlToBytes(authenticatorDataB64);
20
+ if (bytes.length < 37) {
21
+ throw new SignatureError("Authenticator data too short: minimum 37 bytes required");
22
+ }
23
+ // rpIdHash (32 bytes)
24
+ const rpIdHash = bytesToHex(bytes.slice(0, 32));
25
+ // flags (1 byte)
26
+ const flags = bytes[32];
27
+ // signCount (4 bytes, big endian)
28
+ const signCount = (bytes[33] << 24) | (bytes[34] << 16) | (bytes[35] << 8) | bytes[36];
29
+ return {
30
+ rpIdHash,
31
+ flags,
32
+ signCount,
33
+ raw: bytesToHex(bytes),
34
+ };
35
+ }
36
+ /**
37
+ * Parses a DER-encoded ECDSA signature into r and s components.
38
+ * WebAuthn signatures are DER-encoded ASN.1 sequences.
39
+ *
40
+ * DER format: 0x30 [total-length] 0x02 [r-length] [r] 0x02 [s-length] [s]
41
+ *
42
+ * @param signatureB64 - Base64URL encoded DER signature
43
+ * @returns Object with r and s as 32-byte hex strings
44
+ */
45
+ export function parseDERSignature(signatureB64) {
46
+ const bytes = base64UrlToBytes(signatureB64);
47
+ if (bytes.length < 8) {
48
+ throw new SignatureError("DER signature too short");
49
+ }
50
+ // Verify it's a SEQUENCE
51
+ if (bytes[0] !== 0x30) {
52
+ throw new SignatureError(`Invalid DER signature: expected SEQUENCE (0x30), got 0x${bytes[0].toString(16)}`);
53
+ }
54
+ let offset = 2; // Skip SEQUENCE tag and length
55
+ // Parse R
56
+ if (bytes[offset] !== 0x02) {
57
+ throw new SignatureError(`Invalid DER signature: expected INTEGER (0x02) for R, got 0x${bytes[offset].toString(16)}`);
58
+ }
59
+ offset++;
60
+ const rLength = bytes[offset];
61
+ offset++;
62
+ let rBytes = bytes.slice(offset, offset + rLength);
63
+ offset += rLength;
64
+ // Parse S
65
+ if (bytes[offset] !== 0x02) {
66
+ throw new SignatureError(`Invalid DER signature: expected INTEGER (0x02) for S, got 0x${bytes[offset].toString(16)}`);
67
+ }
68
+ offset++;
69
+ const sLength = bytes[offset];
70
+ offset++;
71
+ let sBytes = bytes.slice(offset, offset + sLength);
72
+ // Remove leading zero bytes (DER uses them for positive integers with high bit set)
73
+ if (rBytes[0] === 0x00 && rBytes.length > 32) {
74
+ rBytes = rBytes.slice(1);
75
+ }
76
+ if (sBytes[0] === 0x00 && sBytes.length > 32) {
77
+ sBytes = sBytes.slice(1);
78
+ }
79
+ // Pad to 32 bytes if needed
80
+ const r = padHex(bytesToHex(rBytes), 32);
81
+ const s = padHex(bytesToHex(sBytes), 32);
82
+ return { r, s };
83
+ }
84
+ /**
85
+ * Normalizes the S value of an ECDSA signature to low-S form.
86
+ * This is required by some smart contract implementations to prevent
87
+ * signature malleability.
88
+ *
89
+ * For P-256, the curve order n is:
90
+ * 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
91
+ *
92
+ * If s > n/2, we replace s with n - s.
93
+ *
94
+ * @param s - The S component of the signature
95
+ * @returns The normalized S value in low-S form
96
+ */
97
+ export function normalizeSignatureS(s) {
98
+ const sClean = s.startsWith("0x") ? s.slice(2) : s;
99
+ const sValue = BigInt(`0x${sClean}`);
100
+ // P-256 curve order
101
+ const n = BigInt("0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551");
102
+ const halfN = n / 2n;
103
+ if (sValue > halfN) {
104
+ const normalizedS = n - sValue;
105
+ return padHex(`0x${normalizedS.toString(16)}`, 32);
106
+ }
107
+ return padHex(s, 32);
108
+ }
109
+ /**
110
+ * Finds the position of a substring in a JSON string.
111
+ * Used to locate the challenge and type fields in clientDataJSON.
112
+ *
113
+ * @param json - The JSON string to search
114
+ * @param key - The key to find (e.g., "challenge", "type")
115
+ * @returns The byte offset of the key's value
116
+ */
117
+ export function findJsonFieldPosition(json, key) {
118
+ // Find the key with quotes: "key":"
119
+ const searchPattern = `"${key}":"`;
120
+ const position = json.indexOf(searchPattern);
121
+ if (position === -1) {
122
+ throw new SignatureError(`Field "${key}" not found in clientDataJSON`);
123
+ }
124
+ // Return position after the opening quote of the value
125
+ return position + searchPattern.length;
126
+ }
127
+ /**
128
+ * Parses a WebAuthn assertion response into its components.
129
+ *
130
+ * @param assertion - The WebAuthn assertion response
131
+ * @returns Parsed signature components
132
+ */
133
+ export function parseWebAuthnAssertion(assertion) {
134
+ // Parse authenticator data
135
+ const authenticatorData = base64UrlToHex(assertion.authenticatorData);
136
+ // Decode clientDataJSON
137
+ const clientDataJSONBytes = base64UrlToBytes(assertion.clientDataJSON);
138
+ const decoder = new TextDecoder();
139
+ const clientDataJSON = decoder.decode(clientDataJSONBytes);
140
+ // Parse the DER signature
141
+ const { r, s: rawS } = parseDERSignature(assertion.signature);
142
+ // Normalize S to low-S form
143
+ const s = normalizeSignatureS(rawS);
144
+ // Find positions for challenge and type in clientDataJSON
145
+ const challengeLocation = findJsonFieldPosition(clientDataJSON, "challenge");
146
+ const responseTypeLocation = findJsonFieldPosition(clientDataJSON, "type");
147
+ return {
148
+ authenticatorData,
149
+ clientDataJSON,
150
+ r,
151
+ s,
152
+ challengeLocation,
153
+ responseTypeLocation,
154
+ };
155
+ }
156
+ /**
157
+ * Encodes a WebAuthn signature for smart contract verification.
158
+ * Different smart contract implementations expect different formats.
159
+ *
160
+ * @param signature - The parsed WebAuthn signature
161
+ * @param format - The encoding format to use
162
+ * @returns The encoded signature as hex
163
+ */
164
+ export function encodeWebAuthnSignature(signature, format = "kernel") {
165
+ switch (format) {
166
+ case "kernel":
167
+ return encodeKernelSignature(signature);
168
+ case "rhinestone":
169
+ return encodeRhinestoneSignature(signature);
170
+ case "raw":
171
+ return encodeRawSignature(signature);
172
+ default:
173
+ throw new SignatureError(`Unknown signature format: ${format}`);
174
+ }
175
+ }
176
+ /**
177
+ * Encodes signature for Kernel/ZeroDev smart accounts.
178
+ *
179
+ * Format: abi.encode(
180
+ * bytes authenticatorData,
181
+ * string clientDataJSON,
182
+ * uint256 responseTypeLocation,
183
+ * uint256 r,
184
+ * uint256 s,
185
+ * bool usePrecompile
186
+ * )
187
+ */
188
+ function encodeKernelSignature(signature) {
189
+ // Find the challengeIndex (position of challenge value in clientDataJSON)
190
+ const challengeIndex = signature.challengeLocation;
191
+ // Find responseTypeLocation (position after "type":" in the JSON)
192
+ const responseTypeIndex = signature.responseTypeLocation;
193
+ return encodeAbiParameters([
194
+ { type: "bytes" }, // authenticatorData
195
+ { type: "string" }, // clientDataJSON
196
+ { type: "uint256" }, // challengeIndex
197
+ { type: "uint256" }, // responseTypeIndex
198
+ { type: "uint256" }, // r
199
+ { type: "uint256" }, // s
200
+ ], [
201
+ signature.authenticatorData,
202
+ signature.clientDataJSON,
203
+ BigInt(challengeIndex),
204
+ BigInt(responseTypeIndex),
205
+ BigInt(signature.r),
206
+ BigInt(signature.s),
207
+ ]);
208
+ }
209
+ /**
210
+ * Encodes signature for Rhinestone smart accounts.
211
+ *
212
+ * Format: abi.encode(
213
+ * bytes authenticatorData,
214
+ * bytes clientDataJSON,
215
+ * uint256[2] signature (r, s)
216
+ * )
217
+ */
218
+ function encodeRhinestoneSignature(signature) {
219
+ const encoder = new TextEncoder();
220
+ const clientDataBytes = encoder.encode(signature.clientDataJSON);
221
+ return encodeAbiParameters([
222
+ { type: "bytes" }, // authenticatorData
223
+ { type: "bytes" }, // clientDataJSON as bytes
224
+ { type: "uint256[2]" }, // [r, s]
225
+ ], [
226
+ signature.authenticatorData,
227
+ bytesToHex(clientDataBytes),
228
+ [BigInt(signature.r), BigInt(signature.s)],
229
+ ]);
230
+ }
231
+ /**
232
+ * Encodes signature in raw format (just r || s).
233
+ * Useful for custom implementations or debugging.
234
+ */
235
+ function encodeRawSignature(signature) {
236
+ // Simple concatenation of r and s (64 bytes total)
237
+ const rClean = signature.r.startsWith("0x")
238
+ ? signature.r.slice(2)
239
+ : signature.r;
240
+ const sClean = signature.s.startsWith("0x")
241
+ ? signature.s.slice(2)
242
+ : signature.s;
243
+ return `0x${rClean}${sClean}`;
244
+ }
245
+ /**
246
+ * Creates a WebAuthn challenge from a message hash.
247
+ * The challenge is typically the Base64URL encoding of the hash.
248
+ *
249
+ * @param messageHash - The message hash (usually a UserOpHash)
250
+ * @returns The challenge as Base64URL string
251
+ */
252
+ export function createChallenge(messageHash) {
253
+ return hexToBase64Url(messageHash);
254
+ }
255
+ /**
256
+ * Hashes a message according to EIP-191 (personal_sign).
257
+ * This is used when signing arbitrary messages.
258
+ *
259
+ * @param message - The message to hash
260
+ * @returns The EIP-191 hash
261
+ */
262
+ export function hashMessage(message) {
263
+ const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
264
+ // EIP-191: "\x19Ethereum Signed Message:\n" + len(message) + message
265
+ const prefix = `\x19Ethereum Signed Message:\n${messageBytes.length}`;
266
+ const prefixBytes = new TextEncoder().encode(prefix);
267
+ const combined = new Uint8Array(prefixBytes.length + messageBytes.length);
268
+ combined.set(prefixBytes, 0);
269
+ combined.set(messageBytes, prefixBytes.length);
270
+ return keccak256(combined);
271
+ }
272
+ /**
273
+ * Creates an assertion options object for react-native-passkey.
274
+ *
275
+ * @param challenge - The challenge as Base64URL string
276
+ * @param rpId - The Relying Party ID
277
+ * @param credentialId - The credential ID to use (Base64URL)
278
+ * @param userVerification - User verification requirement
279
+ * @param timeout - Timeout in milliseconds
280
+ * @returns Options object for Passkey.get()
281
+ */
282
+ export function createAssertionOptions(challenge, rpId, credentialId, userVerification = "required", timeout = 60000) {
283
+ return {
284
+ rpId,
285
+ challenge,
286
+ allowCredentials: [
287
+ {
288
+ id: credentialId,
289
+ type: "public-key",
290
+ },
291
+ ],
292
+ userVerification,
293
+ timeout,
294
+ };
295
+ }
296
+ //# sourceMappingURL=passkey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkey.js","sourceRoot":"","sources":["../../src/utils/passkey.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@mentaproject/signer-react-native",
3
+ "version": "0.0.1",
4
+ "description": "React Native Passkey signer for Menta wallet - implements SmartAccountSigner via WebAuthn",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./types": {
16
+ "types": "./dist/types/index.d.ts",
17
+ "import": "./dist/types/index.js",
18
+ "default": "./dist/types/index.js"
19
+ },
20
+ "./utils": {
21
+ "types": "./dist/utils/index.d.ts",
22
+ "import": "./dist/utils/index.js",
23
+ "default": "./dist/utils/index.js"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "src"
29
+ ],
30
+ "scripts": {
31
+ "build": "tsc",
32
+ "dev": "tsc --watch",
33
+ "clean": "rm -rf dist",
34
+ "typecheck": "tsc --noEmit",
35
+ "prepublishOnly": "npm run clean && npm run build",
36
+ "prepack": "npm run typecheck",
37
+ "publish:patch": "npm version patch && npm publish --access public",
38
+ "publish:minor": "npm version minor && npm publish --access public",
39
+ "publish:major": "npm version major && npm publish --access public",
40
+ "publish:dry": "npm publish --dry-run"
41
+ },
42
+ "keywords": [
43
+ "react-native",
44
+ "passkey",
45
+ "webauthn",
46
+ "smart-account",
47
+ "erc-4337",
48
+ "wallet",
49
+ "menta"
50
+ ],
51
+ "author": "Menta Project",
52
+ "license": "MIT",
53
+ "dependencies": {
54
+ "cbor-x": "^1.6.0"
55
+ },
56
+ "peerDependencies": {
57
+ "@mentaproject/core": ">=0.5.0",
58
+ "react-native-passkey": ">=3.0.0",
59
+ "viem": ">=2.0.0"
60
+ },
61
+ "devDependencies": {
62
+ "@mentaproject/core": "^0.5.2",
63
+ "@types/node": "^20.10.0",
64
+ "react-native-passkey": "^3.0.0",
65
+ "typescript": "^5.3.0",
66
+ "viem": "^2.21.0"
67
+ },
68
+ "engines": {
69
+ "node": ">=18.0.0"
70
+ }
71
+ }
package/src/index.ts ADDED
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @mentaproject/signer-react-native
3
+ *
4
+ * React Native Passkey signer for Menta wallet.
5
+ * Implements SmartAccountSigner using WebAuthn/Passkeys with P-256 keys.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ // Main signer class
11
+ export {
12
+ ReactNativePasskeySigner,
13
+ PasskeySignerError,
14
+ isPasskeyCredential,
15
+ serializeCredential,
16
+ deserializeCredential,
17
+ } from "./signer.js";
18
+
19
+ // Types
20
+ export type {
21
+ SmartAccountSigner,
22
+ SmartAccountSignerSource,
23
+ SignableMessage,
24
+ PasskeyConfig,
25
+ P256PublicKey,
26
+ PasskeyCredential,
27
+ AuthenticatorData,
28
+ WebAuthnSignature,
29
+ SignatureEncodingFormat,
30
+ ReactNativePasskeySignerConfig,
31
+ } from "./types/index.js";
32
+
33
+ // Utilities (for advanced use cases)
34
+ export {
35
+ // Base64URL utilities
36
+ base64UrlToBytes,
37
+ bytesToBase64Url,
38
+ base64UrlToHex,
39
+ hexToBase64Url,
40
+ bytesToHex,
41
+ hexToBytes,
42
+ padHex,
43
+ concatHex,
44
+
45
+ // COSE parsing
46
+ extractP256PublicKey,
47
+ extractPublicKeyFromAttestation,
48
+ encodeUncompressedPublicKey,
49
+ isValidP256PublicKey,
50
+ COSEParseError,
51
+
52
+ // Signature utilities
53
+ parseWebAuthnAssertion,
54
+ encodeWebAuthnSignature,
55
+ parseDERSignature,
56
+ normalizeSignatureS,
57
+ createChallenge,
58
+ SignatureError,
59
+ } from "./utils/index.js";