Guest User

Untitled

a guest
Aug 22nd, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.91 KB | None | 0 0
  1. /**
  2. * Encrypt a text using AES encryption in Counter mode of operation
  3. *
  4. * Unicode multi-byte character safe
  5. *
  6. * @param plaintext Source text to be encrypted
  7. * @param password The password to use to generate a key
  8. * @param nBits Number of bits to be used in the key (128, 192, or 256)
  9. * @returns Encrypted text
  10. */
  11.  
  12.  
  13. public function encrypt(plaintext : String, password : String, nBits : int) : String //Done in LV
  14. {
  15. var blockSize : int = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
  16. if (!(nBits == BIT_KEY_128 || nBits == BIT_KEY_192 || nBits == BIT_KEY_256))
  17. {
  18. // standard allows 128/192/256 bit keys
  19. throw new Error("Must be a key mode of either 128, 192, 256 bits");
  20. }
  21. plaintext = Utf8.encode(plaintext);
  22. password = Utf8.encode(password);
  23.  
  24. // use AES itself to encrypt password to get cipher key (using plain password as source for key
  25. // expansion) - gives us well encrypted key
  26. var nBytes : int = nBits / 8; // no bytes in key
  27. var pwBytes : Array = new Array(nBytes);
  28. for (var i : int = 0;i < nBytes;i++)
  29. {
  30. pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i);
  31. }
  32. var key : Array = cipher(pwBytes, keyExpansion(pwBytes)); // gives us 16-byte key
  33.  
  34. key = key.concat(key.slice(0, nBytes - 16)); // expand key to 16/24/32 bytes long
  35.  
  36. // initialise counter block (NIST SP800-38A ยงB.2): millisecond time-stamp for nonce in 1st 8 bytes,
  37. // block counter in 2nd 8 bytes
  38. var counterBlock : Array = new Array(blockSize);
  39. var nonce : int = 123456789;////DEBUG!!!(new Date()).getTime(); // timestamp: milliseconds since 1-Jan-1970
  40. var nonceSec : int = Math.floor(nonce / 1000);
  41. var nonceMs : int = nonce % 1000;
  42.  
  43. // encode nonce with seconds in 1st 4 bytes, and (repeated) ms part filling 2nd 4 bytes
  44. for (i = 0;i < 4;i++)
  45. {
  46. counterBlock[i] = (nonceSec >>> (i * 8)) & 0xff;
  47. }
  48.  
  49. for (i = 0;i < 4;i++)
  50. {
  51. counterBlock[i + 4] = nonceMs & 0xff;
  52. }
  53. // and convert it to a string to go on the front of the ciphertext
  54. var ctrTxt : String = '';
  55. for (i = 0;i < 8;i++)
  56. {
  57. ctrTxt += String.fromCharCode(counterBlock[i]);
  58. }
  59. // generate key schedule - an expansion of the key into distinct Key Rounds for each round
  60. var keySchedule : Array = keyExpansion(key);
  61. var blockCount : int = Math.ceil(plaintext.length / blockSize);
  62. var ciphertxt : Array = new Array(blockCount); // ciphertext as array of strings
  63.  
  64. for (var b : int = 0;b < blockCount;b++)
  65. {
  66. // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
  67. // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
  68. for (var c : int = 0;c < 4;c++)
  69. {
  70. counterBlock[15 - c] = (b >>> (c * 8)) & 0xff;
  71. }
  72.  
  73. for (c = 0;c < 4;c++)
  74. {
  75. counterBlock[15 - c - 4] = (b / 0x100000000 >>> c * 8);
  76. }
  77.  
  78. var cipherCntr : Array = cipher(counterBlock, keySchedule); // -- encrypt counter block --
  79.  
  80. // block size is reduced on final block
  81. var blockLength : int = b < blockCount - 1 ? blockSize : (plaintext.length - 1) % blockSize + 1;
  82. var cipherChar : Array = new Array(blockLength);
  83.  
  84. for (i = 0;i < blockLength;i++)
  85. {
  86. // -- xor plaintext with ciphered counter char-by-char --
  87. cipherChar[i] = cipherCntr[i] ^ plaintext.charCodeAt(b * blockSize + i);
  88. //trace("i=",i,"plaintext.charCodeAt(b * blockSize + i)",plaintext.charCodeAt(b * blockSize + i),"cipherChar[i]=",cipherChar[i]);
  89. cipherChar[i] = String.fromCharCode(cipherChar[i]);
  90.  
  91. }
  92.  
  93. ciphertxt[b] = cipherChar.join('');
  94. //trace(ciphertxt);
  95. }
  96.  
  97. // Array.join is more efficient than repeated string concatenation in IE
  98. var ciphertext : String = ctrTxt + ciphertxt.join('');
  99. //trace("before 64 encode:",ciphertext);
  100. ciphertext = Base64.encode(ciphertext); // encode in base64
  101. //trace("after 64 encode:",ciphertext);
  102. //alert((new Date()) - t);
  103.  
  104. return ciphertext;
  105. }
  106.  
  107. /**
  108. * Decrypt a text encrypted by AES in counter mode of operation
  109. *
  110. * @param ciphertext Source text to be encrypted
  111. * @param password The password to use to generate a key
  112. * @param nBits Number of bits to be used in the key (128, 192, or 256)
  113. * @returns Decrypted text
  114. */
  115. public function decrypt(ciphertext : String, password : String, nBits : int) : String
  116. {
  117. var blockSize : int = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
  118. if (!(nBits == BIT_KEY_128 || nBits == BIT_KEY_192 || nBits == BIT_KEY_256)) {
  119. // standard allows 128/192/256 bit keys
  120. throw new Error("Must be a key mode of either 128, 192, 256 bits");
  121. }
  122.  
  123. ciphertext = Base64.decode(ciphertext.split("n").join(""));
  124. password = Utf8.encode(password);
  125. //var t = new Date(); // timer
  126.  
  127. // use AES to encrypt password (mirroring encrypt routine)
  128. var nBytes : int = nBits / 8; // no bytes in key
  129. var pwBytes : Array = new Array(nBytes);
  130. for (var i : int = 0;i < nBytes;i++)
  131. {
  132. pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i);
  133. }
  134. var key : Array = cipher(pwBytes, keyExpansion(pwBytes));
  135. key = key.concat(key.slice(0, nBytes - 16)); // expand key to 16/24/32 bytes long
  136.  
  137. // recover nonce from 1st 8 bytes of ciphertext
  138. var counterBlock : Array = new Array(8);
  139. var ctrTxt : String = ciphertext.slice(0, 8);
  140. for (i = 0;i < 8;i++)
  141. {
  142. counterBlock[i] = ctrTxt.charCodeAt(i);
  143. }
  144.  
  145. // generate key schedule
  146. var keySchedule : Array = keyExpansion(key);
  147.  
  148. // separate ciphertext into blocks (skipping past initial 8 bytes)
  149. var nBlocks : int = Math.ceil((ciphertext.length - 8) / blockSize);
  150. var ct : Array = new Array(nBlocks);
  151. for (b = 0;b < nBlocks;b++)
  152. {
  153. ct[b] = ciphertext.slice(8 + b * blockSize, 8 + b * blockSize + blockSize);
  154.  
  155. //trace("ct[b]=",ct[b],"blockSize=",blockSize,8 + b * blockSize, 8 + b * blockSize + blockSize);
  156. }
  157. //var temp:String=ct[1];
  158. // for (var i:int=0;i<temp.length;i++)
  159. // {
  160. // trace("ct[1]Byte Array:",temp.charCodeAt(i));
  161. // }
  162.  
  163. var ciphertextArr : Array = ct; // ciphertext is now array of block-length strings
  164.  
  165. // plaintext will get generated block-by-block into array of block-length strings
  166. var plaintxt : Array = new Array(ciphertextArr.length);
  167.  
  168. for (var b : int = 0;b < nBlocks;b++)
  169. {
  170. // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
  171. for (var c : int = 0;c < 4;c++)
  172. {
  173. counterBlock[15 - c] = ((b) >>> c * 8) & 0xff;
  174. }
  175. for (c = 0;c < 4;c++)
  176. {
  177. counterBlock[15 - c - 4] = (((b + 1) / 0x100000000 - 1) >>> c * 8) & 0xff;
  178. }
  179. //trace(counterBlock);
  180. var cipherCntr : Array = cipher(counterBlock, keySchedule); // encrypt counter block
  181. //trace(cipherCntr);
  182. var plaintxtByte : Array = new Array(String(ciphertextArr[b]).length);
  183. for (i = 0;i < String(ciphertextArr[b]).length;i++)
  184. {
  185. // -- xor plaintxt with ciphered counter byte-by-byte --
  186. plaintxtByte[i] = cipherCntr[i] ^ String(ciphertextArr[b]).charCodeAt(i);
  187. //trace("i=",i,"plaintxtByte[i]=",plaintxtByte[i],"cipherCntr[i]=",cipherCntr[i],"String(ciphertextArr[b]).charCodeAt(i)=",String(ciphertextArr[b]).charCodeAt(i));
  188. //trace(plaintxtByte[i]);
  189. plaintxtByte[i] = String.fromCharCode(plaintxtByte[i]);
  190.  
  191. }
  192. plaintxt[b] = plaintxtByte.join('');
  193. }
  194.  
  195. // join array of blocks into single plaintext string
  196. var plaintext : String = plaintxt.join('');
  197. plaintext = Utf8.decode(plaintext); // decode from UTF8 back to Unicode multi-byte chars
  198. return plaintext;
  199. }
Add Comment
Please, Sign In to add comment