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.
Related
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.
In Java ,I use Bouncy Castle encrypt data using padding:
Cipher cipher = Cipher.getInstance("RSA/ECB/NOPADDING");
The Base64 encoded result is :
AAAAAAAAAAAAAAAAA.....H6hBDxOrCI0K8fd13vOYtsKdo4SI3VZTa3...
Ant it won't change every time.
And in C++, I use OpenSSL library to encrypt data :
RSA_public_encrypt(rsa_len, (unsigned char *)str, (unsigned char*)p_en, p_rsa, RSA_NO_PADDING);
The Base64 encoded result is :
bxeeBPfFRJsLOzJLMS/qGKtDe1zPw8H491QsE+uuRRay6/ep69fqv386j8...
And it will change every time I run code.
I read Wiki and know RSA encryption is a deterministic encryption algorithm.
So the result of java is reasonable and my question is:
Is "AAAAAAAA..." padding is correct for no padding of java?
What has openssl done in C++ code to cause the result seems to have padding and time varying?
Update
I found that my java code is correct.
And When calling RSA_private_encrypt with RSA_NO_PADDING, the input must
have the same size as the RSA key modulus. .After I fill my input to 256 bytes , openssl can decrypt the java encrypt result.
So, the question become to:
What has openssl done to fill the input to reach the required length?
Update
At last, I don't have much time to research the OAEP in openssl.And the server use this unsafe way due to history problem. So I fill my input with byte 0.Just like:
This is input //<-----following many ASCII 0 char to reach 256 bytes length
But this will cause the output be the same. Any other code should prevent this in either server and client.
And it will change every time I run code.
Yes. That's due to Optimal Asymmetric Encryption Padding (OAEP).
If you send the same message twice, like Attack at dawn, your adversary who observes the message won't be able to learn anything (or make an educated guess) when he sees the message again. The property is known as semantic security or Ciphertext Indistinguishability (IND-CPA).
Here's a related talk by Dr. Matt Green on PKCS padding versus OAEP padding. Its very approachable: A bad couple of years for the cryptographic token industry.
Is "AAAAAAAA..." padding is correct for no padding of java?
Possibly. I believe its just a string of leading 0x00 bytes that have been Base64 encoded.
What has openssl done in C++ code to cause the result seems to have padding and time varying?
Its using OAEP.
So, the question become to:
What has openssl done to fill the input to reach the required length?
Its using OAEP.
The question may become: why is Java not using it because lack of OAEP means you could leak information for each message encrypted.
I am using a 3rd party platform to create a landing page, it is a business requirement that I use this particular platform.
On their page I can encrypt data and send it to my server through a request parameter when calling a resource on my site. This is done through an AES Symmetric Encryption.
I need to specify a password, salt (which must be a hex value) and an initialization vector (but be 16 characters).
Their backend is a .NET platform. I know this because if I specify an IV longer than it expects the underlying exception is:
System.Security.Cryptography.CryptographicException: Specified initialization vector (IV) does not match the block size for this algorithm.
Source: mscorlib
So for example, on their end I specify:
EncryptSymmetric("Hello World","AES","P4ssw0rD","00010203040506070809", "000102030405060708090A0B0C0D0E0F")
Where the inputs are: plain text, algorithm, pass phrase, salt, and IV respectively.
I get the value: eg/t9NIMnxmh412jTGCCeQ==
If I try and decrypt this on my end using the JCE or the BouncyCastle provider I get (same algo,pass phrase, salt & IV, with 1000 iterations): 2rrRdHwpKGRenw8HKG1dsA== which is completely different.
I have looked at many different Java examples online on how to decrypt AES. One such demo is the following: http://blogs.msdn.com/b/dotnetinterop/archive/2005/01/24/java-and-net-aes-crypto-interop.aspx
How can I decrypt a AES Symmetric Encryption that uses a pass phrase, salt and IV, which was generated by the .NET framework on a Java platform?
I don't necessarily need to be able to decrypt the contents of the encryption string if I can generate the same signature on the java side and compare (if it turns out what is really being generated here is a hash).
I'm using JDK 1.5 in production so I need to use 1.5 to do this.
As a side note, a lot of the example in Java need to specify an repetition count on the java side, but not on the .NET side. Is there a standard number of iterations I need to specify on the java side which matches the default .NET output.
It all depends on how the different parts/arguments of the encryption are used.
AES is used to encrypt bytes. So you need to convert the string to a byte array. So you need to know the encoding used to convert the string. (UTF7, UTF8, ...).
The key in AES has some fixed sizes. So you need to know, how to come from a passphrase to an AES key with the correct bitsize.
Since you provide both salt and IV, I suppose the salt is not the IV. There is no standard way to handle the Salt in .Net. As far as I remember a salt is mainly used to protect against rainbow tables and hashes. The need of a Salt in AES is unknown to me.
Maybe the passphrase is hashed (you did not provide the method for that) with the salt to get an AES key.
The IV is no secret. The easiest method is to prepend the encrypted data with the IV. Seen the length of the encrypted data, this is not the case.
I don't think your unfamiliarity of .Net is the problem here. You need to know what decisions the implementer of the encryption made, to come from your parameters to the encrypted string.
As far as I can see, it is the iteration count which is causing the issue. With all things the same (salt,IV,iterations), the .Net implementation generates the same output as the Java implementation. I think you may need to ask the 3rd party what iterations they are using
I've tried but failed to encode a string in Javascript to decode on a java server. We'd like to use the bouncycastle algorithm PBEWITHSHA256AND256BITAES-CBC-BC to decode serverside.
I've tried using crypto.js to do the encoding using the following code:
var encrypted = Crypto.AES.encrypt("it was Professor Plum in the library with the candlestick",
key,
{ mode: new Crypto.mode.CBC });
var encryptedString = Crypto.util.bytesToHex(Crypto.charenc.Binary.stringToBytes(crypted));
However this doesn't decode correctly on the server, my guess is its something to do with the SHA256 but I can't work out what it would be digesting & can't find any documentation. Does anyone know how to perform the encryption in javascript?
You need to do everything the same at both ends. You need the same key. You need the same mode (CBC) you need the same padding (use PKCS7) and you need the same IV.
Check that the actual key you are using is the same at both ends by displaying the hex, after you have run the passphrase through SHA-256. Check the hex for the IVs as well. Don't use any defaults, but explicitly pick the mode and padding to use.
If you think that it is the PBE/SHA-256 that is going wrong then you might want to look at how your text passphrase is being turned into bytes. Again, check the hex at both sides before it is passed to SHA-256. Converting text to bytes is a common source of errors. You need to be very sure what stringToBytes() is doing and that whatever you are using on the Java side is doing exactly the same.
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