nxs_AesCtr

The NextScripts: Social Networks Auto-Poster nxs AesCtr class.

Defined (1)

The class is defined in the following location(s).

/inc-cl/st.api.php  
  1. if (!class_exists('nxs_AesCtr')) { class nxs_AesCtr extends nxs_Aes { 
  2. public static function encrypt($plaintext, $password, $nBits) { 
  3. $blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES 
  4. if (!($nBits==128 || $nBits==192 || $nBits==256)) return ''; // standard allows 128/192/256 bit keys 
  5. // note PHP (5) gives us plaintext and password in UTF8 encoding! 
  6.  
  7. // use AES itself to encrypt password to get cipher key (using plain password as source for  
  8. // key expansion) - gives us well encrypted key 
  9. $nBytes = $nBits/8; // no bytes in key 
  10. $pwBytes = array(); 
  11. for ($i=0; $i<$nBytes; $i++) $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff; 
  12. $key = nxs_Aes::cipher($pwBytes, nxs_Aes::keyExpansion($pwBytes)); 
  13. $key = array_merge($key, array_slice($key, 0, $nBytes-16)); // expand key to 16/24/32 bytes long  
  14.  
  15. // initialise 1st 8 bytes of counter block with nonce (NIST SP800-38A B.2): [0-1] = millisec,  
  16. // [2-3] = random, [4-7] = seconds, giving guaranteed sub-ms uniqueness up to Feb 2106 
  17. $counterBlock = array(); 
  18. $nonce = floor(microtime(true)*1000); // timestamp: milliseconds since 1-Jan-1970 
  19. $nonceMs = $nonce%1000; 
  20. $nonceSec = floor($nonce/1000); 
  21. $nonceRnd = floor(rand(0, 0xffff)); 
  22.  
  23. for ($i=0; $i<2; $i++) $counterBlock[$i] = self::urs($nonceMs, $i*8) & 0xff; 
  24. for ($i=0; $i<2; $i++) $counterBlock[$i+2] = self::urs($nonceRnd, $i*8) & 0xff; 
  25. for ($i=0; $i<4; $i++) $counterBlock[$i+4] = self::urs($nonceSec, $i*8) & 0xff; 
  26.  
  27. // and convert it to a string to go on the front of the ciphertext 
  28. $ctrTxt = ''; 
  29. for ($i=0; $i<8; $i++) $ctrTxt .= chr($counterBlock[$i]); 
  30.  
  31. // generate key schedule - an expansion of the key into distinct Key Rounds for each round 
  32. $keySchedule = nxs_Aes::keyExpansion($key); 
  33. //print_r($keySchedule); 
  34.  
  35. $blockCount = ceil(strlen($plaintext)/$blockSize); 
  36. $ciphertxt = array(); // ciphertext as array of strings 
  37.  
  38. for ($b=0; $b<$blockCount; $b++) { 
  39. // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes) 
  40. // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB) 
  41. for ($c=0; $c<4; $c++) $counterBlock[15-$c] = self::urs($b, $c*8) & 0xff; 
  42. for ($c=0; $c<4; $c++) $counterBlock[15-$c-4] = self::urs($b/0x100000000, $c*8); 
  43.  
  44. $cipherCntr = nxs_Aes::cipher($counterBlock, $keySchedule); // -- encrypt counter block -- 
  45.  
  46. // block size is reduced on final block 
  47. $blockLength = $b<$blockCount-1 ? $blockSize : (strlen($plaintext)-1)%$blockSize+1; 
  48. $cipherByte = array(); 
  49.  
  50. for ($i=0; $i<$blockLength; $i++) { // -- xor plaintext with ciphered counter byte-by-byte -- 
  51. $cipherByte[$i] = $cipherCntr[$i] ^ ord(substr($plaintext, $b*$blockSize+$i, 1)); 
  52. $cipherByte[$i] = chr($cipherByte[$i]); 
  53. $ciphertxt[$b] = implode('', $cipherByte); // escape troublesome characters in ciphertext 
  54.  
  55. // implode is more efficient than repeated string concatenation 
  56. $ciphertext = $ctrTxt . implode('', $ciphertxt); 
  57. $ciphertext = base64_encode($ciphertext); 
  58. return $ciphertext; 
  59. }  
  60. private static function urs($a, $b) { 
  61. $a &= 0xffffffff; $b &= 0x1f; // (bounds check) 
  62. if ($a&0x80000000 && $b>0) { // if left-most bit set 
  63. $a = ($a>>1) & 0x7fffffff; // right-shift one bit & clear left-most bit 
  64. $a = $a >> ($b-1); // remaining right-shifts 
  65. } else { // otherwise 
  66. $a = ($a>>$b); // use normal right-shift 
  67. }  
  68. return $a;  
  69. } }