how to decode and decrypt a string in swift

177 views Asked by At

From a server, I get an encrypted and base 64 encoded string, these are criteria used to encrypt it.

  • aes 256 cbc encryption system with hexadecimal digest
  • the key is hash sha 512 of a phone number
  • the first 32 characters are the key, the last 16 characters are the ivs
  • I get the result in base 64 of the AES encryption

I tried many solutions, these are two of many versions of the code. It runs, but I'm not getting the right decryption.

updated version, still not running

import UIKit
import CryptoKit
import Security
import CommonCrypto

class ViewController: UIViewController {

    let encryptedString = "myEncryptedAndEncodedString"
    let phoneNumber = "myPhoneNumber"

    override func viewDidLoad() {
        super.viewDidLoad()

        var sha512HashFromPhoneNumber = ""

        // 1. Get the hash from the number
        if let tempSha512Hash = sha512(phoneNumber) {
            print("✅ SHA-512 hash: \(tempSha512Hash)")
            sha512HashFromPhoneNumber = tempSha512Hash
        } else {
            print("❌ error calculating hash")
        }

        var key = Data()
        var iv = Data()

        // 2. Extract key and IV
        if let (tempKey, tempIv) = extractKeyAndIV(from: sha512HashFromPhoneNumber) {
            key = tempKey
            iv = tempIv
        } else {
            print("❌ Error extracting key and IV")
        }

        print("✅ Key NSData: \(key as NSData)")
        print("✅ IV NSData: \(iv as NSData)")

        var decodedData = Data()
        // 3. Decode the Base64 string
        if let tempDecodedData = decodeBase64(encryptedString) {
            decodedData = tempDecodedData
        } else {
            print("❌ Error decoding base64 string.")
        }

        print("✅ Decoded Data: \(decodedData as NSData)")

        // 4. Decrypt the encrypted data
        if let decryptedString = decryptAES256CBC(encryptedData: decodedData, key: key, iv: iv) {
            print("✅ Decrypted string: \(decryptedString)")
        } else {
            print("❌ error decrypting String.")
        }
    }


    // 1. Get the hash from the number
    func sha512(_ string: String) -> String? {
        guard let data = string.data(using: .utf8) else { return nil }

        var hash = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
        data.withUnsafeBytes {
            _ = CC_SHA512($0.baseAddress, CC_LONG(data.count), &hash)
        }

        return hash.map { String(format: "%02x", $0) }.joined()
    }

    // 2. Extract key and IV
    func extractKeyAndIV(from hash: String) -> (key: Data, iv: Data)? {
        let keyString = String(hash.prefix(32))
        let ivString = String(hash.dropFirst(32).suffix(16))
        print("keyString \(keyString) count \(keyString.count)")
        print("ivString  \(ivString)  count \(ivString.count)")
        // This part handles the hexadecimal digest
        guard let keyData = Data(hexString: keyString), let ivData = Data(hexString: ivString) else { return nil }
        return (key: keyData, iv: ivData)
    }

    // 3. Decode the Base64 string
    func decodeBase64(_ base64String: String) -> Data? {
        return Data(base64Encoded: base64String)
    }

    // 4. Decrypt the encrypted data
    func decryptAES256CBC(encryptedData: Data, key: Data, iv: Data) -> String? {
        let bufferSize = encryptedData.count
        var buffer = Data(count: bufferSize)

        let options = CCOptions(kCCOptionPKCS7Padding)
        var numBytesDecrypted: size_t = 0
        // This part handles the AES-256-CBC decryption
        let cryptStatus = key.withUnsafeBytes { keyBytes in
            iv.withUnsafeBytes { ivBytes in
                encryptedData.withUnsafeBytes { dataBytes in
                    buffer.withUnsafeMutableBytes { mutableBytes in
                        CCCrypt(CCOperation(kCCDecrypt), CCAlgorithm(kCCAlgorithmAES), options,
                                keyBytes.baseAddress, key.count,
                                ivBytes.baseAddress,
                                dataBytes.baseAddress, bufferSize,
                                mutableBytes.baseAddress, bufferSize,
                                &numBytesDecrypted)
                    }
                }
            }
        }

        if cryptStatus == kCCSuccess {
            buffer.count = numBytesDecrypted
            return String(data: buffer, encoding: .utf8)
        } else {
            return nil
        }
    }

}

// Extension to handle hex string conversion
extension Data {
    init?(hexString: String) {
        let length = hexString.count / 2
        var data = Data(capacity: length)
        for i in 0..<length {
            let j = hexString.index(hexString.startIndex, offsetBy: i*2)
            let k = hexString.index(j, offsetBy: 2)
            //print("j: \(hexString.distance(from: hexString.startIndex, to: j))")
            //print("k: \(hexString.distance(from: hexString.startIndex, to: k))")

            let bytes = hexString[j..<k]
            if var num = UInt8(bytes, radix: 16) {
                data.append(&num, count: 1)
            } else {
                return nil
            }
        }
        self = data
    }
}






import UIKit
import CryptoKit
import CommonCrypto

class ViewController: UIViewController {

    let encryptedString = "myencryptedSring"
        let phoneNumber = "mygivengNumber"
        

    override func viewDidLoad() {
        super.viewDidLoad()

        if let decryptedString = decryptAES256CBC(encryptedData: encryptedString, key: phoneNumber) {
            print("original email: \(decryptedString)")
        } else {
            print("error during decoding")
        }
    }

    func decryptAES256CBC(encryptedData: String, key: String) -> String? {
        guard let data = Data(base64Encoded: encryptedData) else { return nil }

        let keyData = SHA512.hash(data: key.data(using: .utf8)!)
        let keyBytes = Data(keyData.prefix(32)).bytes
        let ivBytes = Data(keyData.suffix(16)).bytes

        var numBytesDecrypted = 0
        var decryptedData = Data(count: data.count + kCCBlockSizeAES128)

        let status = decryptedData.withUnsafeMutableBytes { (decryptedBytes: UnsafeMutableRawBufferPointer) -> CCCryptorStatus in
            let decryptedDataCopy = Data(decryptedData)
            return decryptedDataCopy.withUnsafeBytes { (dataBytes: UnsafeRawBufferPointer) -> CCCryptorStatus in
                data.withUnsafeBytes { (dataBytes: UnsafeRawBufferPointer) -> CCCryptorStatus in
                    CCCrypt(CCOperation(kCCDecrypt), CCAlgorithm(kCCAlgorithmAES), CCOptions(kCCOptionPKCS7Padding), keyBytes, kCCKeySizeAES256, ivBytes, dataBytes.baseAddress, data.count, decryptedBytes.baseAddress, decryptedDataCopy.count, &numBytesDecrypted)
                }
            }
        }

        if status == kCCSuccess {
            decryptedData = Data(decryptedData.prefix(numBytesDecrypted))
            return String(data: decryptedData, encoding: .utf8)
        } else {
            return nil
        }
    }
}

extension Data {
    var bytes: [UInt8] {
        return [UInt8](self)
    }
}
0

There are 0 answers