AES/GCM/NoPadding Encryption Swift iOS

Currently I have been doing AES with CBC mode encryption but as backend change in requirement we have to change to to GCM mode with random IV generation .

currently I have this code :

Code Block
 static func encryptsData(parameters: parameters?) -> (String, String) {
 var jsonStr = DefaultValues.empty
        do {
            if let str = String(data: try JSONSerialization.data(withJSONObject: parameters ?? [:], options: .prettyPrinted), encoding: .utf8) {
                jsonStr = str
            }
        } catch {
            debugPrint(error.localizedDescription)
        }
        // Get Secrete key, iv of 128 bits
        let iv = [UInt8](repeating: 0, count: 16)
        let randomStr = randomString(length: 16)
        let key: Array<UInt8> = Array(randomStr.utf8)
        // Encrypt Request Data with Secrete Key (AES)
        let aes =  try! AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs5)
        let encrypted = try? aes.encrypt(Array(jsonStr.utf8))
             if let encryptedMsg = encrypted {
            let encryptedData =  Data(bytes: encryptedMsg, count: Int(encryptedMsg.count))
            let encryptedBase64 = encryptedData.base64EncodedString()
            //Encrypt Secrete Key using Server Public key (RSA)
            let keyData = Data(bytes: key, count: key.count)
            let encryptedSceKey = encryptSecKeyWithPublickKey(key: String(data: keyData, encoding: .utf8) ?? "")
            return (encryptedBase64, encryptedSceKey)
        }
        return (DefaultValues.empty, DefaultValues.empty)
}

  Now , have changed the code for GCM Mode in the following lines :
Code Block
  let iv = AES.randomIV(AES.blockSize) //[UInt8](repeating: 0, count: 16)
        var bytes = [Int8](repeating: 0, count: 16)
         let randomStr = randomString(length:16)
        let key: Array<UInt8> = Array(randomStr.utf8)
        // Encrypt Request Data with Secrete Key (AES)
        let aes =  try! AES(key: key, blockMode: GCM(iv: iv), padding: .noPadding)

else , remaining the same..But could get success through this as our encryption has to be in sync with the android/java side.

On Android end this is the encryption code :
Code Block lpackage com.jio.ngo.datalayer.network.encryption
import android.util.Base64
import android.util.Log
import com.jio.ngo.datalayer.BuildConfig
import java.nio.charset.Charset
import java.security.*
import java.security.spec.InvalidKeySpecException
import java.security.spec.X509EncodedKeySpec
import javax.crypto.*
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
object Encryption
{
val TAG = "Encryption"
private const val GCM_IV_LENGTH = 12
fun encrypt(message: String): EncryptedRequest
{
val encryptedRequest = EncryptedRequest()
try
{
// 1. generate secret key using AES
val keyGenerator = KeyGenerator.getInstance("AES")
keyGenerator.init(256)
// AES is currently available in three key sizes: 128, 192 and 256 bits.The
// design and strength of all key lengths of the AES algorithm are sufficient to
// protect classified information up to the SECRET level
val secretKey = keyGenerator.generateKey()
// 2. get string which needs to be encrypted
// 3. encrypt string using secret key
val raw = secretKey.encoded
val skeySpec = SecretKeySpec(raw, "AES")
// val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val iv = ByteArray(GCM_IV_LENGTH)
SecureRandom().nextBytes(iv)
val parameterSpec = GCMParameterSpec(128, iv) //128
// val parameterSpec: GCMParameterSpec = cipher.parameters.getParameterSpec(GCMParameterSpec::class.java)
// cipher.init(Cipher.ENCRYPT_MODE, skeySpec, IvParameterSpec(ByteArray(16)))
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, parameterSpec)
val encryptedMessageBytes: ByteArray = cipher.doFinal(message.toByteArray(Charset.forName("UTF-8")))
val encrypted = ByteArray(iv.size + encryptedMessageBytes.size)
System.arraycopy(iv, 0, encrypted, 0, iv.size)
System.arraycopy(encryptedMessageBytes, 0, encrypted, iv.size, encryptedMessageBytes.size)
val cipherTextString = Base64.encodeToString(encrypted, Base64.DEFAULT)
Log.d(TAG, "cipherTextString : $cipherTextString")
Log.d(TAG, "cipherTextString 1: ${Base64.encodeToString(skeySpec.encoded, Base64.DEFAULT)}")
// 4. get public key
val publicSpec = X509EncodedKeySpec(Base64.decode(BuildConfig.apikey, Base64.DEFAULT))
val keyFactory = KeyFactory.getInstance("RSA")
val publicKey = keyFactory.generatePublic(publicSpec)
// 6. encrypt secret key using public key
val cipher2 = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding")
cipher2.init(Cipher.ENCRYPT_MODE, publicKey)
val encryptedSecretKey = Base64.encodeToString(cipher2.doFinal(secretKey.encoded), Base64.DEFAULT)
//System.out.println(encryptedSecretKey);
Log.d(TAG, "encryptedSecretKey : $encryptedSecretKey")
// 7. pass cipherTextString (encypted sensitive data) and encryptedSecretKey to
// your server via your preferred way.
// Tips:
// You may use JSON to combine both the strings under 1 object.
// You may use a volley call to send this data to your server.
encryptedRequest.encryptedText = cipherTextString
encryptedRequest.encryptedSecretKeyString = encryptedSecretKey
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
} catch (e: InvalidKeyException) {
e.printStackTrace()
} catch (e: NoSuchPaddingException) {
e.printStackTrace()
} catch (e: IllegalBlockSizeException) {
e.printStackTrace()
} catch (e: BadPaddingException) {
e.printStackTrace()
} catch (e: InvalidKeySpecException) {
e.printStackTrace()
} catch (e: InvalidAlgorithmParameterException) {
e.printStackTrace()
}
catch (e: Exception)
{
e.printStackTrace()
}
return encryptedRequest
}
}

So, have to find way around like what Java end encryption is happening , not able to get what is the issue at our end.

failing decrypting in backend when using above iOS encryption code :
Code Block
javax.crypto.AEADBadTagException: Tag mismatch!

Please help ....
Thanks !!

Did you find any solution?

Can you share encryptSecKeyWithPublickKey code?

Any lead here?

Did you find solution?

Did you find any solution? Please update

Any update on this

AES/GCM/NoPadding Encryption Swift iOS
 
 
Q