Skip to content

Commit

Permalink
cherry picked JWK thumbprint function from b0790aa
Browse files Browse the repository at this point in the history
  • Loading branch information
overheadhunter committed Jun 12, 2024
1 parent a2f8d7e commit 8207484
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
31 changes: 31 additions & 0 deletions frontend/src/common/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -477,3 +477,34 @@ export async function getFingerprint(key: string | undefined) {
return hashHex;
}
}

/**
* Computes the JWK Thumbprint (RFC 7638) using SHA-256.
* @param key A key to compute the thumbprint for
* @throws Error if the key is not supported
*/
export async function getJwkThumbprint(key: JsonWebKey | CryptoKey): Promise<string> {
let jwk: JsonWebKey;
if (key instanceof CryptoKey) {
jwk = await crypto.subtle.exportKey('jwk', key);
} else {
jwk = key;
}
// see https://datatracker.ietf.org/doc/html/rfc7638#section-3.2
let orderedJson: string;
switch (jwk.kty) {
case 'EC':
orderedJson = `{"crv":"${jwk.crv}","kty":"${jwk.kty}","x":"${jwk.x}","y":"${jwk.y}"}`;
break;
case 'RSA':
orderedJson = `{"e":"${jwk.e}","kty":"${jwk.kty}","n":"${jwk.n}"}`;
break;
case 'oct':
orderedJson = `{"k":"${jwk.k}","kty":"${jwk.kty}"}`;
break;
default: throw new Error('Unsupported key type');
}
const bytes = new TextEncoder().encode(orderedJson);
const hashBuffer = await crypto.subtle.digest('SHA-256', bytes);
return base64url.stringify(new Uint8Array(hashBuffer), { pad: false });
}
22 changes: 21 additions & 1 deletion frontend/test/common/crypto.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { use as chaiUse, expect } from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { before, describe } from 'mocha';
import { base64 } from 'rfc4648';
import { UnwrapKeyError, UserKeys, VaultKeys } from '../../src/common/crypto';
import { UnwrapKeyError, UserKeys, VaultKeys, getJwkThumbprint } from '../../src/common/crypto';

chaiUse(chaiAsPromised);

Expand Down Expand Up @@ -236,6 +236,26 @@ describe('crypto', () => {
expect(result).to.eql('7C3USOO3VU7IVQRKFMRFV3QE4VEZJECV');
});
});


describe('JWK Thumbprint', () => {

// https://datatracker.ietf.org/doc/html/rfc7638#section-3.1
it('compute example thumbprint from RFC 7638, Section 3.1', async () => {
const input: JsonWebKey & any = {
kty: 'RSA',
n: '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw',
e: 'AQAB',
alg: 'RS256',
kid: '2011-04-29'
};

const thumbprint = await getJwkThumbprint(input);

expect(thumbprint).to.eq('NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs');
});

});
});

/* ---------- MOCKS ---------- */
Expand Down

0 comments on commit 8207484

Please sign in to comment.