Skip to content

Commit 1dce8af

Browse files
committed
fix(web-demo): pad base64url before atob in toArrayBuffer
passkey-crypto stores PRF salts and credential IDs as canonical base64url (no padding). atob requires the input length to be a multiple of 4 — without the padding it silently drops the trailing partial group and the PRF extension receives a salt that's missing its last byte. That bad salt produces a different PRF output, the derived password no longer matches what attachPasskeyToWallet stored, and decryption fails with ccm tag mismatch. Pad with '=' up to the next multiple of 4 before atob. Refs: WCN-194 TICKET: WCN-194
1 parent 4b30c68 commit 1dce8af

1 file changed

Lines changed: 6 additions & 1 deletion

File tree

  • modules/web-demo/src/components/PasskeyDemo

modules/web-demo/src/components/PasskeyDemo/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,12 @@ function toArrayBuffer(val: any): ArrayBuffer {
166166
) as ArrayBuffer;
167167
}
168168
if (typeof val === 'string') {
169-
const b64 = val.replace(/-/g, '+').replace(/_/g, '/');
169+
// Treat strings as base64url. Pad to a multiple of 4 before atob so
170+
// unpadded base64url (the canonical form used by passkey-crypto) decodes
171+
// correctly — without padding atob silently drops the trailing byte and
172+
// the PRF receives the wrong salt.
173+
let b64 = val.replace(/-/g, '+').replace(/_/g, '/');
174+
while (b64.length % 4 !== 0) b64 += '=';
170175
const binary = atob(b64);
171176
const bytes = new Uint8Array(binary.length);
172177
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);

0 commit comments

Comments
 (0)