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)
}
}