CryptoSwift - Getting nil when using makeEncryptor() for string of less than 16 bytes in iOS

I am using cryptoSwift library for encryption and decryption. But it's working with only string 16 bytes. If i am passing small string or less than 16 bytes then getting nil result.
I am using Incremental operations use instance of Cryptor and encrypt/decrypt one part at a time.
Please help me here, is there anything which i am doing wrong.
Thanks in advance.

Code Block func encAndDec(){
do {
// Encryption start
let data = Data.init(base64Encoded: "12345678901234567890123456789012".base64Encoded()!)
let iv : Array<UInt8> = [0,0,0,0,0,0,0,0,0,0,0,0]
let nIv = Data(iv)
let gcmEnc = GCM(iv: nIv.bytes, mode: .detached)
var enc = try? AES(key: data!.bytes, blockMode: gcmEnc, padding: .noPadding).makeEncryptor()
let arrStr = ["My name is tarun"] // Working
//let arrStr = ["tarun"] // Not working for this string
var ciphertext = Array<UInt8>()
for txt in arrStr{
let ciperText = try? enc?.update(withBytes: Array(txt.utf8)) // Getting nil for small string.
ciphertext.append(contentsOf: ciperText!)
}
var res = try? enc?.finish()
gcmEnc.authenticationTag = self.randomGenerateBytes(count: 16)?.bytes
res?.append(contentsOf: (gcmEnc.authenticationTag)!)
let cipherData = Data(ciphertext) + Data(res!)
let strEnc = String(decoding: cipherData, as: UTF8.self)
print(strEnc)
// Decryption start from here
do {
let gcmDec = GCM.init(iv: nIv.bytes, additionalAuthenticatedData: nil, tagLength: 16, mode: .detached)
var aesDec = try! AES(key: data!.bytes, blockMode: gcmDec, padding: .noPadding).makeDecryptor()
let tag_length = 16
let encData = cipherData.subdata(in: 0..<cipherData.count - tag_length)
let tag = cipherData.subdata(in: encData.count ..< cipherData.count)
let decData = try? aesDec.update(withBytes: encData.bytes) //Getting nil here for small string
let strData = String(decoding: decData!, as: UTF8.self)
print(strData)
do{
var res = try? aesDec.finish(withBytes: tag.bytes)
res?.append(contentsOf: tag)
}catch{
}
} catch {
// failed
}
}
}
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)
}


Replies

In this tutorial they effectively use 16 char for encryption.

Code Block
if let base64cipher = try? Rabbit(key: "1234567890123456"),
let base64 = try? testString.encryptToBase64(cipher: base64cipher) {
print("encrypted base64: \(base64!)")
let decrypted = try? base64!.decryptBase64ToString(cipher: base64cipher)
print("decrypted base64: \(decrypted!)")
}

But free text for signature.
https ://agostini. tech/2019/03/31/using-cryptoswift/

Have you checked if you need dataPadding ?
I don't want padding here..
You don't want… My point was Do you need ?
No, I don't want padding. I have done the same with Ruby, Java, Go, and others and none require padding or the input value to be a multiple of 16 bytes like the Swift library seems to require.

Code Block const crypto = require('crypto');
const key = '12345678901234567890123456789012';
const iv = '000000000000'
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
const plaintext = 'Hello';
const ciphertext = cipher.update(plaintext, 'utf8');
console.log("ciphertext length %d", ciphertext.length)
cipher.final();
const tag = cipher.getAuthTag();
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(tag);
const receivedPlaintext = decipher.update(ciphertext, null, 'utf8');
try {
decipher.final();
} catch (err) {
console.error('Authentication failed!');
return;
}
console.log(receivedPlaintext);




You should ask the question directly to CryptoSwift.

Good continuation.
You should also read this with interest.

https://stackoverflow.com/questions/58582139/how-to-solve-datapaddingrequired-error-cryptoswift

No, I don't want padding.

I’m sorry but this is nonsense. AES is a 128-bit block cypher, which means it always works on blocks of 16 bytes. It’s simply not possible to encode arbitrary length data using AES without some sort of padding. You have two options here:
  • If you want PKCS#7 padding, don’t set the .noPadding flag.

  • If you want some other sort of padding, apply that padding yourself to the plaintext and then set the .noPadding flag.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"