I am trying to decrypt the encrypted string with a key and iv with CBC no padding.
Am using 3Des algo with CBC no padding.Am getting nil value after decrypting the encrypted string.
let decryptedKey1: () = decrypt3Des(inputString: "31656F05CF3BEBBAC30DAF0D59689FFF", uniqueKey: "77FAA64817954DE1BA12C0C41B4A2128", ivString: "2203090543243693")
func decrypt3Des (inputString: String, uniqueKey: String, ivString: String) {
let inputData: Data = inputString.data (using: String.Encoding.utf8)!
// publicKey = privateKeyString
/* Using the process 3DES to decrypt(kCCKeySize3DES)*/
/* Uses algorithm kCCAlgorithm3DES*/
let keyData: Data = uniqueKey.data (using: String.Encoding.utf8)!
let keyBytes = UnsafeMutableRawPointer (mutating: (keyData as NSData) .bytes)
let keyLength = size_t (kCCKeySize3DES)
let dataLength = Int (inputData.count)
let dataBytes = UnsafeRawPointer ((inputData as NSData) .bytes)
let bufferData = NSMutableData (length: Int (dataLength) + kCCBlockSize3DES)!
let bufferPointer = UnsafeMutableRawPointer (bufferData.mutableBytes)
let bufferLength = size_t (bufferData.length)
var bytesDecrypted = Int (0)
let cryptStatus = CCCrypt(
UInt32 (kCCDecrypt),
UInt32 (kCCAlgorithm3DES),
UInt32 (kCCModeCBC),
keyBytes,
keyLength,
ivString,
dataBytes,
dataLength,
bufferPointer,
bufferLength,
&bytesDecrypted)
if Int32 (cryptStatus) == Int32 (kCCSuccess) {
bufferData.length = bytesDecrypted
print("DecryptcryptLength = \(bytesDecrypted), Decrypt = \(bufferData)")
let myResult : NSData = NSData(bytes: dataBytes, length: bytesDecrypted)
print("decrypt \(myResult)")
let stringResult = NSString(data: myResult as Data, encoding:String.Encoding.utf8.rawValue)
print(stringResult ?? "No string decription")
print(myResult ?? "result")
print( "utf8 actual string = \(NSString(data: bufferData as Data, encoding: String.Encoding.utf8.rawValue))");
let base64cryptString = bufferData.base64EncodedString(options: .lineLength64Characters)
print("BASE64",base64cryptString)
guard
let decryptedString = String(data: bufferData as Data, encoding: String.Encoding.utf8) else {
print("Error retrieving string")
return
}
// bufferData.length = bytesDecrypted
let clearDataAsString = NSString (data: bufferData as Data, encoding: String.Encoding.utf8.rawValue)
if clearDataAsString != nil {
print ("Decrypt content:\(clearDataAsString! as String)")
}
else{
print(clearDataAsString)
}
} else {
print ("Error in decryption process:\(cryptStatus)")
}
}
Related
Trying to perform encryption and decryption using AES ( common crypto ) in swift, For some reason while decrypting the first 16 characters are getting trimmed off. Can anyone please look at the below playground code and suggest what could be going wrong here ?. The decodedString variable trims off the intial 16 characters of the original payloadString during decryption.
playground code
import UIKit
import CommonCrypto
class AESNew {
enum MyError: LocalizedError {
case first(message: String)
case second(message: String)
var errorDescription: String? { return "Some description here!" }
}
func encrypt(plainText: String, keyData:Data, iv: Data, options:Int = kCCOptionPKCS7Padding) -> Result<Data, Error> {
let plainData = Data(plainText.utf8)
if let cryptData = NSMutableData(length: Int((plainData.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 value = iv.withUnsafeBytes { $0.load(as: UInt32.self) }
let cryptResult = iv.withUnsafeBytes { (dataBytes : UnsafePointer<UInt8>) -> Result<Data, Error> in
print(dataBytes)
print(UnsafeRawPointer(dataBytes))
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes,
keyLength,
UnsafeRawPointer(dataBytes),
(plainData as NSData).bytes, plainData.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
print("base64cryptString: \(base64cryptString)")
return .success(cryptData as Data)
} else {
print("failure")
return .failure(MyError.first(message: "crypt failed"))
}
}
return cryptResult
}
return .failure(MyError.second(message: "no value failure"))
}
// The iv is prefixed to the encrypted data
func decrypt(data: Data, keyData: Data) throws -> Data? {
let keyLength = keyData.count
let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
if validKeyLengths.contains(keyLength) == false {
print("validKeyLengths does not match")
}
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.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)
}
}
}
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
clearData.count = numBytesDecrypted
} else {
print("Decryption failed")
}
return clearData
}
}
func randomGenerateBytes(count: Int) -> Data? {
let bytes = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: 1)
defer { bytes.deallocate() }
let status = CCRandomGenerateBytes(bytes, count)
guard status == kCCSuccess else { return nil }
return Data(bytes: bytes, count: count)
}
var ivBytesNew = Data()
if let ivBytes = randomGenerateBytes(count: 16) {
ivBytesNew = ivBytes
} else {
print("randomGenerateBytes failed")
}
let keyString = "keyData890123456"
let keyData = "keyData890123456".data(using:String.Encoding.utf8)!
let payloadString = "asdflkasfdkaslfd12345"
let aesObject = AESNew()
let encrytedObject = aesObject.encrypt(plainText: payloadString, keyData: keyData, iv: ivBytesNew, options: kCCOptionPKCS7Padding)
var encryptedData = Data()
switch encrytedObject {
case .success(let encData):
print(encData)
encryptedData = encData
case .failure(let error):
print(error)
default:
print("enc failed")
}
if let decrypedData = try? aesObject.decrypt(data: encryptedData, keyData: keyData) {
if let decodedString = String(data: decrypedData, encoding: .utf8) {
print(decodedString) // 1234, first 16 characters are omitted.
} else {
print("conversion from data to string failed")
}
} else {
print("decryption failed")
}
Seems you have picked up two different kinds of encrypt and decrypt.
Do you see your decrypt does not have a parameter iv which is needed for AES decryption?
Your decrypt expects first 16 bytes of data as iv and the rest as encrypted data. But your encrypt returns only encrypted data.
Please try changing the line calling decrypt as follows:
if let decrypedData = try? aesObject.decrypt(data: ivBytesNew + encryptedData, keyData: keyData) {
Generally, your encrypt uses NSMutableData and handling bytes inappropriately. That is fragile and it might crash on some different context. I strongly recommend you not to use your current encrypt.
Anyway, you should make encrypt and decrypt consistent, or sort of symmetric, currently they are not.
Trying to write my own encrypt/decrypt functions in Swift 5, based on tons of other similar questions -- and failing miserably.
I'm using CommonCrypto + CCCrypt to encrypt/decrypt (AES, 256 key, random iv).
I'm favouring NSData.bytes over withUnsafeBytes (which is just too confusing in Swift 5).
My encrypt function goes like this:
func encrypt(_ string: String) throws -> Data {
guard let dataToEncrypt: Data = string.data(using: .utf8) else {
throw AESError.stringToDataFailed
}
// Seems like the easiest way to avoid the `withUnsafeBytes` mess is to use NSData.bytes.
let dataToEncryptNSData = NSData(data: dataToEncrypt)
let bufferSize: Int = ivSize + dataToEncryptNSData.length + kCCBlockSizeAES128
let buffer = UnsafeMutablePointer<NSData>.allocate(capacity: bufferSize)
defer { buffer.deallocate() }
let status: Int32 = SecRandomCopyBytes(
kSecRandomDefault,
kCCBlockSizeAES128,
buffer
)
guard status == 0 else {
throw AESError.generateRandomIVFailed
}
var numberBytesEncrypted: Int = 0
let cryptStatus: CCCryptorStatus = CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCEncrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES), // alg: CCAlgorithm
options, // options: CCOptions
key.bytes, // key: the "password"
key.length, // keyLength: the "password" size
buffer, // iv: Initialization Vector
dataToEncryptNSData.bytes, // dataIn: Data to encrypt bytes
dataToEncryptNSData.length, // dataInLength: Data to encrypt size
buffer + kCCBlockSizeAES128, // dataOut: encrypted Data buffer
bufferSize, // dataOutAvailable: encrypted Data buffer size
&numberBytesEncrypted // dataOutMoved: the number of bytes written
)
guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw AESError.encryptDataFailed
}
return Data(bytes: buffer, count: numberBytesEncrypted + ivSize)
}
The decrypt function:
func decrypt(_ data: Data) throws -> String {
// Seems like the easiest way to avoid the `withUnsafeBytes` mess is to use NSData.bytes.
let dataToDecryptNSData = NSData(data: data)
let bufferSize: Int = dataToDecryptNSData.length - ivSize
let buffer = UnsafeMutablePointer<NSData>.allocate(capacity: bufferSize)
defer { buffer.deallocate() }
var numberBytesDecrypted: Int = 0
let cryptStatus: CCCryptorStatus = CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCDecrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES128), // alg: CCAlgorithm
options, // options: CCOptions
key.bytes, // key: the "password"
key.length, // keyLength: the "password" size
dataToDecryptNSData.bytes, // iv: Initialization Vector
dataToDecryptNSData.bytes + kCCBlockSizeAES128, // dataIn: Data to decrypt bytes
bufferSize, // dataInLength: Data to decrypt size
buffer, // dataOut: decrypted Data buffer
bufferSize, // dataOutAvailable: decrypted Data buffer size
&numberBytesDecrypted // dataOutMoved: the number of bytes written
)
guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw AESError.decryptDataFailed
}
let decryptedData = Data(bytes: buffer, count: numberBytesDecrypted)
guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
throw AESError.dataToStringFailed
}
return decryptedString
}
Those were based on this awesome answer from the user "#zaph".
Although encrypt seems to be working, decrypt fails.
This line specifically:
guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
throw AESError.dataToStringFailed
}
So of course I'm missing something, but I can't figure out what it is. Could you?
Here is the pastebin with the entire code, which you could copy/paste in a Playground and hit play. Swift 5 is required: https://pastebin.com/raw/h6gacaHX
Update
I'm now following #OOper's suggested approach. The final code can be seen here:
https://github.com/backslash-f/aescryptable
In fact, using Data.withUnsafeBytes is sort of a mess in Swift 5, though NSData.bytes cannot be the easiest way, as using it would sometimes seemingly work, and sometimes not.
You need to be accustomed work with Data.withUnsafeBytes if you want to write an always-works code in Swift with Data.
struct AES {
private let key: Data //<- Use `Data` instead of `NSData`
private let ivSize: Int = kCCBlockSizeAES128
private let options: CCOptions = CCOptions(kCCOptionPKCS7Padding)
init(keyString: String) throws {
guard keyString.count == kCCKeySizeAES256 else {
throw AESError.invalidKeySize
}
guard let keyData: Data = keyString.data(using: .utf8) else {
throw AESError.stringToDataFailed
}
self.key = keyData
}
}
extension AES: Cryptable {
func encrypt(_ string: String) throws -> Data {
guard let dataToEncrypt: Data = string.data(using: .utf8) else {
throw AESError.stringToDataFailed
}
let bufferSize: Int = ivSize + dataToEncrypt.count + kCCBlockSizeAES128
var buffer = Data(count: bufferSize)
let status: Int32 = buffer.withUnsafeMutableBytes {bytes in
SecRandomCopyBytes(
kSecRandomDefault,
kCCBlockSizeAES128,
bytes.baseAddress!
)
}
guard status == 0 else {
throw AESError.generateRandomIVFailed
}
var numberBytesEncrypted: Int = 0
let cryptStatus: CCCryptorStatus = key.withUnsafeBytes {keyBytes in
dataToEncrypt.withUnsafeBytes {dataBytes in
buffer.withUnsafeMutableBytes {bufferBytes in
CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCEncrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES), // alg: CCAlgorithm
options, // options: CCOptions
keyBytes.baseAddress, // key: the "password"
key.count, // keyLength: the "password" size
bufferBytes.baseAddress, // iv: Initialization Vector
dataBytes.baseAddress, // dataIn: Data to encrypt bytes
dataToEncrypt.count, // dataInLength: Data to encrypt size
bufferBytes.baseAddress! + kCCBlockSizeAES128, // dataOut: encrypted Data buffer
bufferSize, // dataOutAvailable: encrypted Data buffer size
&numberBytesEncrypted // dataOutMoved: the number of bytes written
)
}
}
}
guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw AESError.encryptDataFailed
}
return buffer[..<(numberBytesEncrypted + ivSize)]
}
func decrypt(_ data: Data) throws -> String {
let bufferSize: Int = data.count - ivSize
var buffer = Data(count: bufferSize)
var numberBytesDecrypted: Int = 0
let cryptStatus: CCCryptorStatus = key.withUnsafeBytes {keyBytes in
data.withUnsafeBytes {dataBytes in
buffer.withUnsafeMutableBytes {bufferBytes in
CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCDecrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES128), // alg: CCAlgorithm
options, // options: CCOptions
keyBytes.baseAddress, // key: the "password"
key.count, // keyLength: the "password" size
dataBytes.baseAddress, // iv: Initialization Vector
dataBytes.baseAddress! + kCCBlockSizeAES128, // dataIn: Data to decrypt bytes
bufferSize, // dataInLength: Data to decrypt size
bufferBytes.baseAddress, // dataOut: decrypted Data buffer
bufferSize, // dataOutAvailable: decrypted Data buffer size
&numberBytesDecrypted // dataOutMoved: the number of bytes written
)
}
}
}
guard cryptStatus == CCCryptorStatus(kCCSuccess) else {
throw AESError.decryptDataFailed
}
let decryptedData = buffer[..<numberBytesDecrypted]
guard let decryptedString = String(data: decryptedData, encoding: .utf8) else {
throw AESError.dataToStringFailed
}
return decryptedString
}
}
I trying to write an encryption (AESCBC256) function based on CCCrypt and the CCCrypt is generating a random value.
for example, when I pass 1234567 to function it'll return "HlFP2rCmycZS1269Cm47Q==" or "TTuSJrBcsOmOCDHc5IQ8Dw==" for the same iv and Key.
here's the iv: b5f89591
and the key is : 366e9c1b4b2ed2b1daf751d7500aaa01
func encrypt(Value: String)->String{
let keyData = keyString.data(using: .utf8, allowLossyConversion: false)!
let iv = SecretKey.data(using: .utf8, allowLossyConversion: false)!
let message = SecretKey+Value
let data = message.data(using: .utf8, allowLossyConversion: false)!
let cryptData = NSMutableData(length: Int(data.count) + kCCBlockSizeAES128)!
let keyLength = size_t(kCCKeySizeAES256)
let operation: CCOperation = CCOperation(UInt32(kCCEncrypt))
let algoritm: CCAlgorithm = CCAlgorithm(UInt32(kCCAlgorithmAES128))
let options: CCOptions = CCOptions(UInt32(kCCOptionPKCS7Padding))
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> UnsafePointer<UInt8> in return bytes},
keyLength,
iv.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> UnsafePointer<UInt8> in return bytes},
data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> UnsafePointer<UInt8> in return bytes},
data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
return String(describing: cryptData.base64EncodedString(options: .lineLength64Characters))
}else{
return ""
}
}
Your IV is the wrong length. It's 8 bytes long, but AES requires a 16 byte IV, so it's reading random data out of memory for the other 8 bytes.
I have the following method that I want to decrypt. The following method Encrypts. What should I do to decrypt?
Code
PlainString = "5lg3yg7Q+Y8="
func tripleDesEncrypt(PlainString: String) -> String {
let keyData = "FIFEDCBA98765432104AABFD"
let PlainStringvar = PlainString
guard let data = PlainStringvar.data(using: .utf8) else {
return ""
}
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 = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
nil,
data.bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
var base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString //// encodeString(str: base64cryptString)
} else {
print("Error: \(cryptStatus)")
}
return ""
}
I never did encrypt/decrypt on Swift but based on that code you just need to change this line
let operation: CCOperation = UInt32(kCCEncrypt)
to
let operation: CCOperation = UInt32(kCCDecrypt)
While making a small search for this answer I came across this
https://github.com/DigitalLeaves/CommonCrypto-in-Swift
It might be useful, not only as a library that you can use, but to study code and also looks that you're new to the Swift language so I advise you to take a look
Your tripleDesEncrypt does not compile in Swift 4, so I needed to fix it:
func tripleDesEncrypt(plainString: String) -> String {
let keyData = "FIFEDCBA98765432104AABFD".data(using: .utf8)!
//Converting plainString to UTF-8 encoded data
guard let data = plainString.data(using: .utf8) else {
return ""
}
var cryptData = Data(count: data.count + kCCBlockSize3DES)
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = CCOperation(kCCEncrypt)
let algoritm: CCAlgorithm = CCAlgorithm(kCCAlgorithm3DES)
let options: CCOptions = CCOptions(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
//Encrypting UTF-8 encoded data in 3DES, ECB, PKCS7 with keyData
let cryptStatus = keyData.withUnsafeBytes {keyBytes in
data.withUnsafeBytes {dataBytes in
cryptData.withUnsafeMutableBytes {mutableBytes in
CCCrypt(operation,
algoritm,
options,
keyBytes, keyLength,
nil,
dataBytes, data.count,
mutableBytes, cryptData.count,
&numBytesEncrypted)
}
}
}
if cryptStatus == CCCryptorStatus(kCCSuccess) {
//Converting encrypted data into base-64 String
cryptData.count = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString
} else {
print("Error: \(cryptStatus)")
return ""
}
}
The code is made of 3 parts:
Converting plainString to UTF-8 encoded data
Encrypting UTF-8 encoded data in 3DES, ECB, PKCS7 with keyData
Converting encrypted data into base-64 String
So, to decrypt, you need to apply inverse conversion in reversed order:
Converting base-64 String into encrypted data
Decrypting to UTF-8 encoded data in 3DES, ECB, PKCS7 with keyData
Converting UTF-8 encoded data into plainString
The method looks like this:
func tripleDesDecrypt(base64String: String) -> String {
let keyData = "FIFEDCBA98765432104AABFD".data(using: .utf8)!
//Converting base-64 String into encrypted data
guard let encryptedData = Data(base64Encoded: base64String, options: .ignoreUnknownCharacters) else {
return ""
}
var decryptedData = Data(count: encryptedData.count)
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = CCOperation(kCCDecrypt)
let algoritm: CCAlgorithm = CCAlgorithm(kCCAlgorithm3DES)
let options: CCOptions = CCOptions(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesDecrypted :size_t = 0
//Decrypting to UTF-8 encoded data in 3DES, ECB, PKCS7 with keyData
let cryptStatus = keyData.withUnsafeBytes {keyBytes in
encryptedData.withUnsafeBytes {dataBytes in
decryptedData.withUnsafeMutableBytes {mutableBytes in
CCCrypt(operation,
algoritm,
options,
keyBytes, keyLength,
nil,
dataBytes, encryptedData.count,
mutableBytes, decryptedData.count,
&numBytesDecrypted)
}
}
}
if cryptStatus == CCCryptorStatus(kCCSuccess) {
//Converting UTF-8 encoded data into plainString
let plainString = String(data: decryptedData, encoding: .utf8) ?? ""
return plainString
} else {
print("Error: \(cryptStatus)")
return ""
}
}
Usage:
let encryptedString = tripleDesEncrypt(plainString: "This is a test.")
print(encryptedString) //->QmWafUwPY/MVWu3lHa3c5A==
let decryptedString = tripleDesDecrypt(base64String: encryptedString)
print(decryptedString) //->This is a test.
//Try by yourself...
let origString = tripleDesDecrypt(base64String: "5lg3yg7Q+Y8=")
print(origString)
It is the first time I try to use encryption so I am not sure if what I need is achievable with the following code.
MY PROBLEM - I need it to generate an encoded string with 16 characters instead of the 64 character that is being generated at the moment.
I have a preference for using a native swift library instead of an external framework. And because of that could not find much about how to use CommonCrypto. Not sure if it is correct approach as well.
Where I got the example
http://sketchytech.blogspot.co.nz/2016/02/resurrecting-commoncrypto-in-swift-for.html
My usage
let keyString = "1234567812345678"
let message = "12345678123456781234567812345678"
let iv = "iv-salt-string--" // string of 16 characters in length
let encoded = message.aesEncrypt(keyString, iv: iv)!
print("encoded -> \(encoded)")
let unencode = encoded.aesDecrypt(keyString, iv: iv)!
print("unencode -> \(unencode)")
Output
encoded -> S81qV6F31xO8mUA1+HhsF7pHOMeE0f6Bbcmj3Zzk3EFLhQTCmfYlouorrUkYKL6K
unencode -> 12345678123456781234567812345678
Extension
extension String {
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
}
}
You have 16 bytes of input after converting to data from hex. You specify PKCS#7 padding kCCOptionPKCS7Padding. If the data is an exact multiple of the block size PKCS#7 padding must add an entire block of padding to the data to be encrypted making 32-bytes of data. (That is because some padding must always be added and if there is no partial block the only way is to add a block of padding.) On decryption the 16-bytes of padding will be removed so you will get back 16-bytes of data.
See: PKCS#7 padding.
If the input data is always a multiple of the block size (16-bytes) then you do not need to add padding, so you do not need to supply the kCCOptionPKCS7Padding as an option.
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
}
}
Is this 16 bit of length