125 lines
4.0 KiB
JavaScript
125 lines
4.0 KiB
JavaScript
define(function(require) {
|
|
|
|
// AES encryption, see http://code.google.com/p/crypto-js/#AES
|
|
require("crypto-js/rollups/aes");
|
|
|
|
// Move back and forth from Uint8Arrays and CryptoJS WordArray
|
|
// See http://code.google.com/p/crypto-js/#The_Cipher_Input and
|
|
// https://groups.google.com/forum/#!topic/crypto-js/TOb92tcJlU0
|
|
var WordArray = CryptoJS.lib.WordArray;
|
|
function fromWordArray(wordArray) {
|
|
var words = wordArray.words;
|
|
var sigBytes = wordArray.sigBytes;
|
|
var u8 = new Uint8Array(sigBytes);
|
|
var b;
|
|
for (var i = 0; i < sigBytes; i++) {
|
|
b = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
|
u8[i] = b;
|
|
}
|
|
return u8;
|
|
}
|
|
function toWordArray(u8arr) {
|
|
var len = u8arr.length;
|
|
var words = [];
|
|
for (var i = 0; i < len; i++) {
|
|
words[i >>> 2] |= (u8arr[i] & 0xff) << (24 - (i % 4) * 8);
|
|
}
|
|
return WordArray.create(words, len);
|
|
}
|
|
|
|
|
|
// UTF8 Text De/Encoders
|
|
require('encoding');
|
|
function encode(str) {
|
|
return (new TextEncoder('utf-8')).encode(str);
|
|
}
|
|
function decode(u8arr) {
|
|
return (new TextDecoder('utf-8')).decode(u8arr);
|
|
}
|
|
|
|
|
|
function CryptoContext(context, encrypt, decrypt) {
|
|
this.context = context;
|
|
this.encrypt = encrypt;
|
|
this.decrypt = decrypt;
|
|
}
|
|
CryptoContext.prototype.clear = function(callback) {
|
|
this.context.clear(callback);
|
|
};
|
|
CryptoContext.prototype.get = function(key, callback) {
|
|
var decrypt = this.decrypt;
|
|
this.context.get(key, function(err, value) {
|
|
if(err) {
|
|
callback(err);
|
|
return;
|
|
}
|
|
if(value) {
|
|
value = decrypt(value);
|
|
}
|
|
callback(null, value);
|
|
});
|
|
};
|
|
CryptoContext.prototype.put = function(key, value, callback) {
|
|
var encryptedValue = this.encrypt(value);
|
|
this.context.put(key, encryptedValue, callback);
|
|
};
|
|
CryptoContext.prototype.delete = function(key, callback) {
|
|
this.context.delete(key, callback);
|
|
};
|
|
|
|
|
|
// It is up to the app using this wrapper how the passphrase is acquired, probably by
|
|
// prompting the user to enter it when the file system is being opened.
|
|
function CryptoAdapter(passphrase, provider) {
|
|
this.provider = provider;
|
|
|
|
// Cache cipher algorithm we'll use in encrypt/decrypt
|
|
var cipher = CryptoJS.AES;
|
|
|
|
// To encrypt:
|
|
// 1) accept a buffer (Uint8Array) containing binary data
|
|
// 2) convert the buffer to a CipherJS WordArray
|
|
// 3) encrypt the WordArray using the chosen cipher algorithm + passphrase
|
|
// 4) convert the resulting ciphertext to a UTF8 encoded Uint8Array and return
|
|
this.encrypt = function(buffer) {
|
|
var wordArray = toWordArray(buffer);
|
|
var encrypted = cipher.encrypt(wordArray, passphrase);
|
|
var utf8EncodedBuf = encode(encrypted);
|
|
return utf8EncodedBuf;
|
|
};
|
|
|
|
// To decrypt:
|
|
// 1) accept a buffer (Uint8Array) containing a UTF8 encoded Uint8Array
|
|
// 2) convert the buffer to string (i.e., the ciphertext we got from encrypting)
|
|
// 3) decrypt the ciphertext string
|
|
// 4) convert the decrypted cipherParam object to a UTF8 string
|
|
// 5) encode the UTF8 string to a Uint8Array buffer and return
|
|
this.decrypt = function(buffer) {
|
|
var encryptedStr = decode(buffer);
|
|
var decrypted = cipher.decrypt(encryptedStr, passphrase);
|
|
var decryptedUtf8 = decrypted.toString(CryptoJS.enc.Utf8);
|
|
var utf8EncodedBuf = encode(decryptedUtf8);
|
|
return utf8EncodedBuf;
|
|
};
|
|
}
|
|
CryptoAdapter.isSupported = function() {
|
|
return true;
|
|
};
|
|
|
|
CryptoAdapter.prototype.open = function(callback) {
|
|
this.provider.open(callback);
|
|
};
|
|
CryptoAdapter.prototype.getReadOnlyContext = function() {
|
|
return new CryptoContext(this.provider.getReadOnlyContext(),
|
|
this.encrypt,
|
|
this.decrypt);
|
|
};
|
|
CryptoAdapter.prototype.getReadWriteContext = function() {
|
|
return new CryptoContext(this.provider.getReadWriteContext(),
|
|
this.encrypt,
|
|
this.decrypt);
|
|
};
|
|
|
|
return CryptoAdapter;
|
|
});
|