def recoverBytes(): # first, determine number of bytes needed to push prefix up to a block boundry # and where the first block fully controlled by my input lies (effectively, determine prefix length) numBytesForPrefix, firstControlledBlock = determinePrefixLength() # deterine target plaintext length targetPlaintextLength = prob14DeterminePlaintextLength() + ( numBytesForPrefix) - (firstControlledBlock * 16) # do the problem 12 process knownPlaintext = b'' blockSize = 16 for i in range(targetPlaintextLength): # Set first unknown byte to be last byte in block padLen = numBytesForPrefix + (blockSize - 1) - (len(knownPlaintext) % blockSize) pad = padStr * padLen # Collect cipher, identify cipher blocks of interest cipherOutput = prob14Encrypt(pad) blockOfInterest = firstControlledBlock + (len(knownPlaintext) // 16) cipherChunks = chunks(cipherOutput, blockSize) cipherOfInterest = cipherChunks[blockOfInterest] ###knownPlainChunks.append(b''); # prefix is last 15 bytes of (pad|knownPlaintext) prefix = (pad + knownPlaintext)[-15:] knownPlaintext += prob14DetermineNextByte(prefix, cipherOfInterest, numBytesForPrefix, firstControlledBlock) return knownPlaintext
def detectMode(): plaintext = b'A' * 48; cipher = append_and_encrypt(plaintext); blocks = chunks(cipher, 16); if (blocks[1] == blocks[2]): return "ECB"; else: return "NOT ECB";
def detectMode(): plaintext = b'A' * 48; #ensure that 2nd, 3rd blocks of cipher have same plaintext cipher = encryption_oracle(plaintext); blocks = chunks(cipher, 16); if (blocks[1] == blocks[2]): print("ECB"); else: print("CBC");
def aes_ctr(rawInput, rawKey, rawIV): inputBlocks = chunks(rawInput, 16); rawOutput = b''; for block in inputBlocks: keyStream = aes_ecb_enc(rawIV, rawKey); rawOutput += raw_xor(keyStream, block); rawIV = incrementIV(rawIV); return rawOutput;
def detectMode(): plaintext = b'A' * 48 cipher = append_and_encrypt(plaintext) blocks = chunks(cipher, 16) if (blocks[1] == blocks[2]): return "ECB" else: return "NOT ECB"
def recoverPlaintext(): targetCipher, iv = encryptString(); targetBlocks = chunks(targetCipher, 16); plaintext = b''; for i in range(len(targetBlocks)): plaintext += recoverBlock(targetBlocks[i], iv); iv = targetBlocks[i]; return plaintext;
def aes_ctr(rawInput, rawKey, rawIV): inputBlocks = chunks(rawInput, 16) rawOutput = b'' for block in inputBlocks: keyStream = aes_ecb_enc(rawIV, rawKey) rawOutput += raw_xor(keyStream, block) rawIV = incrementIV(rawIV) return rawOutput
def aes_cbc_dec(rawCipher, rawKey, rawIV): cipherBlocks = chunks(rawCipher, 16); plain = b''; for block in cipherBlocks: ecbOut = aes_ecb_dec(block, rawKey); cbcOut = hexToRaw(hex_xor(rawToHex(ecbOut), rawToHex(rawIV))); rawIV = block; plain += cbcOut; return plain;
def aes_cbc_enc(rawPlain, rawKey, rawIV): plainBlocks = chunks(rawPlain, 16); cipher = b''; for block in plainBlocks: blockIn = hexToRaw(hex_xor(rawToHex(block), rawToHex(rawIV))); blockOut = aes_ecb_enc(blockIn, rawKey); rawIV = blockOut; cipher += blockOut; return cipher;
def detectMode(): plaintext = b'A' * 48 #ensure that 2nd, 3rd blocks of cipher have same plaintext cipher = encryption_oracle(plaintext) blocks = chunks(cipher, 16) if (blocks[1] == blocks[2]): print("ECB") else: print("CBC")
def aes_cbc_dec(rawCipher, rawKey, rawIV): cipherBlocks = chunks(rawCipher, 16) plain = b"" for block in cipherBlocks: ecbOut = aes_ecb_dec(block, rawKey) cbcOut = hexToRaw(hex_xor(rawToHex(ecbOut), rawToHex(rawIV))) rawIV = block plain += cbcOut return plain
def aes_cbc_dec(rawCipher, rawKey, rawIV): cipherBlocks = chunks(rawCipher, 16) plain = b'' for block in cipherBlocks: ecbOut = aes_ecb_dec(block, rawKey) cbcOut = hexToRaw(hex_xor(rawToHex(ecbOut), rawToHex(rawIV))) rawIV = block plain += cbcOut return plain
def aes_cbc_enc(rawPlain, rawKey, rawIV): plainBlocks = chunks(rawPlain, 16) cipher = b"" for block in plainBlocks: blockIn = hexToRaw(hex_xor(rawToHex(block), rawToHex(rawIV))) blockOut = aes_ecb_enc(blockIn, rawKey) rawIV = blockOut cipher += blockOut return cipher
def aes_cbc_enc(rawPlain, rawKey, rawIV): plainBlocks = chunks(rawPlain, 16) cipher = b'' for block in plainBlocks: blockIn = hexToRaw(hex_xor(rawToHex(block), rawToHex(rawIV))) blockOut = aes_ecb_enc(blockIn, rawKey) rawIV = blockOut cipher += blockOut return cipher
def determinePrefixLength(): plainLength = 32 while (True): plain = b'A' * plainLength cipher = prob14Encrypt(plain) cipherBlocks = chunks(cipher, 16) for i in range(len(cipherBlocks) - 1): if (cipherBlocks[i] == cipherBlocks[i + 1]): return (len(plain) % 16), i plainLength += 1
def determinePrefixLength(): plainLength = 32; while (True): plain = b'A' * plainLength; cipher = prob14Encrypt(plain); cipherBlocks = chunks(cipher, 16); for i in range(len(cipherBlocks)-1): if (cipherBlocks[i] == cipherBlocks[i+1]): return (len(plain)%16), i; plainLength += 1;
def prob14DetermineNextByte(rawPrefix, observedCipher, numBytesForPrefix, firstControlledBlock): blockSize = 16; plain = (padStr) * (numBytesForPrefix + blockSize - 1 - len(rawPrefix)); plain += rawPrefix; for i in range(256): thisPlain = plain + bytes(chr(i), 'UTF-8'); thisCipher = prob14Encrypt(thisPlain); if (chunks(thisCipher, blockSize)[firstControlledBlock] == observedCipher): return bytes(chr(i), 'UTF-8'); return b'***ERROR***';
def prob14DetermineNextByte(rawPrefix, observedCipher, numBytesForPrefix, firstControlledBlock): blockSize = 16 plain = (padStr) * (numBytesForPrefix + blockSize - 1 - len(rawPrefix)) plain += rawPrefix for i in range(256): thisPlain = plain + bytes(chr(i), 'UTF-8') thisCipher = prob14Encrypt(thisPlain) if (chunks(thisCipher, blockSize)[firstControlledBlock] == observedCipher): return bytes(chr(i), 'UTF-8') return b'***ERROR***'
def determineNextByte(rawPrefix, observedCipher): ''' Given a prefix, generates 256 blocks of the form: AA..AA|prefix|?, and checks for a match against the observed cipher ''' blockSize = determineBlockSize() plain = (padStr) * (blockSize - 1 - len(rawPrefix)) plain += rawPrefix for i in range(256): thisPlain = plain + bytes(chr(i), 'UTF-8') thisCipher = append_and_encrypt(thisPlain) if (chunks(thisCipher, blockSize)[0] == observedCipher): return bytes(chr(i), 'UTF-8') return b'***ERROR***'
def determineNextByte(rawPrefix, observedCipher): ''' Given a prefix, generates 256 blocks of the form: AA..AA|prefix|?, and checks for a match against the observed cipher ''' blockSize = determineBlockSize() plain = (padStr) * (blockSize - 1 - len(rawPrefix)); plain += rawPrefix; for i in range(256): thisPlain = plain + bytes(chr(i), 'UTF-8'); thisCipher = append_and_encrypt(thisPlain); if (chunks(thisCipher, blockSize)[0] == observedCipher): return bytes(chr(i), 'UTF-8'); return b'***ERROR***';
def determinePlaintext(): blockSize = determineBlockSize() plaintextLength = determinePlaintextLength(); knownPlaintext = b''; for i in range(plaintextLength): # Set first unknown byte to be last byte in block padLen = (blockSize - 1) - (len(knownPlaintext) % blockSize); pad = padStr * padLen; # Collect cipher, identify cipher blocks of interest cipherOutput = append_and_encrypt(pad); blockOfInterest = len(knownPlaintext) // 16; cipherChunks = chunks(cipherOutput, blockSize); cipherOfInterest = cipherChunks[blockOfInterest]; ###knownPlainChunks.append(b''); # prefix is last 15 bytes of (pad|knownPlaintext) prefix = (pad + knownPlaintext)[-15:]; knownPlaintext += determineNextByte(prefix, cipherOfInterest); return knownPlaintext;
def determinePlaintext(): blockSize = determineBlockSize() plaintextLength = determinePlaintextLength() knownPlaintext = b'' for i in range(plaintextLength): # Set first unknown byte to be last byte in block padLen = (blockSize - 1) - (len(knownPlaintext) % blockSize) pad = padStr * padLen # Collect cipher, identify cipher blocks of interest cipherOutput = append_and_encrypt(pad) blockOfInterest = len(knownPlaintext) // 16 cipherChunks = chunks(cipherOutput, blockSize) cipherOfInterest = cipherChunks[blockOfInterest] ###knownPlainChunks.append(b''); # prefix is last 15 bytes of (pad|knownPlaintext) prefix = (pad + knownPlaintext)[-15:] knownPlaintext += determineNextByte(prefix, cipherOfInterest) return knownPlaintext
def recoverBytes(): # first, determine number of bytes needed to push prefix up to a block boundry # and where the first block fully controlled by my input lies (effectively, determine prefix length) numBytesForPrefix, firstControlledBlock = determinePrefixLength(); # deterine target plaintext length targetPlaintextLength = prob14DeterminePlaintextLength() + (numBytesForPrefix) - (firstControlledBlock * 16); # do the problem 12 process knownPlaintext = b''; blockSize = 16; for i in range(targetPlaintextLength): # Set first unknown byte to be last byte in block padLen = numBytesForPrefix + (blockSize - 1) - (len(knownPlaintext) % blockSize); pad = padStr * padLen; # Collect cipher, identify cipher blocks of interest cipherOutput = prob14Encrypt(pad); blockOfInterest = firstControlledBlock + (len(knownPlaintext) // 16); cipherChunks = chunks(cipherOutput, blockSize); cipherOfInterest = cipherChunks[blockOfInterest]; ###knownPlainChunks.append(b''); # prefix is last 15 bytes of (pad|knownPlaintext) prefix = (pad + knownPlaintext)[-15:]; knownPlaintext += prob14DetermineNextByte(prefix, cipherOfInterest, numBytesForPrefix, firstControlledBlock); return knownPlaintext;
def generateEncryptedAdminProfile(): # get to a fresh block s = 'A' * (16 - (len(prefix) % 16)); #locate the IV for my block myIVBlock = ((len(prefix) + len(s)) // 16) - 1; # add a known block value s += 'X' * 16; # encrypt cip = padAndEncryptString(s); # extract IV for block of interest allBlocks = chunks(cip, 16); myIV = allBlocks[myIVBlock]; # xor in IV with desired value hexIV = rawToHex(myIV); hexKnown = rawToHex('X'*16); hexDesired = rawToHex(";admin=true;XXXX") newHexIV = hex_xor(hexIV, hex_xor(hexKnown, hexDesired)); newIV = hexToRaw(newHexIV); # insert "error" allBlocks[myIVBlock] = newIV; myCipher = b''; for b in allBlocks: myCipher += b; return myCipher;