1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-30 15:13:32 +00:00

Replace webcrypto RSA with PureCrypto RSA (#17742)

This commit is contained in:
Bernd Schoolmann
2025-12-03 13:11:03 +01:00
committed by GitHub
parent cf416388d7
commit a6100d8a0e
6 changed files with 48 additions and 101 deletions

View File

@@ -4,6 +4,7 @@ import * as forge from "node-forge";
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
import { UnsignedPublicKey } from "@bitwarden/common/key-management/types";
import { SdkLoadService } from "@bitwarden/common/platform/abstractions/sdk/sdk-load.service";
import { EncryptionType } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import {
@@ -12,6 +13,7 @@ import {
} from "@bitwarden/common/platform/models/domain/decrypt-parameters";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { CsprngArray } from "@bitwarden/common/types/csprng";
import { PureCrypto } from "@bitwarden/sdk-internal";
export class NodeCryptoFunctionService implements CryptoFunctionService {
pbkdf2(
@@ -205,72 +207,34 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
return Promise.resolve(this.toUint8Buffer(decBuf));
}
rsaEncrypt(
async rsaEncrypt(
data: Uint8Array,
publicKey: Uint8Array,
algorithm: "sha1" | "sha256",
_algorithm: "sha1",
): Promise<Uint8Array> {
if (algorithm === "sha256") {
throw new Error("Node crypto does not support RSA-OAEP SHA-256");
}
const pem = this.toPemPublicKey(publicKey);
const decipher = crypto.publicEncrypt(pem, this.toNodeBuffer(data));
return Promise.resolve(this.toUint8Buffer(decipher));
await SdkLoadService.Ready;
return PureCrypto.rsa_encrypt_data(data, publicKey);
}
rsaDecrypt(
async rsaDecrypt(
data: Uint8Array,
privateKey: Uint8Array,
algorithm: "sha1" | "sha256",
_algorithm: "sha1",
): Promise<Uint8Array> {
if (algorithm === "sha256") {
throw new Error("Node crypto does not support RSA-OAEP SHA-256");
}
const pem = this.toPemPrivateKey(privateKey);
const decipher = crypto.privateDecrypt(pem, this.toNodeBuffer(data));
return Promise.resolve(this.toUint8Buffer(decipher));
await SdkLoadService.Ready;
return PureCrypto.rsa_decrypt_data(data, privateKey);
}
async rsaExtractPublicKey(privateKey: Uint8Array): Promise<UnsignedPublicKey> {
const privateKeyByteString = Utils.fromBufferToByteString(privateKey);
const privateKeyAsn1 = forge.asn1.fromDer(privateKeyByteString);
const forgePrivateKey: any = forge.pki.privateKeyFromAsn1(privateKeyAsn1);
const forgePublicKey = (forge.pki as any).setRsaPublicKey(forgePrivateKey.n, forgePrivateKey.e);
const publicKeyAsn1 = forge.pki.publicKeyToAsn1(forgePublicKey);
const publicKeyByteString = forge.asn1.toDer(publicKeyAsn1).data;
const publicKeyArray = Utils.fromByteStringToArray(publicKeyByteString);
return publicKeyArray as UnsignedPublicKey;
await SdkLoadService.Ready;
return PureCrypto.rsa_extract_public_key(privateKey) as UnsignedPublicKey;
}
async rsaGenerateKeyPair(length: 1024 | 2048 | 4096): Promise<[UnsignedPublicKey, Uint8Array]> {
return new Promise<[UnsignedPublicKey, Uint8Array]>((resolve, reject) => {
forge.pki.rsa.generateKeyPair(
{
bits: length,
workers: -1,
e: 0x10001, // 65537
},
(error, keyPair) => {
if (error != null) {
reject(error);
return;
}
const publicKeyAsn1 = forge.pki.publicKeyToAsn1(keyPair.publicKey);
const publicKeyByteString = forge.asn1.toDer(publicKeyAsn1).getBytes();
const publicKey = Utils.fromByteStringToArray(publicKeyByteString);
const privateKeyAsn1 = forge.pki.privateKeyToAsn1(keyPair.privateKey);
const privateKeyPkcs8 = forge.pki.wrapRsaPrivateKey(privateKeyAsn1);
const privateKeyByteString = forge.asn1.toDer(privateKeyPkcs8).getBytes();
const privateKey = Utils.fromByteStringToArray(privateKeyByteString);
resolve([publicKey as UnsignedPublicKey, privateKey]);
},
);
});
async rsaGenerateKeyPair(_length: 2048): Promise<[UnsignedPublicKey, Uint8Array]> {
await SdkLoadService.Ready;
const privateKey = PureCrypto.rsa_generate_keypair();
const publicKey = await this.rsaExtractPublicKey(privateKey);
return [publicKey, privateKey];
}
aesGenerateKey(bitLength: 128 | 192 | 256 | 512): Promise<CsprngArray> {