This question already has answers here:
Good AES Initialization Vector practice
(8 answers)
Closed 6 years ago.
I understand the IV should be random and XORed with the plain text to start the encryption. My question is, in addition to the key, do I have to remember the random IV as well for decryption?
The IV needs to be random, but does not need to be secret. Usual practice is to prepend the IV to the cyphertext before transmitting it. When decrypting, use the first 16 bytes of the cyphertext as the IV to decrypt the remainder. That way you do not have to store it separately, as it is included in the cyphertext.
Related
I have a question about aes keys.
I have a binary file which contains an aes256 key (32 bytes) at an unknown offset.
Would it be somehow possible to find this key in the file? Is it somehow possible to tell whether the next 32 bytes would be a valid aes key?
Thanks in advance
EDIT:
Thanks for all of your answers,
The key is stored in the file as normal bytes.
I finally managed to create a way to get it.
I basically filter out all strings, which actually made it work.
Thanks again
Well, yes and no. AES-256 keys should consist of just 32 bytes that are indistinguishable from random. Most files do not consist of just random bytes, so it could be possible t find a sequence that is most likely random, and this could be that key you are looking for. However, it might very well be that there are other random sequences in the file, or sequences that look like random but aren't random at all (such as the binary representation of the number Pi).
It may also be that you are unlucky and that the AES key doesn't look all that random. Or that the key is stored in hexadecimals (text) rather than binary byte values. Then there is the issue of finding the exact offset that might be the problem (is that initial byte with value 0x20 indicating the size of the AES key, a space character or part of the key value)?
Most files have a specific format, so you should first have a look at that. Just looking for random sequences may give you both false positives (rather likely) or false negatives (less likely). If you expect 64 bytes of randomness (two keys) then I suggest you search for that first, as it brings down the chance of false positives by a rather large amount.
No - unless you have a way to verify the key against a known plaintext/ciphertext pair - an AES key is not distinguishable from random noise. Any set of 16, 24 or 32 bytes is a valid AES key.
I have a bank device that is used to do money transfers among accounts. I'm curious about trying to figure out what algorithm is used to cipher the input. It follows the next conditions
-The text that needs to be cipher consists of only 8 digits (e.g. 00000000, 00000001, 99999999, etc)
-It uses some key/password to cipher this input
-The key/pass is a string of n characters
-The output should be of the same length (8 digits)
Is there any standard crypto algos for this?
Yes, this is so-called Format-preserving encryption. And yes, it's standartized.
https://doi.org/10.6028%2FNIST.SP.800-38G
https://en.wikipedia.org/wiki/Format-preserving_encryption
I have an API to call where I have to encrypt my data using RSA/ECB/PKCS1 Padding & AES/CBC/PKCS5PADDING.
Sample Data: {"KEY":"VALUE"}
Step.1:
I have to generate a random number of 16 digit. eg: '1234567890123456'
Step.2:
Do RSA/ECB/PKCS1Padding to random number and base64Encode the result. we get "encrypted_key"
Step.3:
Concatenate random number & data:
DATA = 1234567890123456{"KEY":"VALUE"}
Step.4:
Do AES/CBC/PKCS5Padding on DATA (from Step 3) using random number(1234567890123456) as KEY & Base64Encoded random number as IV. we get "ENCRYPTED_DATA"
So, for Step 1 I am using JSEncrypt javascript library.
for Step 4 I am using CrytoJS.AES.encrypt() function. I am pretty sure that my JSEncrypt function is running fine as the client is able to decrypt it but client is not able to decrypt my data. I feel that I am making a mistake while using CryptoJS.
Can someone guide me properly on how to use the library.
What I am doing is:
KEY = '1234567890123456'
IV = MTIzNDU2Nzg5MDEyMzQ1Ng== (result of btoa('1234567890123456') )
DATA = "1234567890123456{"KEY":"VAL"}"
cryptedData = Crypto.AES.encrypt(DATA, KEY, {iv: IV, mode: CryptoJS.mode.CBC,padding:CryptoJS.pad.Pkcs7})
I am told to use PKCS5Padding in AES/CBC Encryption ( Step 4 ) but it seems that AES does not support PKCS5Padding but PKCS7Padding.
I think I am making a mistake in the way I am passing KEY & IV to CryptoJS.
Any help will be greatly appreciated.
For the start lets see why are you doing the exercise. RSA is intended to encode only limited amout of data. So we use "hybrid encryption", where the data are encrypted using a symmetric cipher with a random key and the key itself is encrypted using RSA
Encryption works on binary data, to safely transmit binary data, the data are encoded to printable form (hex or base64)
Step.1: I have to generate a random number of 16 digit
What we see is 16 digits 0-9. That's not really safe. Generating 16 digits you will get a key of 10^16, which is equals of approx 2^53 (if I did the math wrong, please comment).
You need to generate 16 random bytes (digits 0-256 resulting in 2^128 key). That is your DEK (data encryption key).
You may encode the DEK to be in printable form, in hexadecimal encoding it will have 32 characters.
Step.2:
ok, you now get encrypted encoded_encryption_key
Step 3, Step 4
And here you should understand what are you doing.
encrypt DATA using DEK ( not encoded random number in binary form), you will get encrypted_data. You can encode the result to encoded_encrypted_data
concatenate the encrypted key and encrypted data. It. is up to you to choose if you encode it before or after encoding. I suggest you make concatenation of encoded_encryption_key and encoded_encrypted_data with some separator, because if RSA key length changes, the length of encoded_encryption_key changes too
Make sure to discuss with the client what format is expected exactly.
Notes:
IV needs to be 16 bytes long for AES and for CryptoJS I believe it needs to be Hex encoded, so using btoa may not be the best idea. I believe the CryptoJS just trims the value to 16 bytes, but formally it is not correct.
CBC cipher needs some sort of integrity check, I suggest to add some HMAC or signature to the result (otherwise someone could change the ciphertext without you being able to detect the tamper)
but it seems that AES does not support PKCS5Padding but PKCS7Padding.
Indeed AES supports Pkcs7. Pkcs5 is functionally the same, but defined on 64 blocks. The designation is still used in Java as heritage from DES encryption.
I'm working on a homework assignment on paper where I must design an RSA cryptosystem and show the steps of encrypting/decrypting a message by hand.
I have selected and calculated my p, q, n, and phi(n). I am now encrypting the message "HELLO". I have started by breaking each letter into its ASCII equivalent such that H = 72, E = 69, and so forth.
My question is should I encrypt/decrypt each letter separately to/from ciphertext or is there a better way to do it while leaving it as one string?
It seems daunting to have to do the Extended Euclidean Algorithm by hand for all the letters in order to find the decryption key.
I ask this question because I assume that RSA handles this in a better way as to not have to run encryption on each character but encrypt it as a whole.
TL;DR Should I encrypt each letter separately or can I do it all at once?
RSA encrypts the whole message by converting the whole text into a very large integer usually by putting an integer representation of each character in the text side by side and then applying the public key. If each character is encrypted separately, the encrypted message will be vulnerable to frequency analysis.
How can I decrypt a random block of encrypted data using aes-cbc?
First information:
AES has a block size of 128-bits. So when you say "AES-128" the assumption is a key size of 128-bits and "AES-256" the assumption is a key size of 256-bits.
CBC mode requires an iv. The iv is used for the first block, each other block use the value of the previous block in a similar way. See Cipher Block Chaining (CBC).
Decryption must be done on a block boundary. The first block will use the iv, subsequent blocks will use the value of the previous encrypted block essentially for it's iv. Thus decryption can start from other than the beginning of the encrypted data.
An assumption on my part is that gpg and openssl place the iv preceding the encrypted data, that is usual procedure but this is a guess by me but may be more complicated (I am to lazy to look that up). This would explain why decryption from the first block would work and not from other starting locations.
For more information study the available documentation.
There is a good online AES calculator provided by Cryptomathic.
With info in zaph's answer I was able to do it in python like this:
from os import urandom
from Crypto.Cipher import AES
import hashlib
IV = urandom(16)
aes = AES.new(hashlib.sha256(b'123').digest(), AES.MODE_CBC, IV)
T='1234567890'*160
C=aes.encrypt(T)
# Now if we make a new aes instance with IV we will be able to decrypt first block:
aes = AES.new(hashlib.sha256(b'123').digest(), AES.MODE_CBC, IV)
aes.decrypt(q[:16]) # It returns b'1234567890123456'
# But if we need to decrypt block 4 we need to instanciate aes with contents of block 3 as iv parameter:
aes = AES.new(hashlib.sha256(b'123').digest(), AES.MODE_CBC, q[48:64])
aes.decrypt(q[64:80]) # It returns b'5678901234567890'
So to sum it up if you want to decrypt some encrypted text using aes-cbc from block n to block m for example (which is bytes n×16 to m×16), you need data from block n-1 (bytes (n-1)×16 to (n×16)-1) as IV to start decryption on block n. This way you can decrypt any chunk of data even though you don't have access to whole data except for its first block (first 16 bytes).