Decrypt data using AES.GCM.SealedBox in Swift
Asked Answered
B

2

6

I am trying to decrypt data using AES.GCM.The encrypted data works fine but when I try to decrypt the data using the same key it gives authentication error. Below is the code to decrypt

func decryptData(decryptToData: Data, key: SymmetricKey) -> String {
    var decryptedString: String!
    let combinedData = decryptToData // Previous sealed bo
    let sealedBoxToOpen = try! AES.GCM.SealedBox(combined: decryptToData)

    if let decryptedData = try? AES.GCM.open(sealedBoxToOpen, using: key) {
        decryptedString = String(data: decryptedData, encoding: .utf8)!
        print(decryptedString)
    } else {
        print("error", CryptoKitError.self)
        // Ouch, doSomething() threw an error.
    }
    return decryptedString
}

The following is my encryption code

let iv = AES.GCM.Nonce()
var encryptedData: Data!
let key = SymmetricKey(size: .bits128)

func encryptData(encryptString: String, key: SymmetricKey) -> Data {
    var encryptedData: Data?
    do {
        let datatoEncrypt1 = encryptString.data(using: .utf8)!
        let mySealedBox  = try AES.GCM.seal(datatoEncrypt1, using: key, nonce: iv)
        encryptedData = mySealedBox.combined
    } catch {
        print("Error")
    }
    return encryptedData
}
Brewage answered 14/1, 2020 at 20:50 Comment(9)
Usually this is due to differences in either the key or the encoding of the combined IV, ciphertext and authentication tag. However, those are not in the code. Could you verify that those are the same at both sides by comparing the hexadecimal values of the bytes? Do you have used different sizes of IV or authentication tag maybe (I'm not sure if that's even possible, but it can be an issue if it is)?Illustration
I have iv generated only once and I am not using authentication tag.Is the encryptedData packaged in the right wayBrewage
Yes, you are, because it is part of the data returned as mySealedBox.combined. So do you do anything with the key and ciphertext in between the calls of these methods? Could you print out encryptedData and decryptToData in hexadecimals or base64? The code I must admit looks a bit haphazard, with let combinedData = decryptToData // Previous sealed bo not even being utilized... Preferably print out the key value as well!Illustration
I think let combinedData = decryptToData might be the reason because I need a sealed object and this is a data object.How do we make a Data object to a AES.GCM.SealedBox for decryptionBrewage
I don't think there is anything wrong there. Please reread my previous comment and print out the keys and encrypted values after encryption and before decryption...Illustration
@MaartenBodewes I got it working.There were some extra bytes added to the the decrypt data which was different from encrypted data lengthBrewage
Cool, no reason to keep the question around then. And if you get into the situation again, compare input / output in hexadecimals! That should always provide the solution, assuming you got the algorithm right.Illustration
thanks for asking this. I was looking for encryption using a symmetric key. please post how you solved your problem, maybe one like me used your codes.Mindamindanao
Do NOT use that code, it is unsafe, you are creating an IV in global scope and it gets reused between encryptions, that is STRONGLY DISCOURAGED, instead use the func which generates its own unique IV every time. I.e. skip passing the IV in.Coulee
P
1
    import XCTest
    import CryptoKit
    import Foundation
    
    class CryptoKitUnitTest: XCTestCase {
    
        func testEncryptandDecrypt(){
            let secret = "my-256-bit-secret-my-secret-my-s"
    
            let key = SymmetricKey(data: secret.data(using: .utf8)!)
    
            let plain = "Say hello to my little friend!"
            let nonce = try! AES.GCM.Nonce(data: Data(base64Encoded: "fv1nixTVoYpSvpdA")!)
    
            // Encrypt
            let sealedBox = try! AES.GCM.seal(plain.data(using: .utf8)!, using: key, nonce: nonce)
    
            let ciphertext = sealedBox.ciphertext.base64EncodedString()
            print("ciphertext: \(ciphertext)") // bWtTZkPAu7oXpQ3QpHvoTvc4NQgDTIycXHFJWvjk
    
            let sealedBoxToDecrypt = try! AES.GCM.SealedBox(nonce: nonce,
                                                            ciphertext: Data(base64Encoded: ciphertext)!,
                                                            tag: sealedBox.tag)
            let decrypted = try! AES.GCM.open(sealedBoxToDecrypt, using: key)
    
            print(String(decoding: decrypted, as: UTF8.self))
    
        }
    
        func testEncryptandDecryptFirstWay() {
            let keyStr = "d5a423f64b607ea7c65b311d855dc48f36114b227bd0c7a3d403f6158a9e4412"
            let key = SymmetricKey(data: Data(hex:keyStr))
            let nonceData = Data(hex: "131348c0987c7eece60fc0bc")
            let nonce: AES.GCM.Nonce = try! AES.GCM.Nonce(data: nonceData)
            let plain = "This is first cypto graphy method"
            var decyptedStr = ""
            if let encyptedData = plain.asData.encrypt(nonce: nonce, key: key) {
                decyptedStr = encyptedData.decrypt(nonce: nonce, key: key)
            }
            XCTAssertEqual(plain, decyptedStr)
        }
    }
      extension Data {
        func encrypt(nonce: AES.GCM.Nonce, key: SymmetricKey) ->Data?{
            // Encrypt
            do {
                let sealedBox = try AES.GCM.seal(self, using: key, nonce: nonce)
                let cipherText = sealedBox.ciphertext.base64EncodedString()
                let tag = sealedBox.tag
                let tagPlusCipherText = tag + cipherText.asData
                return tagPlusCipherText
            }
            catch let exceptionInfo {
                debugPrint("Encrypt exception Info: \(exceptionInfo)")
            }
            return nil
        }
    func decrypt(nonce: AES.GCM.Nonce, key: SymmetricKey) -> String{
            let tag = self.subtract(0, 16)
            let cipherTextData = self.subtract(tag.count, self.count - tag.count)
            let cipherText = cipherTextData.asString
            // Decrypt
            var decodeStr: String = ""
            do {
                let sealedBoxToDecrypt = try AES.GCM.SealedBox(nonce: nonce,
                                                               ciphertext: Data(base64Encoded: cipherText)!,
                                                               tag: tag)
                let decrypted = try AES.GCM.open(sealedBoxToDecrypt, using: key)
    
                decodeStr = String(decoding: decrypted, as: UTF8.self)
            } catch let exceptionInfo {
                debugPrint("Decrypt exception info: \(exceptionInfo)")
            }
    
            return decodeStr
        }
    
  public func subtract(_ start: Int, _ length: Int) ->Data {
        precondition(self.count >=  start + length,
                     "Invalid data range range. trying to find out of bound data")
        let allBytes = Array(Data(bytes: self.bytes, count: self.count))
        let partBytes = Array(allBytes[start..<start + length])
        let dataPart = Data(bytes: partBytes, count: partBytes.count)
        return dataPart
    }
    var asString: String {
        let str = String(decoding: self, as: UTF8.self)
        return str
    }

    }

