I'm a complete newbie to this kind of encryption things but I have a Java app and an iOS, and I want them to both be able to ecrypt a text to a same result. I use AES. I found these codes, with a little modification of course, but they return different result
iOS Code:
- (NSData *)AESEncryptionWithKey:(NSString *)key {
unsigned char keyPtr[kCCKeySizeAES128] = { 'T', 'h', 'e', 'B', 'e', 's', 't', 'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };
size_t bufferSize = 16;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
const char iv2[16] = { 65, 1, 2, 23, 4, 5, 6, 7, 32, 21, 10, 11, 12, 13, 84, 45 };
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmAES128,
kCCOptionECBMode | kCCOptionPKCS7Padding,,
keyPtr,
kCCKeySizeAES128,
iv2,
@"kayvan",
6,
dataInLength,
buffer,
bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
and the Java code is:
public static void main(String[] args) throws Exception {
String password = "kayvan";
String key = "TheBestSecretKey";
String newPasswordEnc = AESencrp.newEncrypt(password, key);
System.out.println("Encrypted Text : " + newPasswordEnc);
}
and in another java class (AESencrp.class
) I have:
public static final byte[] IV = { 65, 1, 2, 23, 4, 5, 6, 7, 32, 21, 10, 11, 12, 13, 84, 45 };
public static String newEncrypt(String text, String key) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes= new byte[16];
byte[] b= key.getBytes("UTF-8");
int len = 16;
System.arraycopy(b, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(IV);
System.out.println(ivSpec);
cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivSpec);
byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
String result = DatatypeConverter.printBase64Binary(results);
return result;
}
The string I wanted to encrypt is kayvan
with the key TheBestSecretKey
. and the results after Base64 encoding are:
for iOS: 9wXUiV+ChoLHmF6KraVtDQ==
for Java: /s5YyKb3tDlUXt7pqA5OFA==
What should I do now?
I made a gist with iOS/Android/Node.js AES256 same result encoding, https://gist.github.com/m1entus/f70d4d1465b90d9ee024
And here is the Android Version wich is generating the String for decrypt/encrypt Messages, it uses Cipher and generates the right vector to make the same result as iOS. This is corresponding to the iOS Version of @亚历山大 here in this thread.
public class MyCrypter {
private static String TAG = "MyCrypter";
public MyCrypter() {
}
/**
* Encodes a String in AES-128 with a given key
*
* @param context
* @param password
* @param text
* @return String Base64 and AES encoded String
* @throws NoPassGivenException
* @throws NoTextGivenException
*/
public String encode(Context context, String password, String text)
throws NoPassGivenException, NoTextGivenException {
if (password.length() == 0 || password == null) {
throw new NoPassGivenException("Please give Password");
}
if (text.length() == 0 || text == null) {
throw new NoTextGivenException("Please give text");
}
try {
SecretKeySpec skeySpec = getKey(password);
byte[] clearText = text.getBytes("UTF8");
//IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID
final byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x00);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
// Cipher is not thread safe
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
String encrypedValue = Base64.encodeToString(
cipher.doFinal(clearText), Base64.DEFAULT);
Log.d(TAG, "Encrypted: " + text + " -> " + encrypedValue);
return encrypedValue;
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return "";
}
/**
* Decodes a String using AES-128 and Base64
*
* @param context
* @param password
* @param text
* @return desoded String
* @throws NoPassGivenException
* @throws NoTextGivenException
*/
public String decode(Context context, String password, String text)
throws NoPassGivenException, NoTextGivenException {
if (password.length() == 0 || password == null) {
throw new NoPassGivenException("Please give Password");
}
if (text.length() == 0 || text == null) {
throw new NoTextGivenException("Please give text");
}
try {
SecretKey key = getKey(password);
//IMPORTANT TO GET SAME RESULTS ON iOS and ANDROID
final byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x00);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
byte[] encrypedPwdBytes = Base64.decode(text, Base64.DEFAULT);
// cipher is not thread safe
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
byte[] decrypedValueBytes = (cipher.doFinal(encrypedPwdBytes));
String decrypedValue = new String(decrypedValueBytes);
Log.d(TAG, "Decrypted: " + text + " -> " + decrypedValue);
return decrypedValue;
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return "";
}
/**
* Generates a SecretKeySpec for given password
* @param password
* @return SecretKeySpec
* @throws UnsupportedEncodingException
*/
public SecretKeySpec getKey(String password)
throws UnsupportedEncodingException {
int keyLength = 128;
byte[] keyBytes = new byte[keyLength / 8];
// explicitly fill with zeros
Arrays.fill(keyBytes, (byte) 0x0);
// if password is shorter then key length, it will be zero-padded
// to key length
byte[] passwordBytes = password.getBytes("UTF-8");
int length = passwordBytes.length < keyBytes.length ? passwordBytes.length
: keyBytes.length;
System.arraycopy(passwordBytes, 0, keyBytes, 0, length);
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
return key;
}
public class NoTextGivenException extends Exception {
public NoTextGivenException(String message) {
super(message);
}
}
public class NoPassGivenException extends Exception {
public NoPassGivenException(String message) {
super(message);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With