/** * Decrypt a text encrypted by AES in counter mode of operation * * @param ciphertext source text to be decrypted * @param password the password to use to generate a key * @param nBits number of bits to be used in the key (128, 192, or 256) * @return decrypted text */ public static function decrypt($ciphertext, $password, $nBits) { $blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) { return ''; } // standard allows 128/192/256 bit keys $ciphertext = base64_decode($ciphertext); // use AES to encrypt password (mirroring encrypt routine) $nBytes = $nBits / 8; // no bytes in key $pwBytes = array(); for ($i = 0; $i < $nBytes; $i++) { $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff; } $key = Aes::cipher($pwBytes, Aes::keyExpansion($pwBytes)); $key = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long // recover nonce from 1st element of ciphertext $counterBlock = array(); $ctrTxt = substr($ciphertext, 0, 8); for ($i = 0; $i < 8; $i++) { $counterBlock[$i] = ord(substr($ctrTxt, $i, 1)); } // generate key schedule $keySchedule = Aes::keyExpansion($key); // separate ciphertext into blocks (skipping past initial 8 bytes) $nBlocks = ceil((strlen($ciphertext) - 8) / $blockSize); $ct = array(); for ($b = 0; $b < $nBlocks; $b++) { $ct[$b] = substr($ciphertext, 8 + $b * $blockSize, 16); } $ciphertext = $ct; // ciphertext is now array of block-length strings // plaintext will get generated block-by-block into array of block-length strings $plaintxt = array(); for ($b = 0; $b < $nBlocks; $b++) { // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes) for ($c = 0; $c < 4; $c++) { $counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff; } for ($c = 0; $c < 4; $c++) { $counterBlock[15 - $c - 4] = self::urs(($b + 1) / 0x100000000 - 1, $c * 8) & 0xff; } $cipherCntr = Aes::cipher($counterBlock, $keySchedule); // encrypt counter block $plaintxtByte = array(); for ($i = 0; $i < strlen($ciphertext[$b]); $i++) { // -- xor plaintext with ciphered counter byte-by-byte -- $plaintxtByte[$i] = $cipherCntr[$i] ^ ord(substr($ciphertext[$b], $i, 1)); $plaintxtByte[$i] = chr($plaintxtByte[$i]); } $plaintxt[$b] = implode('', $plaintxtByte); } // join array of blocks into single plaintext string $plaintext = implode('', $plaintxt); return $plaintext; }
function decrypt($ciphertext, $password, $nBits) { $blockSize = 16; if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) { return ''; } $ciphertext = base64_decode($ciphertext); $nBytes = $nBits / 8; $pwBytes = array(); for ($i = 0; $i < $nBytes; $i++) { $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff; } $key = Aes::cipher($pwBytes, Aes::keyExpansion($pwBytes)); $key = array_merge($key, array_slice($key, 0, $nBytes - 16)); $counterBlock = array(); $ctrTxt = substr($ciphertext, 0, 8); for ($i = 0; $i < 8; $i++) { $counterBlock[$i] = ord(substr($ctrTxt, $i, 1)); } $keySchedule = Aes::keyExpansion($key); $nBlocks = ceil((strlen($ciphertext) - 8) / $blockSize); $ct = array(); for ($b = 0; $b < $nBlocks; $b++) { $ct[$b] = substr($ciphertext, 8 + $b * $blockSize, 16); } $ciphertext = $ct; $plaintxt = array(); for ($b = 0; $b < $nBlocks; $b++) { for ($c = 0; $c < 4; $c++) { $counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff; } for ($c = 0; $c < 4; $c++) { $counterBlock[15 - $c - 4] = self::urs(($b + 1) / 0x100000000 - 1, $c * 8) & 0xff; } $cipherCntr = Aes::cipher($counterBlock, $keySchedule); $plaintxtByte = array(); for ($i = 0; $i < strlen($ciphertext[$b]); $i++) { $plaintxtByte[$i] = $cipherCntr[$i] ^ ord(substr($ciphertext[$b], $i, 1)); $plaintxtByte[$i] = chr($plaintxtByte[$i]); } $plaintxt[$b] = implode('', $plaintxtByte); } $plaintext = implode('', $plaintxt); return $plaintext; }
public function decrypt($input, $key) { $aesops = new Aes(); $w = $aesops->keyExpansion($key); //generate roundkeys in key expansion $input = $this->addRoundKey($input, $w, 10); for ($round = 9; $round > 0; $round--) { $input = $this->invShiftRows($input); $input = $this->invSubBytes($input); $input = $this->addRoundKey($input, $w, $round); $input = $this->invMixColumns($input); } $input = $this->invShiftRows($input); $input = $this->invSubBytes($input); $input = $this->addRoundKey($input, $w, 0); return $input; }