@meeco/cryppo
Version:
In-browser encryption and decryption. Clone of Ruby Cryppo
74 lines • 2.97 kB
JavaScript
import forge from 'node-forge';
import { EncryptionKey } from '../encryption-key.js';
import { generateDerivedKey } from '../key-derivation/pbkdf2-hmac.js';
import { SerializationFormat } from '../serialization-versions.js';
import { binaryStringToBytesBuffer, serialize } from '../util.js';
const { cipher: forgeCipher, random, util } = forge;
export async function encryptWithGeneratedKey({ data, strategy, keyLength, iv }, serializationVersion = SerializationFormat.latest_version) {
const key = EncryptionKey.generateRandom(keyLength || 32);
const result = await encryptWithKey({ key, data, strategy, iv }, serializationVersion);
return {
...result,
generatedKey: key,
};
}
export async function encryptWithKeyDerivedFromString({ passphrase, data, strategy, iv, serializationVersion = SerializationFormat.latest_version, }) {
const derived = await generateDerivedKey({ passphrase });
const result = await encryptWithKey({
key: derived.key,
data,
strategy,
iv,
}, serializationVersion);
const serializedKey = derived.options.serialize(serializationVersion);
result.serialized = `${result.serialized}.${serializedKey}`;
return {
...result,
...derived,
};
}
export async function encryptWithKey({ key, data, strategy, iv }, serializationVersion = SerializationFormat.latest_version) {
if (!data || data.length === 0) {
return {
encrypted: null,
serialized: null,
};
}
const output = encryptWithKeyUsingArtefacts({ key, data, strategy, iv });
const { encrypted, artifacts } = output;
const keyLengthBits = key.bytes.length * 8;
const [cipher, mode] = strategy.split('-').map(upperWords);
const serialized = serialize(`${cipher}${keyLengthBits}${mode}`, encrypted || '', artifacts, serializationVersion);
return {
encrypted,
serialized,
};
}
/**
* UpperCamelCase helper
*/
const upperWords = (val) => val.slice(0, 1).toUpperCase() + val.slice(1).toLowerCase();
export function encryptWithKeyUsingArtefacts({ key, data, strategy, iv }) {
if (data.length === 0) {
return { encrypted: null };
}
// @ts-expect-error node-forge createBuffer accepts Uint8Array at runtime
const cipher = forgeCipher.createCipher(strategy, util.createBuffer(key.bytes));
iv = iv || random.getBytesSync(12);
cipher.start({ iv: util.createBuffer(iv), additionalData: 'none', tagLength: 128 });
// @ts-expect-error node-forge createBuffer accepts Uint8Array at runtime
cipher.update(util.createBuffer(data));
cipher.finish();
const artifacts = {
iv: binaryStringToBytesBuffer(iv),
};
if (cipher.mode.tag) {
artifacts.at = binaryStringToBytesBuffer(cipher.mode.tag.data);
}
artifacts.ad = 'none';
return {
encrypted: cipher.output.data,
artifacts,
};
}
//# sourceMappingURL=encryption.js.map