Related
I was followed this answer to encrypt the data. The encryption is success. But I am stuck with the decrypting the data. I've lot of datas are encrypted. But I used another answers for decryption and decrypted data is not as original. I tried to decrypt the data form the same answer but it is success but the decrypted data is just empty. So, I tried to update the deprication of decryption code but I can't resolve this error when converting clearData to bytes in the line let cryptStatus = clearData.withUnsafeBytes { (cryptBytes)
Cannot convert value of type 'UnsafeRawBufferPointer' to expected
argument type 'UnsafeMutableRawPointer?'
Can you please help me to resolve the error? Thank you.
import Accelerate
import CommonCrypto
Encryption:
func encrypt() {
let data = "Hello,World".data(using: .utf8)!
let keyData = "SOME_SECRET_CODE".data(using: .utf8)!
if let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
"",
(data as NSData).bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
print("Encryption Success...")
cryptData.length = Int(numBytesEncrypted)
self.decrypt(data: cryptData as Data, keyData: keyData)
}else {
print("Encryption isn't success!")
}
}else{
print("Can't encrypt")
}
}
Decryption:
func decrypt(data:Data, keyData:Data){
let keyLength = keyData.count
let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
if (validKeyLengths.contains(keyLength) == false) {
fatalError("Invalid key length")
}
let ivSize = kCCBlockSizeAES128;
let clearLength = size_t(data.count - ivSize)
var clearData = Data(count:clearLength)
var numBytesDecrypted :size_t = 0
let options = CCOptions(kCCOptionPKCS7Padding)
let cryptStatus = clearData.withUnsafeBytes { (cryptBytes) -> CCCryptorStatus in
data.withUnsafeBytes { (dataBytes) -> CCCryptorStatus in
keyData.withUnsafeBytes { (keyBytes) -> CCCryptorStatus in
return CCCrypt(CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
options,
keyBytes, keyLength,
dataBytes,
dataBytes+kCCBlockSizeAES128, clearLength,
cryptBytes, clearLength, // Error here
&numBytesDecrypted)
}
}
}
/*
let cryptStatus = clearData.withUnsafeMutableBytes {cryptBytes in
data.withUnsafeBytes {dataBytes in
keyData.withUnsafeBytes {keyBytes in
CCCrypt(CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
options,
keyBytes, keyLength,
dataBytes,
dataBytes+kCCBlockSizeAES128, clearLength,
cryptBytes, clearLength,
&numBytesDecrypted)
}
}
}
*/
clearData.count = numBytesDecrypted
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
clearData.count = numBytesDecrypted
if let string = String(data: clearData, encoding: .utf8){
print("Decrypted: \(string)")
}else{
print("Decryption failed! \(clearData.count)")
}
}
else {
fatalError("Decryption failed")
}
}
Your code needs a little refactoring and you're good to go.
let cryptStatus: CCCryptorStatus = clearData.withUnsafeBytes {cryptBytes in
data.withUnsafeBytes {dataBytes in
keyData.withUnsafeMutableBytes {keyBytes in
return CCCrypt(CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
options,
cryptBytes, keyLength,
dataBytes,
dataBytes+kCCBlockSizeAES128, clearLength,
keyBytes.baseAddress!, clearLength,
&numBytesDecrypted)
}
}
}
Now there will be a compile time error saying Cannot use mutating member on immutable value: 'keyData' is a 'let' constant
In order to get rid of this error, just modify the keyData parameter of your decrypt func like below.
func decrypt(data:Data, keyData: inout Data)
Function Call
self.decrypt(data: cryptData as Data, keyData: &keyData)
inout Parameters:
All parameters passed into a Swift function are constants, so you can’t change them. If you want, you can pass in one or more parameters as inout, which means they can be changed inside your function, and those changes reflect in the original value outside the function.
I want to encrypt a message on playground. my code is given below. i write another class to generate a secretkey. when convert the secret key into string, it gives error.
import UIKit
import Foundation
import CommonCrypto
class SecretSpec {
var algorithm: String = "AES/ECB/PKCS5padding"
var key = [UInt8]()
func SecretSpec(key: [UInt8], algorithm: String){
self.key = key
self.algorithm = algorithm
}
func getAlgorithm() -> String {
return self.algorithm
}
func getFormat() -> String {
return "RAW"
}
func getEncoded() -> [UInt8] {
return self.key
}
func hashCode() -> Int {
var retval: Int = 0
for i in 1...key.count-1 {
retval = retval + Int(key[i]) * Int(i)
}
if (algorithm.lowercased() == "tripledes"){
retval = retval ^ Int("desede".hashValue)
return retval
}else{
retval = retval ^ Int(algorithm.lowercased().hashValue)
return retval
}
}
}
extension String {
func aesEncrypt(key: String, options:Int = (kCCOptionECBMode + kCCOptionPKCS7Padding)) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = self.data(using: String.Encoding.utf8),
let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation, algoritm, options,
(keyData as NSData).bytes, keyLength,
nil, (data as NSData).bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
var bytes = [UInt8](repeating: 0, count: cryptData.length)
cryptData.getBytes(&bytes, length: cryptData.length)
var hexString = ""
for byte in bytes {
hexString += String(format:"%02x", UInt8(byte))
}
return hexString
}
else {
return nil
}
}
return nil
}
}
func MD5(_ string: String) -> String? {
let length = Int(CC_MD5_DIGEST_LENGTH)
var digest = [UInt8](repeating: 0, count: length)
if let d = string.data(using: String.Encoding.utf8) {
_ = d.withUnsafeBytes { (body: UnsafePointer<UInt8>) in
CC_MD5(body, CC_LONG(d.count), &digest)
}
}
return (0..<length).reduce("") {
$0 + String(format: "%02x", digest[$1])
}
}
var mdT = "YourStrongKeyasdfghjklzxcvbnm"
var algorithm: String = "AES/ECB/PKCS7padding"
var s = MD5(mdT)
let buf: [UInt8] = Array(s!.utf8)
var skcSpec = SecretSpec()
skcSpec.SecretSpec(key: buf, algorithm: algorithm)
print("hello: \(skcSpec)")
skcSpec.getEncoded()
skcSpec.getFormat()
skcSpec.getAlgorithm()
skcSpec.hashCode()
let msg: NSMutableDictionary = NSMutableDictionary()
msg.setValue("uttam kumar", forKey: "name")
msg.setValue("1001", forKey: "id")
let msgData: NSData
var msgStr: String = ""
var requestUrl: String = ""
do {
msgData = try JSONSerialization.data(withJSONObject: msg, options: JSONSerialization.WritingOptions()) as NSData
msgStr = NSString(data: msgData as Data, encoding: String.Encoding.utf8.rawValue)! as String
} catch _ {
print ("JSON Failure")
}
var skc = String(data: Data(skcSpec), encoding: .utf8)!
var encoded = msgStr.aesEncrypt(key: String(skc))!
print("encoded: \(encoded)")
I want to get String value of 'skc'. and print it. but it gives 'Argument type 'SecretSpec' does not conform to expected type 'Sequence'' error. please help me.
Data does not have an initialiser for your custom type. Did you mean to get the encoded value?
var skc = String(data: Data(skcSpec.getEncoded()), encoding: .utf8)!
I am trying to use DES algorithm for Encryption and decryption in swift
But with the code that I have written the encrypted message is changing for every build
Here is my code:
import UIKit
import CommonCrypto
public class IAppEncryptionUtitlity: NSObject {
private override init(){}
public static let sharedNetworkVar: IAppEncryptionUtitlity = IAppEncryptionUtitlity()
let key = IAppConfig.key
func myEncrypt(encryptData:String) -> NSData?{
var myKeyData : NSData = ("DyfmgL9p" as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData
var myRawData : NSData = encryptData.data(using: String.Encoding.utf8)! as NSData
var iv : [UInt8] = [56, 101, 63, 23, 96, 182, 209, 205] // I didn't use
var buffer_size : size_t = myRawData.length + kCCBlockSize3DES
var buffer = UnsafeMutablePointer<NSData>.allocate(capacity: buffer_size)
var num_bytes_encrypted : size_t = 0
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
let keyLength = size_t(kCCKeySize3DES)
var Crypto_status: CCCryptorStatus = CCCrypt(operation, algoritm, options, myKeyData.bytes, keyLength, nil, myRawData.bytes, myRawData.length, buffer, buffer_size, &num_bytes_encrypted)
if UInt32(Crypto_status) == UInt32(kCCSuccess){
var myResult: NSData = NSData(bytes: buffer, length: num_bytes_encrypted)
free(buffer)
print("my result \(myResult)") //This just prints the data
let keyData: NSData = myResult
let hexString = keyData.hexEncodedString()
print("hex result \(keyData)") // I needed a hex string output
//myDecrypt(decryptData: myResult) // sent straight to the decryption function to test the data output is the same
return myResult
}else{
free(buffer)
return nil
}
}
func myDecrypt(decryptData : NSData) -> NSData?{
var mydata_len : Int = decryptData.length
var keyData : NSData = ("myEncryptionKey" as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData
var buffer_size : size_t = mydata_len+kCCBlockSizeAES128
var buffer = UnsafeMutablePointer<NSData>.allocate(capacity: buffer_size)
var num_bytes_encrypted : size_t = 0
var iv : [UInt8] = [56, 101, 63, 23, 96, 182, 209, 205] // I didn't use
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionPKCS7Padding)
let keyLength = size_t(kCCKeySize3DES)
var decrypt_status : CCCryptorStatus = CCCrypt(operation, algoritm, options, keyData.bytes, keyLength, nil, decryptData.bytes, mydata_len, buffer, buffer_size, &num_bytes_encrypted)
if UInt32(decrypt_status) == UInt32(kCCSuccess){
var myResult : NSData = NSData(bytes: buffer, length: num_bytes_encrypted)
free(buffer)
print("decrypt \(myResult)")
var stringResult = NSString(data: myResult as Data, encoding:String.Encoding.utf8.rawValue)
print("my decrypt string \(stringResult!)")
return myResult
}else{
free(buffer)
return nil
}
}
}
extension NSData {
struct HexEncodingOptions: OptionSet {
let rawValue: Int
static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
}
func hexEncodedString(options: HexEncodingOptions = []) -> String {
let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
//var map = { String(format: format, $0) }.joined()
return ""
}
}
Output is changing for every build . Whats wrong in the code or
And is kCCOptionPKCS7Padding and kCCOptionPKCS5Padding is same?
Thanks In advance
Got Solution by changing the code
import UIKit
import CommonCrypto
var message: String?
public class IAppEncryptionUtitlity: NSObject {
//Calling method to encrypt using extensions
public func methodToCallEncryption( stringToEncrypt : String ) ->String {
let iVValue:String = "nzug8FrX"
let keyValue = IAppConfig.key //DyfmgL9p
let encoded = stringToEncrypt.desEncrypt( key : keyValue , iv : iVValue )
return encoded!
}
public func methodToCallDecryption( stringToDecrypt : String ) -> String{
let iVValue:String = "nzug8FrX"
let keyValue = IAppConfig.key //DyfmgL9p
let decoded = stringToDecrypt.desEncrypt( key : keyValue , iv : iVValue )
return decoded!
}
}
extension String {
func desEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = self.data(using: String.Encoding.utf8),
let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeDES) {
let keyLength = size_t(kCCKeySizeDES)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmDES)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
(data as NSData).bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString
}
else {
return nil
}
}
return nil
}
func desDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
let cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeDES) {
let keyLength = size_t(kCCKeySizeDES)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmDES)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
}
Thanks everyone for the help
We can use a String category like shown below for all symmetric encryption and decryption including DES, 3DES, and AES.
/// Extension for Symmetric Encryption and Decryption with DES, 3DES, AES algorithms
extension String {
/// Encrypts message with DES algorithm
func desEncrypt(key:String) -> String? {
return symetricEncrypt(key: key, blockSize: kCCBlockSizeDES, keyLength: size_t(kCCKeySizeDES), algorithm: UInt32(kCCAlgorithmDES))
}
/// Encrypts message with 3DES algorithm
func tripleDesEncrypt(key:String) -> String? {
return symetricEncrypt(key: key, blockSize: kCCBlockSize3DES, keyLength: size_t(kCCKeySize3DES), algorithm: UInt32(kCCAlgorithm3DES))
}
/// Encrypts message with AES 128 algorithm
func aes128Encrypt(key:String) -> String? {
return symetricEncrypt(key: key, blockSize: kCCBlockSizeAES128, keyLength: size_t(kCCKeySizeAES128), algorithm: UInt32(kCCAlgorithmAES128))
}
/// Encrypts message with AES algorithm
func aesEncrypt(key:String) -> String? {
return symetricEncrypt(key: key, blockSize: kCCBlockSizeAES128, keyLength: size_t(kCCKeySizeAES256), algorithm: UInt32(kCCAlgorithmAES))
}
/// Encrypts a message with symmetric algorithm
func symetricEncrypt(key:String, blockSize: Int, keyLength: size_t, algorithm: CCAlgorithm, options: Int = kCCOptionPKCS7Padding) -> String? {
let keyData = key.data(using: String.Encoding.utf8)! as NSData
let data = self.data(using: String.Encoding.utf8)! as NSData
let cryptData = NSMutableData(length: Int(data.length) + blockSize)!
let operation: CCOperation = UInt32(kCCEncrypt)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algorithm,
UInt32(options),
keyData.bytes, keyLength,
nil,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString
}
else {
return nil
}
}
/// Decrypts message with DES algorithm
func desDecrypt(key:String) -> String? {
return symetricDecrypt(key: key, blockSize: kCCBlockSizeDES, keyLength: size_t(kCCKeySizeDES), algorithm: UInt32(kCCAlgorithmDES))
}
/// Decrypts message with 3DES algorithm
func tripleDesDecrypt(key:String) -> String? {
return symetricDecrypt(key: key, blockSize: kCCBlockSize3DES, keyLength: size_t(kCCKeySize3DES), algorithm: UInt32(kCCAlgorithm3DES))
}
/// Decrypts message with AES 128 algorithm
func aes128Decrypt(key:String) -> String? {
return symetricDecrypt(key: key, blockSize: kCCBlockSizeAES128, keyLength: size_t(kCCKeySizeAES128), algorithm: UInt32(kCCAlgorithmAES128))
}
/// Decrypts message with AES algorithm
func aesDecrypt(key:String) -> String? {
return symetricDecrypt(key: key, blockSize: kCCBlockSizeAES128, keyLength: size_t(kCCKeySizeAES256), algorithm: UInt32(kCCAlgorithmAES))
}
/// Decrypts a message with symmetric algorithm
func symetricDecrypt(key:String, blockSize: Int, keyLength: size_t, algorithm: CCAlgorithm, options: Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
let cryptData = NSMutableData(length: Int((data.length)) + blockSize) {
let operation: CCOperation = UInt32(kCCDecrypt)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algorithm,
UInt32(options),
(keyData as NSData).bytes, keyLength,
nil,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
}
Full source:
https://gist.github.com/tharindu/1cf0201492e41f1c287e51abb02902cd
I'm doing tripleDES encryption and decryption. Getting this error:
UnsafePointer<UInt8>' is not convertible to 'UnsafePointer<_>
The code where I'm getting the error is:
let keyString = "25d1d4cb0a08403e2acbcbe0"
let keyData = keyString.data(using: .utf8)!
let message = pass
let data = message.data(using: .utf8)!
let cryptData = NSMutableData(length: Int(data.count) + kCCBlockSize3DES)!
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = keyData.withUnsafeBytes { (keyBytes: UnsafePointer<UInt8>) in
data.withUnsafeBytes { (dataBytes: UnsafePointer<UInt8>) in
cryptData.withUnsafeMutableBytes { (cryptBytes: UnsafeMutablePointer<UInt8>) in
CCCrypt(operation,
algoritm,
options,
keyBytes,
keyLength,
nil,
dataBytes,
data.count,
cryptBytes,
cryptData.count,
&numBytesEncrypted)
}
}
}
Anyone could help?
This error message is the result of a sort of compiler bug: the compiler cannot compile the code and emits an invalid and misleading error message. Also see https://bugs.swift.org/browse/SR-5931
In most cases, you can:
remove the type annotation (<UInt8>) to reveal the real cause
fix the cause
add the type annotation again
let keyString = "25d1d4cb0a08403e2acbcbe0"
let keyData = keyString.data(using: .utf8)!
let message = pass
let data = message.data(using: .utf8)!
let cryptData = NSMutableData(length: Int(data.count) + kCCBlockSize3DES)!
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = keyData.withUnsafeBytes { (keyBytes: UnsafePointer<UInt8>) in
data.withUnsafeBytes { (dataBytes: UnsafePointer<UInt8>) in
cryptData.withUnsafeMutableBytes { (cryptBytes: UnsafeMutablePointer<UInt8>) in
CCCrypt(operation,
algoritm,
options,
keyBytes,
keyLength,
nil,
dataBytes,
data.count,
&cryptBytes, //<-----try to do this
cryptData.count,
&numBytesEncrypted)
}
}
}
cryptData is a NSMutableData object, so it has mutableBytes to work with.
How about:
let keyString = "25d1d4cb0a08403e2acbcbe0"
let keyData = keyString.data(using: .utf8)!
let message = pass
let data = message.data(using: .utf8)!
let cryptData = NSMutableData(length: Int(data.count) + kCCBlockSize3DES)!
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = keyData.withUnsafeBytes { (keyBytes : UnsafePointer<UInt8>) in
data.withUnsafeBytes { (dataBytes : UnsafePointer<UInt8>) in
CCCrypt(operation,
algoritm,
options,
keyBytes,
keyLength,
nil,
dataBytes,
data.count,
cryptData.mutableBytes,
cryptData.length,
&numBytesEncrypted)
}
}
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
print("success!")
}
I write an application by swift, i need AES Encrypt and Decrypt functionality, i received encrypted data from another .Net solution, but i can't find something to do it.
This is my .net Encryption:
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
I need to decrypt function in swift.
CryptoSwift Example
Updated to Swift 2
import Foundation
import CryptoSwift
extension String {
func aesEncrypt(key: String, iv: String) throws -> String{
let data = self.dataUsingEncoding(NSUTF8StringEncoding)
let enc = try AES(key: key, iv: iv, blockMode:.CBC).encrypt(data!.arrayOfBytes(), padding: PKCS7())
let encData = NSData(bytes: enc, length: Int(enc.count))
let base64String: String = encData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0));
let result = String(base64String)
return result
}
func aesDecrypt(key: String, iv: String) throws -> String {
let data = NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions(rawValue: 0))
let dec = try AES(key: key, iv: iv, blockMode:.CBC).decrypt(data!.arrayOfBytes(), padding: PKCS7())
let decData = NSData(bytes: dec, length: Int(dec.count))
let result = NSString(data: decData, encoding: NSUTF8StringEncoding)
return String(result!)
}
}
Usage:
let key = "bbC2H19lkVbQDfakxcrtNMQdd0FloLyw" // length == 32
let iv = "gqLOHUioQ0QjhuvI" // length == 16
let s = "string to encrypt"
let enc = try! s.aesEncrypt(key, iv: iv)
let dec = try! enc.aesDecrypt(key, iv: iv)
print(s) // string to encrypt
print("enc:\(enc)") // 2r0+KirTTegQfF4wI8rws0LuV8h82rHyyYz7xBpXIpM=
print("dec:\(dec)") // string to encrypt
print("\(s == dec)") // true
Make sure you have the right length of iv (16) and key (32) then you won't hit "Block size and Initialization Vector must be the same length!" error.
CryptoSwift Example
Updated SWIFT 4.*
func aesEncrypt() throws -> String {
let encrypted = try AES(key: KEY, iv: IV, padding: .pkcs7).encrypt([UInt8](self.data(using: .utf8)!))
return Data(encrypted).base64EncodedString()
}
func aesDecrypt() throws -> String {
guard let data = Data(base64Encoded: self) else { return "" }
let decrypted = try AES(key: KEY, iv: IV, padding: .pkcs7).decrypt([UInt8](data))
return String(bytes: decrypted, encoding: .utf8) ?? self
}
Code provided by SHS didn't work for me, but this one apparently did (I used a Bridging Header: #import <CommonCrypto/CommonCrypto.h>):
extension String {
func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = self.data(using: String.Encoding.utf8),
let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
(data as NSData).bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString
}
else {
return nil
}
}
return nil
}
func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
let cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
}
From my ViewController:
let encoded = message.aesEncrypt(key: keyString, iv: iv)
let unencode = encoded?.aesDecrypt(key: keyString, iv: iv)
There is an interesting "pure-swift" Open Source library:
CryptoSwift: https://github.com/krzyzanowskim/CryptoSwift
It supports: AES-128, AES-192, AES-256, ChaCha20
Example with AES decrypt (got from project README.md file):
import CryptoSwift
let setup = (key: keyData, iv: ivData)
let decryptedAES = AES(setup).decrypt(encryptedData)
I was using CommonCrypto to generate Hash through the code of MihaelIsaev/HMAC.swift from Easy to use Swift implementation of CommonCrypto HMAC. This implementation is without using Bridging-Header, with creation of Module file.
Now to use AESEncrypt and Decrypt, I directly added the functions inside "extension String {" in HAMC.swift.
func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
data = self.dataUsingEncoding(NSUTF8StringEncoding),
cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
return base64cryptString
}
else {
return nil
}
}
return nil
}
func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.dataUsingEncoding(NSUTF8StringEncoding),
data = NSData(base64EncodedString: self, options: .IgnoreUnknownCharacters),
cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData, encoding:NSUTF8StringEncoding)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
The functions were taken from RNCryptor. It was an easy addition in the hashing functions and in one single file "HMAC.swift", without using Bridging-header. I hope this will be useful for developers in swift requiring Hashing and AES Encryption/Decryption.
Example of using the AESDecrypt as under.
let iv = "AA-salt-BBCCDD--" // should be of 16 characters.
//here we are convert nsdata to String
let encryptedString = String(data: dataFromURL, encoding: NSUTF8StringEncoding)
//now we are decrypting
if let decryptedString = encryptedString?.aesDecrypt("12345678901234567890123456789012", iv: iv) // 32 char pass key
{
// Your decryptedString
}
CryptoSwift is very interesting project but for now it has some AES speed limitations. Be carefull if you need to do some serious crypto - it might be worth to go through the pain of bridge implemmenting CommonCrypto.
BigUps to Marcin for pureSwift implementation
You can use CommonCrypto from iOS or CryptoSwift as external library. There are implementations with both tools below. That said, CommonCrypto output with AES should be tested, as it is not clear in CC documentation, which mode of AES it uses.
CommonCrypto in Swift 4.2
import CommonCrypto
func encrypt(data: Data) -> Data {
return cryptCC(data: data, key: key, operation: kCCEncrypt)
}
func decrypt(data: Data) -> Data {
return cryptCC(data: data, key: key, operation: kCCDecrypt)
}
private func cryptCC(data: Data, key: String operation: Int) -> Data {
guard key.count == kCCKeySizeAES128 else {
fatalError("Key size failed!")
}
var ivBytes: [UInt8]
var inBytes: [UInt8]
var outLength: Int
if operation == kCCEncrypt {
ivBytes = [UInt8](repeating: 0, count: kCCBlockSizeAES128)
guard kCCSuccess == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count, &ivBytes) else {
fatalError("IV creation failed!")
}
inBytes = Array(data)
outLength = data.count + kCCBlockSizeAES128
} else {
ivBytes = Array(Array(data).dropLast(data.count - kCCBlockSizeAES128))
inBytes = Array(Array(data).dropFirst(kCCBlockSizeAES128))
outLength = inBytes.count
}
var outBytes = [UInt8](repeating: 0, count: outLength)
var bytesMutated = 0
guard kCCSuccess == CCCrypt(CCOperation(operation), CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding), Array(key), kCCKeySizeAES128, &ivBytes, &inBytes, inBytes.count, &outBytes, outLength, &bytesMutated) else {
fatalError("Cryptography operation \(operation) failed")
}
var outData = Data(bytes: &outBytes, count: bytesMutated)
if operation == kCCEncrypt {
ivBytes.append(contentsOf: Array(outData))
outData = Data(bytes: ivBytes)
}
return outData
}
CryptoSwift v0.14 in Swift 4.2
enum Operation {
case encrypt
case decrypt
}
private let keySizeAES128 = 16
private let aesBlockSize = 16
func encrypt(data: Data, key: String) -> Data {
return crypt(data: data, key: key, operation: .encrypt)
}
func decrypt(data: Data, key: String) -> Data {
return crypt(data: data, key: key, operation: .decrypt)
}
private func crypt(data: Data, key: String, operation: Operation) -> Data {
guard key.count == keySizeAES128 else {
fatalError("Key size failed!")
}
var outData: Data? = nil
if operation == .encrypt {
var ivBytes = [UInt8](repeating: 0, count: aesBlockSize)
guard 0 == SecRandomCopyBytes(kSecRandomDefault, ivBytes.count, &ivBytes) else {
fatalError("IV creation failed!")
}
do {
let aes = try AES(key: Array(key.data(using: .utf8)!), blockMode: CBC(iv: ivBytes))
let encrypted = try aes.encrypt(Array(data))
ivBytes.append(contentsOf: encrypted)
outData = Data(bytes: ivBytes)
} catch {
print("Encryption error: \(error)")
}
} else {
let ivBytes = Array(Array(data).dropLast(data.count - aesBlockSize))
let inBytes = Array(Array(data).dropFirst(aesBlockSize))
do {
let aes = try AES(key: Array(key.data(using: .utf8)!), blockMode: CBC(iv: ivBytes))
let decrypted = try aes.decrypt(inBytes)
outData = Data(bytes: decrypted)
} catch {
print("Decryption error: \(error)")
}
}
return outData!
}
Swift4:
let key = "ccC2H19lDDbQDfakxcrtNMQdd0FloLGG" // length == 32
let iv = "ggGGHUiDD0Qjhuvv" // length == 16
func encryptFile(_ path: URL) -> Bool{
do{
let data = try Data.init(contentsOf: path)
let encodedData = try data.aesEncrypt(key: key, iv: iv)
try encodedData.write(to: path)
return true
}catch{
return false
}
}
func decryptFile(_ path: URL) -> Bool{
do{
let data = try Data.init(contentsOf: path)
let decodedData = try data.aesDecrypt(key: key, iv: iv)
try decodedData.write(to: path)
return true
}catch{
return false
}
}
Install CryptoSwift
import CryptoSwift
extension Data {
func aesEncrypt(key: String, iv: String) throws -> Data{
let encypted = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7).encrypt(self.bytes)
return Data(bytes: encypted)
}
func aesDecrypt(key: String, iv: String) throws -> Data {
let decrypted = try AES(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: .pkcs7).decrypt(self.bytes)
return Data(bytes: decrypted)
}
}
Update Swift 4.2
Here, for instance, we encrypt a string to base64encoded string. And then we decrypt the same to a readable string. (That would be same as our input string).
In my case, I use this to encrypt a string and embed that to QR Code. Then another party scan that and decrypt the same. So intermediate won't understand the QR codes.
Step 1: Encrypt a string "Encrypt My Message 123"
Step 2: Encrypted base64Encoded string : +yvNjiD7F9/JKmqHTc/Mjg== (The same printed on QR code)
Step 3: Scan and decrypt the string "+yvNjiD7F9/JKmqHTc/Mjg=="
Step 4: It comes final result - "Encrypt My Message 123"
Functions for Encrypt & Decrypt:
func encryption(stringToEncrypt: String) -> String{
let key = "MySecretPKey"
//let iv = "92c9d2c07a9f2e0a"
let data = stringToEncrypt.data(using: .utf8)
let keyD = key.data(using: .utf8)
let encr = (data as NSData?)!.aes128EncryptedData(withKey: keyD)
let base64String: String = (encr as NSData?)!.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
print(base64String)
return base64String
}
func decryption(encryptedString:String) -> String{
let key = "MySecretPKey"
//let iv = "92c9d2c07a9f2e0a"
let keyD = key.data(using: .utf8)
let decrpStr = NSData(base64Encoded: encryptedString, options: NSData.Base64DecodingOptions(rawValue: 0))
let dec = (decrpStr)!.aes128DecryptedData(withKey: keyD)
let backToString = String(data: dec!, encoding: String.Encoding.utf8)
print(backToString!)
return backToString!
}
Usage:
let enc = encryption(stringToEncrypt: "Encrypt My Message 123")
let decryptedString = decryption(encryptedString: enc)
print(decryptedString)
Classes for supporting AES encrypting functions, these are written in Objective-C. So for swift, you need to use bridge header to support these.
Class Name: NSData+AES.h
#import <Foundation/Foundation.h>
#interface NSData (AES)
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key;
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key;
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key iv:(NSData *)iv;
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key iv:(NSData *)iv;
#end
Class Name: NSData+AES.m
#import "NSData+AES.h"
#import <CommonCrypto/CommonCryptor.h>
#implementation NSData (AES)
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key
{
return [self AES128EncryptedDataWithKey:key iv:nil];
}
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key
{
return [self AES128DecryptedDataWithKey:key iv:nil];
}
- (NSData *)AES128EncryptedDataWithKey:(NSData *)key iv:(NSData *)iv
{
return [self AES128Operation:kCCEncrypt key:key iv:iv];
}
- (NSData *)AES128DecryptedDataWithKey:(NSData *)key iv:(NSData *)iv
{
return [self AES128Operation:kCCDecrypt key:key iv:iv];
}
- (NSData *)AES128Operation:(CCOperation)operation key:(NSData *)key iv:(NSData *)iv
{
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
key.bytes,
kCCBlockSizeAES128,
iv.bytes,
[self bytes],
dataLength,
buffer,
bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
#end
I found the solution, it is a good library.
Cross platform 256bit AES encryption / decryption.
This project contains the implementation of 256 bit AES encryption which works on all the platforms (C#, iOS, Android). One of the key objective is to make AES work on all the platforms with simple implementation.
Platforms Supported:
iOS ,
Android ,
Windows (C#).
https://github.com/Pakhee/Cross-platform-AES-encryption
This is a pretty old post but XCode 10 added the CommonCrypto module so you don't need a module map. Also with Swift 5, no need for the annoying casts.
You could do something like:
func decrypt(_ data: Data, iv: Data, key: Data) throws -> String {
var buffer = [UInt8](repeating: 0, count: data.count + kCCBlockSizeAES128)
var bufferLen: Int = 0
let status = CCCrypt(
CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
CCOptions(kCCOptionPKCS7Padding),
[UInt8](key),
kCCBlockSizeAES128,
[UInt8](iv),
[UInt8](data),
data.count,
&buffer,
buffer.count,
&bufferLen
)
guard status == kCCSuccess,
let str = String(data: Data(bytes: buffer, count: bufferLen),
encoding: .utf8) else {
throw NSError(domain: "AES", code: -1, userInfo: nil)
}
return str
}
You can just copy & paste these methods (Swift 4+):
class func encryptMessage(message: String, encryptionKey: String, iv: String) -> String? {
if let aes = try? AES(key: encryptionKey, iv: iv),
let encrypted = try? aes.encrypt(Array<UInt8>(message.utf8)) {
return encrypted.toHexString()
}
return nil
}
class func decryptMessage(encryptedMessage: String, encryptionKey: String, iv: String) -> String? {
if let aes = try? AES(key: encryptionKey, iv: iv),
let decrypted = try? aes.decrypt(Array<UInt8>(hex: encryptedMessage)) {
return String(data: Data(bytes: decrypted), encoding: .utf8)
}
return nil
}
Example:
let encryptMessage = encryptMessage(message: "Hello World!", encryptionKey: "mykeymykeymykey1", iv: "myivmyivmyivmyiv")
// Output of encryptMessage is: 649849a5e700d540f72c4429498bf9f4
let decryptedMessage = decryptMessage(encryptedMessage: encryptMessage, encryptionKey: "mykeymykeymykey1", iv: "myivmyivmyivmyiv")
// Output of decryptedMessage is: Hello World!
Don't forget encryptionKey & iv should be 16 bytes.