| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /* keep track of which salts have been used. */
- var form, usedIvs = {'':1}, usedSalts = {'':1};
- /* enter actions */
- var enterActions = {
- password: doPbkdf2,
- salt: doPbkdf2,
- iter: doPbkdf2
- };
- function loaded() {
- form = new formHandler('theForm', enterActions);
- form._extendedKey = [];
- sjcl.random.startCollectors();
- document.getElementById("password").focus();
- }
- /* there's probaby a better way to tell the user something, but oh well */
- function error(x) {
- alert(x);
- }
- /* compute PBKDF2 on the password. */
- function doPbkdf2(decrypting) {
- var v = form.get(), salt=v.salt, key, hex = sjcl.codec.hex.fromBits, p={},
- password = v.password;
-
- p.iter = v.iter;
-
- if (password.length == 0) {
- if (decrypting) { error("Can't decrypt: need a password!"); }
- return;
- }
-
- if (salt.length === 0 && decrypting) {
- error("Can't decrypt: need a salt for PBKDF2!");
- return;
- }
-
- if (decrypting || !v.freshsalt || !usedSalts[v.salt]) {
- p.salt = v.salt;
- }
-
- p = sjcl.misc.cachedPbkdf2(password, p);
- form._extendedKey = p.key;
- v.key = p.key.slice(0, v.keysize/32);
- v.salt = p.salt;
-
- form.set(v);
- form.plaintext.el.select();
- }
- /* Encrypt a message */
- function doEncrypt() {
- var v = form.get(), iv = v.iv, password = v.password, key = v.key, adata = v.adata, aes, plaintext=v.plaintext, rp = {}, ct, p;
-
- if (plaintext === '' && v.ciphertext.length) { return; }
- if (key.length == 0 && password.length == 0) {
- error("need a password or key!");
- return;
- }
-
- p = { adata:v.adata,
- iter:v.iter,
- mode:v.mode,
- ts:parseInt(v.tag),
- ks:parseInt(v.keysize) };
- if (!v.freshiv || !usedIvs[v.iv]) { p.iv = v.iv; }
- if (!v.freshsalt || !usedSalts[v.salt]) { p.salt = v.salt; }
- ct = sjcl.encrypt(password || key, plaintext, p, rp).replace(/,/g,",\n");
- v.iv = rp.iv;
- usedIvs[rp.iv] = 1;
- if (rp.salt) {
- v.salt = rp.salt;
- usedSalts[rp.salt] = 1;
- }
- v.key = rp.key;
-
- if (v.json) {
- v.ciphertext = ct;
- v.adata = '';
- } else {
- v.ciphertext = ct.match(/ct:"([^"]*)"/)[1]; //"
- }
-
- v.plaintext = '';
-
- form.set(v);
- form.ciphertext.el.select();
- }
- /* Decrypt a message */
- function doDecrypt() {
- var v = form.get(), iv = v.iv, key = v.key, adata = v.adata, aes, ciphertext=v.ciphertext, rp = {};
-
- if (ciphertext.length === 0) { return; }
- if (!v.password && !v.key.length) {
- error("Can't decrypt: need a password or key!"); return;
- }
-
- if (ciphertext.match("{")) {
- /* it's jsonized */
- try {
- v.plaintext = sjcl.decrypt(v.password || v.key, ciphertext, {}, rp);
- } catch(e) {
- error("Can't decrypt: "+e);
- return;
- }
- v.mode = rp.mode;
- v.iv = rp.iv;
- v.adata = rp.adata;
- if (v.password) {
- v.salt = rp.salt;
- v.iter = rp.iter;
- v.keysize = rp.ks;
- v.tag = rp.ts;
- }
- v.key = rp.key;
- v.ciphertext = "";
- document.getElementById('plaintext').select();
- } else {
- /* it's raw */
- ciphertext = sjcl.codec.base64.toBits(ciphertext);
- if (iv.length === 0) {
- error("Can't decrypt: need an IV!"); return;
- }
- if (key.length === 0) {
- if (v.password.length) {
- doPbkdf2(true);
- key = v.key;
- }
- }
- aes = new sjcl.cipher.aes(key);
-
- try {
- v.plaintext = sjcl.codec.utf8String.fromBits(sjcl.mode[v.mode].decrypt(aes, ciphertext, iv, v.adata, v.tag));
- v.ciphertext = "";
- document.getElementById('plaintext').select();
- } catch (e) {
- error("Can't decrypt: " + e);
- }
- }
- form.set(v);
- }
- function extendKey(size) {
- form.key.set(form._extendedKey.slice(0,size));
- }
- function randomize(field, words, paranoia) {
- form[field].set(sjcl.random.randomWords(words, paranoia));
- if (field == 'salt') { form.key.set([]); }
- }
|