AESCryptoServiceProvider Java equivalent - java

Is there an equivalent to the aforementioned class in Java? I need a function that is given a string to encrypt, an encryption key, a salt and returns the encrypted string.

Related

Why does my encryption returns weird string of symbols as the encrypted text?

I am creating an algorithm where it has to encrypt and decrypt passwords by using JCE and AES. I will keep the encrypted text into a database, however I'm facing two problems. The first problem being that the encrypted text is returning weird symbols and not letters, like "c~ù▼=¡£¡?Å♠?¡Ç²?", but it returns the correct normal text. The second problem is that the algorithm would return a different encrypted text every time and if I were to save the encrypted text into a database and decrypt it later, would it still work? Or would I have to store the value as byte[] or String.
public static void main(String[] args) throws Exception {
byte[] text1 = "welcome back".getBytes();
byte[] text2 = "hello guys".getBytes();
KeyGenerator gen = KeyGenerator.getInstance("AES");
SecretKey key = gen.generateKey();
Cipher x = Cipher.getInstance("AES");
x.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedText1 = x.doFinal(text1);
byte[] encryptedText2 = x.doFinal(text2);
x.init(Cipher.DECRYPT_MODE,key);
byte[] decryptedText2 = x.doFinal(encryptedText2);
byte[] decryptedText1 = x.doFinal(encryptedText1);
System.out.println(new String(encryptedText1));
System.out.println(new String(encryptedText2));
System.out.println(new String(decryptedText1));
System.out.println(new String(decryptedText2));
}
The results are something like this:
c~ù▼=¡£¡?Å♠?¡Ç²?
àÉ?<-??Yò*?b?]?
welcome back
hello guys
Is there anything I can do to fix these problems? Thank you very much.
Second Problem
The second problem is that the algorithm would return a different encrypted text every time and if I were to save the encrypted text into a database and decrypt it later, would it still work?
Not completely sure I understand what the problem is. At least for the code in your question, for the same key and same input bytes, you'll get the same encrypted bytes out. But you must use the same key, both when encrypting and decrypting. And this means you need to (securely!) store the key somewhere.
If you're worried about seeing different output each time you run your example code, then that's because you generate a new key each time.
This can get complicated though, and I'd like to state I'm not a cryptography expert. I believe to use symmetric encryption properly, you want to avoid the same plain text resulting in the same cipher text. There are also different modes of AES, requiring different approaches. My point is that you should either do a lot of research, or hire an expert (if not both).
First Problem
The first problem being that the encrypted text is returning weird symbols and not letters, like "c~ù▼=¡£¡?Å♠?¡Ç²?", but it returns the correct normal text
Those "weird symbols" are not indicative of a problem. This is the sort of thing you should expect to see when you attempt to decode a random sequence of bytes into characters.
Your code first encodes a sequence of characters (the String) into a sequence of bytes (a byte[]). You then encrypt this sequence of bytes and receive a new essentially random sequence of bytes back. The encrypted bytes do not represent a sequence of characters anymore. Attempting to decode these encrypted bytes into a sequence of characters can yield anything from the charset used, including the "fallback/error" character. This is okay though because, again, the encrypted bytes do not represent a sequence of characters.
When you decrypt the encrypted bytes, you get the original sequence of bytes back. The decrypted bytes do, of course, represent a sequence of characters, and thus can be decoded into those characters. Note you must use the same charset when encoding and decoding the plain text in order to guarantee correctness. To ensure this, you should specify a charset. For example:
// encode
byte[] bytes = "Hello, World!".getBytes(StandardCharasets.UTF_8);
// decode
String string = new String(bytes, StandardCharsets.UTF_8);
Note this does not attempt to decode a sequence of encrypted bytes. It decodes the original bytes, the same bytes you'd get back after decrypting the encrypted bytes.
If you want to view the encrypted bytes as a String, then encoding those bytes into Base64 is a common solution. Base64 can also be used for other non-character bytes, such as image files, or even bytes representing characters.
byte[] bytes = "Hello, World!".getBytes(StandardCharasets.UTF_8);
byte[] encryptedBytes = encrypt(bytes);
String base64Text = Base64.getEncoder().encodeToString(encryptedBytes);
Note if you store the base64Text, then when you go to decrypt, you'll first need to decode the Base64 bytes into the original encrypted bytes.
Most if not all enryptions algorithm and (secure) hash functions just produce bytes, without any encoding as what they are producing is not text but literally just a byte[].
Most of the time these bytes are showns as base64 encoded in a tutorial or when saved in a textual representation - see here on how to do this with Java 8+: https://stackoverflow.com/a/26897706/4934324
Because your algorithm have not any information about your plaintext's Charset. You have to set it when you're getting bytes.
byte[] text1 = "welcome back".getBytes(StandardCharsets.UTF_8);
byte[] text2 = "hello guys".getBytes(StandardCharsets.UTF_8);
And for printing:
System.out.println(new String(encryptedText1, StandardCharsets.UTF_8));
System.out.println(new String(encryptedText2, StandardCharsets.UTF_8));
This approach should work.
But if do you want to see something you can read use Base64 encoder.
System.out.println(Base64.getEncoder().encodeToString(encryptedText1));
System.out.println(Base64.getEncoder().encodeToString(encryptedText2));

