I am using AES for encryption and CRC to check data integrity and I have the impression that the CRC check is redundant in my case. I am doing the following:
Encryption:
Take the payload data and calculate CRC from it
Encrypt payload data plus CRC
Decryption:
Decrypt data
Calculate new CRC of payload data and compare it with the old CRC
I wanted to provoke a CRC check failure in my unit test but when I manipulate the payload data the decryption always throws a BadPaddingException.
My question is: If the decryption always throws this exception when data is corrupted or manipulated (will it?) isn´t the CRC check redundant the way I am using it?
Assuming the incorrectly decrypted data is uniformly distributed, it will appear to be correctly PKCS5/PKCS7 padded about 1 time for every 255 incorrect passwords. This means that there is still a 1/255 chance that a correct change will occur and the item will decrypt into garbage. Therefore your check is not a waste.
If you actually want the behavior you expected, you can use "AES/CTR/NoPadding", which will not require an exact block size and will always return a decrypted byte[], whether or not the keys match.
However if an attacker can repeatedly alter the ciphertext and get you to decrypt it, (an example might be encrypted data stored in a cookie) and if they can distinguish between your behavior when the decrypted data throws an exception for bad padding and when it is simply garbage, then they can determine the plaintext via a "padding oracle attack".
You may also want to consider if a more robust fingerprint than CRC may be appropriate like SHA-256 for ensuring message integrity.
A lot of this is repeated from: AES BadPaddingException
Related
So, I'm attempting to write a cryptography method that uses a hash that both the sender and the receiver know. I'm confused as to how to dehash a message.
For example, the sender sends a the message
M: 50 and hashes it
So 50 % 30 = 20.
H = 30
So after hashing, the resulting message would be 30.
How would the receiver be able to dehash the message to receive the original with knowing the hash?
There's no code or anything. Just an important concept that I wish to grasp.
EDIT: So, I have a general understanding of encryption and decryption. For the sake of understanding. How would I get the original message using RSA?
For for example,
Sender Private Key: 55,27
Sender Public Key: 55,3
Receiver Private Key: 35,29
Receiver Public Key: 35, 5
Is this possible?
What you are looking for is encrypting and decrypting. Hashing is a one way function which usually loses information making it impossible to recreate the original message.
Is there any way to receive the original message after hashing through encryption?
When you use encryption, you create some bytes which look random and can look like a long hash value. The difference is that the data can be decrypted back to the original information, whereas with hashing this is designed to be as hard as possible.
If so, which encryption/decryption method do I use?
The key decision to make is whether you want symmetric or asymmetric encryption. Symmetric is faster but requires the key for decryption be the same as encryption i.e. both the point of encryption and decryption needs to be secure. If you use asymmetric encryption, you can allow one end to either decrypt or encrypt but not both. i.e. only one end needs to be secure.
We encrypt with AES 256 CBC PKCS5PADDING in Java with the libraries one has to download from Oracle, with Base64 encoding of the resulting byte arrays. I have read that static common initialization vector drastically decreases the security as texts that starts with the chars will looks the same when encrypted. Is this still true for short strings (12 numeric chars)?
I have encrypted a large set and I cannot find any reoccurring substrings in the resulting encrypted strings, even when they start with the same sequence.
Example (plaintext on the left and resulting encrypted string on the right)
555555555501 -> U0Mkd0PPloB5iLBy5jM6nw==
555555555502 -> NUHWaFs62LMEeyoGA0mGoQ==
555555555503 -> X3/XJNd4TzEsMv7V0bXwqg==
Albeit separate from the question, but to preempt some suggestions: we need to be able to do look ups based on plaintext strings and to be able to decrypt. We could do both hashing and encryption, but prefer to avoid it if it does not improve security significantly as it adds complexity.
I have read that static common initialization vector are bad as one can derive the key from encrypted strings.
I'm curious: where have you read that?
With short (<=16 bytes) plaintext, a random IV effectifely works as a Salt, i.e. it causes the ciphertext to differ even if the plain text is the same. This is an important feature in a lot of applications. But you write:
We need to be able to do look ups based on plaintext strings.
So you want to build some sort of pseudonymization database? If that is a requirement for you, the feature that salt, and in your case random IV adds, is actually one that you specifically don't want. Depending on your other requirements you can probably get away with using a static IV here. But for pseudonymization in general, it is recommended to use a dedicated pseudonym. In your case the data seems to be atomic. But in the general case of, for example, address data, you want to hash the name, the zip code, the city and whatever else your pseudonym is, separately, both to allow more specific queries, and to keep access to and information flow from your data under strict control.
Hi is it possible to encrypt the string with the certain length that i want? for example: i want to encrypt this string BI000001 to something like hex value A3D5F2ARD3(random) fixed it at 10 length. Therefore when user enter this value A3D5F2ARD3, system will based on this value and decrypt it to get back the value BI000001 .
is it possible to do this in java?
I tried a lot of method but all encrypted length are way too long.
I am not aware of any JDK built-in Java encryption method which provides this feature. Then again, I am not an encryption expert, but I guess such a custom feature won't be built in the JDK.
Maybe this discussion is also useful: https://crypto.stackexchange.com/questions/6098/is-there-a-length-preserving-encryption-scheme
Why do you want to preserve size of the string? maybe there is another solution for your problem.
Typically you would use a block cipher such as AES to encrypt data. Block ciphers (as their name suggest) work in blocks of data of a fixed size, for example AES works in blocks of 128 bits. If a block cipher encounters input smaller than the block size it pads it, which is likely why you are seeing the ciphertext larger than the plaintext.
If you want to preserve the length then consider Format Preserving Encryption as mentioned in this question.
I'm working on communicating with a server and I've reached the final stage, where after negotiating keys and setting the session key, I send an encrypted message and the server answers back.
Currently, we're working with AES-256 CBC, with a random IV that gets sent to the server and I locally store. The problem that I'm currently facing is when I decrypt the data I got from the server:
decryptCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(cipher.getIV(), 0, 16));
//Get the array after the 7 bytes from the header
byte[] encrypted = Arrays.copyOfRange(sbResponse.toString().getBytes(), 7, sbResponse.toString().length());
When I try to decrypt that parsed array, any of the following happen, however, the response from the server does not vary in length or content at all:
I can't decrypt it, because of the following error:
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
I can't decrypt it, this error comes up:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
I can decrypt it, certain blocks come up fine, but some of them, have weird characters among clear text:
k¤kC²O©æÖ—Õw½QøX»ÌEXøÀWHÌËùtiÓaÚo at?the application
Everything comes up just fine.
So, I have to make a bunch of calls until I get a clean response from the server.
What I've noticed is that the server does change the IV on its end, however, on my end, the IV always remains the same when I ask the Cipher for it, so I really don't know where else to look.
Here's an excerpt of the code that gets the response from the server:
StringBuilder sb = new StringBuilder();
while (ConnectionStatus.LISTENING.equals(status)) {
if (in.ready()) {
sb.append((char) in.read());
} else {
if (sb.length() > 0) {
status = ConnectionStatus.OPEN;
}
}
}
if (ConnectionStatus.TIMEOUT.equals(status)) {
status = ConnectionStatus.OPEN;
throw new TimeoutException();
}
Does anyone have any idea on what might be happening?
Let me know if you need further details, code or anything.
The problem is with storing binary data into a String.
If the InputStreamReader expects UTF-8, it most likely encounters invalid data since most binary streams are not valid UTF-8. Data is lost when the reader encounters a sequence of bytes that is not a valid character.
There are at least two or three solutions:
Switch to the underlying InputStream for binary data. Since an InputStreamReader may perform buffering, this is problematic - even if this might happen with some charsets only (To enable the efficient conversion of bytes to characters, more bytes may be read ahead from the underlying stream than are necessary to satisfy the current read operation.)
Always treat data as binary, and only if you expect textual data, convert the data to String.
Encode the encrypted message to text before transmission, and decode it after receiving. There are several standard encoding schemes or you may roll your own. Here are some:
Hexadecimal - not exactly efficient (4 bits per character) but easier to implement manually.
Base64 - the de-facto standard in binary data encoding (6 bits per character). While not a part of the JFC (yet), there's at least one library for that.
Ascii85 - the top notch in encoding density to printable text (6.4 bits per character), if you can find a library for that. It's not widely used.
For Encryption in Java... the article at http://cwe.mitre.org/data/definitions/329.html states that the Initialization Vector should be different each time, but if I use a different IV to decrypt than the one I used to encrypt, I get garbage characters instead of the data I expected.
What is the proper way to encrypt on one server and decrypt on another without having to communicate the IV back and forth in between servers?
The common technique seems to be to hardcode a byte array, but supposedly that's insecure???
I believe an IV is like a salt - it's not a secret, it's just used to introduce an extra element of randomness so that the same message encrypted with the same key still comes out differently each time.
So you can transmit the IV used to encrypt as part of the encrypted value, just like you'd store the salt along with a hash for a hashed value.
Of course, I could be completely incorrect...
you have to add the information that you want to avoid, inside the encrypted data, which is an array of bytes, and then removing during the conversation.
the IvParameterSpec is based on fixed array, so you know the length of the part to add and to remove. The removed part is used to recreate the parameters you pass during the chypher initialization.
please have a look at this class I created:
https://github.com/spannozzo/tk-integration/blob/master/tk-integration-util/src/main/java/org/acme/util/AESUtil.java