rc4.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. function RC4(key) {
  2. this.privateKey = keySetup(key);
  3. this.byteStream = byteStreamGenerator(this.privateKey.slice(0));
  4. }
  5. /**
  6. * Converts the text into an array of the characters numeric Unicode values
  7. * @param {String} text, the text to convert
  8. * @return {Array} the array of Unicode values
  9. */
  10. function convert(text) {
  11. var codes = [];
  12. for (var i = 0, ii = text.length; i < ii; i++) { codes.push(text.charCodeAt(i)); }
  13. return codes;
  14. }
  15. /**
  16. * Sets up the key to use with the byte stream
  17. * @param {String} key, The key that you want to use
  18. * @return {Array}, the key stream which with be used in the byteStreamGenerator
  19. */
  20. function keySetup(key) {
  21. var K = [...Array(256).keys()], j = 0, key = convert(key);
  22. for (var i = 0, ii = K.length; i < ii; i++) {
  23. j = (j + K[i] + key[i % key.length]) % 256;
  24. [K[i], K[j]] = [K[j], K[i]];
  25. }
  26. return K;
  27. }
  28. /**
  29. * byteStreamGenerator uses ES6 generators which will be 'XOR-ed' to encrypt and decrypt
  30. * @param {Array} K, the array generated from the keySetup
  31. * @yield {Integer}, the current value which will be 'XOR-ed' to encrypt or decrypt
  32. */
  33. var byteStreamGenerator = function* (K) {
  34. var i = 0, j = 0;
  35. while (true) {
  36. i = (i + 1) % 256;
  37. j = (j + K[i]) % 256;
  38. [K[i], K[j]] = [K[j], K[i]];
  39. yield (K[(K[i] + K[j]) % 256]);
  40. }
  41. }
  42. /**
  43. * Encrypts the input text
  44. * @param {String} input, the text to encrypt
  45. * @return {String}, the encrypted text
  46. */
  47. RC4.prototype.encrypt = function (input) {
  48. var outputText = '';
  49. for (var i = 0, ii = input.length; i < ii; i++) { outputText += ('00' + (input.charCodeAt(i) ^ this.byteStream.next().value).toString(16)).substr(-2); }
  50. return outputText;
  51. }
  52. /**
  53. * Decrypts the input text
  54. * @param {String} input, the text to decrypt
  55. * @return {String}, the decrypted text (if the same key was used)
  56. */
  57. RC4.prototype.decrypt = function (input) {
  58. var outputText = '';
  59. input = input.match(/[a-z0-9]{2}/gi);
  60. for (var i = 0, ii = input.length; i < ii; i++) { outputText += String.fromCharCode((parseInt(input[i], 16) ^ byteStream.next().value)); }
  61. return outputText;
  62. }
  63. module.exports = RC4;