How to hash String using SHA-256 with only 32characters?

I am using org.apache.commons.codec.digest.DigestUtils for sha256 implementation like below.
DigestUtils.sha256Hex("myString")
this is returning 64characters hash String. But I need only 32characters hashed String.
How to hash the String value using SHA-256 with only 32 characters hashed value?
As the name SHA-256 implies, the hash consists of 256 bits, i.e. 64 characters (256 / 4 = 64) in the hex representation.
If you want 32 characters, you'd have to use the MD5 algorithm:
DigestUtils.md5Hex("myString")
But if you really need to use 32 characters from a 64 character string, you can use String#substring() - (which I would definitely not recommend, rather use MD5):
String hash64 = "9F86D081884C7D659A2FEAA0C55AD015A3BF4F1B2B0B822CD15D6C15B0F00A08";
String hash32 = hash64.substring(0, 32): // 9F86D081884C7D659A2FEAA0C55AD015

RC4 ENCRYPTION algorithm binary conversion

I was referring this site for RC4 encryption.
there they are getting 2 outputs after encryption one hexadecimal output and other is hexadecimal converted to special characters.
like in the following image
I was able to replicate the hexadecimal output in java.
My problem is:
what type of conversion is this?
It seems to be the characters as obtained by interpreting the bytes as characters encoded using ISO-88659-1.

Hashalgorithm and hashencoding

I am using build in Jboss login-module. It has to encode what user entered as a password and compare with encrypted password in db.
<module-option name="hashAlgorithm" value="MD5"/>
<module-option name="hashEncoding" value="base64"/>
For storing password in db I use following line
newUser.setPassword(DatatypeConverter.printBase64Binary(purePassword.getBytes("UTF-8")));
When I debug my application it appears:
encrypted password from DB = MTIzNDU2Nzg=
encrypted password from
user login = JdVa0oOqQAr0ZMdtcTwHrQ==
Questions:
What is happening? When do jboss use base64 algorithm and when md5
What is the difference between hashAlgorithm and hashEncoding?
What is happening? When do jboss use base64 algorithm and when md5
MD5 is the hash algorithm and Base64 is the output character encoding.
A character encoding is what defines which characters correspond to a byte or series of bytes.
MD5 is a cryptographic hash algorithm that produces a 16-byte output of 8-bit bytes, not characters. Not all 8-bit bytes are printable characters.
Base64 accepts an array of bytes and produces a printable character string. It is generally used the an array of bytes needs to be encoded to a printable character string.
What is the difference between hashAlgorithm and hashEncoding?
Some hash functions allow specification of the hash algorithm hashAlgorithm such as MD5, SHA1, SHA-256, etc that is used to hash the output encoding hashEncoding such as hexadecimal or Base64. This allows one function call to both hash the input with a selected hash algorithm and selected output encoding in one call.

Does an array of bytes with negative values lose information when converted to String?

I've got a code like this where in the encoding i convert the letters to bytes and then flip them with unary bitwise complement ~ at the end convert it to String.
After that i want to decrypt it with a similar method. The problem is that for two similar input Strings (but not the same) i get the same encoded String with the same hashcode.
Does the String(bytes) method lose the information because the bytes are negative or can i retrieve it somehow without changing my encryption part?
thanx
static String encrypt(String s){
byte[] bytes=s.getBytes();
byte[] enc=new byte[bytes.length];
for (int i=0;i<bytes.length;i++){
enc[i]=(byte) ~bytes[i];
}
return new String(enc);
}
static String decrypt(String s){
...
You should never use new String(...) to encode arbitrary binary data. That's not what it's there for.
Additionally, you should only very rarely use the default platform encoding, which is what you get when you call String.getBytes() and new String(byte[]) without specifying an encoding.
In general, encryption converts binary data to binary data. The normal process of encrypting a string to a string is therefore:
Convert the string into bytes with a known encoding (e.g. UTF-8)
Encrypt the binary data
Convert the encrypted binary data back into a string using base64.
Base64 is used to encode arbitrary binary data as ASCII data in a lossless fashion. Decryption is just a matter of reversing the steps:
Convert the base64 text back to a byte array
Decrypt the byte array
Decode the decrypted byte array as a string using UTF-8
(Note that what you've got currently is not really encryption - it's obfuscation at best.)
Your effectively converting arbitrary byte data into a String.
That's not what that constructor is for.
The String constructor that takes a byte[] is meant to convert text in the platform default encoding into a String. Since what you have is not text, the behaviour will be "bad".
If, for example, your platform default encoding is a 8-bit encoding (such as ISO-8859-*), then you'll "only" get random characters.
If your platform default encoding is UTF-8 you'll probably get random characters and some replacement characters for malformed byte sequences.
To summarize: don't do that. I can't tell you what to do instead, since it's not obvious what you're trying to achieve.

Categories