Cross platform AES Encryption between iOS and Kotlin/Java using Apples CryptoKit
could you try this (or something like it) with your setup. From what I undestand
you need to prefix data with nonce, because data from kotlin/java contains the cipher text plus the tag at the end. CryptoKit needs nonce || ciphertext || tag.
func decrypt(data: Data) -> String {
// need to prefix data with nonce, because data from kotlin/java contains the cipher text plus the tag at the end.
// we want nonce || ciphertext || tag for CryptoKit to be happy
let combine = nonce + data
if let myNewSealedBox = try? AES.GCM.SealedBox(combined: combine),
let res = try? AES.GCM.open(myNewSealedBox, using: mykey),
let myText = try? String(decoding: res, as: UTF8.self) {
return myText
}
return ""
}
How to get compatible encryption version in flutter as in iOS
I finally resolved it myself. Posting the answer over here hoping it helps someone.
I had to change the below line,
from
final key = Key.fromBase64("Some_Key");
to
final key = Key.fromUtf8("Some_Key");
That't it. It works!!
iOS CryptoSwift AES Encryption to Python Decryption works - but not the inverse
In the encrypt()
method the IV is not considered. As in aesEncrypt()
, the IV must be passed and used when creating the AES object.
Furthermore there are bugs in the encoding: The plaintext must be UTF8 encoded and the ciphertext must be hex encoded:
from Crypto.Cipher import AES
import binascii
def encrypt(key, iv, plaintext):
cipher = AES.new(key, MODE, iv, segment_size=128)
plaintext_bytes = plaintext.encode("utf-8")
ciphertext = cipher.encrypt(plaintext_bytes)
ciphertext_hex = binascii.b2a_hex(ciphertext)
return ciphertext_hex
This function is the counterpart to decrypt()
, i.e. encrypt()
can be used to generate a ciphertext which can be decrypted with decrypt()
(or aesDecrypt()
).
In the iOS code there are two bugs, both concerning the encoding: The ciphertext must not be UTF8 encoded, but hex decoded. And the decrypted data must not be hex encoded, but UTF-8 decoded.
A possible fix is:
func aesDecrypt(stringToDecrypt: String, key: Array<UInt8>, iv: Array<UInt8>) throws -> String {
let data = Array<UInt8>(hex: stringToDecrypt)
let decrypted = try AES(key: key, blockMode: CFB(iv: iv), padding: .noPadding).decrypt(data)
return String(bytes: decrypted, encoding: .utf8)!
}
This function is the counterpart to aesEncrypt()
, i.e. aesDecrypt()
can be used to decrypt a ciphertext generated with aesEncrypt()
(or encrypt()
).
Regarding security: A static IV is insecure. Instead, the IV should be randomly generated for each encryption. Since the (non-secret IV) is needed for decryption, it is passed along with the ciphertext (typically concatenated).
Related Topics
Get Bogus Value When Execute Break Point in a Variable
How to Create a Struct to Match This JSON
Error: Binary Operator '<=' Cannot Be Applied to Operands of Type 'Int' and 'Int'
Differencebetween ":" and "=" in Swift
When Calling a Function in Swift, What Does Each Part Mean
How to Make a Button Have a Rounded Border in Swift
How to Make an Enum Conform to a Protocol in Swift
Xcode & Swift - Window Without Title Bar But with Close, Minimize and Resize Buttons
Converting Url to String and Back Again
Map or Reduce with Index in Swift
Build Input File Cannot Be Found' Swift 4.2, Xcode 10.0
Default Optional Parameter in Swift Function
How to Do an If-Else Comparison on Enums with Arguments
What Is the Swift Equivalent of -[Nsobject Description]