I have a stringBuilder message appended with "||" symbol.(Ex: Hi||How||are||26 04 2016||finish) i have to encrypt the message and send it to the server using AES and decrypt the same at the server side. Can anyone help me out in solving this?
You can encrypt and decrypt like this:
public class AES {
public static byte[] encrypt(String key, String initVector, String value) {
try {
IvParameterSpec vector = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, vector);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string: "+ Base64.encodeBase64(encrypted));
return Base64.encodeBase64(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String key, String initVector, byte[] encrypted) {
try {
IvParameterSpec vector = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey, vector);
byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String key = "Foo12345Bar67890"; // 128 bit key
String initVector = "RandomInitVector"; // 16 bytes IV
StringBuilder sb = new StringBuilder("Hi||How||are||26 04 2016||finish"); //Your Text here
byte[] encryptedBytes = encrypt(key, initVector, sb.toString());
System.out.println(decrypt(key, initVector,encryptedBytes));
}
}
Related
I am currently using Cipher cipher = Cipher.getInstance ("AES / CBC / PKCS5Padding") on my Android app.
Those responsible for the security of the app tell me this: "It should also be noted that AES encryption is secure when it is not AES CBC.", so they want me to modify the algorithm.
I tried AES/GCM/NoPadding and AES/CTR/PKCS5Padding, if I uninstall the old version and install it again, the app works, but if I install it on top of a version with CBC I get the following error: javax.crypto.BadPaddingException: pad block corrupted
How can I solve this? I am afraid that if I update the app that is in the store, this error will happen to end users.
Notes:
public static String encrypt (String plaintext, String pwd) {
try {
byte [] salt = generateSalt ();
SecretKey key = deriveKey (salt, pwd);
Cipher cipher = Cipher.getInstance (CIPHER_ALGORITHM);
byte [] iv = generateIv (cipher.getBlockSize ());
IvParameterSpec ivParams = new IvParameterSpec (iv);
cipher.init (Cipher.ENCRYPT_MODE, key, ivParams);
byte [] cipherText = cipher.doFinal (plaintext.getBytes ("UTF-8"));
if (salt! = null) {
return String.format ("% s% s% s% s% s", toBase64 (salt), DELIMITER,
toBase64 (iv), DELIMITER, toBase64 (cipherText));
}
return String.format ("% s% s% s", toBase64 (iv), DELIMITER,
toBase64 (cipherText));
} catch (GeneralSecurityException e) {
throw new RuntimeException (e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException (e);
}
}
public static String decrypt (byte [] cipherBytes, SecretKey key, byte [] iv) {
try {
Cipher cipher = Cipher.getInstance (CIPHER_ALGORITHM);
IvParameterSpec ivParams = new IvParameterSpec (iv);
cipher.init (Cipher.DECRYPT_MODE, key, ivParams);
byte [] plaintext = cipher.doFinal (cipherBytes);
String plainrStr = new String (plaintext, "UTF-8");
return plainrStr;
} catch (GeneralSecurityException e) {
throw new RuntimeException (e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException (e);
}
}
etc...
Update!
I decided to make the code cleaner and here it is for you to understand. My goal was to replace "AES / CBC / PKCS7Padding" with "AES / GCM / NoPadding", as they consider AES with CBC unsafe :(
Questions that arose for this GCM implementation: do I have to use GCMParameterSpec on the cipher? Do I need to import the BouncyCastle provider?
public static final String PBKDF2_DERIVATION_ALGORITHM = "PBKDF2WithHmacSHA1";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
//private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
private static String DELIMITER = "]";
private static final int PKCS5_SALT_LENGTH = 8;
private static SecureRandom random = new SecureRandom();
private static final int ITERATION_COUNT = 1000;
private static final int KEY_LENGTH = 256;
public static String encrypt(String plaintext, String pwd) {
byte[] salt = generateSalt();
SecretKey key = deriveKey(pwd, salt);
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
byte[] iv = generateIv(cipher.getBlockSize());
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivParams);
byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF-8"));
return String.format("%s%s%s%s%s", toBase64(salt), DELIMITER, toBase64(iv), DELIMITER, toBase64(cipherText));
} catch (GeneralSecurityException | UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static String decrypt(String ciphertext, String pwd) {
String[] fields = ciphertext.split(DELIMITER);
if (fields.length != 3) {
throw new IllegalArgumentException("Invalid encypted text format");
}
byte[] salt = fromBase64(fields[0]);
byte[] iv = fromBase64(fields[1]);
byte[] cipherBytes = fromBase64(fields[2]);
SecretKey key = deriveKey(pwd, salt);
try {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivParams);
byte[] plaintext = cipher.doFinal(cipherBytes);
return new String(plaintext, "UTF-8");
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
private static byte[] generateSalt() {
byte[] b = new byte[PKCS5_SALT_LENGTH];
random.nextBytes(b);
return b;
}
private static byte[] generateIv(int length) {
byte[] b = new byte[length];
random.nextBytes(b);
return b;
}
private static SecretKey deriveKey(String pwd, byte[] salt) {
try {
KeySpec keySpec = new PBEKeySpec(pwd.toCharArray(), salt, ITERATION_COUNT, KEY_LENGTH);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(PBKDF2_DERIVATION_ALGORITHM);
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
return new SecretKeySpec(keyBytes, "AES");
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
}
private static String toBase64(byte[] bytes) {
return Base64.encodeToString(bytes, Base64.NO_WRAP);
}
public static byte[] fromBase64(String base64) {
return Base64.decode(base64, Base64.NO_WRAP);
}
a i need help to decrypt values generated in Android Java App on Flutter.
I need a class who this but in Dart/Flutter:
public class TrippleDes {
// public static String ALGO = "DESede/CBC/PKCS7Padding";
public static String ALGO = "DESede/ECB/PKCS7Padding";
public static String _encrypt(String message, String secretKey) throws Exception {
Cipher cipher = Cipher.getInstance(ALGO);
cipher.init(Cipher.ENCRYPT_MODE, getSecreteKey(secretKey));
byte[] plainTextBytes = message.getBytes("UTF-8");
byte[] buf = cipher.doFinal(plainTextBytes);
byte[] base64Bytes = Base64.encode(buf, Base64.DEFAULT);
String base64EncryptedString = new String(base64Bytes);
return base64EncryptedString;
}
public static String _decrypt(String encryptedText, String secretKey) throws Exception {
byte[] message = Base64.decode(encryptedText.getBytes(), Base64.DEFAULT);
Cipher decipher = Cipher.getInstance(ALGO);
decipher.init(Cipher.DECRYPT_MODE, getSecreteKey(secretKey));
byte[] plainText = decipher.doFinal(message);
return new String(plainText, "UTF-8");
}
public static SecretKey getSecreteKey(String secretKey) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] digestOfPassword = md.digest(secretKey.getBytes("utf-8"));
byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
SecretKey key = new SecretKeySpec(keyBytes, "DESede");
return key;
}
}
Im trying to decrypt the encrypted xml file. Im getting it as a inputstream as follows.I have the correct encrypt key. but each time my program returns empty string. Every time i enter the correct key. but each time it returns Badpadding Exception.
try{
InputStream is = new ByteArrayInputStream(decryption.getFileData().getBytes());
String xmlEncryptedStr = getStringFromInputStream(is);
String xmlStr = CipherUtils.decrypt(xmlEncryptedStr, new Long(key));
.......
here is my CipherUtils.java class
.........
public static String decrypt(String strToDecrypt,Long key)
{
String keyString=String.format("%016d", key);
//System.out.println("decrypt keyString :"+keyString);
return decrypt(strToDecrypt, keyString.getBytes());
}
public static String decrypt(String strToDecrypt,byte[] key)
{
if(strToDecrypt==null)
return strToDecrypt;
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
final String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
System.out.println("CipherUtils.decryptedString :"+decryptedString);
return decryptedString;
}
catch (Exception e)
{
log.error("Ops!", e);
}
return null;
}
.......
For more information here is my encrypting code
public static String encrypt(String strToEncrypt,Long key)
{
String keyString=String.format("%016d", key);
//System.out.println("encrypt keyString :"+keyString);
return encrypt(strToEncrypt,keyString.getBytes());
}
public static String encrypt(String strToEncrypt,byte[] key)
{
if(strToEncrypt==null)
return strToEncrypt;
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
// System.out.println("CipherUtils.encrypt :"+encryptedString);
return encryptedString;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
I am sorry I couldn't comment so I am writing in answers section.
I faced this issue when I was using different keys though I was passing the same but i used CBC methodology.
Just to note that have you checked that encryption is also done by the AES/ECB/PKCS5Padding and not other format like AES/CBC/PKCS5Padding
Also check if key format for encryption is also having the same format like %016d of your keyValue. Also the key is 16 char long.
I created a simple AES and DESede encryption utility and it worked fine.
private static final byte[] keyValue = new String(
"CjxI&S#V&#DSA_S0dA-SDSA$").getBytes();
public static void main(String[] args) throws Exception {
Client cli = new Client();
System.out.println(cli.encrypt("your password for encryption"));
Client cli1 = new Client();
System.out.println(cli1.decrypt("fTsgVQtXvv49GynHazT4OGZ4Va1H57d+6AM+44Ex040="));
}
public String encrypt(String Data) throws Exception {
Key key = new SecretKeySpec(keyValue, "AES");
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = DatatypeConverter.printBase64Binary(encVal);
// String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
public String decrypt(String encryptedData) throws Exception {
Key key = new SecretKeySpec(keyValue, "AES");
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = DatatypeConverter
.parseBase64Binary(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
I am using this method to decrypt my incoming messages:
private static String decrypt(String key, String initVector, String dataToDecrypt) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
String safeString = dataToDecrypt.replace('-', '+').replace('_', '/');
byte[] decodedString = Base64.decodeBase64(safeString);
byte[] original = cipher.doFinal(decodedString);
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
However, my Android app crashes, showing the following exception:
java.lang.NoSuchMethodError: No static method
decodeBase64(Ljava/lang/String;)[B in class
Lorg/apache/commons/codec/binary/Base64; or its super classes
(declaration of 'org.apache.commons.codec.binary.Base64' appears in
/system/framework/ext.jar)
accordingly, the method decodeBase64 takes base64string, but I pass string. Here comes my question:
How to convert String to base64string ?!
Please note that I am trying to DECODE not ENCODE. Almost all the solutions provided are for the encoding part which is not my worry.
P.S.: I am developing an Android-app on Android-Studio
try this:
Base64.encodeToString(mStringToEncode.getBytes(), Base64.NO_WRAP)
it exist many encoding mode use autocompletion to see more Base64.NO_WRAP, Base64.CRLF, etc...
you need to import package:
import android.util.Base64;
public static String toBase64(String value){
if (value == null)
value = "";
return Base64.encodeToString(value.trim().getBytes(), android.util.Base64.DEFAULT);
}
Have you check this answer
// decode data from base 64
private static byte[] decodeBase64(String dataToDecode)
{
byte[] dataDecoded = Base64.decode(dataToDecode, Base64.DEFAULT);
return dataDecoded;
}
//enconde data in base 64
private static byte[] encodeBase64(byte[] dataToEncode)
{
byte[] dataEncoded = Base64.encode(dataToEncode, Base64.DEFAULT);
return dataEncoded;
}
Try this code
private static String encryptNew(String key, String initVector, String dataToEncrypt) throws Exception{
byte[] plainTextbytes = dataToEncrypt.getBytes("UTF-8");
byte[] keyBytes = key.getBytes("UTF-8");
byte[] IvkeyBytes = initVector.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(IvkeyBytes);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
plainTextbytes = cipher.doFinal(plainTextbytes);
return Base64.encodeToString(plainTextbytes, Base64.DEFAULT);
}
private static String decrypt(String key, String initVector, String dataToDecrypt) {
try {
byte[] cipheredBytes = Base64.decode(dataToDecrypt, Base64.DEFAULT);
byte[] keyBytes = key.getBytes("UTF-8");
byte[] IvkeyBytes = initVector.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
SecretKeySpec secretKeySpecy = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(IvkeyBytes);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpecy, ivParameterSpec);
cipheredBytes = cipher.doFinal(cipheredBytes);
return new String(cipheredBytes,"UTF-8");
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
I have algorithm of encryption\ decryption files:
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = new SecureRandom();
sr.setSeed(seed);
kgen.init(sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
It works great, but on Android 4.4 (api 19) I have strangely exception
javax.crypto.BadPaddingException: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
What is it?
Here what I got: http://www.logikdev.com/2010/11/01/encrypt-with-php-decrypt-with-java/
public class AES2 {
private static final String TRANSFORMATION = "AES/CFB8/NoPadding";
private static final String ALGO_MD5 = "MD5";
private static final String ALGO_AES = "AES";
/**
* See http://www.logikdev.com/2012/12/12/md5-generates-31-bytes-instead-of-32/ form more detail.
*
* #param input
* #return
* #throws NoSuchAlgorithmException
*/
private static String md5(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance(ALGO_MD5);
byte[] messageDigest = md.digest(input.getBytes());
BigInteger number = new BigInteger(1, messageDigest);
return String.format("%032x", number);
}
public static String decrypt(String encryptedData, String initialVectorString, String secretKey) {
String decryptedData = null;
try {
String md5Key = md5(secretKey);
SecretKeySpec skeySpec = new SecretKeySpec(md5Key.getBytes(), ALGO_AES);
IvParameterSpec initialVector = new IvParameterSpec(initialVectorString.getBytes());
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, initialVector);
byte[] encryptedByteArray = Base64.decode(encryptedData.getBytes(), Base64.DEFAULT);
byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray);
decryptedData = new String(decryptedByteArray);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decryptedData;
}
}
So you have to create a initialVectorString (example: "fedcba9876543210"). Hope this help.