I'm using this code for DES-encryption: How do I use 3des encryption/decryption in Java?
Now, I want to encrypt a byte array with this. How can I do that?
I have changed the name of algo from DESede to DES and am obviously using an 8-byte key (not 24).
Cipher#doFinal takes and returns byte[]. The only thing that you need to do is removing the additional encoding steps like
message.getBytes("utf-8") // before encryption
and
new String(plainText, "UTF-8") // after decryption
Obviously, you need to change the method signature from String to byte[] for both encryption and decryption.
Related
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 tried many answers from SO and all over the web but still without success.
I use following tool to encrypt.
text to encrypt: tom
key: exo123exo1exo123
input (textfield or selected file above) is: text/binary
Convert output to: [i leave this unselected]
Mode: CTR
Ciphers: Rijndael-128 and Rijndael-256
After getting result I move here:
and encode it with base64.
Then I copy string and send it as a parameter to my function:
public String authenticate(String base64EncodedData){
byte[] input = Base64.decodeBase64(base64EncodedData);
byte[] ivBytes = "1234567812345678".getBytes();
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(
Cipher.DECRYPT_MODE,
new SecretKeySpec("exo123exo1exo123".getBytes(), "AES"),
new IvParameterSpec(ivBytes)
);
byte[] plainText = new byte[cipher.getOutputSize(input.length)];
int plainTextLength = cipher.update(input, 0, input.length, plainText, 0);
plainTextLength += cipher.doFinal(plainText, plainTextLength);
return new String(plainText);
}
Result I got is always something similar to this (no matter if I use Rijndael-128 or 256 encrypted string):
.�v�Y�
When I try to return input value - I get the encrypted string. So base64 works just fine.
What I do wrong?
Am slowly getting mad here.
Thank you.
There are some problem with your assumptions and your code:
The output of the first tool is already Base 64 encoded. RIJNDAEL-128: r0GR and RIJNDAEL-256: yAVy. It doesn't need to be encoded a second time. It automatically selects this option, because binary data cannot be printed.
There is no native Rijndael-256 in Java, you will have to use BouncyCastle for this. Rijndael-128 is supposed to be AES which means that both have a block size of 128-bit.
The IV almost certainly needs to consist of zero bytes. For example:
byte[] ivBytes = new byte[16];
Arrays.fill(ivBytes, (byte)0); // might not be necessary
Note that CTR mode doesn't use an IV, but rather a nonce.
Always specify an encoding when retrieving bytes: "exo123exo1exo123".getBytes("UTF-8"). It is probably best to use UTF-8 everywhere. If you send data across systems that use different system encodings, it will lead to hard to find problems.
On second look at the online tool is not usable for anything, because it is unclear how it works. What I found:
Any key produces a ciphertext regardless of size, which suggests that the "key" that you enter is actually hashed and there exist a million ways that could be done. I could decrypt it with the above method, so the key is actually uses as-is without hashing. This suggests that the key is filled up with 0x00 bytes until a valid key size. When the key size is too big, it is probably truncated.
Plaintext of 16 characters encrypts to a ciphertext of 16 bytes (encoded 24) and a plaintext of 17 characters encrypts to a ciphertext of 32 bytes (encoded 44). This means that no discernible padding is used which might actually be zero padding.
And here is the deal breaker:
Every time you encrypt something, you get a different ciphertext. In CBC mode it means a random IV is generated before encrypting. The problem is that this IV is not shown. So there is no way to decrypt this fully. So if you encrypt more than 16 characters you can recover all but the first 16 characters when you decrypt it in the way I describe it in the first part of this answer.
You shouldn't make your system dependent on closed source online tools. Write your own encryption tool. Some general advice:
IV should be generated randomly every time you encrypt something. It is not secrect, but should be unique. Simply prepend it to the ciphertext after encryption and slice it off before decryption.
Use an authenticated mode like CCM or GCM where possible. It is harder to do authenticated encryption yourself, but the other way to go would be to use encrypt-then-mac paradigm.
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.
I want to encrypt a image and then decrypt it. Is there any good references or tutorials or sample showing how to convert the image into a string then encrypt the string? Or there are other ways in encrypting the image? As I am a newbie to this and also I have went to search but there aren't any easy examples for me to understand and also to follow.
If I'm not wrong, i have to use the FileInputstream, and the ImageIO, but i do not know how does it fully works. Anyone can guide me? thanks
An image is a binary file, so I don't think it makes much sense to convert to a String for the purpose of encryption. This would add quite a bit of overhead and complexity for no additional benefit.
You should probably just encrypt the binary file directly.
See:
How to encrypt/decrypt a file in Java?
If your question is "how do I perform encryption in Java", then have a look at some stuff I've written on Java cryptography, in partcular the section on symmetric key encryption. Essentially, you create some secret key, which can just be a string of random bytes generated with SecureRandom:
byte[] key = new byte[16];
(new SecureRandom()).nextBytes(key);
Then you construct a Cipher object and init it with the key, then pass it the data you need to encrypt:
public byte[] encryptData(byte[] key, byte[] data) {
Cipher c = Cipher.getInstance("AES/CTR/PKCS5PADDING");
byte[] initialCounter = new byte[16];
c.init(Cipher.ENCRYPT_MODE,
new SecretKeySpec(key, "AES"),
new IvParameterSpec(initialCounter));
byte[] encryptedData = c.doFinal(plaintextData);
return encryptedData;
}
There's nothing necessarily very special about encrypting an image-- it's just a bunch of bytes like anything else at the end of the day.
The main problem with cryptography is that there are various subtleties that you need to understand for it to be secure.
This link here may also help you out alot:
Using AES with Java Technology
NB you wont need to convert it to a String more like a byte array-
I am reading about encryption and having a lot of difficulty understanding these 3 Java statements of an encryption program.
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
encrypted = cipher.doFinal(str.getBytes())
Can somebody help?
In simpler terms,
create a new Encrypting Device using the AES algorithm;
make it ready
get the bytes of the string str and encrypt them; return the result into the encrypted object, whatever that is.
what exactly did you not understand?
cipher = Cipher.getInstance("AES");
Get a Cipher object that can encrypt/decrypt using the AES algorithm. Java's cryptography code is a bit weird - instead of directly creating objects, you generally use a getInstance call with a String argument. (Note that "cipher" means "way of encrypting something".)
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
Tell the cipher that you would like to encrypt something (Cipher.ENCRYPT_MODE), and give it the encryption key skeyspec.
encrypted = cipher.doFinal(str.getBytes())
The way ciphers work is that you feed them chunks of byte data using the update method, which causes the cipher to accumulate the encrypted data within itself. For the final block of data, doFinal is used, which tells the cipher that the encryption process is done. A different method is needed because the cipher often has to pad out the data returned to a particular length. doFinal then returns the final bit of encrypted information.
However, if there is a single readily available chunk of data, you can just call doFinal and it will give you all the encrypted bytes at once. But this explains why the method is called doFinal, not say, "process".
So in summary, the code above creates an AES encryption engine, gives it an encryption key, then uses it to encrypt the String str into the byte array encrypted.
Note that cryptography is very tricky business and very easy to get wrong. There's all kinds of things you need warning about that I haven't touched on because my wrists hurt now. So I would heavily recommend you get a copy of Beginning Cryptography with Java - it's where I learned to understand this stuff.