extension String {
    var asData: Data {
        return self.data(using: .utf8) ?? Data()
    }
}
Prate answered 11/8, 2022 at 11:10 Comment(1)
Give self.bytesSurefooted
P
0
    extension Data {
    func encrypt(nonce: AES.GCM.Nonce, key: SymmetricKey) ->Data?{
        // Encrypt
        do {
            let sealedBox = try AES.GCM.seal(self, using: key, nonce: nonce)
            let cipherText = sealedBox.ciphertext.base64EncodedString()
            let tag = sealedBox.tag
            let tagPlusCipherText = tag + cipherText.asData
            return tagPlusCipherText
        }
        catch let exceptionInfo {
            debugPrint("Encrypt exception Info: \(exceptionInfo)")
        }
        return nil
    }
func decrypt(nonce: AES.GCM.Nonce, key: SymmetricKey) -> String{
        let tag = self.subtract(0, 16)
        let cipherTextData = self.subtract(tag.count, self.count - tag.count)
        let cipherText = cipherTextData.asString
        // Decrypt
        var decodeStr: String = ""
        do {
            let sealedBoxToDecrypt = try AES.GCM.SealedBox(nonce: nonce,
                                                           ciphertext: Data(base64Encoded: cipherText)!,
                                                           tag: tag)
            let decrypted = try AES.GCM.open(sealedBoxToDecrypt, using: key)

            decodeStr = String(decoding: decrypted, as: UTF8.self)
        } catch let exceptionInfo {
            debugPrint("Decrypt exception info: \(exceptionInfo)")
        }

        return decodeStr
    }

}
Prate answered 11/8, 2022 at 11:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.