Skip to content

Commit 64716bf

Browse files
committed
refactor: update DPoP keypair generation and signing algorithm to use ES256 for improved compatibility and security
1 parent 0adcc2f commit 64716bf

2 files changed

Lines changed: 7 additions & 19 deletions

File tree

src/App.svelte

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,7 @@
222222
if (isDpopEnabled) {
223223
const { publicKey, privateKey } = JSON.parse(localStorage.getItem('dpop_keypair'));
224224
// Import the private JWK to a CryptoKey for signing
225-
// Add the algorithm parameter if it's missing (required by JOSE)
226-
const privateKeyWithAlg = { ...privateKey };
227-
if (!privateKeyWithAlg.alg) {
228-
privateKeyWithAlg.alg = 'EdDSA';
229-
}
230-
const signingKey = await jose.importJWK(privateKeyWithAlg, 'EdDSA');
225+
const signingKey = await jose.importJWK(privateKey, 'ES256');
231226
// Create a minimal DPoP proof JWT (RFC 9449)
232227
// Generate SHA256 hash of the code for c_hash
233228
// Convert to BASE64URL as per spec section 1.8
@@ -245,15 +240,15 @@
245240
htm: 'POST'
246241
};
247242
// Restrict public JWK in header to RFC 7638 members only
248-
// For EdDSA (Ed25519), we need kty, crv, and x parameters
249243
const publicJwkMinimal = {
250244
kty: publicKey.kty,
251245
crv: publicKey.crv,
252-
x: publicKey.x
246+
x: publicKey.x,
247+
y: publicKey.y
253248
};
254249
const dpopToken = await new jose.SignJWT(dpopPayload)
255250
.setProtectedHeader({
256-
alg: 'EdDSA',
251+
alg: 'ES256',
257252
typ: 'dpop+jwt',
258253
jwk: publicJwkMinimal
259254
})

src/lib/dpop.js

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// Get existing EdDSA (Ed25519) keypair from storage or create a new one if missing
2-
// EdDSA provides better performance and security compared to ES256
1+
// Get existing ES256 keypair from storage or create a new one if missing
32
async function generateDpopJkt() {
43
let stored = null;
54
try {
@@ -12,15 +11,12 @@ async function generateDpopJkt() {
1211
if (stored?.publicKey && stored?.privateKey) {
1312
publicJwk = stored.publicKey;
1413
} else {
15-
const keyPair = await crypto.subtle.generateKey({ name: 'Ed25519' }, true, [
14+
const keyPair = await crypto.subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, [
1615
'sign',
1716
'verify'
1817
]);
1918
const newPublicJwk = await crypto.subtle.exportKey('jwk', keyPair.publicKey);
2019
const newPrivateJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey);
21-
// Add algorithm parameter to JWKs for JOSE compatibility
22-
newPublicJwk.alg = 'EdDSA';
23-
newPrivateJwk.alg = 'EdDSA';
2420
localStorage.setItem(
2521
'dpop_keypair',
2622
JSON.stringify({
@@ -38,15 +34,12 @@ async function generateDpopJkt() {
3834

3935
// Explicitly rotate the DPoP keypair and return the new jkt
4036
async function regenerateDpopJkt() {
41-
const keyPair = await crypto.subtle.generateKey({ name: 'Ed25519' }, true, [
37+
const keyPair = await crypto.subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, [
4238
'sign',
4339
'verify'
4440
]);
4541
const publicJwk = await crypto.subtle.exportKey('jwk', keyPair.publicKey);
4642
const privateJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey);
47-
// Add algorithm parameter to JWKs for JOSE compatibility
48-
publicJwk.alg = 'EdDSA';
49-
privateJwk.alg = 'EdDSA';
5043
localStorage.setItem(
5144
'dpop_keypair',
5245
JSON.stringify({

0 commit comments

Comments
 (0)