I'm writing small program to encrypt/decrypt files using AES. I'm using Cryptopp library.
I need help to understand some things.
When I'm encrypting file I should write IV at the beginning of file to decrypt it later?
I wan't to check password given do decrypt file was correct. Should I:
put some string at beginning of file (ex. TRUE) before it's encrypted. After decryption check it.
Check MD5 of file before encryption. Put it at beginning of encrypted file. Read MD5 before decryption, decrypt file, check MD5 of decrypted file and compare them.
Writing the IV at the beginning of the file is fine. Appending to the end is another option.
Do not put a static string into the plaintext: ENIGMA transcripts were more easily broken for very similar reasons, and the zip format makes brute-forcing passwords very easy for this identical mistake.
The md5 approach sounds tolerable; but hmac-sha256 would provide significantly stronger integrity claims. (I think you could even re-use the AES key or the IV for hmac-sha256, but I'm not positive of its safety.)
Related
Simple question. What is the best (most universal) way to display a file hash? Below are two SHA256 hashes for the same file. One is displayed as base64 and one is...something else. The file hash will be used for auditing to make sure the file we send is the same as the file the auditor received. If the hash needs to be verified, I want to make sure I provide the hash that is the most easily verifiable.
SHA256 55461e72cccb74b475278189956b9db307bf44945e1639af93c34b224b7fcfd
SHA256 Base 64 VUYecszLdLR1J4GJlWudswe/RJReFjmvk8NLIkt/z9s=
55461e72cccb74b475278189956b9db307bf44945e1639af93c34b224b7fcfd
The point of Base64 is to constrain the character set to displayable characters. The hash is in hexadecimal which is even more constrained.
I need to generate a large random string to encrypt some passwords with in perl. The keys I am using now to encrypt with are generated from the Gibson Research Corp website. They were meant to be place holders for me to test with. Now I am looking to make something final.
I would like the key to be something enclosed in a file kinda like a SSL cert but not nearly as long, right now I am using a 64-bit key for testing I would think 1024-bit key would be a bit overkill, this key is NEVER going to be seen on the internet it is just to encrypt password in my config file from "prying" eyes more or less. The reason for it to be in file of some kind would so the encrypter could read it and the decrypter could also read and they would stay in sync using the same key rather than have to copy and paste the keys into each script and therefore have a chance of user error.
Using the Perl hex function, you can convert a decimal number into a hexadecimal one.
Here's a snippet that creates a string of 32 random hex digits:
my $rand_hex = join "", map { unpack "H*", chr(rand(256)) } 1..16;
Here's another - simpler - way to generate 32 random hex digits:
use Digest::MD5 qw(md5_hex);
my $rand_hex2 = md5_hex(rand);
I was wondering if there is a way to "test" to see if a particular string is encrypted or not.
I am using Crypt::CBC to encrypt a password with Rijndael.
As it stands my script has a "switch" that is either set as 0 or 1 that tells the script weather or not the password needs to be passed through the decrypt phase in order to be read.
I would like to eliminate that phase if I could.
The reason is I am trying to prevent the users of script from possibly prsenting the script with a situation where the password is encrypted but the "switch" was set to 0 meaning not encrypted because this would create a huge "trainwreck".
change your apps so passwords are only stored encrypted. confusion gone.
Rijndael has a block size of 128-bits so the output will always be a multiple of this.
If the encrypted passwords are hex-encoded then that will give you strings that are a multiple of 32 characters. In fact, with the IV added, the strings will always be at least 64 characters: 128 bits of IV followed by 128 bits of ciphertext block 1.
You could therefore look for strings of the right length that contain only [0-9a-f]. They are probably encrypted because I suspect few people can use a 64-character string of randomness as their real password.
If they're base64 encoded then the strings will be a different length, obviously.
This doesn't guarantee that you can always detect an encrypted password but it's probably not too bad.
Use AES/Rijndael or any symmetric encryption.
Encrypt the hidden value using itself as the key and a random IV.
Store the ciphertext + IV. Discard everything else.
To check the hash: try to decrypt using provided plaintext. If provided == decrypted, then it's OK.
Ignore ciphertext length problems.
Is this secure?
There is an existing method of generating a hash or MAC using an block cipher like AES. It's called CBC-MAC. It's operation is pretty simple. Just encrypt the data to be hashed using AES in CBC mode and output the last block of the ciphertext, discarding all prior blocks of the ciphertext. The IV for CBC would normally be left as zero, and the AES key can be used to produce a MAC.
CBC-MAC does have some limitations. Do not encrypt and MAC your data using the same key and IV, or the MAC will simply be equal to the last block of the ciphertext. Also, the size of the hash/MAC is limited to the size of block cipher. Using AES with CBC-MAC produces a 128 bit MAC, and MACs are usually expected to be at least this size.
Something worth noting is that CBC-MAC is a very inefficient way to produce a MAC. A better way to go would be to use SHA2-256 or SHA2-512 in HMAC. In my recent tests, using SHA256 in HMAC produces a result approximately as fast as AES in CBC-MAC, and the HMAC in this case is twice as wide. However, new CPUs will be produced with hardware acceleration for AES, allowing AES in CBC-MAC mode to be used to very quickly produce a 128 bit MAC.
As described, it has a problem in that it reveals information about the length of the data being hashed. That in itself would be some kind of weakness.
Secondly ... it is not clear that you would be able to check the hash. It would be necessary to store the randomly generated IV with the hash.
I was thinking about this while bicycling home, and one other possible issue came to mind. With a typical hashing scheme to store a password, it is best to run the hash a bunch of iterations (e.g., PBKDF2). This makes it much more expensive to run a brute force attack. One possibility to introduce that idea into your scheme might be to repeatedly loop over the encrypted data (e.g., feed back the encrypted block back into itself).
Which symmetrical encryption algorithm to use to encrypt e-mail address(short message)? I would like to have ciphertext to be comparable in length to paintext.
According to Little known features: Symmetric encryption with PGP/GPG:
A little known feature of both PGP and
GPG is that they can also do symmetric
encryption. Just a passphrase is
needed- no public or private keys are
involved. It’s a quick and dirty way
to get strong encryption that even a
novice can use.
To encrypt a file with symmetric
encryption, the syntax is:
pgp --symmetric filename
gpg --symmetric filename
The result is a binary file with the
same name as the original and ".pgp"
or ".gpg" appended.
If the encrypted file must be pasted
into the body of an e-mail message
(instead of added as an attachment),
you’ll want to use the plain ASCII
form of output:
pgp --symmetric --armor filename
gpg --symmetric --armor filename
The result is a plain text file ending
in ".asc"
Decryption is performed using the
usual "-d" switch:
pgp -d filename
gpg -d filename
But I'm not sure this is what you're looking for. Maybe you can clarify your question.
If you really want to have the cipher text comparable in length to the email address, you can use a block cipher in a mode like CFB or OFB that allows encryption of one byte at a time.
However, I don't recommend it, because that gives an attacker a little information about what the message is (how long is the message?). Using an algorithm like 3DES or AES with 16-byte blocks in CBC mode with PKCS #5 padding, most email addresses will be encrypted in two blocks.
I see there is a bit of confusion about lengths of plaintext/ciphertext. Actually, those lengths are quite similar if you use a symmetric encryption algorithm.
Consider a block cipher (e.g. AES). It encrypts 128-bit blocks into 128-bit blocks. So if your plaintext is exactly 128 bits (or its multiple), AES in any mode of operation will produce the ciphertext with the same length. If your plaintext length is not a multiple of 128 bits, then it will get padded to the full block and the ciphertext will be slightly longer (by at most 127 bits). You still can avoid that by using some tricks like ciphertext stealing.
If you use a stream cipher, the encryption process is just XOR-ing bits (or bytes) of the plaintext with bits (or bytes) of the keystream and then the length of the ciphertext is by definition equal to the length of the plaintext.
To answer directly your question, if you don't need any specific format of the encrypted email, just use AES.
If you want the encrypted email to be also in the format of an email, you may want to check how Format-Preserving Encryption works.
#Bobby: ROT13 is NOT an encryption algorithm.
Symmetric block ciphers produce the same length as the input, in multiples of block size (usually 8 bytes or 16 bytes for AES). Because the output is always multiple of block sizes (in fact the output is always the same size as the input and the input must be multiple of block sizes) then you cannot know the original size of the plain text. Common encryption schemes solve this by adding a padding scheme, like PKCS, ISO 10126 or ANSI X923. These schemes place information about the original clear text length in the last block.
If the clear text size is multiple of 8 (16 for AES) then one more block is added to the encrypted text. If the original size is not multiple of block size, then the encrypted size will be rounded up to the next multiple block size.
To this you should add a salt value for each record. A salt (or initialization vector, to be correct) has the same size as a block. Usually is stored in front of the encrypted block.
And finaly you should sign the encrypted value for validation, so you should add a SHA digest, another 20 bytes, otherwise you cannot know for sure if the decrypted value is correct.
So the overall size is (considering AES): 16 bytes (salt) + (clear text size + 20(hash) ) + (16 - (clear text size + 20)%16).
So for john.doe#anydomain.com (lenght 22) the encrypted size will be 16+22+20+(16-10)=64. To decrypt you take the first 16 bytes as salt, decrypt the remaininf 48, the output is lenght 42, you digest SHA the 42-20 = 22 bytes and compare the digets with the last 20 bytes of the decrypted text for validation.
I know is maybe more than you bargained for, but every step in this scheme has a justification.
I would suggest looking into PGP.
To have cypher results comparable with plain text is not a good idea, having differents lenghts is a part of what encryption is about.
I will suggest you one of the most secure encryption algorithms today: AES
But forget about having comparable sizes!
ROT13 or a substitution cypher might work (keys can be changed or exchanged). Encryption with keeping the original text length is...not really that good.
Bobby