example.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* keep track of which salts have been used. */
  2. var form, usedIvs = {'':1}, usedSalts = {'':1};
  3. /* enter actions */
  4. var enterActions = {
  5. password: doPbkdf2,
  6. salt: doPbkdf2,
  7. iter: doPbkdf2
  8. };
  9. function loaded() {
  10. form = new formHandler('theForm', enterActions);
  11. form._extendedKey = [];
  12. sjcl.random.startCollectors();
  13. document.getElementById("password").focus();
  14. }
  15. /* there's probaby a better way to tell the user something, but oh well */
  16. function error(x) {
  17. alert(x);
  18. }
  19. /* compute PBKDF2 on the password. */
  20. function doPbkdf2(decrypting) {
  21. var v = form.get(), salt=v.salt, key, hex = sjcl.codec.hex.fromBits, p={},
  22. password = v.password;
  23. p.iter = v.iter;
  24. if (password.length == 0) {
  25. if (decrypting) { error("Can't decrypt: need a password!"); }
  26. return;
  27. }
  28. if (salt.length === 0 && decrypting) {
  29. error("Can't decrypt: need a salt for PBKDF2!");
  30. return;
  31. }
  32. if (decrypting || !v.freshsalt || !usedSalts[v.salt]) {
  33. p.salt = v.salt;
  34. }
  35. p = sjcl.misc.cachedPbkdf2(password, p);
  36. form._extendedKey = p.key;
  37. v.key = p.key.slice(0, v.keysize/32);
  38. v.salt = p.salt;
  39. form.set(v);
  40. form.plaintext.el.select();
  41. }
  42. /* Encrypt a message */
  43. function doEncrypt() {
  44. var v = form.get(), iv = v.iv, password = v.password, key = v.key, adata = v.adata, aes, plaintext=v.plaintext, rp = {}, ct, p;
  45. if (plaintext === '' && v.ciphertext.length) { return; }
  46. if (key.length == 0 && password.length == 0) {
  47. error("need a password or key!");
  48. return;
  49. }
  50. p = { adata:v.adata,
  51. iter:v.iter,
  52. mode:v.mode,
  53. ts:parseInt(v.tag),
  54. ks:parseInt(v.keysize) };
  55. if (!v.freshiv || !usedIvs[v.iv]) { p.iv = v.iv; }
  56. if (!v.freshsalt || !usedSalts[v.salt]) { p.salt = v.salt; }
  57. ct = sjcl.encrypt(password || key, plaintext, p, rp).replace(/,/g,",\n");
  58. v.iv = rp.iv;
  59. usedIvs[rp.iv] = 1;
  60. if (rp.salt) {
  61. v.salt = rp.salt;
  62. usedSalts[rp.salt] = 1;
  63. }
  64. v.key = rp.key;
  65. if (v.json) {
  66. v.ciphertext = ct;
  67. v.adata = '';
  68. } else {
  69. v.ciphertext = ct.match(/ct:"([^"]*)"/)[1]; //"
  70. }
  71. v.plaintext = '';
  72. form.set(v);
  73. form.ciphertext.el.select();
  74. }
  75. /* Decrypt a message */
  76. function doDecrypt() {
  77. var v = form.get(), iv = v.iv, key = v.key, adata = v.adata, aes, ciphertext=v.ciphertext, rp = {};
  78. if (ciphertext.length === 0) { return; }
  79. if (!v.password && !v.key.length) {
  80. error("Can't decrypt: need a password or key!"); return;
  81. }
  82. if (ciphertext.match("{")) {
  83. /* it's jsonized */
  84. try {
  85. v.plaintext = sjcl.decrypt(v.password || v.key, ciphertext, {}, rp);
  86. } catch(e) {
  87. error("Can't decrypt: "+e);
  88. return;
  89. }
  90. v.mode = rp.mode;
  91. v.iv = rp.iv;
  92. v.adata = rp.adata;
  93. if (v.password) {
  94. v.salt = rp.salt;
  95. v.iter = rp.iter;
  96. v.keysize = rp.ks;
  97. v.tag = rp.ts;
  98. }
  99. v.key = rp.key;
  100. v.ciphertext = "";
  101. document.getElementById('plaintext').select();
  102. } else {
  103. /* it's raw */
  104. ciphertext = sjcl.codec.base64.toBits(ciphertext);
  105. if (iv.length === 0) {
  106. error("Can't decrypt: need an IV!"); return;
  107. }
  108. if (key.length === 0) {
  109. if (v.password.length) {
  110. doPbkdf2(true);
  111. key = v.key;
  112. }
  113. }
  114. aes = new sjcl.cipher.aes(key);
  115. try {
  116. v.plaintext = sjcl.codec.utf8String.fromBits(sjcl.mode[v.mode].decrypt(aes, ciphertext, iv, v.adata, v.tag));
  117. v.ciphertext = "";
  118. document.getElementById('plaintext').select();
  119. } catch (e) {
  120. error("Can't decrypt: " + e);
  121. }
  122. }
  123. form.set(v);
  124. }
  125. function extendKey(size) {
  126. form.key.set(form._extendedKey.slice(0,size));
  127. }
  128. function randomize(field, words, paranoia) {
  129. form[field].set(sjcl.random.randomWords(words, paranoia));
  130. if (field == 'salt') { form.key.set([]); }
  131. }