181 lines
5.4 KiB
JavaScript
181 lines
5.4 KiB
JavaScript
const test = require('tape');
|
|
const Cryptr = require('../');
|
|
|
|
const testSecret = 'myTotalySecretKey';
|
|
const testData = 'bacon';
|
|
|
|
test('works...', (t) => {
|
|
t.plan(1);
|
|
|
|
const cryptr = new Cryptr(testSecret);
|
|
const encryptedString = cryptr.encrypt(testData);
|
|
const decryptedString = cryptr.decrypt(encryptedString);
|
|
|
|
t.equal(decryptedString, testData, 'decrypted aes256 correctly');
|
|
});
|
|
|
|
test('works with custom encoding', (t) => {
|
|
const encodings = ['hex', 'base64', 'latin1'];
|
|
|
|
t.plan(encodings.length);
|
|
|
|
encodings.forEach((encoding) => {
|
|
const cryptr = new Cryptr(testSecret, { encoding });
|
|
const encryptedString = cryptr.encrypt(testData);
|
|
const decryptedString = cryptr.decrypt(encryptedString);
|
|
|
|
t.equal(decryptedString, testData, `decrypted correctly with ${encoding} encoding`);
|
|
});
|
|
});
|
|
|
|
test('custom encoding affects output length', (t) => {
|
|
t.plan(1);
|
|
|
|
const cryptr = new Cryptr(testSecret, { encoding: 'base64' });
|
|
const cryptr2 = new Cryptr(testSecret);
|
|
const encryptedString = cryptr.encrypt(testData);
|
|
const encryptedString2 = cryptr2.encrypt(testData);
|
|
|
|
t.ok(encryptedString.length < encryptedString2.length, 'custom encoding was shorter');
|
|
});
|
|
|
|
test('works with custom pbkdf2Iterations', (t) => {
|
|
t.plan(1);
|
|
|
|
const cryptr = new Cryptr(testSecret, { pbkdf2Iterations: 10000 });
|
|
const encryptedString = cryptr.encrypt(testData);
|
|
const decryptedString = cryptr.decrypt(encryptedString);
|
|
|
|
t.equal(decryptedString, testData, 'decrypted aes256 correctly with custom iterations');
|
|
});
|
|
|
|
test('custom pbkdf2Iterations affects speed', (t) => {
|
|
t.plan(1);
|
|
|
|
const cryptr = new Cryptr(testSecret, { pbkdf2Iterations: 1000 });
|
|
const cryptr2 = new Cryptr(testSecret);
|
|
const customStart = performance.now();
|
|
for (let index = 0; index < 10; index++) {
|
|
const encryptedString = cryptr.encrypt(testData + index);
|
|
cryptr.decrypt(encryptedString);
|
|
}
|
|
const customEnd = performance.now();
|
|
|
|
const defaultStart = performance.now();
|
|
for (let index = 0; index < 10; index++) {
|
|
const encryptedString = cryptr2.encrypt(testData + index);
|
|
cryptr2.decrypt(encryptedString);
|
|
}
|
|
const defaultEnd = performance.now();
|
|
|
|
const customTime = customEnd - customStart;
|
|
const defaultTime = defaultEnd - defaultStart;
|
|
|
|
t.ok(customTime < defaultTime, 'custom iterations were faster');
|
|
});
|
|
|
|
test('works with custom saltLength', (t) => {
|
|
t.plan(1);
|
|
|
|
const cryptr = new Cryptr(testSecret, { saltLength: 10 });
|
|
const encryptedString = cryptr.encrypt(testData);
|
|
const decryptedString = cryptr.decrypt(encryptedString);
|
|
|
|
t.equal(decryptedString, testData, 'decrypted aes256 correctly with custom salt length');
|
|
});
|
|
|
|
test('custom saltLength affects output length', (t) => {
|
|
t.plan(1);
|
|
|
|
const customSaltLength = 30;
|
|
const cryptr = new Cryptr(testSecret, { saltLength: customSaltLength });
|
|
const cryptr2 = new Cryptr(testSecret);
|
|
const encryptedString = cryptr.encrypt(testData);
|
|
const encryptedString2 = cryptr2.encrypt(testData);
|
|
|
|
t.equal(
|
|
encryptedString2.length - encryptedString.length,
|
|
(64 - customSaltLength) * 2,
|
|
'output length is affected by salt length',
|
|
);
|
|
});
|
|
|
|
test('works with utf8 specific characters', (t) => {
|
|
t.plan(1);
|
|
|
|
const testString = 'ßáÇÖÑ 🥓';
|
|
const cryptr = new Cryptr(testSecret);
|
|
const encryptedString = cryptr.encrypt(testString);
|
|
const decryptedString = cryptr.decrypt(encryptedString);
|
|
|
|
t.equal(decryptedString, testString, 'decrypted aes256 correctly with UTF8 chars');
|
|
});
|
|
|
|
test('goes bang if bad secret', (t) => {
|
|
const badSecrets = [null, undefined, 0, 123451345134, '', Buffer.from('buffer'), {}];
|
|
|
|
t.plan(badSecrets.length);
|
|
|
|
for (let i = 0; i < badSecrets.length; i++) {
|
|
t.throws(
|
|
() => new Cryptr(badSecrets[i]),
|
|
/Cryptr: secret must be a non-0-length string/,
|
|
`throws on bad secret ${badSecrets[i]}`,
|
|
);
|
|
}
|
|
});
|
|
|
|
test('encrypt goes bang if value is null or undefined', (t) => {
|
|
const cryptr = new Cryptr(testSecret);
|
|
const badValues = [null, undefined];
|
|
|
|
t.plan(badValues.length);
|
|
|
|
for (let i = 0; i < badValues.length; i++) {
|
|
t.throws(
|
|
() => cryptr.encrypt(badValues[i]),
|
|
/value must not be null or undefined/,
|
|
`throws on value ${badValues[i]}`,
|
|
);
|
|
}
|
|
});
|
|
|
|
test('decrypt goes bang if value is null or undefined', (t) => {
|
|
const cryptr = new Cryptr(testSecret);
|
|
const badValues = [null, undefined];
|
|
|
|
t.plan(badValues.length);
|
|
|
|
for (let i = 0; i < badValues.length; i++) {
|
|
t.throws(
|
|
() => cryptr.decrypt(badValues[i]),
|
|
/value must not be null or undefined/,
|
|
`throws on value ${badValues[i]}`,
|
|
);
|
|
}
|
|
});
|
|
|
|
test('decrypt goes bang if value has been tampered with', (t) => {
|
|
t.plan(1);
|
|
|
|
const cryptr = new Cryptr(testSecret);
|
|
|
|
const encryptedString = cryptr.encrypt(testData);
|
|
|
|
const encryptedBuffer = Buffer.from(encryptedString, 'hex');
|
|
const b1 = Buffer.from(testData);
|
|
const b2 = Buffer.from('hello');
|
|
|
|
for (let i = 0; i < b1.length; i++) {
|
|
encryptedBuffer[i + 16] ^= b1[i] ^ b2[i];
|
|
}
|
|
|
|
const modifiedValue = encryptedBuffer.toString('hex');
|
|
|
|
t.throws(
|
|
() => cryptr.decrypt(modifiedValue),
|
|
/Unsupported state or unable to authenticate data/,
|
|
'throws on tampered data',
|
|
);
|
|
});
|