padloc/packages/core/src/sjcl.ts

82 lines
2.6 KiB
TypeScript

import { PBKDF2Params, AESKey, AESEncryptionParams } from "./crypto";
import { Err, ErrorCode } from "./error";
import { sjcl } from "../vendor/sjcl";
// Shorthands for codec functions
const bytesToBits = sjcl.codec.bytes.toBits;
const bitsToBytes = sjcl.codec.bytes.fromBits;
/**
* [[CrypoProvider]] implemenation using the [SJCL](https://github.com/bitwiseshiftleft/sjcl)
* library. This is used to decrypt legacy (<3.x) Padlock containers that use AES in CCM mode
* which is unfortunately not supported by the WebCrypto standard. Only
* supports encryption/decryption using AES-CCM.
*/
const SJCLProvider = {
isAvailable() {
return true;
},
randomBytes(_bytes: number): Uint8Array {
throw new Err(ErrorCode.NOT_SUPPORTED);
},
async deriveKey(_password: string, _params: PBKDF2Params): Promise<AESKey> {
throw new Err(ErrorCode.NOT_SUPPORTED);
},
async randomKey(_n = 256) {
throw new Err(ErrorCode.NOT_SUPPORTED);
},
async decrypt(key: AESKey, ct: Uint8Array, params: AESEncryptionParams): Promise<Uint8Array> {
if (params.algorithm !== "AES-CCM") {
throw new Err(ErrorCode.INVALID_ENCRYPTION_PARAMS);
}
// Only AES and CCM are supported
const algorithm = "aes";
const mode = "ccm";
try {
const cipher = new sjcl.cipher[algorithm](bytesToBits(key));
const pt = sjcl.mode[mode].decrypt(
cipher,
bytesToBits(ct),
bytesToBits(params.iv!),
bytesToBits(params.additionalData!),
params.tagSize
);
return new Uint8Array(bitsToBytes(pt));
} catch (e) {
throw new Err(ErrorCode.DECRYPTION_FAILED);
}
},
async encrypt(key: AESKey, pt: Uint8Array, params: AESEncryptionParams): Promise<Uint8Array> {
if (params.algorithm !== "AES-CCM") {
throw new Err(ErrorCode.INVALID_ENCRYPTION_PARAMS);
}
// Only AES and CCM are supported
const algorithm = "aes";
const mode = "ccm";
try {
const cipher = new sjcl.cipher[algorithm](bytesToBits(key));
var ct = sjcl.mode[mode].encrypt(
cipher,
bytesToBits(pt),
bytesToBits(params.iv!),
bytesToBits(params.additionalData!),
params.tagSize
);
return new Uint8Array(bitsToBytes(ct));
} catch (e) {
throw new Err(ErrorCode.ENCRYPTION_FAILED);
}
},
};
export default SJCLProvider;