mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
Add a crypto module to convert ECDSA private CryptoKey into a public key
This commit is contained in:
parent
6430dd11ad
commit
1ed6cac1c4
2 changed files with 53 additions and 0 deletions
28
src/utils/crypto.test.ts
Normal file
28
src/utils/crypto.test.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { assertEquals } from '@std/assert';
|
||||||
|
|
||||||
|
import { getEcdsaPublicKey } from '@/utils/crypto.ts';
|
||||||
|
|
||||||
|
Deno.test('getEcdsaPublicKey', async () => {
|
||||||
|
const { publicKey, privateKey } = await crypto.subtle.generateKey(
|
||||||
|
{
|
||||||
|
name: 'ECDSA',
|
||||||
|
namedCurve: 'P-256',
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
['sign', 'verify'],
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await getEcdsaPublicKey(privateKey, true);
|
||||||
|
|
||||||
|
assertKeysEqual(result, publicKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Assert that two CryptoKey objects are equal by value. Keys must be exportable. */
|
||||||
|
async function assertKeysEqual(a: CryptoKey, b: CryptoKey): Promise<void> {
|
||||||
|
const [jwk1, jwk2] = await Promise.all([
|
||||||
|
crypto.subtle.exportKey('jwk', a),
|
||||||
|
crypto.subtle.exportKey('jwk', b),
|
||||||
|
]);
|
||||||
|
|
||||||
|
assertEquals(jwk1, jwk2);
|
||||||
|
}
|
||||||
25
src/utils/crypto.ts
Normal file
25
src/utils/crypto.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* Convert an ECDSA private key into a public key.
|
||||||
|
* https://stackoverflow.com/a/72153942
|
||||||
|
*/
|
||||||
|
export async function getEcdsaPublicKey(
|
||||||
|
privateKey: CryptoKey,
|
||||||
|
extractable: boolean,
|
||||||
|
): Promise<CryptoKey> {
|
||||||
|
if (privateKey.type !== 'private') {
|
||||||
|
throw new Error('Expected a private key.');
|
||||||
|
}
|
||||||
|
if (privateKey.algorithm.name !== 'ECDSA') {
|
||||||
|
throw new Error('Expected a private key with the ECDSA algorithm.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const jwk = await crypto.subtle.exportKey('jwk', privateKey);
|
||||||
|
const keyUsages: KeyUsage[] = ['verify'];
|
||||||
|
|
||||||
|
// Remove the private property from the JWK.
|
||||||
|
delete jwk.d;
|
||||||
|
jwk.key_ops = keyUsages;
|
||||||
|
jwk.ext = extractable;
|
||||||
|
|
||||||
|
return crypto.subtle.importKey('jwk', jwk, privateKey.algorithm, extractable, keyUsages);
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue