AES encryption with String IV - java

now i am using scotabb libs AESCryptor for AES encryption in my android project,
i really need the string IV bcs my other project in swift(IOS) and the webservice (c#) using AES encrypt/decrypt 256 with String IV.
but in the scotabb aesencriptor using blank IV.
is it possible to change the blank IV(bytes) to the 16-length string ?
and how to do that ?
this is my class
public final class AEScrypt{
private static final String TAG = "AESCrypt";
//AESCrypt-ObjC uses CBC and PKCS7Padding
private static final String AES_MODE = "AES/CBC/PKCS7Padding";
private static final String CHARSET = "UTF-8";
//AESCrypt-ObjC uses SHA-256 (and so a 256-bit key)
private static final String HASH_ALGORITHM = "SHA-256";
//AESCrypt-ObjC uses blank IV (not the best security, but the aim here is compatibility)
private static final byte[] ivBytes = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//togglable log option (please turn off in live!)
public static boolean DEBUG_LOG_ENABLED = false;
private static SecretKeySpec generateKey(final String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
final MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
byte[] bytes = password.getBytes("UTF-8");
digest.update(bytes, 0, bytes.length);
byte[] key = digest.digest();
log("SHA-256 key ", key);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
return secretKeySpec;
}
public static String encrypt(final String password, String message)
throws GeneralSecurityException {
try {
final SecretKeySpec key = generateKey(password);
log("message", message);
byte[] cipherText = encrypt(key, ivBytes, message.getBytes(CHARSET));
//NO_WRAP is important as was getting \n at the end
String encoded = Base64.encodeToString(cipherText, Base64.NO_WRAP);
log("Base64.NO_WRAP", encoded);
return encoded;
} catch (UnsupportedEncodingException e) {
if (DEBUG_LOG_ENABLED)
Log.e(TAG, "UnsupportedEncodingException ", e);
throw new GeneralSecurityException(e);
}
}
public static byte[] encrypt(final SecretKeySpec key, final byte[] iv, final byte[] message)
throws GeneralSecurityException {
final Cipher cipher = Cipher.getInstance(AES_MODE);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] cipherText = cipher.doFinal(message);
log("cipherText", cipherText);
return cipherText;
}
public static String decrypt(final String password, String base64EncodedCipherText)
throws GeneralSecurityException {
try {
final SecretKeySpec key = generateKey(password);
log("base64EncodedCipherText", base64EncodedCipherText);
byte[] decodedCipherText = Base64.decode(base64EncodedCipherText, Base64.NO_WRAP);
log("decodedCipherText", decodedCipherText);
byte[] decryptedBytes = decrypt(key, ivBytes, decodedCipherText);
log("decryptedBytes", decryptedBytes);
String message = new String(decryptedBytes, CHARSET);
log("message", message);
return message;
} catch (UnsupportedEncodingException e) {
if (DEBUG_LOG_ENABLED)
Log.e(TAG, "UnsupportedEncodingException ", e);
throw new GeneralSecurityException(e);
}
}
public static byte[] decrypt(final SecretKeySpec key, final byte[] iv, final byte[] decodedCipherText)
throws GeneralSecurityException {
final Cipher cipher = Cipher.getInstance(AES_MODE);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decryptedBytes = cipher.doFinal(decodedCipherText);
log("decryptedBytes", decryptedBytes);
return decryptedBytes;
}
private static void log(String what, byte[] bytes) {
if (DEBUG_LOG_ENABLED)
Log.d(TAG, what + "[" + bytes.length + "] [" + bytesToHex(bytes) + "]");
}
private static void log(String what, String value) {
if (DEBUG_LOG_ENABLED)
Log.d(TAG, what + "[" + value.length() + "] [" + value + "]");
}
private static String bytesToHex(byte[] bytes) {
final char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] hexChars = new char[bytes.length * 2];
int v;
for (int j = 0; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
private AESCrypt() {
}
}

You can change the IV to whatever 16 byte value you want. You can see that a static IV (a bad idea) is defined at the class level as 0x00 * 16. You can replace that byte array with another value, either raw bytes or a decoded hexadecimal or Base64 value, etc.
You should be providing a unique and non-predictable IV for every encryption operation and passing the IV along with the cipher text for use in decryption. The IV does not need to be protected or encrypted and can travel in the clear alongside the cipher text.

Related

Converting a String to byte[] for decryption

im facing a problem in my code.
I want to encrypt the Password from the user and save it to an SQL Database.
The Code im Using to Encrypt the Password with AES:
String key = "1234567890123456"; // 128 bit key
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(Passwort.getBytes());
String verschlüsselt = new String(encrypted);
Now im saving the String "verschlüsselt" to my Database.
In my LoginGUI im getting the String with the Password from the database:
String psswd = res.getString("Passwort"); //Getting the Password from Database and saving it into String
System.out.println(psswd);
The PrintOut is: "!?¿[ŸÊm,r~¤u" which is the correct encrypted password.
Now i'm trying to decrypt the password with following code:
String key = "1234567890123456"; // 128 bit key
cipher.init(Cipher.DECRYPT_MODE, aesKey);
EPasswort = new String(cipher.doFinal(bpsswd)); //Im facing the problem here
I Know that i can't decrypt the String and that I have to convert the String into an byte[].
I've done that in several ways:
byte[] password = psswd.getBytes();
System.out.println(password);
password = psswd.getBytes("UTF-8");
System.out.println(password);
EPasswort = new String(cipher.doFinal(password));
But the Output is always something the decrypter can't work with:
[B#ab33b4
[B#189090b
How do i convert my String with the Password (!?¿[ŸÊm,r~¤u) into an byte[] so my decrypter can work with it?
Thanks for any help.
You should encrypt the String and than save it as a String, in this example I'm using a Base64 encoder and a different cypher but the logic behind is the same. You should save bytes or String instead of using the reference to your bytes, here an example:
#Test
public void testCrypt () {
final String ENCRYPT_ALGO = "AES/GCM/NoPadding";
final int TAG_LENGTH_BIT = 128;
final int IV_LENGTH_BYTE = 12;
final int SALT_LENGTH_BYTE = 16;
final String password = "password";
final byte[] salt = getRandomNonce(SALT_LENGTH_BYTE);
final byte[] iv = getRandomNonce(IV_LENGTH_BYTE);
final SecretKey aesKeyFromPassword = getAESKeyFromPassword(password.toCharArray(), salt);
String msg = "Test";
String out = "";
try {
out = encrypt(ENCRYPT_ALGO, TAG_LENGTH_BIT, iv, aesKeyFromPassword, msg);
} catch (Exception e) {
e.printStackTrace();
}
byte[] plainText = new byte[0];
try {
plainText = decrypt(ENCRYPT_ALGO, TAG_LENGTH_BIT, iv, aesKeyFromPassword, out);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Decrypted " + out + " in: " + new String(plainText, StandardCharsets.ISO_8859_1));
}
following the encrypt method:
private String encrypt(final String ENCRYPT_ALGO, final int TAG_LENGTH_BIT, final byte[] iv,
final SecretKey aesKeyFromPassword, String msg) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
final byte[] pText = msg.getBytes(StandardCharsets.ISO_8859_1);
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
cipher.init(Cipher.ENCRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
final byte[] cipherText = cipher.doFinal(pText);
String out = Base64.getEncoder().encodeToString(cipherText);
System.out.println("Encrypted " + msg + " as: " + out);
return out;
}
private static SecretKey getAESKeyFromPassword(final char[] password, final byte[] salt) {
final int KEY_LENGTH = 128;
final int ITERATION_COUNT = 65536;
try {
final SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
final KeySpec spec = new PBEKeySpec(password, salt, ITERATION_COUNT, KEY_LENGTH);
return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
} catch (final Exception e) {
LOGGER.error(e);
throw new RedException(e);
}
}
private static byte[] getRandomNonce(final int numBytes) {
final byte[] nonce = new byte[numBytes];
new SecureRandom().nextBytes(nonce);
return nonce;
}
Once you save the msgCrypted in db you should retrieve it and process it to decrypt like this:
private byte[] decrypt(final String ENCRYPT_ALGO, final int TAG_LENGTH_BIT, final byte[] iv,
final SecretKey aesKeyFromPassword, String out) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
Cipher dCipher = Cipher.getInstance(ENCRYPT_ALGO);
dCipher.init(Cipher.DECRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
final byte[] plainText = dCipher.doFinal(Base64.getDecoder().decode(out));
return plainText;
}
In the console you should have something like this:
You are printing the reference to the byte array, not the elements.
Run this for demonstration:
public static void main (String [] args) {
String s = "12345678";
byte [] b = s.getBytes ();
System.out.println (b);
for (int i = 0; i < 8; i++) {
System.out.println (b [i]);
}
}
Output:
[B#7a81197d
49
50
51
52
53
54
55
56

AES encryption .Net to Android for mobile

I referred to the below link
AES Encryption .net to swift,
But, applying the same for ANDROID, I am not able to get the correct AES encryption with version(PBKDF2) conversion for my code. NEED HELP.
public static String Encrypt(String PlainText) throws Exception {
try {
byte[] salt = new byte[] { 0x49, 0x76, 0x61, 0x6E, 0x20, 0x4D,
0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 };
System.out.println("Exception setting up cipher: "+pbkdf2("<keyname>",salt.toString(),1024,128));
Cipher _aesCipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
byte[] keyBytes =pbkdf2("<keyname>",salt.toString(),1024,128).getBytes();
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
byte[] iv ="OFRna73m*aze01xY".getBytes();//pbkdf2("<keyname>",salt.toString(),2,64).getBytes();
IvParameterSpec ivSpec = new IvParameterSpec(iv);
_aesCipher.init(1, keySpec, ivSpec);
byte[] plainText = PlainText.getBytes();
byte[] result = _aesCipher.doFinal(plainText);
return Base64.encodeToString(result, Base64.DEFAULT);//Base64.encode(result,1));
} catch (Exception ex1) {
System.out.println("Exception setting up cipher: "
+ ex1.getMessage() + "\r\n");
ex1.printStackTrace();
return "";
}
}
public static String pbkdf2(String password, String salt, int iterations, int keyLength) throws NoSuchAlgorithmException, InvalidKeySpecException {
char[] chars = password.toCharArray();
PBEKeySpec spec = new PBEKeySpec(chars, salt.getBytes(), iterations, keyLength);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = skf.generateSecret(spec).getEncoded();
return toHex(hash);
}
// Converts byte array to a hexadecimal string
private static String toHex(byte[] array) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; i++) {
sb.append(Integer.toString((array[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
Please check below code .
I have created Singletone class for the same so that i can access it anywhere in app.
Below Points Should be same like .net or swift
Important Points are IV , SALT and PASSWORD
Please check this too PBKDF2WithHmacSHA1
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
to generate key we used this
KeySpec spec = new PBEKeySpec(password, salt, 2, 256);
Importnant points are (password, salt,iterantion,bytes) this must be same like other platform which you are using with like .net or swift
public class AesBase64Wrapper {
private static String IV = "it should be same like server or other platform";
private static String PASSWORD = "it should be same like server or other platform";
private static String SALT = "it should be same like server or other platform";
private static volatile AesBase64Wrapper sSoleInstance = new AesBase64Wrapper();
//private constructor.
private AesBase64Wrapper() {
}
public static AesBase64Wrapper getInstance() {
return sSoleInstance;
}
// For Encryption
public String encryptAndEncode(String raw) {
try {
Cipher c = getCipher(Cipher.ENCRYPT_MODE);
byte[] encryptedVal = c.doFinal(getBytes(raw));
//String retVal = Base64.encodeToString(encryptedVal, Base64.DEFAULT);
String retVal = Base64.encodeToString(encryptedVal, Base64.NO_WRAP);
return retVal;
}catch (Throwable t) {
throw new RuntimeException(t);
}
}
public String decodeAndDecrypt(String encrypted) throws Exception {
// byte[] decodedValue = Base64.decode(getBytes(encrypted),Base64.DEFAULT);
byte[] decodedValue = Base64.decode(getBytes(encrypted), Base64.NO_WRAP);
Cipher c = getCipher(Cipher.DECRYPT_MODE);
byte[] decValue = c.doFinal(decodedValue);
return new String(decValue);
}
private String getString(byte[] bytes) throws UnsupportedEncodingException {
return new String(bytes, "UTF-8");
}
private byte[] getBytes(String str) throws UnsupportedEncodingException {
return str.getBytes("UTF-8");
}
private Cipher getCipher(int mode) throws Exception {
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = getBytes(IV);
String xyz = String.valueOf(generateKey());
Log.i("generateKey", xyz);
c.init(mode, generateKey(), new IvParameterSpec(iv));
return c;
}
private Key generateKey() throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
char[] password = PASSWORD.toCharArray();
byte[] salt = getBytes(SALT);
KeySpec spec = new PBEKeySpec(password, salt, 2, 256);
SecretKey tmp = factory.generateSecret(spec);
byte[] encoded = tmp.getEncoded();
byte b = encoded[1];
Log.e("Secrete Key", String.valueOf(encoded));
return new SecretKeySpec(encoded, "CBC");
}
}
In Activity you can use it like
String EncryptString = AesBase64Wrapper.getInstance().encryptAndEncode("hello");
String DecryptString = AesBase64Wrapper.getInstance().encryptAndEncode(EncryptString);
// You will Get Output in Decrypted String

Is there a way to cipher in java/kotlin and decipher in nodejs with AES/CBC?

I try to cipher a text in java and decipher it in nodejs (and vice versa)
I can cipher and decipher in the same language but I can't with them both ...
Here is my code in Kotlin :
#Throws(Exception::class)
fun encrypt(text: String, password: String?): String?
{
if (password == null)
return null
val hash = toHash(password).copyOf(16)
val keySpec = SecretKeySpec(hash, "AES")
val ivSpec = IvParameterSpec(hash)
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec)
val results = cipher.doFinal(text.toByteArray())
return Base64.encodeToString(results, Base64.NO_WRAP or Base64.DEFAULT)
}
#Throws(Exception::class)
fun decrypt(text: String, password: String?): String?
{
if (password == null)
return null
val hash = toHash(password).copyOf(16)
val keySpec = SecretKeySpec(hash, "AES")
val ivSpec = IvParameterSpec(hash)
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec)
return String(cipher.doFinal(Base64.decode(text, Base64.DEFAULT)))
}
And here is my code in JS :
function decrypt(data, password)
{
var hash = sha256(password).substring(0, 16)
var decipher = crypto.createDecipheriv('aes-128-cbc', hash, hash);
var dec = decipher.update(data, 'hex', 'utf8');
dec += decipher.final('utf8');
return dec;
}
function encrypt(data, password)
{
var hash = sha256(password).substring(0, 16)
var cipher = crypto.createCipheriv('aes-128-cbc', hash, hash);
var crypted = cipher.update(data, 'utf8', 'hex');
crypted += cipher.final('hex');
return crypted;
}
I have tried to play with the differents block size in Java and nodeJS (192, 128 and 256) but it's not working.
I don't want to cipher in ECB, I want to achive this in CBC or CTR.
Does someone know how to do this please ? Thank you per advance !
I have tried using cbc,noPadding and applied same padding algorithm in both js and java and worked fine it generated same encrypted string in js and java as well please check the link:
JS link:
https://plnkr.co/edit/aihF54rkxxw3Jjcly9Uo?p=preview
Java code:
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;
public class CipherConversion {
private static final String algorithm = "AES/CBC/NoPadding";
private static final byte[] keyValue = new byte[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
private static final byte[] ivValue = new byte[] { 'f', 'e', 'd', 'c', 'b', 'a', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0' };
private static final IvParameterSpec ivspec = new IvParameterSpec(ivValue);
private static final SecretKeySpec keyspec = new SecretKeySpec(keyValue, "AES");
// final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String encrypt(String Data) throws Exception {
Cipher c = Cipher.getInstance(algorithm);
c.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
public static String decrypt(String encryptedData) throws Exception {
Cipher c = Cipher.getInstance(algorithm);
c.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
private static String padString(String source) {
char paddingChar = ' ';
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++)
{
source += paddingChar;
}
return source;
}
public static void main(String[] args) throws Exception {
System.out.println("keyValue"+keyValue);
System.out.println("keyValue"+ivValue);
String password = "ChangeMe1";
String passwordEnc = CipherConversion.encrypt(padString(password));
String passwordDec = CipherConversion.decrypt(passwordEnc);
System.out.println("Plain Text : " + password);
System.out.println("Encrypted Text : " + passwordEnc);
System.out.println("Decrypted Text : " + passwordDec);
}
}
I have faced a similar situation before, where the AES encryption was not working for both application and server side. Finally, I could make it work for both Android and server side. I am providing the class that I used for AES encryption. However, I have a java implementation and I thought that would be a help.
import android.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class AESProvider {
private static final String ALGORITHM = "AES";
private static final String ENCRYPTION_KEY = "YourEncryptionKey";
public static String encrypt(String stringToEncrypt) {
try {
SecretKeySpec secretKey = new SecretKeySpec(ENCRYPTION_KEY, ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] data = cipher.doFinal(stringToEncrypt.getBytes("UTF-8"));
return Base64.encodeToString(data, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static String decrypt(String stringToDecrypt) throws Exception {
SecretKeySpec secretKey = new SecretKeySpec(ENCRYPTION_KEY, ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return new String(cipher.doFinal(Base64.decode(stringToDecrypt, Base64.DEFAULT)));
}
}
I was missing the Base64 encode and decode while encoding and decoding the AES encryption in my case. Hope that helps!

Using JSON with AES is throwing javax.crypto.IllegalBlockSizeException

When I encrypt with AES/CBC/PKCS5Padding a normal String there is no problem.
When I use a JSON String which contains typical JSON type data and it throws an exception when doing Decryption:
Full Exception:
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at io.crypto.Crypto.doFinal(Crypto.java:60)
at io.crypto.Crypto.decrypt(Crypto.java:50)
at io.Controller.main(Controller.java:38)
AES Code:
public class Crypto {
private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'b', 'c', 'D', 'e', 'F'};
private static Cipher cipher;
public static void init() {
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
NetworkModule.handleException(e);
}
}
public static String encrypt(String password, String message) throws Exception {
String salt = random(16);
String iv = random(16);
SecretKey key = generateKey(salt, password);
byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, iv, message.getBytes("UTF-8"));
String code = Base64.getEncoder().encodeToString(encrypted);
return salt + code.substring(0, code.length() - 2) + iv;
}
public static String decrypt(String password, String message) throws Exception {
String salt = message.substring(0, 32);
String iv = message.substring(message.length() - 32, message.length());
String base = message.substring(32, message.length() - 32) + "==";
SecretKey key = generateKey(salt, password);
byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, Base64.getDecoder().decode(base));
return new String(decrypted, "UTF-8");
}
private static byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) {
try {
cipher.init(encryptMode, key, new IvParameterSpec(hex(iv)));
return cipher.doFinal(bytes);
} catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
NetworkModule.handleException(e);
return null;
}
}
private static SecretKey generateKey(String salt, String passphrase) {
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), hex(salt), 1000, 128);
SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return key;
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
NetworkModule.handleException(e);
return null;
}
}
private static String random(int length) {
byte[] salt = new byte[length];
new SecureRandom().nextBytes(salt);
return hex(salt);
}
private static String hex(byte[] data) {
int l = data.length;
char[] out = new char[l << 1];
int i = 0;
for (int var5 = 0; i < l; ++i) {
out[var5++] = HEX[(240 & data[i]) >>> 4];
out[var5++] = HEX[15 & data[i]];
}
return new String(out);
}
private static byte[] hex(String hex) {
char[] data = hex.toCharArray();
int len = data.length;
if ((len & 1) != 0) {
return null;
} else {
byte[] out = new byte[len >> 1];
int i = 0;
for (int j = 0; j < len; ++i) {
int f = Character.digit(data[j], 16) << 4;
++j;
f |= Character.digit(data[j], 16);
++j;
out[i] = (byte) (f & 255);
}
return out;
}
}
}
Working Example:
Crypto.init();
String password = "42cb54a0b6a89a53709301ee320f45de102dda05ccd1a49c3c62c19b7319ca73";
String message = "Hello World";
System.out.println(message);
String encrypt = Crypto.encrypt(password, message);
System.out.println(encrypt);
String decrypt = Crypto.decrypt(password, encrypt);
System.out.println(decrypt);
Ouput:
Hello World
3cc6b607175011Fc50bb498c8064863ebbAePnO7nmGSFLBr2KnfhQDAb84b338007b4e3e9bbFF3e35b0341A
Hello World
Exception Example:
Crypto.init();
String password = "42cb54a0b6a89a53709301ee320f45de102dda05ccd1a49c3c62c19b7319ca73";
String message = new PacketBuilder("example").build();
System.out.println(message);
String encrypt = Crypto.encrypt(password, message);
System.out.println(encrypt);
String decrypt = Crypto.decrypt(password, encrypt);
System.out.println(decrypt);
Ouput:
{"packet":"EXAMPLE"}
6b1FbA86e4F17A21633AA12c352eAD63ebKIw+ljAx4XsqBgK5Q3KQ2Hd5w8nO4NP9sqxC+CLI0A4D2e4AbF47ecF6b6149A8F2445658F
Exception in thread "main" ... full stacktrace on the top of the post
Alright, I have found the issue.
Upon checking variables I discovered that printing the code in the encrypt method would yield a String ending in a single space. However, you cut off two letters in your substring so the first thing you need to do is rewrite you return in that method like this
return salt + code.replace("=","") + iv;
Next whenever you are about to decode from base you do this
String base = message.substring(32, message.length() - 32) + "==";
But this is not necesary so change it like this
String base = message.substring(32, message.length() - 32);
After changing these your methods should work.

How to decrypt a C# encrypted AES string in java

I have a string that encrypted in java by "AES", Now i need decrypt in my C# program (I have the key)
Now i need decrypt in C#.How do I decode it into the C#?
my Encrypte and Decrypt in java :
public class AES {
public static String encrypt(String seed, String cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
public static String decrypt(String seed, String encrypted) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = toByte(encrypted);
//ggggg
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecureRandom secrand = SecureRandom.getInstance("SHA1PRNG", "Crypto");
secrand.setSeed(seed);
keygen.init(128, secrand);
SecretKey seckey = keygen.generateKey();
byte[] rawKey = seckey.getEncoded();
return rawKey;
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
//0000
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static byte[] toByte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
public static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2*buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private final static String HEX = "0123456789ABCDEF";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
and
try {
String plaintext = "Hello world", key = "111";
String ciphertext = AES.encrypt(key, plaintext);
Log.i("ddddddd",ciphertext);
String plaintext2 = AES.decrypt(key, ciphertext);
Log.i("ddddddd","Encrypting '" + plaintext +
"' yields: (" + ciphertext.length() + ") " + ciphertext);
Log.i("ddddddd","Decrypting it yields: " + plaintext2);
}
catch (Exception ex) {
ex.printStackTrace();
}
Now i need decrypt in C#.How do I decode it into the C#?
the best way would be to use the RijndaelManaged Class to perform your task in C#.
Here you can find an excellent example on encryption/decryption:
https://stackoverflow.com/a/212707/282649
Let me know...

Categories