mirror of
https://github.com/Blah-IM/typescript-core.git
synced 2025-04-30 16:21:10 +00:00
refactor: Replace key wrapping with manual PKCS8/raw key encryption
Implement utility functions for conversion between Ed25519 raw key data and PKCS8 format, and update KeyPair encode/decode methods to use direct encrypt/decrypt operations instead of wrapKey/unwrapKey.
This commit is contained in:
parent
23bd666a6e
commit
249bbf2b54
3 changed files with 42 additions and 8 deletions
|
@ -3,7 +3,11 @@ import { hexToBuf } from "./mod.ts";
|
|||
import { pbkdf2Key } from "./pbkdf2.ts";
|
||||
import { BlahPublicKey } from "./publicKey.ts";
|
||||
import type { BlahPayloadSignee, BlahSignedPayload } from "./signedPayload.ts";
|
||||
import { bufToHex } from "./utils.ts";
|
||||
import {
|
||||
bufToHex,
|
||||
ed25519PKCS8ToRawPrivateKey,
|
||||
ed25519RawPrivateKeyToPKCS8,
|
||||
} from "./utils.ts";
|
||||
|
||||
export type EncodedBlahKeyPair =
|
||||
& {
|
||||
|
@ -72,14 +76,20 @@ export class BlahKeyPair {
|
|||
}
|
||||
|
||||
const derviedKey = await pbkdf2Key(password, encoded.salt);
|
||||
const privateKey = await crypto.subtle.unwrapKey(
|
||||
"pkcs8",
|
||||
hexToBuf(encoded.passwordProtectedPrivateKey),
|
||||
derviedKey,
|
||||
const encryptedKeyData = hexToBuf(encoded.passwordProtectedPrivateKey);
|
||||
const decryptedKeyData = await crypto.subtle.decrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv: hexToBuf(encoded.iv),
|
||||
},
|
||||
derviedKey,
|
||||
encryptedKeyData,
|
||||
);
|
||||
const pkcs8Bytes = ed25519RawPrivateKeyToPKCS8(decryptedKeyData);
|
||||
|
||||
const privateKey = await crypto.subtle.importKey(
|
||||
"pkcs8",
|
||||
pkcs8Bytes,
|
||||
{ name: "Ed25519" },
|
||||
true,
|
||||
["sign"],
|
||||
|
@ -114,14 +124,20 @@ export class BlahKeyPair {
|
|||
const iv = bufToHex(ivBuf);
|
||||
|
||||
const derviedKey = await pbkdf2Key(password, saltBuf);
|
||||
const wrappedPrivateKey = await crypto.subtle.wrapKey(
|
||||
|
||||
const pkcs8Bytes = await crypto.subtle.exportKey(
|
||||
"pkcs8",
|
||||
this.internalPrivateKey,
|
||||
derviedKey,
|
||||
);
|
||||
const rawPrivateKeyBytes = ed25519PKCS8ToRawPrivateKey(pkcs8Bytes);
|
||||
|
||||
const wrappedPrivateKey = await crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv: ivBuf,
|
||||
},
|
||||
derviedKey,
|
||||
rawPrivateKeyBytes,
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
|
@ -22,7 +22,7 @@ export async function pbkdf2Key(
|
|||
passwordKey,
|
||||
{ name: "AES-GCM", length: 256 },
|
||||
false,
|
||||
["wrapKey", "unwrapKey"],
|
||||
["encrypt", "decrypt"],
|
||||
);
|
||||
|
||||
return key;
|
||||
|
|
|
@ -9,3 +9,21 @@ export function hexToBuf(hex: string): Uint8Array {
|
|||
(hex.match(/[\da-f]{2}/gi) ?? []).map((m) => parseInt(m, 16)),
|
||||
);
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/79145876
|
||||
const ed25519PKCS8Prefix = hexToBuf("302e020100300506032b657004220420");
|
||||
export function ed25519RawPrivateKeyToPKCS8(
|
||||
buf: ArrayBufferLike | Uint8Array,
|
||||
): Uint8Array {
|
||||
const u8Array = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
|
||||
const pkcs8 = new Uint8Array(ed25519PKCS8Prefix.length + u8Array.length);
|
||||
pkcs8.set(ed25519PKCS8Prefix, 0);
|
||||
pkcs8.set(u8Array, ed25519PKCS8Prefix.length);
|
||||
return pkcs8;
|
||||
}
|
||||
export function ed25519PKCS8ToRawPrivateKey(
|
||||
buf: ArrayBufferLike | Uint8Array,
|
||||
): Uint8Array {
|
||||
const u8Array = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
|
||||
return u8Array.slice(ed25519PKCS8Prefix.length);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue