diff --git a/crypto/keypair.ts b/crypto/keypair.ts index 2f176e3..226e02c 100644 --- a/crypto/keypair.ts +++ b/crypto/keypair.ts @@ -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 { diff --git a/crypto/pbkdf2.ts b/crypto/pbkdf2.ts index 7aa2e82..31d2539 100644 --- a/crypto/pbkdf2.ts +++ b/crypto/pbkdf2.ts @@ -22,7 +22,7 @@ export async function pbkdf2Key( passwordKey, { name: "AES-GCM", length: 256 }, false, - ["wrapKey", "unwrapKey"], + ["encrypt", "decrypt"], ); return key; diff --git a/crypto/utils.ts b/crypto/utils.ts index 35caffe..a80b677 100644 --- a/crypto/utils.ts +++ b/crypto/utils.ts @@ -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); +}