iOS - Decrypt values encrypted by AES - ios

I need decrypt value encrypted very similar to first example in PHP mcrypt-encrypt
This is what I know:
iv is base64 encoded
values are base64 encoded as well
After decoding both values from base64 then I should use decrypt method similar to PHP mcrypt-decrypt
I am using CryptoSwift library and I created this helper method (it needs to use parameters and not values in code, it's just until I get it working):
class func aesDecrypt(value: String, key: String) {
let vector = "8Z2IwsEwZ5lh27kFUmhiww=="
let vectorData = Data(base64Encoded: vector)
let vectorDecodedString = String(data: vectorData!, encoding: .unicode)
print("Vector decoded: \(vectorDecodedString)") // foo
let key = "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3"
let manufacture = "t0gEQWTxKgrGCOqXYOIuf6syF7nm1oCrwJVsxUJvw6e2sRQ25TgmML6vzfA3YFFe"
let keyBytes: [UInt8] = Array(key.utf8) //16
let ivBytes: [UInt8] = [UInt8](vectorData!)//Array(vectorDecodedString!.utf8)
let manufactureData = Data(base64Encoded: manufacture)
let valueInBytes = [UInt8](manufactureData!)
do {
let aes = try AES(key: keyBytes, iv: ivBytes, blockMode: .CBC)
let decryptedBytes = try aes.decrypt(valueInBytes)
let decryptedData = Data(bytes: decryptedBytes)
let decryptedString = String(bytes: decryptedBytes, encoding: .utf8)
let decryptedString2 = String(data: decryptedData, encoding: .utf8)
print("decryptedString: \(decryptedString)")
} catch let error {
print(error.localizedDescription)
// some error
}
}
Values in code I get from server. I tried AES with bytes or with strings but without luck. What's wrong with my code? How could I fix it? Thanks for help

Related

Issue in converting Base64string into string

I am trying to convert base64 string in to string format but I always get nil. My base64 string is "NWQwMDU2ZjhiZjRjYmI2M2MxZTI0NzQzNjAxMjMxMzAyMDh8NjAxMjMxMzAyMDh8NWQwMDU2Zjhi\nZjRjYmI2M2MxZTI0NzQzfDYwMTIzMTMwMjA4fG5hdmlnYXRpb25UZXN0MDA1fDIwMTktMDYtMjEg\nMDk6MzQ6MDB8MA==\n"
After decoding, Is suppose to look like this "5d0056f8bf4cbb63c1e2474360123130208|60123130208|5d0056f8bэ͌Ŕ٥ѥQشĂs3C�".
Here is my code event I tried to remove the "=\n" from string but not succeed.
func qrScanningSucceededWithCode(_ str: String?) {
scanTicketView.qrData = QRData(codeString: str)
let charsToRemove: Set<Character> = Set("=\n")
let newNumberCharacters = String(str!.filter { !charsToRemove.contains($0) })
let decodedString = String(data: Data(base64Encoded: newNumberCharacters)!, encoding: .utf8)!
print(decodedString)
}
This works:
let string = "NWQwMDU2ZjhiZjRjYmI2M2MxZTI0NzQzNjAxMjMxMzAyMDh8NjAxMjMxMzAyMDh8NWQwMDU2Zjhi\nZjRjYmI2M2MxZTI0NzQzfDYwMTIzMTMwMjA4fG5hdmlnYXRpb25UZXN0MDA1fDIwMTktMDYtMjEg\nMDk6MzQ6MDB8MA==\n"
let joined = string.replacingOccurrences(of: "\n", with: "")
if let data = Data(base64Encoded: joined) {
String(data: data, encoding: .utf8)
}

AES Encryption to strange characters

I am using AES Encryption in swift 3, I use this CryptoSwift library.
This is my code to encrypt a string and the result is readable string: /QOEtrf3o8buv2wA9FeAyg==.
How can I get the strange character (non readable) like this: Ί�^��h��y^ғ?
var input = "CryptoSwift"
var key = "passwordpassword"
var iv = "drowssapdrowssap"
func aesEncrypt(input: String, key: String, iv: String) throws -> String {
let data = input.utf8
let encrypted = try! AES(key: key, iv: iv, blockMode: .CBC, padding: PKCS7()).encrypt([UInt8](data))
let encryptedData = Data(encrypted)
return encryptedData.base64EncodedString()
}
let encrypted = try! aesEncrypt(input: input, key: key, iv: iv)
print("encrypted: \(encrypted)")
---------
Result: /QOEtrf3o8buv2wA9FeAyg==
I want the result something like this: Ί�^��h��y^ғ, the strange characters.
You shouldn't convert it to Base64.
let encrypted = try! AES(key: key, iv: iv, blockMode: .CBC, padding: PKCS7()).encrypt([UInt8](data))
let encryptedData = Data(bytes: UnsafePointer<UInt8>(encrypted), count: Int(encrypted.count))
// let encryptedString = String(data: encryptedData,encoding: String.Encoding.utf8)
// use the encryptedData to write it into a file.
"Ί�^��h��y^ғ" isn't a proper string. The character "�" means "this isn't a character." (It's technical name is the "substitution character" that is used when a byte sequence is not valid for the Unicode-based encoding you're using). Since "�" could be many different byte sequences, "Ί�^��h��y^ғ" isn't really meaningful. There are a huge number of byte sequences that would decode into that nonsense string.
You're getting a "readable string" because you're encoding the random bytes that come out of the encryption function in Base64.
It's not really clear what you mean by "wanting" something that includes � (since that's nonsense). If you want the data, just return the Data (don't call base64EncodedString()). As a general rule, this is what you want to work with. Encrypted data is Data, it's not `String.
What are you trying to do that you want a nonsense string that has lost information in the encoding?
You're returning a base64 encoded string which will always be readable ASCII. I'm unfamiliar with CryptoSwift, but if you can find some way to return the raw encrypted data, it should look the way you want.
Here is how I use it to properly decrypt and encrypt strings. You need to make string in hexString and hexString in data later. This is how CryptoSwift work.
extension String{
func aesEncrypt(key: String, iv: String) throws -> String {
let data = self.data(using: .utf8)!
let encrypted = try! AES(key: key, iv: iv, blockMode: .CBC).encrypt([UInt8](data))
let encryptedData = Data(encrypted)
try? encryptedData.toHexString().aesDecrypt(key: key, iv: iv)
return encryptedData.toHexString()
}
func aesDecrypt(key: String, iv: String) throws -> String {
let data = self.dataFromHexadecimalString()!
print(data)
let decrypted = try! AES(key: key, iv: iv, blockMode: .CBC).decrypt([UInt8](data))
let decryptedData = Data(decrypted)
return String(bytes: decryptedData.bytes, encoding: .utf8) ?? "Could not decrypt"
}
func dataFromHexadecimalString() -> Data? {
var data = Data(capacity: characters.count / 2)
let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
regex.enumerateMatches(in: self, options: [], range: NSMakeRange(0, characters.count)) { match, flags, stop in
let byteString = (self as NSString).substring(with: match!.range)
var num = UInt8(byteString, radix: 16)
data.append(num!)
}
return data
}
}
extension Data {
public var bytes: Array<UInt8> {
return Array(self)
}
public func toHexString() -> String {
return self.bytes.toHexString()
}
}

How to convert Data received from UIImagePNGRepresentation() to String and vice versa?

This is how I create Data from UIImage:
let data = UIImagePNGRepresentation(image)
And then I need to convert it to String;
if let data = data {
let stringFromData = String(data: data, encoding: .utf8)
}
but stringFromData is nil. Why?
You can get it using the Data method base64EncodedString()
if let data = data {
let stringFromData = data.base64EncodedString()
// to decode base 64 string you can use Data base64Encoded String initializer
if let dataFromBase64 = Data(base64Encoded: stringFromData) {
print(data)
}
}
Convert Your image data in Base64 string
For Encode
let stringFromData : Data = Data(base64Encoded: strBase64, options: .ignoreUnknownCharacters)!
And decode
let strBase64 = imageData.base64EncodedStringWithOptions(.allZeros)

Could not decrypt a base64String using CryptoSwift

String for encryption "secret"
after encryption "64c2VjcmV0"
this is the code that works properly
let inputNSData: NSData = input.dataUsingEncoding(NSUTF8StringEncoding)!
let inputBytes: [UInt8] = inputNSData.arrayOfBytes()
let key: [UInt8] = self.generateArray("secret0key000000") //16
let iv: [UInt8] = self.generateArray("0000000000000000") //16
do {
let encrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .CBC).encrypt(inputBytes, padding: PKCS7())
let decrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .CBC).decrypt(encrypted, padding: PKCS7())
let decryptNsData: NSData = NSData(bytes: decrypted, length: decrypted.count)
let c = decryptNsData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
let decryptedString: String = NSString(data: decryptNsData, encoding: NSUTF8StringEncoding) as! String
print("String after decryption\t\(decryptedString)")
} catch {
// some error
}
but i could not decrypt by using the same key and iv
I am getting fatal error: unexpectedly found nil while unwrapping an Optional value for the encrypted string
let key: [UInt8] = self.generateArray("secret0key000000") //16
let iv: [UInt8] = self.generateArray("0000000000000000") //16
let input: String = "64c2VjcmV0"
var encryptedStrData = NSData(base64EncodedString: input, options: NSDataBase64DecodingOptions())!
let inputBytes: [UInt8] = encryptedStrData.arrayOfBytes()
print("String in uint8\(inputBytes)")
//var keyData = keyStr.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
//var ivData:NSData = ivStr.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
do{
let decryptedTryData = try AES(key: key, iv: iv, blockMode: .CBC).decrypt(inputBytes)
print(decryptedTryData)
}
catch{
}
I am getting fatal error: unexpectedly found nil while unwrapping an Optional value for the encrypted string
You are using Base64 when it is not necessary, only Base64 encode non string data.
Here is the first test code:
let inputBytes: [UInt8] = Array("secret".utf8)
let key: [UInt8] = Array("secret0key000000".utf8) //16
let iv: [UInt8] = Array("0000000000000000".utf8) //16
var encryptedBase64 = ""
do {
let encrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .CBC).encrypt(inputBytes, padding: PKCS7())
let encryptedNSData = NSData(bytes: encrypted, length: encrypted.count)
encryptedBase64 = encryptedNSData.base64EncodedStringWithOptions([])
let decrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .CBC).decrypt(encrypted, padding: PKCS7())
let result = String(bytes: decrypted, encoding: NSUTF8StringEncoding)!
print("result\t\(result )")
} catch {
// some error
}
print("encryptedBase64: \(encryptedBase64)")
Output:
result: secret
encryptedBase64: 0OCxa0yJszq9MvkrWjn3wg==
let encryptedData = NSData(base64EncodedString: encryptedBase64, options:[])!
print("decodedData: \(encryptedData)")
let encrypted = Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>(encryptedData.bytes), count: encryptedData.length))
do {
let decryptedData = try AES(key: key, iv: iv, blockMode: .CBC).decrypt(encrypted)
let decryptedString = String(bytes: decryptedData, encoding: NSUTF8StringEncoding)!
print("decryptedString: \(decryptedString)")
}
catch{
// some error
}
Output:
decryptedString: secret
Notes:
Don't use CryptoSwift, it does not use the build-in encryption hardware and is 400 to 1000 times slower than the Apple Security.framework Common Crypto. It is also not well vetted and used non-certified encryption code.
Don't use a string directly as the key, it is not secure. Instead derive a key from the string using PBKDK2 (Password Based Key Derivation Function).
Base64 strings must be divisible by 4. Yours is not.
You can use a website, such as https://www.base64decode.org, to test your strings.
For Swift3 (to avoid the UnsafePointer error) this has worked for me for the second part (decoding the base64 variable):
let encryptedData = NSData(base64Encoded: encryptedBase64, options:[])!
print("decodedData: \(encryptedData)")
let count = encryptedData.length / MemoryLayout<UInt8>.size
// create an array of Uint8
var encrypted = [UInt8](repeating: 0, count: count)
// copy bytes into array
encryptedData.getBytes(&encrypted, length:count * MemoryLayout<UInt8>.size)
do {
let decryptedData = try AES(key: key, iv: iv, blockMode: .CBC).decrypt(encrypted)
let decryptedString = String(bytes: decryptedData, encoding: String.Encoding.utf8)!
print("decryptedString: \(decryptedString)")
}
catch{
// some error
}

Encrypt/Decrypt string in iOS using CryptoSwift

I'm trying to encrypt a string and then decrypt it back using CryptoSwift. Here's the code:
let key: [UInt8] = [0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c]
let iv: [UInt8] = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F]
let message = "Hello there!".dataUsingEncoding(NSUTF8StringEncoding)!.arrayOfBytes()
do {
let encryptedBytes = try ChaCha20(key: key, iv: iv)!.encrypt(message)
let decryptedBytes = try ChaCha20(key: key, iv: iv)!.decrypt(encryptedBytes)
let data = NSData.withBytes(decryptedBytes)
let decrypted = String(data: data, encoding: NSUTF8StringEncoding)
print(decrypted) // this should print "Hello there!", but it doesn't
}
catch { ... }
I think this should print out "Hello there!", the original string. But instead I get this: (<48656c6c 6f207468 65726521>, 4)
Any ideas what am I doing wrong?
I figured this out. Changed this line:
let decrypted = String(data: data, encoding: NSUTF8StringEncoding)
to:
let decrypted = String(bytes: decryptedBytes, encoding: NSUTF8StringEncoding)
and it's working now.

Resources