1

Hi I am building a iOS application that communicates with a restful server. This requires my java AES code and Swift AES code to produce the same results currently I am using CryptoSwift, using the tutorial here (AES Encrypt and Decrypt). However this gives me different results compared to my java code.

Here is my java code:

private static final byte[] keyValue = new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't', 'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' }; public static String encrypt(String Data) throws Exception { Key key = generateKey(); Cipher c = Cipher.getInstance("AES"); c.init(Cipher.ENCRYPT_MODE, key); byte[] encVal = c.doFinal(Data.getBytes()); String encryptedValue = new BASE64Encoder().encode(encVal); return encryptedValue; } public static String decrypt(String encryptedData) throws Exception { Key key = generateKey(); Cipher c = Cipher.getInstance("AES"); c.init(Cipher.DECRYPT_MODE, key); byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData); byte[] decValue = c.doFinal(decordedValue); String decryptedValue = new String(decValue); return decryptedValue; } public static Key generateKey() throws Exception { Key key = new SecretKeySpec(keyValue, "AES"); return key; } public static void main(String[] args) { try { System.out.println(AES.encrypt("test")); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } 

This code gives me xGdooY+6V8q1cze7mR9TjQ==

Here is my code in swift

import Foundation import CryptoSwift extension String { func aesEncrypt(key: String, iv: String) throws -> String{ let data = self.dataUsingEncoding(NSUTF8StringEncoding) let enc = try AES(key: key, iv: iv, blockMode:.CBC).encrypt(data!.arrayOfBytes()) let encData = NSData(bytes: enc, length: Int(enc.count)) let base64String: String = encData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)); let result = String(base64String) return result } func aesDecrypt(key: String, iv: String) throws -> String { let data = NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions(rawValue: 0)) let dec = try AES(key: key, iv: iv, blockMode:.CBC).decrypt(data!.arrayOfBytes()) let decData = NSData(bytes: dec, length: Int(dec.count)) let result = NSString(data: decData, encoding: NSUTF8StringEncoding) return String(result!) } } let key = "TheBestSecretKey" // length == 32 let iv = "gqLOHUioQ0QjhuvI" // length == 16 let s = "test" let enc = try! s.aesEncrypt(key, iv: iv) let dec = try! enc.aesDecrypt(key, iv: iv) print(s) print("enc:\(enc)") print("dec:\(dec)") print("\(s == dec)") 

This code gives me LQu3c4HaOQf7W0CfnMMy1w==

As you may see they do work independently but I need them to be compatible

1
  • What does iv (initialisation vector mean) and how to get it? Commented Apr 11, 2017 at 5:11

1 Answer 1

7

You are doing two different types of encryption.
Your Java code is using the AES cipher which is more accurately AES/ECB/PKCS5Padding while your swift code is doing the equivalent of AES/CBC/PKCS5Padding and is using an IV.
In other words your swift code is doing cipher block chaining and uses a initialization vector. While your java code is doing ECB mode without an IV.
If you don't know what you are doing you shouldn't be implementing encryption schemes, but at a minimum, you should always use a random IV and cipher block chaining.
You should really never use ECB mode.
If you use a random IV, then each time you encrypt something the result will be different.
Rather than checking that the cipher texts are the same you should test that you can encrypt/decrypt messages between each component.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your help, I think I understood what you are saying. However encryption is not a huge element of my application so I don't need to be perfect I just need it to work, without having to send information back and forth in plain text. Is there any library or exiting code I can use for either swift or java that I can use?
I don't know what your requirements are, but the simplest, least error prone method of sending encrypted data between a client and server would be to use HTTPS.
A good cross platform solution is to use RNCryptor which has versions for several platforms/languages. Further is provided authenticated encryption and password to key derivation. It covers the various details that are hard to get correct.
@zaph thanks RNCyptor works perfectly for my requirments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.