@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.
- package/README.md +343 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/signer.d.ts +161 -0
- package/dist/signer.d.ts.map +1 -0
- package/dist/signer.js +378 -0
- package/dist/signer.js.map +1 -0
- package/dist/types/index.d.ts +117 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/base64url.d.ts +75 -0
- package/dist/utils/base64url.d.ts.map +1 -0
- package/dist/utils/base64url.js +142 -0
- package/dist/utils/base64url.js.map +1 -0
- package/dist/utils/cose.d.ts +98 -0
- package/dist/utils/cose.d.ts.map +1 -0
- package/dist/utils/cose.js +259 -0
- package/dist/utils/cose.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/passkey.d.ts +108 -0
- package/dist/utils/passkey.d.ts.map +1 -0
- package/dist/utils/passkey.js +296 -0
- package/dist/utils/passkey.js.map +1 -0
- package/package.json +71 -0
- package/src/index.ts +59 -0
- package/src/signer.ts +499 -0
- package/src/types/index.ts +140 -0
- package/src/utils/base64url.ts +161 -0
- package/src/utils/cose.ts +356 -0
- package/src/utils/index.ts +40 -0
- package/src/utils/passkey.ts +392 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { toHex } from "viem";
|
|
2
|
+
/**
|
|
3
|
+
* Converts a Base64URL encoded string to a Uint8Array.
|
|
4
|
+
* Base64URL uses - instead of + and _ instead of /, with no padding.
|
|
5
|
+
*
|
|
6
|
+
* @param base64url - The Base64URL encoded string
|
|
7
|
+
* @returns The decoded bytes as Uint8Array
|
|
8
|
+
*/
|
|
9
|
+
export function base64UrlToBytes(base64url) {
|
|
10
|
+
// Convert Base64URL to standard Base64
|
|
11
|
+
let base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
|
|
12
|
+
// Add padding if needed
|
|
13
|
+
const padding = base64.length % 4;
|
|
14
|
+
if (padding) {
|
|
15
|
+
base64 += "=".repeat(4 - padding);
|
|
16
|
+
}
|
|
17
|
+
// Decode Base64 to binary string
|
|
18
|
+
const binaryString = atob(base64);
|
|
19
|
+
// Convert binary string to Uint8Array
|
|
20
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
21
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
22
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
23
|
+
}
|
|
24
|
+
return bytes;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Converts a Uint8Array to a Base64URL encoded string.
|
|
28
|
+
*
|
|
29
|
+
* @param bytes - The bytes to encode
|
|
30
|
+
* @returns The Base64URL encoded string (no padding)
|
|
31
|
+
*/
|
|
32
|
+
export function bytesToBase64Url(bytes) {
|
|
33
|
+
// Convert bytes to binary string
|
|
34
|
+
let binaryString = "";
|
|
35
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
36
|
+
binaryString += String.fromCharCode(bytes[i]);
|
|
37
|
+
}
|
|
38
|
+
// Encode to Base64
|
|
39
|
+
const base64 = btoa(binaryString);
|
|
40
|
+
// Convert to Base64URL (remove padding, replace + with -, / with _)
|
|
41
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Converts a Base64URL encoded string to a Hex string.
|
|
45
|
+
*
|
|
46
|
+
* @param base64url - The Base64URL encoded string
|
|
47
|
+
* @returns The hex representation with 0x prefix
|
|
48
|
+
*/
|
|
49
|
+
export function base64UrlToHex(base64url) {
|
|
50
|
+
const bytes = base64UrlToBytes(base64url);
|
|
51
|
+
return toHex(bytes);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Converts a Hex string to a Base64URL encoded string.
|
|
55
|
+
*
|
|
56
|
+
* @param hex - The hex string (with or without 0x prefix)
|
|
57
|
+
* @returns The Base64URL encoded string
|
|
58
|
+
*/
|
|
59
|
+
export function hexToBase64Url(hex) {
|
|
60
|
+
// Remove 0x prefix if present
|
|
61
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
62
|
+
// Convert hex to bytes
|
|
63
|
+
const bytes = new Uint8Array(cleanHex.length / 2);
|
|
64
|
+
for (let i = 0; i < cleanHex.length; i += 2) {
|
|
65
|
+
bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16);
|
|
66
|
+
}
|
|
67
|
+
return bytesToBase64Url(bytes);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Converts a Uint8Array to a Hex string.
|
|
71
|
+
*
|
|
72
|
+
* @param bytes - The bytes to convert
|
|
73
|
+
* @returns The hex representation with 0x prefix
|
|
74
|
+
*/
|
|
75
|
+
export function bytesToHex(bytes) {
|
|
76
|
+
return toHex(bytes);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Converts a Hex string to a Uint8Array.
|
|
80
|
+
*
|
|
81
|
+
* @param hex - The hex string (with or without 0x prefix)
|
|
82
|
+
* @returns The bytes as Uint8Array
|
|
83
|
+
*/
|
|
84
|
+
export function hexToBytes(hex) {
|
|
85
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
86
|
+
const bytes = new Uint8Array(cleanHex.length / 2);
|
|
87
|
+
for (let i = 0; i < cleanHex.length; i += 2) {
|
|
88
|
+
bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16);
|
|
89
|
+
}
|
|
90
|
+
return bytes;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Converts a UTF-8 string to a Base64URL encoded string.
|
|
94
|
+
*
|
|
95
|
+
* @param str - The UTF-8 string
|
|
96
|
+
* @returns The Base64URL encoded string
|
|
97
|
+
*/
|
|
98
|
+
export function stringToBase64Url(str) {
|
|
99
|
+
const encoder = new TextEncoder();
|
|
100
|
+
const bytes = encoder.encode(str);
|
|
101
|
+
return bytesToBase64Url(bytes);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Converts a Base64URL encoded string to a UTF-8 string.
|
|
105
|
+
*
|
|
106
|
+
* @param base64url - The Base64URL encoded string
|
|
107
|
+
* @returns The decoded UTF-8 string
|
|
108
|
+
*/
|
|
109
|
+
export function base64UrlToString(base64url) {
|
|
110
|
+
const bytes = base64UrlToBytes(base64url);
|
|
111
|
+
const decoder = new TextDecoder();
|
|
112
|
+
return decoder.decode(bytes);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Pads a hex value to ensure it has the specified byte length.
|
|
116
|
+
* Useful for ensuring coordinates are 32 bytes.
|
|
117
|
+
*
|
|
118
|
+
* @param hex - The hex string to pad
|
|
119
|
+
* @param byteLength - The desired byte length (default: 32)
|
|
120
|
+
* @returns The padded hex string with 0x prefix
|
|
121
|
+
*/
|
|
122
|
+
export function padHex(hex, byteLength = 32) {
|
|
123
|
+
const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
124
|
+
const targetLength = byteLength * 2;
|
|
125
|
+
if (cleanHex.length >= targetLength) {
|
|
126
|
+
return `0x${cleanHex.slice(-targetLength)}`;
|
|
127
|
+
}
|
|
128
|
+
return `0x${cleanHex.padStart(targetLength, "0")}`;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Concatenates multiple Hex values into a single Hex value.
|
|
132
|
+
*
|
|
133
|
+
* @param hexValues - The hex values to concatenate
|
|
134
|
+
* @returns The concatenated hex string with 0x prefix
|
|
135
|
+
*/
|
|
136
|
+
export function concatHex(...hexValues) {
|
|
137
|
+
const combined = hexValues
|
|
138
|
+
.map((h) => (h.startsWith("0x") ? h.slice(2) : h))
|
|
139
|
+
.join("");
|
|
140
|
+
return `0x${combined}`;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=base64url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base64url.js","sourceRoot":"","sources":["../../src/utils/base64url.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { Hex } from "viem";
|
|
2
|
+
import type { P256PublicKey } from "../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* COSE Key Types (kty)
|
|
5
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#key-type
|
|
6
|
+
*/
|
|
7
|
+
declare const COSE_KEY_TYPE: {
|
|
8
|
+
readonly OKP: 1;
|
|
9
|
+
readonly EC2: 2;
|
|
10
|
+
readonly RSA: 3;
|
|
11
|
+
readonly SYMMETRIC: 4;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* COSE Algorithms
|
|
15
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#algorithms
|
|
16
|
+
*/
|
|
17
|
+
declare const COSE_ALGORITHM: {
|
|
18
|
+
readonly ES256: -7;
|
|
19
|
+
readonly ES384: -35;
|
|
20
|
+
readonly ES512: -36;
|
|
21
|
+
readonly EDDSA: -8;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* COSE Elliptic Curves
|
|
25
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
|
|
26
|
+
*/
|
|
27
|
+
declare const COSE_CURVE: {
|
|
28
|
+
readonly P256: 1;
|
|
29
|
+
readonly P384: 2;
|
|
30
|
+
readonly P521: 3;
|
|
31
|
+
readonly ED25519: 6;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Error thrown when COSE key parsing fails.
|
|
35
|
+
*/
|
|
36
|
+
export declare class COSEParseError extends Error {
|
|
37
|
+
constructor(message: string);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Extracts the attestedCredentialData from authenticatorData.
|
|
41
|
+
* The attestedCredentialData contains the COSE public key.
|
|
42
|
+
*
|
|
43
|
+
* AuthenticatorData structure:
|
|
44
|
+
* - rpIdHash (32 bytes)
|
|
45
|
+
* - flags (1 byte)
|
|
46
|
+
* - signCount (4 bytes, big endian)
|
|
47
|
+
* - attestedCredentialData (variable, if AT flag is set)
|
|
48
|
+
* - aaguid (16 bytes)
|
|
49
|
+
* - credentialIdLength (2 bytes, big endian)
|
|
50
|
+
* - credentialId (credentialIdLength bytes)
|
|
51
|
+
* - credentialPublicKey (remaining bytes, CBOR encoded)
|
|
52
|
+
*
|
|
53
|
+
* @param authenticatorData - Raw authenticator data bytes
|
|
54
|
+
* @returns Object containing credentialId and publicKey bytes
|
|
55
|
+
* @throws COSEParseError if parsing fails
|
|
56
|
+
*/
|
|
57
|
+
export declare function parseAuthenticatorData(authenticatorData: Uint8Array): {
|
|
58
|
+
credentialId: Uint8Array;
|
|
59
|
+
publicKeyBytes: Uint8Array;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Extracts P256 (secp256r1) public key coordinates from a COSE key.
|
|
63
|
+
* This is the CRUCIAL function for Passkey integration.
|
|
64
|
+
*
|
|
65
|
+
* @param coseBytes - The CBOR-encoded COSE key bytes
|
|
66
|
+
* @returns The X and Y coordinates as 32-byte hex strings
|
|
67
|
+
* @throws COSEParseError if the key is not a valid P256 key
|
|
68
|
+
*/
|
|
69
|
+
export declare function extractP256PublicKey(coseBytes: Uint8Array): P256PublicKey;
|
|
70
|
+
/**
|
|
71
|
+
* Extracts the public key from a WebAuthn attestation response.
|
|
72
|
+
*
|
|
73
|
+
* @param attestationObject - Base64URL encoded attestation object from registration
|
|
74
|
+
* @returns The P256 public key coordinates
|
|
75
|
+
* @throws COSEParseError if extraction fails
|
|
76
|
+
*/
|
|
77
|
+
export declare function extractPublicKeyFromAttestation(attestationObject: string): {
|
|
78
|
+
credentialId: Uint8Array;
|
|
79
|
+
publicKey: P256PublicKey;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Encodes a P256 public key to the uncompressed format (0x04 || x || y).
|
|
83
|
+
* This is the standard SEC1 uncompressed point format.
|
|
84
|
+
*
|
|
85
|
+
* @param publicKey - The P256 public key coordinates
|
|
86
|
+
* @returns The uncompressed public key as hex (65 bytes total)
|
|
87
|
+
*/
|
|
88
|
+
export declare function encodeUncompressedPublicKey(publicKey: P256PublicKey): Hex;
|
|
89
|
+
/**
|
|
90
|
+
* Validates that a public key is on the P256 curve.
|
|
91
|
+
* This is a basic validation - for full security, use a proper crypto library.
|
|
92
|
+
*
|
|
93
|
+
* @param publicKey - The public key coordinates to validate
|
|
94
|
+
* @returns true if the key appears valid
|
|
95
|
+
*/
|
|
96
|
+
export declare function isValidP256PublicKey(publicKey: P256PublicKey): boolean;
|
|
97
|
+
export { COSE_KEY_TYPE, COSE_ALGORITHM, COSE_CURVE };
|
|
98
|
+
//# sourceMappingURL=cose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cose.d.ts","sourceRoot":"","sources":["../../src/utils/cose.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD;;;GAGG;AACH,QAAA,MAAM,aAAa;;;;;CAKT,CAAC;AAEX;;;GAGG;AACH,QAAA,MAAM,cAAc;;;;;CAKV,CAAC;AAEX;;;GAGG;AACH,QAAA,MAAM,UAAU;;;;;CAKN,CAAC;AAaX;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAwED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,iBAAiB,EAAE,UAAU,GAAG;IACrE,YAAY,EAAE,UAAU,CAAC;IACzB,cAAc,EAAE,UAAU,CAAC;CAC5B,CAuDA;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,UAAU,GAAG,aAAa,CAwCzE;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,iBAAiB,EAAE,MAAM,GACxB;IACD,YAAY,EAAE,UAAU,CAAC;IACzB,SAAS,EAAE,aAAa,CAAC;CAC1B,CA6BA;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,aAAa,GAAG,GAAG,CAOzE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CA8BtE;AAED,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { decode as cborDecode } from "cbor-x";
|
|
2
|
+
import { base64UrlToBytes, bytesToHex, padHex, concatHex } from "./base64url.js";
|
|
3
|
+
/**
|
|
4
|
+
* COSE Key Types (kty)
|
|
5
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#key-type
|
|
6
|
+
*/
|
|
7
|
+
const COSE_KEY_TYPE = {
|
|
8
|
+
OKP: 1, // Octet Key Pair
|
|
9
|
+
EC2: 2, // Elliptic Curve with x and y coordinates
|
|
10
|
+
RSA: 3, // RSA
|
|
11
|
+
SYMMETRIC: 4, // Symmetric key
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* COSE Algorithms
|
|
15
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#algorithms
|
|
16
|
+
*/
|
|
17
|
+
const COSE_ALGORITHM = {
|
|
18
|
+
ES256: -7, // ECDSA w/ SHA-256 (P-256)
|
|
19
|
+
ES384: -35, // ECDSA w/ SHA-384 (P-384)
|
|
20
|
+
ES512: -36, // ECDSA w/ SHA-512 (P-521)
|
|
21
|
+
EDDSA: -8, // EdDSA
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* COSE Elliptic Curves
|
|
25
|
+
* @see https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
|
|
26
|
+
*/
|
|
27
|
+
const COSE_CURVE = {
|
|
28
|
+
P256: 1, // NIST P-256 (secp256r1)
|
|
29
|
+
P384: 2, // NIST P-384
|
|
30
|
+
P521: 3, // NIST P-521
|
|
31
|
+
ED25519: 6, // Ed25519
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* COSE Key Parameter Labels
|
|
35
|
+
*/
|
|
36
|
+
const COSE_KEY_PARAMS = {
|
|
37
|
+
KTY: 1, // Key type
|
|
38
|
+
ALG: 3, // Algorithm
|
|
39
|
+
CRV: -1, // Curve (for EC2 keys)
|
|
40
|
+
X: -2, // X coordinate (for EC2 keys)
|
|
41
|
+
Y: -3, // Y coordinate (for EC2 keys)
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Error thrown when COSE key parsing fails.
|
|
45
|
+
*/
|
|
46
|
+
export class COSEParseError extends Error {
|
|
47
|
+
constructor(message) {
|
|
48
|
+
super(message);
|
|
49
|
+
this.name = "COSEParseError";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Parses a COSE key from CBOR-encoded bytes.
|
|
54
|
+
*
|
|
55
|
+
* @param coseBytes - The CBOR-encoded COSE key bytes
|
|
56
|
+
* @returns The parsed COSE key structure
|
|
57
|
+
* @throws COSEParseError if parsing fails
|
|
58
|
+
*/
|
|
59
|
+
function parseCOSEKey(coseBytes) {
|
|
60
|
+
let decoded;
|
|
61
|
+
try {
|
|
62
|
+
decoded = cborDecode(coseBytes);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
throw new COSEParseError(`Failed to decode CBOR: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
66
|
+
}
|
|
67
|
+
// COSE keys are encoded as CBOR maps
|
|
68
|
+
if (!(decoded instanceof Map)) {
|
|
69
|
+
throw new COSEParseError("Invalid COSE key format: expected CBOR map");
|
|
70
|
+
}
|
|
71
|
+
const kty = decoded.get(COSE_KEY_PARAMS.KTY);
|
|
72
|
+
if (typeof kty !== "number") {
|
|
73
|
+
throw new COSEParseError("Invalid COSE key: missing or invalid kty");
|
|
74
|
+
}
|
|
75
|
+
const result = { kty };
|
|
76
|
+
// Optional algorithm
|
|
77
|
+
const alg = decoded.get(COSE_KEY_PARAMS.ALG);
|
|
78
|
+
if (typeof alg === "number") {
|
|
79
|
+
result.alg = alg;
|
|
80
|
+
}
|
|
81
|
+
// For EC2 keys, extract curve and coordinates
|
|
82
|
+
if (kty === COSE_KEY_TYPE.EC2) {
|
|
83
|
+
const crv = decoded.get(COSE_KEY_PARAMS.CRV);
|
|
84
|
+
if (typeof crv === "number") {
|
|
85
|
+
result.crv = crv;
|
|
86
|
+
}
|
|
87
|
+
const x = decoded.get(COSE_KEY_PARAMS.X);
|
|
88
|
+
if (x instanceof Uint8Array) {
|
|
89
|
+
result.x = x;
|
|
90
|
+
}
|
|
91
|
+
const y = decoded.get(COSE_KEY_PARAMS.Y);
|
|
92
|
+
if (y instanceof Uint8Array) {
|
|
93
|
+
result.y = y;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Extracts the attestedCredentialData from authenticatorData.
|
|
100
|
+
* The attestedCredentialData contains the COSE public key.
|
|
101
|
+
*
|
|
102
|
+
* AuthenticatorData structure:
|
|
103
|
+
* - rpIdHash (32 bytes)
|
|
104
|
+
* - flags (1 byte)
|
|
105
|
+
* - signCount (4 bytes, big endian)
|
|
106
|
+
* - attestedCredentialData (variable, if AT flag is set)
|
|
107
|
+
* - aaguid (16 bytes)
|
|
108
|
+
* - credentialIdLength (2 bytes, big endian)
|
|
109
|
+
* - credentialId (credentialIdLength bytes)
|
|
110
|
+
* - credentialPublicKey (remaining bytes, CBOR encoded)
|
|
111
|
+
*
|
|
112
|
+
* @param authenticatorData - Raw authenticator data bytes
|
|
113
|
+
* @returns Object containing credentialId and publicKey bytes
|
|
114
|
+
* @throws COSEParseError if parsing fails
|
|
115
|
+
*/
|
|
116
|
+
export function parseAuthenticatorData(authenticatorData) {
|
|
117
|
+
// Minimum length: 37 bytes (rpIdHash + flags + signCount)
|
|
118
|
+
if (authenticatorData.length < 37) {
|
|
119
|
+
throw new COSEParseError("Authenticator data too short: minimum 37 bytes required");
|
|
120
|
+
}
|
|
121
|
+
// Check AT (attestedCredentialData) flag (bit 6)
|
|
122
|
+
const flags = authenticatorData[32];
|
|
123
|
+
const hasAttestedCredData = (flags & 0x40) !== 0;
|
|
124
|
+
if (!hasAttestedCredData) {
|
|
125
|
+
throw new COSEParseError("Authenticator data does not contain attested credential data");
|
|
126
|
+
}
|
|
127
|
+
// Skip rpIdHash (32) + flags (1) + signCount (4) = 37 bytes
|
|
128
|
+
let offset = 37;
|
|
129
|
+
// Skip aaguid (16 bytes)
|
|
130
|
+
offset += 16;
|
|
131
|
+
if (authenticatorData.length < offset + 2) {
|
|
132
|
+
throw new COSEParseError("Authenticator data too short: missing credentialIdLength");
|
|
133
|
+
}
|
|
134
|
+
// Read credentialIdLength (2 bytes, big endian)
|
|
135
|
+
const credentialIdLength = (authenticatorData[offset] << 8) | authenticatorData[offset + 1];
|
|
136
|
+
offset += 2;
|
|
137
|
+
if (authenticatorData.length < offset + credentialIdLength) {
|
|
138
|
+
throw new COSEParseError("Authenticator data too short: missing credentialId");
|
|
139
|
+
}
|
|
140
|
+
// Read credentialId
|
|
141
|
+
const credentialId = authenticatorData.slice(offset, offset + credentialIdLength);
|
|
142
|
+
offset += credentialIdLength;
|
|
143
|
+
// Remaining bytes are the CBOR-encoded public key
|
|
144
|
+
const publicKeyBytes = authenticatorData.slice(offset);
|
|
145
|
+
if (publicKeyBytes.length === 0) {
|
|
146
|
+
throw new COSEParseError("Authenticator data too short: missing public key");
|
|
147
|
+
}
|
|
148
|
+
return { credentialId, publicKeyBytes };
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Extracts P256 (secp256r1) public key coordinates from a COSE key.
|
|
152
|
+
* This is the CRUCIAL function for Passkey integration.
|
|
153
|
+
*
|
|
154
|
+
* @param coseBytes - The CBOR-encoded COSE key bytes
|
|
155
|
+
* @returns The X and Y coordinates as 32-byte hex strings
|
|
156
|
+
* @throws COSEParseError if the key is not a valid P256 key
|
|
157
|
+
*/
|
|
158
|
+
export function extractP256PublicKey(coseBytes) {
|
|
159
|
+
const coseKey = parseCOSEKey(coseBytes);
|
|
160
|
+
// Validate key type
|
|
161
|
+
if (coseKey.kty !== COSE_KEY_TYPE.EC2) {
|
|
162
|
+
throw new COSEParseError(`Invalid key type: expected EC2 (${COSE_KEY_TYPE.EC2}), got ${coseKey.kty}`);
|
|
163
|
+
}
|
|
164
|
+
// Validate curve (if present)
|
|
165
|
+
if (coseKey.crv !== undefined && coseKey.crv !== COSE_CURVE.P256) {
|
|
166
|
+
throw new COSEParseError(`Invalid curve: expected P-256 (${COSE_CURVE.P256}), got ${coseKey.crv}`);
|
|
167
|
+
}
|
|
168
|
+
// Validate algorithm (if present)
|
|
169
|
+
if (coseKey.alg !== undefined && coseKey.alg !== COSE_ALGORITHM.ES256) {
|
|
170
|
+
throw new COSEParseError(`Invalid algorithm: expected ES256 (${COSE_ALGORITHM.ES256}), got ${coseKey.alg}`);
|
|
171
|
+
}
|
|
172
|
+
// Validate coordinates
|
|
173
|
+
if (!coseKey.x || coseKey.x.length === 0) {
|
|
174
|
+
throw new COSEParseError("Missing X coordinate in COSE key");
|
|
175
|
+
}
|
|
176
|
+
if (!coseKey.y || coseKey.y.length === 0) {
|
|
177
|
+
throw new COSEParseError("Missing Y coordinate in COSE key");
|
|
178
|
+
}
|
|
179
|
+
// P-256 coordinates should be exactly 32 bytes
|
|
180
|
+
// However, some implementations may include leading zeros or strip them
|
|
181
|
+
// We handle both cases by padding/trimming to exactly 32 bytes
|
|
182
|
+
const xHex = padHex(bytesToHex(coseKey.x), 32);
|
|
183
|
+
const yHex = padHex(bytesToHex(coseKey.y), 32);
|
|
184
|
+
return { x: xHex, y: yHex };
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Extracts the public key from a WebAuthn attestation response.
|
|
188
|
+
*
|
|
189
|
+
* @param attestationObject - Base64URL encoded attestation object from registration
|
|
190
|
+
* @returns The P256 public key coordinates
|
|
191
|
+
* @throws COSEParseError if extraction fails
|
|
192
|
+
*/
|
|
193
|
+
export function extractPublicKeyFromAttestation(attestationObject) {
|
|
194
|
+
// Decode the attestation object
|
|
195
|
+
const attestationBytes = base64UrlToBytes(attestationObject);
|
|
196
|
+
let attestation;
|
|
197
|
+
try {
|
|
198
|
+
attestation = cborDecode(attestationBytes);
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
throw new COSEParseError(`Failed to decode attestation object: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
202
|
+
}
|
|
203
|
+
// Extract authData from attestation
|
|
204
|
+
if (!attestation.authData || !(attestation.authData instanceof Uint8Array)) {
|
|
205
|
+
throw new COSEParseError("Invalid attestation object: missing or invalid authData");
|
|
206
|
+
}
|
|
207
|
+
// Parse the authenticator data to get the public key
|
|
208
|
+
const { credentialId, publicKeyBytes } = parseAuthenticatorData(attestation.authData);
|
|
209
|
+
// Extract the P256 coordinates from the COSE key
|
|
210
|
+
const publicKey = extractP256PublicKey(publicKeyBytes);
|
|
211
|
+
return { credentialId, publicKey };
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Encodes a P256 public key to the uncompressed format (0x04 || x || y).
|
|
215
|
+
* This is the standard SEC1 uncompressed point format.
|
|
216
|
+
*
|
|
217
|
+
* @param publicKey - The P256 public key coordinates
|
|
218
|
+
* @returns The uncompressed public key as hex (65 bytes total)
|
|
219
|
+
*/
|
|
220
|
+
export function encodeUncompressedPublicKey(publicKey) {
|
|
221
|
+
// Ensure coordinates are exactly 32 bytes each
|
|
222
|
+
const x = padHex(publicKey.x, 32);
|
|
223
|
+
const y = padHex(publicKey.y, 32);
|
|
224
|
+
// Uncompressed format: 0x04 || x || y
|
|
225
|
+
return concatHex("0x04", x, y);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Validates that a public key is on the P256 curve.
|
|
229
|
+
* This is a basic validation - for full security, use a proper crypto library.
|
|
230
|
+
*
|
|
231
|
+
* @param publicKey - The public key coordinates to validate
|
|
232
|
+
* @returns true if the key appears valid
|
|
233
|
+
*/
|
|
234
|
+
export function isValidP256PublicKey(publicKey) {
|
|
235
|
+
// Basic validation: check that coordinates are 32 bytes each
|
|
236
|
+
const xClean = publicKey.x.startsWith("0x")
|
|
237
|
+
? publicKey.x.slice(2)
|
|
238
|
+
: publicKey.x;
|
|
239
|
+
const yClean = publicKey.y.startsWith("0x")
|
|
240
|
+
? publicKey.y.slice(2)
|
|
241
|
+
: publicKey.y;
|
|
242
|
+
// Each coordinate should be at most 64 hex chars (32 bytes)
|
|
243
|
+
if (xClean.length > 64 || yClean.length > 64) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
// Coordinates should not be zero
|
|
247
|
+
if (BigInt(`0x${xClean}`) === 0n || BigInt(`0x${yClean}`) === 0n) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
// P-256 prime
|
|
251
|
+
const p = BigInt("0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff");
|
|
252
|
+
// Coordinates should be less than the prime
|
|
253
|
+
if (BigInt(`0x${xClean}`) >= p || BigInt(`0x${yClean}`) >= p) {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
export { COSE_KEY_TYPE, COSE_ALGORITHM, COSE_CURVE };
|
|
259
|
+
//# sourceMappingURL=cose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cose.js","sourceRoot":"","sources":["../../src/utils/cose.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { base64UrlToBytes, bytesToBase64Url, base64UrlToHex, hexToBase64Url, bytesToHex, hexToBytes, stringToBase64Url, base64UrlToString, padHex, concatHex, } from "./base64url.js";
|
|
2
|
+
export { extractP256PublicKey, extractPublicKeyFromAttestation, parseAuthenticatorData, encodeUncompressedPublicKey, isValidP256PublicKey, COSEParseError, COSE_KEY_TYPE, COSE_ALGORITHM, COSE_CURVE, } from "./cose.js";
|
|
3
|
+
export { parseAuthenticatorDataFromAssertion, parseDERSignature, normalizeSignatureS, findJsonFieldPosition, parseWebAuthnAssertion, encodeWebAuthnSignature, createChallenge, hashMessage, createAssertionOptions, SignatureError, } from "./passkey.js";
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,EACN,SAAS,GACV,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,sBAAsB,EACtB,2BAA2B,EAC3B,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,cAAc,EACd,UAAU,GACX,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,mCAAmC,EACnC,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,WAAW,EACX,sBAAsB,EACtB,cAAc,GACf,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Base64URL encoding utilities
|
|
2
|
+
export { base64UrlToBytes, bytesToBase64Url, base64UrlToHex, hexToBase64Url, bytesToHex, hexToBytes, stringToBase64Url, base64UrlToString, padHex, concatHex, } from "./base64url.js";
|
|
3
|
+
// COSE key parsing utilities
|
|
4
|
+
export { extractP256PublicKey, extractPublicKeyFromAttestation, parseAuthenticatorData, encodeUncompressedPublicKey, isValidP256PublicKey, COSEParseError, COSE_KEY_TYPE, COSE_ALGORITHM, COSE_CURVE, } from "./cose.js";
|
|
5
|
+
// Passkey/WebAuthn utilities
|
|
6
|
+
export { parseAuthenticatorDataFromAssertion, parseDERSignature, normalizeSignatureS, findJsonFieldPosition, parseWebAuthnAssertion, encodeWebAuthnSignature, createChallenge, hashMessage, createAssertionOptions, SignatureError, } from "./passkey.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,EACN,SAAS,GACV,MAAM,gBAAgB,CAAC;AAExB,6BAA6B;AAC7B,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,sBAAsB,EACtB,2BAA2B,EAC3B,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,cAAc,EACd,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,6BAA6B;AAC7B,OAAO,EACL,mCAAmC,EACnC,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,WAAW,EACX,sBAAsB,EACtB,cAAc,GACf,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { type Hex } from "viem";
|
|
2
|
+
import type { AuthenticatorData, WebAuthnSignature, SignatureEncodingFormat } from "../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Error thrown when signature parsing or encoding fails.
|
|
5
|
+
*/
|
|
6
|
+
export declare class SignatureError extends Error {
|
|
7
|
+
constructor(message: string);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Parses the authenticator data from a WebAuthn assertion.
|
|
11
|
+
*
|
|
12
|
+
* @param authenticatorDataB64 - Base64URL encoded authenticator data
|
|
13
|
+
* @returns Parsed authenticator data structure
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseAuthenticatorDataFromAssertion(authenticatorDataB64: string): AuthenticatorData;
|
|
16
|
+
/**
|
|
17
|
+
* Parses a DER-encoded ECDSA signature into r and s components.
|
|
18
|
+
* WebAuthn signatures are DER-encoded ASN.1 sequences.
|
|
19
|
+
*
|
|
20
|
+
* DER format: 0x30 [total-length] 0x02 [r-length] [r] 0x02 [s-length] [s]
|
|
21
|
+
*
|
|
22
|
+
* @param signatureB64 - Base64URL encoded DER signature
|
|
23
|
+
* @returns Object with r and s as 32-byte hex strings
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseDERSignature(signatureB64: string): {
|
|
26
|
+
r: Hex;
|
|
27
|
+
s: Hex;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Normalizes the S value of an ECDSA signature to low-S form.
|
|
31
|
+
* This is required by some smart contract implementations to prevent
|
|
32
|
+
* signature malleability.
|
|
33
|
+
*
|
|
34
|
+
* For P-256, the curve order n is:
|
|
35
|
+
* 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
|
|
36
|
+
*
|
|
37
|
+
* If s > n/2, we replace s with n - s.
|
|
38
|
+
*
|
|
39
|
+
* @param s - The S component of the signature
|
|
40
|
+
* @returns The normalized S value in low-S form
|
|
41
|
+
*/
|
|
42
|
+
export declare function normalizeSignatureS(s: Hex): Hex;
|
|
43
|
+
/**
|
|
44
|
+
* Finds the position of a substring in a JSON string.
|
|
45
|
+
* Used to locate the challenge and type fields in clientDataJSON.
|
|
46
|
+
*
|
|
47
|
+
* @param json - The JSON string to search
|
|
48
|
+
* @param key - The key to find (e.g., "challenge", "type")
|
|
49
|
+
* @returns The byte offset of the key's value
|
|
50
|
+
*/
|
|
51
|
+
export declare function findJsonFieldPosition(json: string, key: string): number;
|
|
52
|
+
/**
|
|
53
|
+
* Parses a WebAuthn assertion response into its components.
|
|
54
|
+
*
|
|
55
|
+
* @param assertion - The WebAuthn assertion response
|
|
56
|
+
* @returns Parsed signature components
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseWebAuthnAssertion(assertion: {
|
|
59
|
+
authenticatorData: string;
|
|
60
|
+
clientDataJSON: string;
|
|
61
|
+
signature: string;
|
|
62
|
+
}): WebAuthnSignature;
|
|
63
|
+
/**
|
|
64
|
+
* Encodes a WebAuthn signature for smart contract verification.
|
|
65
|
+
* Different smart contract implementations expect different formats.
|
|
66
|
+
*
|
|
67
|
+
* @param signature - The parsed WebAuthn signature
|
|
68
|
+
* @param format - The encoding format to use
|
|
69
|
+
* @returns The encoded signature as hex
|
|
70
|
+
*/
|
|
71
|
+
export declare function encodeWebAuthnSignature(signature: WebAuthnSignature, format?: SignatureEncodingFormat): Hex;
|
|
72
|
+
/**
|
|
73
|
+
* Creates a WebAuthn challenge from a message hash.
|
|
74
|
+
* The challenge is typically the Base64URL encoding of the hash.
|
|
75
|
+
*
|
|
76
|
+
* @param messageHash - The message hash (usually a UserOpHash)
|
|
77
|
+
* @returns The challenge as Base64URL string
|
|
78
|
+
*/
|
|
79
|
+
export declare function createChallenge(messageHash: Hex): string;
|
|
80
|
+
/**
|
|
81
|
+
* Hashes a message according to EIP-191 (personal_sign).
|
|
82
|
+
* This is used when signing arbitrary messages.
|
|
83
|
+
*
|
|
84
|
+
* @param message - The message to hash
|
|
85
|
+
* @returns The EIP-191 hash
|
|
86
|
+
*/
|
|
87
|
+
export declare function hashMessage(message: string | Uint8Array): Hex;
|
|
88
|
+
/**
|
|
89
|
+
* Creates an assertion options object for react-native-passkey.
|
|
90
|
+
*
|
|
91
|
+
* @param challenge - The challenge as Base64URL string
|
|
92
|
+
* @param rpId - The Relying Party ID
|
|
93
|
+
* @param credentialId - The credential ID to use (Base64URL)
|
|
94
|
+
* @param userVerification - User verification requirement
|
|
95
|
+
* @param timeout - Timeout in milliseconds
|
|
96
|
+
* @returns Options object for Passkey.get()
|
|
97
|
+
*/
|
|
98
|
+
export declare function createAssertionOptions(challenge: string, rpId: string, credentialId: string, userVerification?: "required" | "preferred" | "discouraged", timeout?: number): {
|
|
99
|
+
rpId: string;
|
|
100
|
+
challenge: string;
|
|
101
|
+
allowCredentials: Array<{
|
|
102
|
+
id: string;
|
|
103
|
+
type: "public-key";
|
|
104
|
+
}>;
|
|
105
|
+
userVerification: "required" | "preferred" | "discouraged";
|
|
106
|
+
timeout: number;
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=passkey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passkey.d.ts","sourceRoot":"","sources":["../../src/utils/passkey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAkC,MAAM,MAAM,CAAC;AAChE,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,uBAAuB,EACxB,MAAM,mBAAmB,CAAC;AAS3B;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CACjD,oBAAoB,EAAE,MAAM,GAC3B,iBAAiB,CAyBnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,GAAG,CAAC;IAAC,CAAC,EAAE,GAAG,CAAA;CAAE,CAwD1E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,GAAG,GAAG,GAAG,CAgB/C;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAWvE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE;IAChD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,iBAAiB,CA2BpB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,iBAAiB,EAC5B,MAAM,GAAE,uBAAkC,GACzC,GAAG,CAWL;AAoFD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,GAAG,GAAG,MAAM,CAExD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,GAAG,CAa7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,gBAAgB,GAAE,UAAU,GAAG,WAAW,GAAG,aAA0B,EACvE,OAAO,SAAQ,GACd;IACD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,YAAY,CAAA;KAAE,CAAC,CAAC;IAC5D,gBAAgB,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;IAC3D,OAAO,EAAE,MAAM,CAAC;CACjB,CAaA"}
|