Esempio n. 1
0
/** 
 * 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
 */
function AESDecryptCtr($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 = Cipher($pwBytes, 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 = 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] = urs($b, $c * 8) & 0xff;
        }
        for ($c = 0; $c < 4; $c++) {
            $counterBlock[15 - $c - 4] = urs(($b + 1) / 0x100000000 - 1, $c * 8) & 0xff;
        }
        $cipherCntr = 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;
}
Esempio n. 2
0
function AESDecryptCtr($ciphertext, $password, $nBits)
{
    if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
        return '';
        // standard allows 128/192/256 bit keys
    }
    $nBytes = $nBits / 8;
    // no bytes in key
    setLength($pwBytes, $nBytes);
    for ($i = 0; $i < $nBytes; $i++) {
        $pwBytes[$i] = ord($password[$i]) & 0xff;
    }
    $pwKeySchedule = KeyExpansion($pwBytes);
    $key = Cipher($pwBytes, $pwKeySchedule);
    $key = array_merge($key, array_slice($key, 0, $nBytes - 16));
    // key is now 16/24/32 bytes long
    $keySchedule = KeyExpansion($key);
    $ciphertext = explode('-', $ciphertext);
    // split ciphertext into array of block-length strings
    // recover nonce from 1st element of ciphertext
    $blockSize = 16;
    // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
    setLength($counterBlock, $blockSize);
    $ctrTxt = unescCtrlChars($ciphertext[0]);
    for ($i = 0; $i < 8; $i++) {
        $counterBlock[$i] = ord($ctrTxt[$i]);
    }
    setLength($plaintext, count($ciphertext) - 1);
    for ($b = 1; $b < count($ciphertext); $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] = zeroFill($b - 1, $c * 8) & 0xff;
        }
        for ($c = 0; $c < 4; $c++) {
            $counterBlock[15 - $c - 4] = zeroFill($b / 0x100000000 - 1, $c * 8) & 0xff;
        }
        $cipherCntr = Cipher($counterBlock, $keySchedule);
        // encrypt counter block
        $ciphertext[$b] = unescCtrlChars($ciphertext[$b]);
        $pt = '';
        for ($i = 0; $i < strlen($ciphertext[$b]); $i++) {
            // -- xor plaintext with ciphered counter byte-by-byte --
            $ciphertextByte = ord($ciphertext[$b][$i]);
            $plaintextByte = $ciphertextByte ^ $cipherCntr[$i];
            $pt .= chr($plaintextByte);
        }
        // pt is now plaintext for this block
        $plaintext[$b - 1] = $pt;
        // b-1 'cos no initial nonce block in plaintext
    }
    return implode('', $plaintext);
}