I am trying to decrypt a Base64Encoded String message with AES decryption.
Encrypted Message (Base64Encoded String): tNC6umcfBS/gelbo2VJF3i4LAhUKMp4oDHWN5KyYUTWeJIQKKYx6oAcQnGncIrPJNC1tUYMKV4kJQj3q9voIOrxc1n7FmRFvDXeRgWGNcGYO66dH3VjoEgF0oxZOpfzwSZKSv3Jm7Q==
Password (String) = "SOMEPASSWORDSTRING"
Steps to Decrypt the Message:
The data must be decoded from base 64 to normal string.
Extract the IV and the encrypted text from input
Use IV and the same passphrase to generate the key that was used to encrypt the text. The key generation should follow the same steps as below.
A PBE Secret Key is generated (256 bits)
a. Specs created with passphrase and IV as salt, 62233 as iteration count
b. Used PBKDF2WithHmacSHA256 to generate a secret factory because it's appropriate for turning passwords into keys.
c. This key is further encoded and converted to another key with AES encryption.
With the generated key and IV, initialize the cipher in the exact same way as below
This key initializes the cipher object
a. Used AES in GCM, GCM specs are prepared using tag size of 128 bits and the IV
b. Cipher object is initialized using AES/GCM/PKCS5Padding.
c. Based on operational mode the cipher is initialized with op mode(encryption), secret key and GCM params.
Generate the cipher to get the message from the encrypted text.
Below is the JAVA Code that is working to decrypt the input message
public class Decryption {
private static final String KEY_GENERATING_ALGO = "PBKDF2WithHmacSHA256";
private static final String ENCRYPTION = "AES";
private static final String TRANSFORMATION_ALGORITHM= "AES/GCM/PKCS5Padding";
private static final int KEY_SIZE_BITS = 256;
private static final int TAG_SIZE_BITS = 128;
private static final int ITERATION_COUNT = 62233;
// Use following sample data to test the decryption-
//tNC6umcfBS/gelbo2VJF3i4LAhUKMp4oDHWN5KyYUTWeJIQKKYx6oAcQnGncIrPJNC1tUYMKV4kJQj3q9voIOrxc1n7FmRFvDXeRgWGNcGYO66dH3VjoEgF0oxZOpfzwSZKSv3Jm7Q==
// This key has is base 64 encoded with IV prepended with encrypted text
public Cipher initCipher(int encryptMode, String password, byte[] iv) throws InvalidKeySpecException {
try {
GCMParameterSpec gcmparams = new GCMParameterSpec(TAG_SIZE_BITS, iv);
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), iv, ITERATION_COUNT, KEY_SIZE_BITS);
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_GENERATING_ALGO);
SecretKey pbeKey = factory.generateSecret(pbeKeySpec);
byte[] keyBytes = pbeKey.getEncoded();
SecretKey key = new SecretKeySpec(keyBytes, ENCRYPTION);
Cipher cipher = Cipher.getInstance(TRANSFORMATION_ALGORITHM);
cipher.init(encryptMode, key, gcmparams);
return cipher;
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
| InvalidAlgorithmParameterException | InvalidKeySpecException ex) {
throw new AssertionError(ex);
}
}
//Decryption Algo
public String decrypt(String encrypted){
byte[] decFeeder = Base64.getDecoder().decode(encrypted);
String key = "someKey"; // A new key will be provided by APIF through a secure channel
char[] password = key.toCharArray();
try {
byte[] iv = Arrays.copyOfRange(decFeeder, 0, 32);
byte[] ciphertext = Arrays.copyOfRange(decFeeder, iv.length, decFeeder.length);
Cipher cipher = initCipher(Cipher.DECRYPT_MODE, key, iv);
byte[] message = cipher.doFinal(ciphertext);
String decrypted = new String(message);
return decrypted;
} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException ex) {
throw new AssertionError(ex);
}
}
}
I used below code in Swift to generate the same as above JAVA code, but I am unable to decrypt the message/cipherText.
func aesDecrypt(encryptedData: Data, password: String) -> Data? {
let iv = Array([UInt8](encryptedData)[0 ..< 33])
let ivData = Data(iv)
let encryptedCipher = [UInt8](encryptedData)[iv.count ..< encryptedData.count]
let encryptedCipherData = Data(encryptedCipher)
let passwordKey = createKey(password:Data(password.utf8) , salt: ivData)
var decryptSuccess = false
let size = (encryptedCipher.count) + kCCBlockSizeAES128
var clearTextData = Data.init(count: size)
var numberOfBytesDecrypted : size_t = 0
let cryptStatus = ivData.withUnsafeBytes {ivBytes in
clearTextData.withUnsafeMutableBytes {clearTextBytes in
encryptedCipherData.withUnsafeBytes {encryptedBytes in
passwordKey.withUnsafeBytes {keyBytes in
CCCrypt(CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
CCOptions(kCCOptionPKCS7Padding),
keyBytes,
passwordKey.count,
ivBytes,
encryptedBytes,
(encryptedCipher.count),
clearTextBytes,
size,
&numberOfBytesDecrypted)
}
}
}
}
if cryptStatus == Int32(kCCSuccess)
{
clearTextData.count = numberOfBytesDecrypted
debugPrint(clearTextData)
decryptSuccess = true
}
return decryptSuccess ? clearTextData : Data.init(count: 0)
}
func createKey(password: Data, salt: Data) -> Data? {
let length = kCCKeySizeAES256
var status = Int32(0)
var derivedBytes = [UInt8](repeating: 0, count: length)
password.withUnsafeBytes { (passwordBytes: UnsafePointer<Int8>!) in
salt.withUnsafeBytes { (saltBytes: UnsafePointer<UInt8>!) in
status = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), // algorithm
passwordBytes, // password
password.count, // passwordLen
saltBytes, // salt
salt.count, // saltLen
UInt32(kCCPRFHmacAlgSHA256), // prf
UInt32(62233), // rounds
&derivedBytes, // derivedKey
length) // derivedKeyLen
}
}
guard status == 0 else {
return nil
}
return Data(bytes: UnsafePointer<UInt8>(derivedBytes), count: length)
}
Usage:
guard let encryptedData = Data(base64Encoded: input) else{
return nil
}
let decryptData = aesDecrypt3(encryptedData: encryptedData)
let decryptedMessage = String(data: decryptData, encoding: .utf8) ?? "Unable to Decrypt"
Any leads would be greatly appreciated, I wonder if I am missing some configuration or data conversion when trying to convert in swift.
I was able to decrypt the input using "CryptoSwift" framework, was wondering if we can solve the same using the apple iOS CommonCrypto framework.
Any leads with using "CommonCrypto" would be greatly appreciated
class func decryptCode123(_ cipher:String)-> String{
let key = "SOMEKEY"
var keyBytes: [UInt8] = []
var codeBytes: [UInt8] = []
var code = ""
if let keyData = NSData(base64Encoded:key, options: .ignoreUnknownCharacters) {
keyBytes = [UInt8](keyData as Data)
}
if let codeData = NSData(base64Encoded: cipher, options: .ignoreUnknownCharacters) {
codeBytes = [UInt8](codeData as Data)
}
debugPrint(codeBytes)
let codeBytescount = [UInt8](codeBytes).count
let iv = Array([UInt8](codeBytes)[0 ..< 32])
let cipher = Array([UInt8](codeBytes)[iv.count ..< codeBytescount])
do{
let gcm = GCM(iv: iv, mode: .combined)
let derKey = createKey(password:Data(key.utf8), salt: Data(iv))!
keyBytes = [UInt8](derKey)
let aes = try AES(key: keyBytes, blockMode: gcm, padding: .pkcs5)
print("aes created")
let decrypted = try aes.decrypt(cipher)
print("decrypted completed")
if let decryptedString = String(bytes: decrypted, encoding: .utf8) {
code = decryptedString
}
debugPrint(code)
}catch let error as AES.Error {
debugPrint(error.localizedDescription)
return code
} catch {
return code
}
return code
}