I am encrypting a string using AES but the encrypted string contains \n and \r at the end.
public class AESImpl {
private static String decryptedString;
private static String encryptedString;
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, ClassNotFoundException {
String strToEncrypt = "This text has to be encrypted";
SecretKey secretKey = generateSecretKey();
String encryptStr = encrypt(strToEncrypt, secretKey);
System.out.println("Encrypted String : " + encryptStr + "It should not come in new line");
String decryptStr = decrypt(encryptStr, secretKey);
System.out.println("Decrypted String : " + decryptStr);
}
private static SecretKey generateSecretKey() throws NoSuchAlgorithmException, IOException {
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);
SecretKey sk = kg.generateKey();
String secretKey = String.valueOf(Hex.encodeHex(sk.getEncoded()));
System.out.println("Secret key is " + secretKey);
return sk;
}
public static String encrypt(String strToEncrypt, SecretKey secretKey) {
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
encryptedString = new String(Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes())));
} catch (Exception e) {
System.out.println("Error while encrypting: " + e.toString());
}
return encryptedString;
}
public static String decrypt(String strToDecrypt, SecretKey secretKey) {
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
} catch (Exception e) {
System.out.println("Error while decrypting: " + e.toString());
}
return decryptedString;
}
}
Output
Secret key is 2df36561b09370637d35b4a310617e60
Encrypted String : TUDUORnWtsZFJAhBw1fYMF9CFExb/tSsLeDx++cpupI=
It should not come in new line
Decrypted String : This text has to be encrypted
Actually, the encrypted string is TUDUORnWtsZFJAhBw1fYMF9CFExb/tSsLeDx++cpupI=/r/n.
Do I need to explicitly replace the \r and \n from encrypted string or I have done something wrong in the above code?
Adding
Base64.encodeBase64String(hashPassword,Base64.NO_WRAP) removes the \n.
By default it uses Base64.DEFAULT which adds newline.
click here: source
click here: Main source
Actually,I was using apache commons-codec-1.4.0.jar to encode the string. Changing it to higher version solves the issue.
The behaviour of encodeBase64String method has been changed from multi-line chunking (commons-codec-1.4) to single-line non-chunking (commons-codec-1.5).
Please follow the link for more details.
http://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/binary/Base64.html
It seems like the base64 encoding standard requires that there is a line break at least every 75 characters. My guess is that the base64 encoding function is adding this automatically, you haven't done anything wrong, and that it's fine to leave it in or remove it. According to the link below, base64 decoding functions should ignore line breaks, so whether you remove it or not is up to you...
See here for someone else who's run into this problem, and a quote from the base64 standard: http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001AprJun/0183.html
Simply perform encryptedString = encryptedString.replaceAll("(?:\\r\\n|\\n\\r|\\n|\\r)", "") on the encoded string.
It works fine when you try do decode it back to bytes. I did test it several times with random generated byte arrays. Obviously decoding process just ignores the newlines either they are present or not. I tested this "confirmed working" by using com.sun.org.apache.xml.internal.security.utils.Base64 Other encoders not tested.
This is the code block which adds \n at the end ofthe encoded string
keyBytes = secret_key.substring(0, 32).toByteArray(charset("UTF8"))
val skey = SecretKeySpec(keyBytes, "AES")
val input = strToEncrypt.toByteArray(charset("UTF8"))
synchronized(Cipher::class.java) {
val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, skey)
val cipherText = ByteArray(cipher.getOutputSize(input.size))
var ctLength = cipher.update(
input, 0, input.size,
cipherText, 0
)
ctLength += cipher.doFinal(cipherText, ctLength)
return String(
android.util.Base64.encode(cipherText, 1)
)
}
and THIS IS THE CODE BELOW WORKS FINE !!
val algorithm = "AES"
val keyValue = secret_key.substring(0, 32).toByteArray(charset("UTF8"))
val key: Key = SecretKeySpec(keyValue, algorithm)
val c: Cipher = Cipher.getInstance(algorithm, "BC")
c.init(Cipher.ENCRYPT_MODE, key);
val encValue: ByteArray =
c.doFinal(
strToEncrypt.toByteArray()
)
return Base64.getEncoder().encodeToString(encValue)
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am trying to create a simple AES encryption/decryption module for use in a larger project, but I'm having trouble getting the AES methods to work. I've done a good amount of research, but I can't figure out what is going wrong within my code (I'm suspecting something simple that I'm missing).
Main:
public static byte[] genKey() {
// Create key generator
KeyGenerator keyGen;
try {
keyGen = KeyGenerator.getInstance("AES");
}
catch(GeneralSecurityException e) {
e.printStackTrace();
return null;
}
// Create random byte generator
SecureRandom r = new SecureRandom();
// Initialize key generator
keyGen.init(256, r);
SecretKey key = keyGen.generateKey();
return key.getEncoded();
}
public static void main(String[] args) throws GeneralSecurityException {
// write your code here
// Create AES handler
AES aes = new AES();
// Generate key
byte[] key = genKey();
// Set key for AES
aes.setKey(key);
Scanner in = new Scanner(System.in);
System.out.print("Please enter a phrase to encrypt: ");
String input = in.nextLine();
// Encrypt phrase
byte[][] encrypted = aes.encrypt(input);
// Decrypt phrase
String plaintext = aes.decrypt(encrypted[0], encrypted[1]);
// Print results
System.out.println("Ciphertext: " + encrypted[1]);
System.out.println("Plaintext: " + plaintext);
}
AES:
private Cipher cipher;
private SecretKey key;
public AES() {
// Create Cipher
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
}
public void setKey(byte[] key) {
this.key = new SecretKeySpec(key, "AES");
}
public byte[][] encrypt(String plaintext) throws GeneralSecurityException {
System.out.println("Using key : " + key.getEncoded() + " to encrypt");
byte[][] values = new byte[2][];
// Decode plaintext into bytes
byte[] decodedPlaintext = new byte[0];
try {
decodedPlaintext = plaintext.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// Generate an IV and set up the Cipher to encrypt
byte[] ivBytes = new byte[16];
SecureRandom rand = new SecureRandom();
rand.nextBytes(ivBytes);
IvParameterSpec iv = new IvParameterSpec(ivBytes);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
// Encrypt decoded plaintext
byte[] ciphertext = cipher.doFinal(decodedPlaintext);
values[0] = ivBytes;
values[1] = ciphertext;
return values;
}
public String decrypt(byte[] ivBytes, byte[] ciphertext) throws GeneralSecurityException {
System.out.println("Using key " + key.getEncoded() + " to decrypt");
// Set up cipher to decrypt
IvParameterSpec iv = new IvParameterSpec(ivBytes);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decodedPlaintext = cipher.doFinal(ciphertext);
// Encode plaintext
String plaintext = Base64.getEncoder().encodeToString(decodedPlaintext);
return plaintext;
}
Results:
Please enter a phrase to encrypt: test
Using key : [B#442d9b6e to encrypt
Using key [B#3d012ddd to decrypt
Ciphertext: [B#515f550a
Plaintext: dGVzdA==
I don't understand why my encryption/decryption seem to be using different keys when I only set the key once in the beginning. Am I creating a key wrong?
I've also tried:
byte[] key = new byte[32];
SecureRandom r = new SecureRandom();
r.nextBytes(key);
// Set key for AES
aes.setKey(key);
And run into the same issue.
If you trace this.key in AES class all the way through encode and decode using Arrays.toString(this.key.getEncoded()) it does look like it's using a persistent key.
this.key.getEncoded().toString()) returns a different representation each time but it seems like the actual byte array is the same.
I replaced
String plaintext = Base64.getEncoder().encodeToString(decodedPlaintext);
with
String plaintext = new String(decodedPlaintext, StandardCharsets.UTF_8);
and it seemed to work.
I have the following code:
public static void main(final String[] args) throws Exception {
try {
String textToEncrypt = "{asdfsad asdf;ls kasdf asdlfjaslfjalksdfjlkadsjflkasfjl;kasj alkdfjaslkfj \r\n" +
"asdfjl;asdfjlasdjfdasfjfdosafjadsf \r\n" +
"as;ldfjal;ksfjlkdasfjadsf" +
"a;ldfjal;ksfjds" +
"}";
String secret = "SOME_SECRET";
String escapedTextToEncrypt = StringEscapeUtils.escapeJava(textToEncrypt);
System.out.println(escapedTextToEncrypt);
String encryptedText = SomeEncryption.encrypt(escapedTextToEncrypt, secret);
encryptedText = encryptedText.concat("3asdasfd"); // CHANGING THE ENCRYPTED TEXT!
System.out.println("Encrypted Text :" + encryptedText);
System.out.println("Decrypted Text :" + SomeEncryption.decrypt(encryptedText, secret)); // THIS WORKS!!
}catch(Throwable t){
t.printStackTrace();
}
}
I am using AES encryption algorithm and apache commons codec. Curiously, when I append a string to the encrypted text, it is still able to decrypt it with no problems. Am I missing something here?
More details:
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2withHmacSHA1");
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
EDIT:
I am using StringEscapeUtils from apache commons lang library.
We found the answer to this question. If I add any string at the end of the encrypted string then it works. But if it is inserted in the middle then it fails.
encryptedText = new StringBuilder(encryptedText).insert(0, "xyz").toString();
The above fails.
I try to do a PHP openssl_encrypt aes-256-cbc with OPENSSL_RAW_DATA in java 6 without success. I found some topic about this, but I'ved successful only to do it in aes-128-cbc without raw_data. The best topic I founded about this it's : AES-256 CBC encrypt in php and decrypt in Java or vice-versa
But the raw_data doesn't work and the 256 bits key is randomly generated.
In fact the Php version is :
<?php>
openssl(
"hello",
"aes-256-cbc",
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
OPENSSL_RAW_DATA,
"aaaaaaaaaaaaaaaa"
)
?>
And I actually have this :
public static void main(String[] args) {
try {
// 128 bits key
openssl_encrypt("hello", "bbbbbbbbbbbbbbbb", "aaaaaaaaaaaaaaaa");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static String openssl_encrypt(String data, String strKey, String strIv) throws Exception {
Base64 base64 = new Base64();
Cipher ciper = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec key = new SecretKeySpec(strKey.getBytes("UTF-8"), "AES");
IvParameterSpec iv = new IvParameterSpec(strIv.getBytes("UTF-8"), 0, ciper.getBlockSize());
// Encrypt
ciper.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] encryptedCiperBytes = base64.encode((ciper.doFinal(data.getBytes())));
String s = new String(encryptedCiperBytes);
System.out.println("Ciper : " + s);
return s;
}
After few modification and some testing I found it :
private static String openssl_encrypt(String data, String strKey, String strIv) throws Exception {
Base64 base64 = new Base64();
Cipher ciper = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec key = new SecretKeySpec(strKey.getBytes(), "AES");
IvParameterSpec iv = new IvParameterSpec(strIv.getBytes(), 0, ciper.getBlockSize());
// Encrypt
ciper.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] encryptedCiperBytes = ciper.doFinal(data.getBytes());
String s = new String(encryptedCiperBytes);
System.out.println("Ciper : " + s);
return s;
}
openssl_encrypt in PHP don't convert his result in base64, and I also use getBytes() without param cause, for some keys, I had an error about the key's lentgh.
So this method do the same thing than :
<?php>
openssl_encrypt(data, "aes-256-cbc", key, OPENSSL_RAW_DATA, iv);
?>
I've wrote a method to encrypt/decrypt a string. Encryption is happening successfully but I cannot manage to make the decryption work... This is the code I have written:
public String encrypt(String a, int x) {
String ret = "";
String text = a;
String key = "Bar12345Bar12345"; // 128 bit key
try {
// Create key and cipher
Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
if(x == 0) { //x==0 means I want to encrypt
// encrypt the text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(text.getBytes());
ret =new String(encrypted);
}
else { //if not 0 I want to decrypt
// decrypt the text
byte[] encrypted = text.getBytes(Charset.forName("UTF-8"));
cipher.init(Cipher.DECRYPT_MODE, aesKey);
String decrypted = new String(cipher.doFinal(encrypted));
ret=decrypted;
}
} catch(Exception e) {
e.printStackTrace();
}
return ret;
}
I think the problem arise when I'm trying to convert the string into byte array. The error I get is:
javax.crypto.BadPaddingException: Given final block not properly padded
So what is the problem ? If I am not converting the string into byte array in right way, how should I do it ?
I would like to encrypt 3 strings using AES 128 in Java / Grails, and using the code below, but i get the error "An error occurred when encrypting", can someone tell me what is wrong with my code, how to fix it. thanks in advance and to Stackoverflow.
String url = "https://someurl.com"
String token = createToken(bookNumber, invNumber, cusNumber)
url += '?ref=' + token
class AesEncryptor {
static byte[] encrypt(String clearText) {
byte[] encrypted = null
try {
byte[] iv = new byte[16]
Arrays.fill(iv, (byte) 0)
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING")
encrypted = cipher.doFinal(clearText.getBytes("UTF-8"))
}
catch (Exception e) {
log.error "An error occurred when encrypting", e
}
encrypted
}
/**
* Creates a token.
* #return
*/
static String createToken(final String bookNumber, final String invNumber, final String cusNumber) {
String data = bookNumber + invNumber + cusNumber
String token = URLEncoder.encode(Base64.encodeBase64String(encrypt(data)), "UTF-8")
token
}
}
the error i get:
java.lang.IllegalStateException: Cipher not initialized
at javax.crypto.Cipher.checkCipherState(Cipher.java:1672)
at javax.crypto.Cipher.doFinal(Cipher.java:2079)
at javax.crypto.Cipher$doFinal$1.call(Unknown Source)
cipher.init method call is missed in your code. Check the below code.
public byte[] encrypt(byte[] data, byte[] key) {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
return cipher.doFinal(data);
}
For decrypt have to change mode to Cipher.DECRYPT_MODE