Implement CBC mode

Sure is a good thing I found this: http://crypto.stackexchange.com/questions/12621/why-does-openssl-append-extra-bytes-when-encrypting-with-aes-128-ecb. It turns out that openssl doesn't do what you'd think it would do. For one, without the -nopad argument, it always pads, even if that means adding an entire extra block of padding. For two, the -a argument doesn't seem to get applied before checking whether or not the number of input bytes is compatible with the blocksize and keylength.


In [ ]:
function stringToBytes(X::String)
    return [UInt8(X[ii]) for ii in 1:length(X)]
end;

function decryptAES128ECBWithKey(ciphertext::String, key::String)
    decrypt = chomp(
        readstring(
            pipeline(`echo -n $ciphertext`,
                     `base64 --decode`,
                     `openssl enc -nopad -d -aes-128-ecb -K $key`,
                     `base64`)))
    return decrypt
end

# takes bytes and returns bytes
function decryptAES128ECBWithKey(cipherbytes::Array{UInt8,1}, keybytes::Array{UInt8,1})
    ciphertext = base64encode(cipherbytes)
    keytext = bytes2hex(keybytes)
    return base64decode(decryptAES128ECBWithKey(ciphertext, keytext))
end

function encryptAES128ECBWithKey(plaintext::String, key::String)
    encrypt = chomp(
        readstring(
            pipeline(`echo -n $plaintext`, 
                     `base64 --decode`,
                     `openssl enc -nopad -e -aes-128-ecb -K $key`,
                     `base64`)))
    return encrypt
end

function encryptAES128ECBWithKey(plaintextbytes::Array{UInt8,1}, keybytes::Array{UInt8,1})
    plaintext = base64encode(plaintextbytes)
    keytext = bytes2hex(keybytes)
    return base64decode(encryptAES128ECBWithKey(plaintext, keytext))
end

function padToNBytes(a::Array{UInt8,1}, nbytes)
    newa = Array{UInt8,1}(nbytes)
    ntopad = nbytes - length(a)
    newa[1:length(a)] = a
    newa[(length(a)+1):nbytes] = UInt8(ntopad)
    return newa
end;

In [ ]:
pt = "im a 16 byte txt"
ptbytes = stringToBytes(pt)
ptb64 = base64encode(ptbytes)
key = "im a 16 byte key"
keybytes = stringToBytes(key)
keyhex = bytes2hex(keybytes);

In [ ]:
ct = encryptAES128ECBWithKey(ptb64, keyhex);

In [ ]:
String(base64decode(decryptAES128ECBWithKey(ct, keyhex)))

In [ ]:
ctbytes = encryptAES128ECBWithKey(ptbytes, keybytes);

In [ ]:
String(decryptAES128ECBWithKey(ctbytes, keybytes))

so that works


In [ ]:
function encryptCBCByHand(ptbytes::Array{UInt8,1}, blocksize, ivbytes::Array{UInt8,1}, keybytes::Array{UInt8,1})
    cipherbytes = Array{UInt8,1}()
    nblocks = convert(Int64, ceil(length(ptbytes)/blocksize))
    ptbytes = padToNBytes(ptbytes, blocksize*nblocks)
    lastblock = ivbytes
    for ii in 1:nblocks
        bytestoencrypt = ptbytes[((ii-1)*blocksize+1):(ii*blocksize)] $ lastblock
        encryptedbytes = encryptAES128ECBWithKey(bytestoencrypt, keybytes)
        append!(cipherbytes, encryptedbytes)
        lastblock = encryptedbytes
    end
    return cipherbytes        
end;

In [ ]:
function decryptCBCByHand(ctbytes::Array{UInt8,1}, blocksize, ivbytes::Array{UInt8,1}, keybytes::Array{UInt8,1})
    ptbytes = Array{UInt8,1}()
    nblocks = convert(Int64, length(ctbytes)/blocksize)
    lastblock = ivbytes
    for ii in 1:nblocks
        bytestodecrypt = ctbytes[((ii-1)*blocksize+1):(ii*blocksize)]
        decryptedbytes = decryptAES128ECBWithKey(bytestodecrypt, keybytes) $ lastblock
        append!(ptbytes, decryptedbytes)
        lastblock = bytestodecrypt
    end
    return ptbytes
end;

In [ ]:
keybytes = stringToBytes("YELLOW SUBMARINE")
ivbytes = zeros(UInt8, length(keybytes));
ptbytes = stringToBytes("this is just a test to see if this cbc stuff could possibly be right")
blocksize = 16;

In [ ]:
ctattempt = encryptCBCByHand(ptbytes, blocksize, ivbytes, keybytes);

In [ ]:
ctattempt

In [ ]:
decryptattempt = decryptCBCByHand(ctattempt, blocksize, ivbytes, keybytes);

In [ ]:
decryptattempt

In [ ]:
String(decryptattempt)

whoah


In [ ]:
ctb64 = chomp(readstring("10.txt"));
ctbytes = base64decode(ctb64);
keytext = "YELLOW SUBMARINE"
keybytes = stringToBytes(keytext)
ivbytes = zeros(UInt8, length(keybytes));
blocksize = 16;

In [ ]:
decryptattempt = decryptCBCByHand(ctbytes, blocksize, ivbytes, keybytes);

In [ ]:
String(decryptattempt)