I am trying to encrypt few database columns (string values) using Java AES algorithm. This is to protect certain sensitive data. For some users these data should decrypted.
In Java AES encryption, if my input character length is 60, I am getting encrypted string length as 88.
But I don't want a change the length of the encrypted data. We have huge amount to tables and many applications are using those tables. We want to minimize the impact of encrypting certain fields in the tables.
Is there is any recommended solution? OR is there is any recommended algorithm, code sample, etc?
In such situation you can use a stream cipher instead of a block cipher. Note that block ciphers can also be used as stream ciphers, for example the AES in counter mode.
If you have to use a block cipher and all your fields are larger than one block you can use cipher text stealing.
Both methods give you an output that has the same length as the input when regarded as byte array. There may be difficulties to represent the output byte array as a string in the same length as the input.
Related
I have a situation where I need to first encrypt a message using a public key and vector, that is already provided. Also as per requirement I need to use SHA-2 as well. For now, I am assuming that I need to hash the encrypted message and then send to the server. I have two questions related to this
1. Is it wise to hash the encrypted message? Also, will sending the encrypted message and hashed value to the server be a good idea?
2. I have done a lot search on internet, but whenever I try to get some example of using AES 256 and SHA-2 together, I actually land up where the difference between the two is explained. Can any help me with some sample code?
Thanks in Advance!!!
Let's break down the stuff first.
Public Key Cryptography
Allows a given pair (Kpriv, Kpub) to be used on a cipher to encrypt and decrypt data.
Any data encrypted with Kpriv can only be decrypted with Kpub and any data encrypted with Kpub can only be decrypted with Kpriv.
A nice and well known example of a public key cipher is RSA.
Asymmetric cryptography requires extremely large keys in order to be secure, such that it's extremely slow to execute! You should never encrypt large amount of data with Asymetric keys cryptography. You can use it in the beginning of a connecition to exchange a symetric key Ks, though.
Symetric Key Cryptography
Allows a Ks to be used on a cipher to encrypt and decrypt data.
An example of a symetric cipher is AES. AES is in fact so versatile you can change lots of parameters, such as, (as you mention) the Blocksize which can be of 128, 192 or 256 bits. AES256 is the AES cipher configured with a blocksize of 256 bits.
The block size is what's used against the provided Ks to perform the actual encryption. Note that your data can be larger than the block size (the algorithm will still work, It'l simply reuse the same Ks). Simply reusing the key every block is known as ECB mode and can reveal patterns if your data is repetitive. An alternative is to use modes like CBC or CTR which rely on also using previous block data and XORing with the next block data, to eliminate such patterns. What mode should you use depends on your data.
Note that, according to your cipher mode, you eventually will need padding. I'm assuming you are already quite familiar with this terms when you asked that question.
Guarantees By Cryptography
Cryptography does guarantee that the encrypted data is confidential but that's just it. It does not give any other guarantees such as whether the data is authentic or whether it has been tampered with or not.
While tampering data will most likely result in unintelligible text even after decryption, in cryptography, there's no such thing as invalid plaintext. As such, you need some mechanism to know if your data is valid or not.
A secure hash algorithm such as SHA can help you know whether your decrypted data is valid or not.
However, for these purposes, you usually shouldn't directly use a Digest algorithm. Try to instead use a MAC. That MAC can use SHA256 algorithm but MAC's and Hashes are not exactly the same.
How To Do It In Practice
If all you want is confidentiality and tampering detection, you would use the cipher and digest (or hash) algorithm as such:
E ks ( SHA(data) || data )
Where E is a symmetric cipher, ks is the shared symmetric key, SHA(data) is the digest of data using a secure hash algorithm, || means concatenation and data is a byte array.
A more safer approach would be:
E ks ( MAC mk(data) || data )
Where mk is the MAC's secret key.
Now just search how to "java symetric cipher" and "java hash byte array" and use the two as I'm describing above.
I'm using the jpbc java library to achieve the HIBE encryption in order to encrypt and decrypt a String data.
In this case, i found a function that's allowed me to get an Element from a String as it shown below and it make me able to encrypt & decrypt this Element :
private static void elementFromString(Element h, String s) throws NoSuchAlgorithmException
{
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(s.getBytes());
h.setFromHash(digest, 0, digest.length);
}
But now, i need a solution to get the string data from the Element after decryption or any other idea can help me.
Thank you
Hashing is not encrypting. SHA-1 is a one-way function, i.e. you can possibly guess the input given the output, but you cannot retrieve the input by any calculation.
To encrypt and decrypt you need a cipher. A cipher often consists of a block cipher and a mode of operation such as "AES/GCM/NoPadding". Kind of surprising, it is represented by the Java Cipher class.
You may need to generate a key or key pair and store it somewhere, such as a KeyStore.
Trying to perform crypto without understanding what you are doing may result in code that runs - eventually. However, the chances that it will be secure is minimal. First try and learn about the subject.
Note that calling getBytes on a String results in platform specific encoding. This can be fun if you switch platforms in the future. Explicitly specifying UTF-8 is a good idea.
I use encryption to create query parameters that get emailed to individuals with download links to various files. However, I've noticed that the encrypted strings are fairly similar for similar file names. I'd like to change that.
Here's the code I'm currently using:
Cipher cipher = Cipher.getInstance('AES/CBC/PKCS5Padding')
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec('****************' as byte[], AES'),
new IvParameterSpec('***************' as byte[]))
String fileId = Base64.encodeBase64String(
IOUtils.toByteArray(
new CipherInputStream(
new DeflaterInputStream(
new ByteArrayInputStream(
('File: ' + filename).getBytes('UTF-8')
)
), cipher
)
)
)
For example if I have a file called Something_8.3.0.1471.exe and Something_8.3.0.1471_License.txt I would get the following two strings:
mVjCmP2GCyxMJ1i5GHT1OOZEYXy1%2Buz%2BQ53QMelR4QU%2FTowMdjNcMjojlbjuTJEd
and
mVjCmP2GCyxMJ1i5GHT1OB%2F5S1rolp%2BwK9dATPdPtHn3uQiXnYUhLmym6hMI65TVfjA5IzSYInI9iIjZn9eExg%3D%3D
The first 20 or so characters of the encrypted string are identical, obviously because the beginning of the file names is identical. I was wondering if it's possible to remove this identicallity (if that's a word). Is it possible to have any change in the unencrypted string more prominently impact the whole encrypted string? If so, how would I go about making this change in Java/Groovy in the above code?
The same key and same plain text will always produce the same cipher text when used in deterministic encryption scheme. Probabilistic encryption schemes introduce some randomness factor so that continuous invocations of encryption with the same key and same plain text produce different cipher texts.
Some crypto algorithms (like EC signatures) generate random values internally and do not even expose them to the user as they do not need to store the value of that randomness factor in order to decrypt the cipher text (or validate a signature) but in most ciphers the user is trusted to provide a random factor like initialization vector or nonce.
AES has a block size of 16 bytes, meaning that it splits the input into 16-byte chunks and processes each chunk separately (in ECB mode) or mixing in the previous processing results in some way (in most other cipher modes). For the very first block regardless of the cipher mode used the only inputs are the key, the IV and the first 16 bytes of the input.
In your example the first 16 bytes are the same in both cases, and it seems that you use the same key and same IV (one of the greatest crypto sins, by the way). As expected, the first 16 bytes (or, equivalently, first 20 Base64 characters) are the same.
The next 16 bytes of the input are different, which leads to completely different second block of cipher text.
You must not use the same IV value twice. Use SecureRandom to generate unique IV values for each encryption attempt.
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[16]; // use the proper IV size for selected cipher
random.nextBytes(bytes);
When using a single storage entity (a single file, for example) storing the IV before the cipher text is the de facto standard, but it is not required (you can store the IV and the cipher text in a separate database columns, for example).
You must not use keys created by simply converting a character sequence into a byte sequence. Such keys have predictable properties (for example, for ASCII text your key will never contain bytes in the range of [0..31]). If you need a password-based key then use the proper key derivation function like PBKDF2.
I am trying to send an encrypted text with each HttpResponse and when I get the next HttpRequest with the encrypted text, I decrypt it and do some stuff :) with it.
I am curious about the best practices surrounding the storage/retrievel of the keys and ivSpec's (or nonce's) in general, but specifically looking at the code posted by #sherif based on #VoidPointer 's suggestions in How to encrypt String in Java,
a) Do we have to initialize ivSpec with random bytes for each string that I want to encrypt?
b) If so, do we store the generated ivSpec in some db and look it up when I need to decrypt using that?
c) If so, how do we look it up? When an encrypted string needs to be decrypted how do we pick the correct ivSpec from db?
d) One suggestion is to send ivParameter along with the encrypted string! itself (which is probably what is happening with #sherif 's implementation!). If we chose to do so, how can I modify the class provided by #sherif to decrypt and separate the iv parameter and encrypted string instead of providing the iv parameter while initializing decrypt cipher?
A. If you do not change the vector, each time you encrypt the same string, you get the same encrypted result.
By changing the IV each time, you make it so that every single encrypted output looks different (even if it's the same input).
Think of it as a the "salt" you use when you are hashing a password.
so under normal circumstances it would be desirable to use a random iv.
B&C. You need to look the IV up, yes. But storing it into a DB isn't very useful. You already have a piece of information that you keep stored secretly: that's the password. IV is just here to increase randomness, no need to keep it, push it out with the output.
D. Sending it is the usual way to go.
One way is to concatenate it at the beginning of the ouput. (output = IV + encrypted data). Then before decrypting first split the input (IV = 32 first bytes of input) and decrypt the rest (crypt_data_to_decrpt = input after byte number 32)
Another way is to have a constant IV and a random part at the beginning:
you simply use a string of NUL byte as an IV.
Then you encrypt 32 bytes of pure random garbage
Then you encrypt your input. (When using a good encryption method, this should always produce a different encrypted output because the beginning was different).
For decryption, you use the same empty IV, then you decrypt everything. You ignore the 32bytes at the beginning. You split and only take the bytes after the 32nd. That's your decrypted output.
It seems the RIM Crypto API provides for only PKCS5 Padding mode for symmetric encryption (3Des) - as far as I know. I'm working with the JDE 4.6.0.
I'm trying to provide cryptography for a blackbery app which needs to be compatible with existing services which already use NoPadding with the standard Java security API.
Is there a way to extend the API to provide for the lacking PADDING modes, or some other hack, to achieve this?
Based on what you've told me, I would use the encrypt function of TripleDESCBCEncryptorEngine to encrypt your blocks.
There is a version of the function that can encrypt multiple blocks at once by specifying the number of blocks.
Here is a reference to that function.
It looks very straightforward, you just pass the key and the IV into the constructor and then proceed to make calls to .encrypt to encrypt the data.
Similarly there is a TripleDESCBCDecryptorEngine here.
I admit to not being familiar at all with the RIM crypto API, but just from reading the documentation it appears just using the the BlockEncryptorEngine.encrypt() method gives you the same functionality as the JCE NoPadding tranformations for block ciphers. So in your example that would be TripleDESEncryptorEngine.
If you are using CBC chaining mode and can arrange for your input data to have a length multiple of the block size (i.e. multiple of eight, when expressed in bytes, if the block cipher is 3DES) then you just have to remove the last block of the encrypted output.
In CBC encryption, input data (m) is first padded into a message which has a length multiple of the block size (with PKCS#5, by adding between 1 and b bytes, where b is the block length, b=8 for 3DES); then it is split into successive b-bytes blocks. Each of those blocks yields an encrypted block of the same size: the encrypted block for message block i is the result of 3DES applied on the bitwise XOR of message block i and encrypted block i-1. Consequently, if the original message m has a length multiple of b, then PKCS#5 padding adds b bytes, i.e. a full block. By removing the last encrypted block, you obtain what you would have got with no padding at all.
Decryption might be trickier. If the RIM API is stream-oriented (if it can gives you some plaintext bytes before having the whole message) then you can feed it with null trailing bytes until it returned you all your message (the extra null bytes will decrypt into pure random-looking junk, just discard it). If the RIM API is message-oriented, then you will have to use your knowledge of the secret key to rebuild a valid "last block" (the one which was you removed during encryption). Namely, with 3DES, this would mean the following: if z is the last encrypted block of the message (the one with "no padding"), then you encrypt an empty message (of no byte at all) with the same key, using z as "initial value" (IV). This should result in a single b-byte block, which you just append to the encrypted message. The effect of that extra block is that the decryption engine will "see" a proper PKCS#5 padding, and transparently remove it, yielding the data you expect.
All of the above assumes that you are using CBC, which is the most common chaining mode, among those which require padding.