AES Decryption

Having trouble decrypting a string using an encryption key and an IV.

var key: String 
var iv:  String

func decryptData(_ encryptedText: String) -> String?
{
      if  let textData = Data(base64Encoded: iv + encryptedText)  {
        do {
            let sealedBox = try AES.GCM.SealedBox(combined: textData)
            let key = SymmetricKey(data: key.data(using: .utf8)!)
            let decryptedData = try AES.GCM.open(sealedBox, using: key)
            return String(data: decryptedData, encoding: .utf8)
        } catch {
            print("Decryption failed: \(error)")
            return nil
        }
    }
    return nil
}

Proper coding choices aside (I'm just trying anything at this point,) the main problem is opening the SealedBox. If I go to an online decryption site, I can paste in my encrypted text, the encryption key, and the IV as plain text and I can encrypt and decrypt just fine.

But I can't seem to get the right combo in my Swift code. I don't have a "tag" even though I'm using the combined option. How can I make this work when all I will be receiving is the encrypted text, the encryption key, and the IV. (the encryption key is 256 bits)

Try an AES site with a key of 32 digits and an IV of 16 digits and text of your choice. Use the encrypted version of the text and then the key and IV in my code and you'll see the problem. I can make the SealedBox but I can't open it to get the decrypted data. So I'm not combining the right things the right way. Anyone notice the problem?

The code you posted is using AES-GCM. If you’ve been given a string with an IV then you’re not using AES-GCM, because AES-GCM doesn’t use IVs [1]. I suspect that your data is encrypted with AES-ECB or AES-CBC [2].

Can you post a test vector? That is, hex dumps of the:

  • Actual cyphertext — It’s length must be an even multiple of 16
  • Key — 16 (AES-128), 24 (AES-192), or 32 (AES-256) bytes
  • IV — 16 bytes
  • Expected plaintext

That should be enough for me to get you heading in the right direction.

IMPORTANT I’m asking for hex dumps rather than strings because that eliminates text encoding concerns.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Well, it uses them internally but… *shrug*… I never did quite grok the full details of GCM (-:

[2] Those are the usual suspects when it comes to badly underspecified cryptographic requirements (-:

You are indeed correct, sir, it is CBC. I failed to mention that. I'm hoping I can still accomplish this without using GCM.

Here is a sample of what works online:

Actual cyphertext : 32334b4659307165655076412b596c4b394d36586c6e69304850694f784e6364434a4b4363506f2f4f7065514e43324367507470783735534b33744f654c2b6964306f4450336265787565577a527564765278707a4f79654471514162684f37576470524f3673444c2f4d3d

Key : 3132333435363738393132333435363738393132333435363738393132333435

IV : 31323334353637383132333435363738

Expected plaintext : 7b20226c6f6164223a20223132333435363637222c2022737570706c696572223a20223938373635343332222c202263617272696572223a20224142434422207d

FYI, your CBC nudge led me to another post of yours where you shared a Swift wrapper around CommonCrypto’s AES CBC support. Digging into that now.

My cyphertext is in fact NOT a multiple of 16. Since the online site I used didn't seem to care, I'm wondering what their method is. Is there some safe padding that can be applied?

AES Decryption
 
 
Q