Add support for AES encrypt/decrypting sensitive values

(closes #7355)
This commit is contained in:
Bryan Housel
2020-02-13 13:11:34 -05:00
parent 614ee3f68e
commit 030a85199f
5 changed files with 83 additions and 0 deletions

28
modules/util/aes.js Normal file
View File

@@ -0,0 +1,28 @@
import aesjs from 'aes-js';
// See https://github.com/ricmoo/aes-js
// We can use keys that are 128 bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 bytes).
// To generate a random key: window.crypto.getRandomValues(new Uint8Array(16));
// This default signing key is built into iD and can be used to mask/unmask sensitive values.
const DEFAULT_128 = [250, 157, 60, 79, 142, 134, 229, 129, 138, 126, 210, 129, 29, 71, 160, 208];
export function utilAesEncrypt(text, key) {
key = key || DEFAULT_128;
const textBytes = aesjs.utils.utf8.toBytes(text);
const aesCtr = new aesjs.ModeOfOperation.ctr(key);
const encryptedBytes = aesCtr.encrypt(textBytes);
const encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
return encryptedHex;
}
export function utilAesDecrypt(encryptedHex, key) {
key = key || DEFAULT_128;
const encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
const aesCtr = new aesjs.ModeOfOperation.ctr(key);
const decryptedBytes = aesCtr.decrypt(encryptedBytes);
const text = aesjs.utils.utf8.fromBytes(decryptedBytes);
return text;
}

View File

@@ -1,3 +1,6 @@
export { utilAesEncrypt } from './aes';
export { utilAesDecrypt } from './aes';
export { utilArrayChunk } from './array';
export { utilArrayDifference } from './array';
export { utilArrayFlatten } from './array';

View File

@@ -46,6 +46,7 @@
"@mapbox/vector-tile": "^1.3.1",
"@turf/bbox-clip": "^6.0.0",
"abortcontroller-polyfill": "^1.4.0",
"aes-js": "^3.1.2",
"alif-toolkit": "^1.2.6",
"browser-polyfills": "~1.5.0",
"diacritics": "1.3.0",

View File

@@ -141,6 +141,7 @@
'spec/ui/fields/localized.js',
'spec/ui/fields/wikipedia.js',
'spec/util/aes.js',
'spec/util/array.js',
'spec/util/clean_tags.js',
'spec/util/keybinding.js',

50
test/spec/util/aes.js Normal file
View File

@@ -0,0 +1,50 @@
describe('iD.utilAes', function() {
it('encrypting and decrypting nothing yields nothing', function() {
expect(iD.utilAesEncrypt('')).to.eql('');
expect(iD.utilAesDecrypt('')).to.eql('');
});
it('encrypts and decrypts with default key', function() {
var text = 'Hello iD!';
var encrypted = '5597506f958c68543c';
expect(iD.utilAesEncrypt(text)).to.eql(encrypted);
expect(iD.utilAesDecrypt(encrypted)).to.eql(text);
});
it('encrypts and decrypts with a custom 16-bit key', function() {
var key = [
216, 159, 213, 140, 129, 75, 80, 121,
67, 201, 179, 120, 71, 237, 185, 42
];
var text = 'Hello iD!';
var encrypted = '9ff50e32b04f86640a';
expect(iD.utilAesEncrypt(text, key)).to.eql(encrypted);
expect(iD.utilAesDecrypt(encrypted, key)).to.eql(text);
});
it('encrypts and decrypts with a custom 24-bit key', function() {
var key = [
180, 138, 124, 87, 157, 23, 209, 147,
64, 65, 68, 206, 212, 79, 215, 114,
37, 18, 159, 94, 168, 68, 177, 202
];
var text = 'Hello iD!';
var encrypted = '85fc05011fa7848417';
expect(iD.utilAesEncrypt(text, key)).to.eql(encrypted);
expect(iD.utilAesDecrypt(encrypted, key)).to.eql(text);
});
it('encrypts and decrypts with a custom 32-bit key', function() {
var key = [
4, 48, 130, 253, 213, 139, 96, 178,
170, 108, 127, 233, 167, 137, 181, 41,
145, 62, 251, 9, 82, 159, 103, 198,
63, 200, 158, 104, 188, 77, 193, 16
];
var text = 'Hello iD!';
var encrypted = '13c21d3dc25165c57c';
expect(iD.utilAesEncrypt(text, key)).to.eql(encrypted);
expect(iD.utilAesDecrypt(encrypted, key)).to.eql(text);
});
});