Encryption-Decryption AES-xxx-CBC
Posted: Fri May 13, 2022 10:49 pm
Hello all, I was sending some messages to the use list but figured that this topic isn't of general interest.
Sadly, crypto is one of the most often misrepresented topics on the internet, so google isn't always your friend. Hopefully we can avoid the typical camp replies of "it's dangerous! don't do it unless you are an expert!" or the old "you must use method x with cypher y", etc.
I am interested in discussion, feedback, tips, criticisms (gently, please) on the topic of encryption within LiveCode. Crypto libraries are the sort of plumbing most people don't think about until they need them. But it's sure useful to get some of the fundamentals down before you need them. When you have a nice toolkit like LiveCode a potential drawback is that not all the options you might find in less elegant alternatives aren't in our kit, or they are abstracted maybe a little too much, and certainly we might be able to get some thoughts together to help out our friends at hq with documentation-examples, etc.
My first foray is into the world of encrypting files, including arbitrarily large ones, that can be safely presumed to be properly "encrypted at rest" and which can also then be transported properly while "encrypted in flight." For this first case let's not get into the transport piece or even authentication (we can cover that in GBC and HMAC).
When both the encryptor and decryptor are your own LiveCode apps, everything is pretty simple. Things can get slowed down a bit when you want to create a pattern to be used on another system from which you can reliably decrypt in reasonable time within reasonable memory utilization on the LC end.
Regardless, here is a portion of the help text concerning the encrypt command:
encrypt source using cipher with {password|key} passorkey [and salt saltvalue] [and IV IVvalue] [at bitvalue bit]
and a simple example:
encrypt myData using "aes-256-cbc" with password "@&^2fy"
This certainly works, and it's an okay pattern to use if you are not re-using the same key to send the same message (we should talk about this). Otherwise you would want to use the IV or randomize some toss away bytes within the start of your message to encrypt.
LiveCode makes doing some relatively difficult things pretty darn easy. You don't even have to construct your key, just provide a password and it's done for you. Which begs the question, how is it done by LiveCode? If you never leave LiveCode for encrypt-decrypt this won't matter. But if you want to use LIveCode for decrypting someone else's stuff (even if they follow your "recipe") -- or you want to send them an encrypted message, then we need to get a little more information and hopefully make it handy for people who don't want to do all this digging.
If you don't provide the salt value with the passwords option then one is made for you. That's cool and very handy.
So here is my first q. If I send a file encrypted using the example value, how would someone using python decrypt this message?
Here's a generic sample python snippet. All aes has a 16 byte block length. We are using 256 so the key length is 32 bytes.
What values would we transmit to the python programmer at the other end of the line to decrypt our message? The default message digest varies depending on age and version of openssl you are using.
def decrypt(ciphertext, password):
blksz = 16
klen=32
maxlen = klen + blksz
salt = ciphertext[8:16] # 0-7 characters are Salted__
keyiv = sha256(password + salt).digest()
tmp = [keyiv]
while len(tmp) < maxlen:
tmp.append( sha256(tmp[-1] + password + salt).digest() )
keyiv += tmp[-1] # append the last byte
key = keyiv[:klen]
iv = keyiv[klen:maxlen]
cipher = AES.new(key, AES.MODE_CBC, iv)
return cipher.decrypt(ciphertext[blksz:])
Sadly, crypto is one of the most often misrepresented topics on the internet, so google isn't always your friend. Hopefully we can avoid the typical camp replies of "it's dangerous! don't do it unless you are an expert!" or the old "you must use method x with cypher y", etc.
I am interested in discussion, feedback, tips, criticisms (gently, please) on the topic of encryption within LiveCode. Crypto libraries are the sort of plumbing most people don't think about until they need them. But it's sure useful to get some of the fundamentals down before you need them. When you have a nice toolkit like LiveCode a potential drawback is that not all the options you might find in less elegant alternatives aren't in our kit, or they are abstracted maybe a little too much, and certainly we might be able to get some thoughts together to help out our friends at hq with documentation-examples, etc.
My first foray is into the world of encrypting files, including arbitrarily large ones, that can be safely presumed to be properly "encrypted at rest" and which can also then be transported properly while "encrypted in flight." For this first case let's not get into the transport piece or even authentication (we can cover that in GBC and HMAC).
When both the encryptor and decryptor are your own LiveCode apps, everything is pretty simple. Things can get slowed down a bit when you want to create a pattern to be used on another system from which you can reliably decrypt in reasonable time within reasonable memory utilization on the LC end.
Regardless, here is a portion of the help text concerning the encrypt command:
encrypt source using cipher with {password|key} passorkey [and salt saltvalue] [and IV IVvalue] [at bitvalue bit]
and a simple example:
encrypt myData using "aes-256-cbc" with password "@&^2fy"
This certainly works, and it's an okay pattern to use if you are not re-using the same key to send the same message (we should talk about this). Otherwise you would want to use the IV or randomize some toss away bytes within the start of your message to encrypt.
LiveCode makes doing some relatively difficult things pretty darn easy. You don't even have to construct your key, just provide a password and it's done for you. Which begs the question, how is it done by LiveCode? If you never leave LiveCode for encrypt-decrypt this won't matter. But if you want to use LIveCode for decrypting someone else's stuff (even if they follow your "recipe") -- or you want to send them an encrypted message, then we need to get a little more information and hopefully make it handy for people who don't want to do all this digging.
If you don't provide the salt value with the passwords option then one is made for you. That's cool and very handy.
So here is my first q. If I send a file encrypted using the example value, how would someone using python decrypt this message?
Here's a generic sample python snippet. All aes has a 16 byte block length. We are using 256 so the key length is 32 bytes.
What values would we transmit to the python programmer at the other end of the line to decrypt our message? The default message digest varies depending on age and version of openssl you are using.
def decrypt(ciphertext, password):
blksz = 16
klen=32
maxlen = klen + blksz
salt = ciphertext[8:16] # 0-7 characters are Salted__
keyiv = sha256(password + salt).digest()
tmp = [keyiv]
while len(tmp) < maxlen:
tmp.append( sha256(tmp[-1] + password + salt).digest() )
keyiv += tmp[-1] # append the last byte
key = keyiv[:klen]
iv = keyiv[klen:maxlen]
cipher = AES.new(key, AES.MODE_CBC, iv)
return cipher.decrypt(ciphertext[blksz:])