I found on Google this code for encrypt/decrypt a string in Java:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
byte[] input = "test".getBytes();
byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
System.out.println(new String(input));
// encryption pass
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
ctLength += cipher.doFinal(cipherText, ctLength);
System.out.println(new String(cipherText));
System.out.println(ctLength);
// decryption pass
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] plainText = new byte[cipher.getOutputSize(ctLength)];
int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0);
ptLength += cipher.doFinal(plainText, ptLength);
System.out.println(new String(plainText));
System.out.println(ptLength);
And this is the output (screenshot because I can't copy-paste some characters): output screenshot
My question is: Why the first input "test" is different from the second (decrypted) "test"? I need this code to encrypt a password and save it on a TXT file and then read this encrypted password from the TXT file and decrypt it.. But if these two outputs are different I can't do this. Second question: Is it possible to exclude ";" from the encrypted text? Can someone help me, please? Thanks!
If you read the documentation for getOutputSize()
then you will see that it returns the maximum amount of plaintext to expect. The cipher
instance cannot know how much padding is added, so it guesses high. You will have to resize the byte array when you are using ECB or CBC mode (or any other non-streaming mode).
System.out.println(ctLength);
As you can see, ctLength
does have the correct size. Use Arrays.copyOf(plainText, ptLength)
to get the right number of bytes, or use the four parameter String
constructor (new String(plainText, 0, ptLength, StandardCharsets.UTF_8)
) in case you're just interested in the string.
The ciphertext consists of random characters. It actually depends on your standard character set what you see on the screen. If you really need text, then you can base 64 encode the ciphertext.
ECB mode encryption is not suitable to encrypt strings. You should try and use a different mode that includes setting / storing an IV.
I'd use new String(StandardCharsets.UTF_8)
and String#getBytes(StandardCharsets.UTF_8)
to convert to and from strings. If you don't specify the character set then it uses the system default character set, and that means decrypting your passwords won't work on all systems. The allowed characters also differ with Linux & Android defaulting on UTF-8 while Java SE on Windows (still?) defaults to the Windows-1252 (extended Western-Latin) character set.
There is absolutely no need to use the Bouncy Castle provider for AES encryption (the compatible padding string is "PKCS5Padding"
).
Please don't grab random code samples from Google. You need to understand cryptography before you start implementing it. The chances that you grab a secure code sample is practically zero unfortunately.