These are some notes about AES encryption in R, because it took me a little fiddling to produce a working example of my own.


First, the example from the digest vignette

msg <- as.raw(rep(1:16, 2)) # encrypt this
key <- as.raw(1:16)         # with this key

Now in CBC mode: each encoding is different

iv <- sample(0:255, 16, replace=TRUE)
aes <- AES(key, mode="CBC", iv)
code <- aes$encrypt(msg)

Need a new object for decryption in CBC mode

aes <- AES(key, mode="CBC", iv)

And here’s the original msg:

aes$decrypt(code, raw=TRUE)

Next, my own example

encryptthis <- "There's no place like home."
stepone <- charToRaw(encryptthis)

Now append to the raw vector as many bytes as needed for its length to be a multiple of 16. What bytes you might append? Just pick the raw byte representation of the number needed. This is also known as PKCS5 padding:

rem <- 16L - length(stepone) %% 16L

This rule also ensures that your raw string is always padded. If by chance the length of the original string in raw format is a multiple of 16 already, then rem = 16 and you will pad it with as.raw(rep(16, 16)). This is nice because if the reader knows that this is your recipe for padding, they just need to check what number the last character is, move back as many elements in the decrypted raw vector, and drop them as padding.

steptwo <- c(stepone, as.raw(rep(rem, rem)))

Now set a key that will be shared with the recipient:

key <- as.raw(sample(0:255, 16, replace=TRUE))

And set an initial vector for encryption:

iv <- sample(0:255, 16, replace=TRUE)

Now encrypt, CBC mode:

aes <- AES(key, mode="CBC", iv)
decryptthis <- aes$encrypt(steptwo)

Pre-pend the iv as raw vector, and send to recipient.

decryptthis <- c(as.raw(iv), decryptthis)

Now the recipient gets the message decryptthis and the key key. She knows that the first 16 raw bytes of the message are the IV, and expects that there’s padding at the end.

So, with this key and this knowledge, here’s the decryption object:

aes <- AES(key, mode="CBC", decryptthis[1:16])

And here’s the original message, in raw bytes:

padded <- aes$decrypt(decryptthis[17:length(decryptthis)], raw = TRUE)

Now find the size of the padding, remove it, then show the original message in plain text:

rem       <- as.integer(paste('0x', as.character(padded[length(padded)]), sep = ''))
plaintext <- rawToChar(padded[1:(length(padded) - rem)])

Check that encryptthis and plaintext are the same: