MARC4.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. (function(){
  2. var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
  3. // Shortcuts
  4. var util = C.util,
  5. charenc = C.charenc,
  6. UTF8 = charenc.UTF8,
  7. Binary = charenc.Binary;
  8. var MARC4 = C.MARC4 = {
  9. /**
  10. * Public API
  11. */
  12. encrypt: function (message, password) {
  13. var
  14. // Convert to bytes
  15. m = UTF8.stringToBytes(message),
  16. // Generate random IV
  17. iv = util.randomBytes(16),
  18. // Generate key
  19. k = password.constructor == String ?
  20. // Derive key from passphrase
  21. C.PBKDF2(password, iv, 32, { asBytes: true }) :
  22. // else, assume byte array representing cryptographic key
  23. password;
  24. // Encrypt
  25. MARC4._marc4(m, k, 1536);
  26. // Return ciphertext
  27. return util.bytesToBase64(iv.concat(m));
  28. },
  29. decrypt: function (ciphertext, password) {
  30. var
  31. // Convert to bytes
  32. c = util.base64ToBytes(ciphertext),
  33. // Separate IV and message
  34. iv = c.splice(0, 16),
  35. // Generate key
  36. k = password.constructor == String ?
  37. // Derive key from passphrase
  38. C.PBKDF2(password, iv, 32, { asBytes: true }) :
  39. // else, assume byte array representing cryptographic key
  40. password;
  41. // Decrypt
  42. MARC4._marc4(c, k, 1536);
  43. // Return plaintext
  44. return UTF8.bytesToString(c);
  45. },
  46. /**
  47. * Internal methods
  48. */
  49. // The core
  50. _marc4: function (m, k, drop) {
  51. // State variables
  52. var i, j, s, temp;
  53. // Key setup
  54. for (i = 0, s = []; i < 256; i++) s[i] = i;
  55. for (i = 0, j = 0; i < 256; i++) {
  56. j = (j + s[i] + k[i % k.length]) % 256;
  57. // Swap
  58. temp = s[i];
  59. s[i] = s[j];
  60. s[j] = temp;
  61. }
  62. // Clear counters
  63. i = j = 0;
  64. // Encryption
  65. for (var k = -drop; k < m.length; k++) {
  66. i = (i + 1) % 256;
  67. j = (j + s[i]) % 256;
  68. // Swap
  69. temp = s[i];
  70. s[i] = s[j];
  71. s[j] = temp;
  72. // Stop here if we're still dropping keystream
  73. if (k < 0) continue;
  74. // Encrypt
  75. m[k] ^= s[(s[i] + s[j]) % 256];
  76. }
  77. }
  78. };
  79. })();