mirror of
https://github.com/bitwarden/browser
synced 2026-02-12 14:34:02 +00:00
Include aes gcm encryption
key connector will always provide the asym keys and the clients will encapsulate a key and encrypt communications with it.
This commit is contained in:
@@ -270,6 +270,47 @@ describe("WebCrypto Function Service", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("aes encrypt GCM mode", () => {
|
||||
it("should successfully encrypt data", async () => {
|
||||
const cryptoFunctionService = getWebCryptoFunctionService();
|
||||
const iv = makeStaticByteArray(12);
|
||||
const key = makeStaticByteArray(32);
|
||||
const data = Utils.fromUtf8ToArray("EncryptMe!");
|
||||
const encValue = await cryptoFunctionService.aesGcmEncrypt(data, iv, key);
|
||||
expect(encValue).toEqual(
|
||||
new Uint8Array(
|
||||
Buffer.concat([Utils.fromB64ToArray("Amy1abyVtlboYFBtLnDAzAwAgb3Qg2m4fMo="), iv]),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("should successfully encrypt with aad", async () => {
|
||||
const cryptoFunctionService = getWebCryptoFunctionService();
|
||||
const iv = makeStaticByteArray(12);
|
||||
const key = makeStaticByteArray(32);
|
||||
const data = Utils.fromUtf8ToArray("EncryptMe!");
|
||||
const aad = Utils.fromUtf8ToArray("aad");
|
||||
const encValue = await cryptoFunctionService.aesGcmEncrypt(data, iv, key, aad);
|
||||
expect(encValue).toEqual(
|
||||
new Uint8Array(
|
||||
Buffer.concat([Utils.fromB64ToArray("Amy1abyVtlboYJTbBTRtNtA4JtxBgjhhSCE="), iv]),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("should successfully encrypt and then decrypt data", async () => {
|
||||
const cryptoFunctionService = getWebCryptoFunctionService();
|
||||
const iv = makeStaticByteArray(12);
|
||||
const key = makeStaticByteArray(32);
|
||||
const value = "EncryptMe!";
|
||||
const data = Utils.fromUtf8ToArray(value);
|
||||
const encAndIv = new Uint8Array(await cryptoFunctionService.aesGcmEncrypt(data, iv, key));
|
||||
const envValue = encAndIv.slice(0, encAndIv.length - 12);
|
||||
const decValue = await cryptoFunctionService.aesDecrypt(envValue, iv, key, "gcm");
|
||||
expect(Utils.fromBufferToUtf8(decValue)).toBe(value);
|
||||
});
|
||||
});
|
||||
|
||||
describe("aesDecryptFast CBC mode", () => {
|
||||
it("should successfully decrypt data", async () => {
|
||||
const cryptoFunctionService = getWebCryptoFunctionService();
|
||||
|
||||
@@ -234,6 +234,26 @@ export class WebCryptoFunctionService implements CryptoFunctionService {
|
||||
return new Uint8Array(buffer);
|
||||
}
|
||||
|
||||
async aesGcmEncrypt(
|
||||
data: Uint8Array,
|
||||
iv: Uint8Array,
|
||||
key: Uint8Array,
|
||||
additionalData?: Uint8Array,
|
||||
): Promise<Uint8Array> {
|
||||
const impKey = await this.subtle.importKey("raw", key, { name: "AES-GCM" } as any, false, [
|
||||
"encrypt",
|
||||
]);
|
||||
const buffer = await this.subtle.encrypt(
|
||||
{ name: "AES-GCM", iv: iv, tagLength: 128, additionalData },
|
||||
impKey,
|
||||
data,
|
||||
);
|
||||
const result = new Uint8Array(buffer.byteLength + iv.byteLength);
|
||||
result.set(new Uint8Array(buffer), 0);
|
||||
result.set(iv, buffer.byteLength);
|
||||
return result;
|
||||
}
|
||||
|
||||
aesDecryptFastParameters(
|
||||
data: string,
|
||||
iv: string,
|
||||
|
||||
@@ -187,6 +187,47 @@ describe("NodeCrypto Function Service", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("aes encrypt GCM mode", () => {
|
||||
it("should successfully encrypt data", async () => {
|
||||
const cryptoFunctionService = new NodeCryptoFunctionService();
|
||||
const iv = makeStaticByteArray(12);
|
||||
const key = makeStaticByteArray(32);
|
||||
const data = Utils.fromUtf8ToArray("EncryptMe!");
|
||||
const encValue = await cryptoFunctionService.aesGcmEncrypt(data, iv, key);
|
||||
expect(encValue).toEqual(
|
||||
new Uint8Array(
|
||||
Buffer.concat([Utils.fromB64ToArray("Amy1abyVtlboYFBtLnDAzAwAgb3Qg2m4fMo="), iv]),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("should successfully encrypt with aad", async () => {
|
||||
const cryptoFunctionService = new NodeCryptoFunctionService();
|
||||
const iv = makeStaticByteArray(12);
|
||||
const key = makeStaticByteArray(32);
|
||||
const data = Utils.fromUtf8ToArray("EncryptMe!");
|
||||
const aad = Utils.fromUtf8ToArray("aad");
|
||||
const encValue = await cryptoFunctionService.aesGcmEncrypt(data, iv, key, aad);
|
||||
expect(encValue).toEqual(
|
||||
new Uint8Array(
|
||||
Buffer.concat([Utils.fromB64ToArray("Amy1abyVtlboYJTbBTRtNtA4JtxBgjhhSCE="), iv]),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it("should successfully encrypt and then decrypt data", async () => {
|
||||
const cryptoFunctionService = new NodeCryptoFunctionService();
|
||||
const iv = makeStaticByteArray(12);
|
||||
const key = makeStaticByteArray(32);
|
||||
const value = "EncryptMe!";
|
||||
const data = Utils.fromUtf8ToArray(value);
|
||||
const encAndIv = new Uint8Array(await cryptoFunctionService.aesGcmEncrypt(data, iv, key));
|
||||
const envValue = encAndIv.slice(0, encAndIv.length - 12);
|
||||
const decValue = await cryptoFunctionService.aesDecrypt(envValue, iv, key, "gcm");
|
||||
expect(Utils.fromBufferToUtf8(decValue)).toBe(value);
|
||||
});
|
||||
});
|
||||
|
||||
describe("aesDecryptFast CBC mode", () => {
|
||||
it("should successfully decrypt data", async () => {
|
||||
const nodeCryptoFunctionService = new NodeCryptoFunctionService();
|
||||
|
||||
@@ -163,6 +163,25 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
|
||||
return Promise.resolve(this.toUint8Buffer(encBuf));
|
||||
}
|
||||
|
||||
async aesGcmEncrypt(
|
||||
data: Uint8Array,
|
||||
iv: Uint8Array,
|
||||
key: Uint8Array,
|
||||
additionalData?: Uint8Array,
|
||||
): Promise<Uint8Array> {
|
||||
const nodeData = this.toNodeBuffer(data);
|
||||
const nodeIv = this.toNodeBuffer(iv);
|
||||
const nodeKey = this.toNodeBuffer(key);
|
||||
const cipher = crypto.createCipheriv("aes-256-gcm", nodeKey, nodeIv, { authTagLength: 16 });
|
||||
if (additionalData != null) {
|
||||
const nodeAdditionalData = this.toNodeBuffer(additionalData);
|
||||
cipher.setAAD(nodeAdditionalData);
|
||||
}
|
||||
const encBuf = Buffer.concat([cipher.update(nodeData), cipher.final()]);
|
||||
const tag = cipher.getAuthTag();
|
||||
return Promise.resolve(this.toUint8Buffer(Buffer.concat([encBuf, tag, nodeIv])));
|
||||
}
|
||||
|
||||
aesDecryptFastParameters(
|
||||
data: string,
|
||||
iv: string,
|
||||
@@ -318,7 +337,7 @@ export class NodeCryptoFunctionService implements CryptoFunctionService {
|
||||
if (typeof value === "string") {
|
||||
buf = Utils.fromUtf8ToArray(value);
|
||||
} else {
|
||||
buf = value;
|
||||
buf = new Uint8Array(value);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user