2

I really need some help to convert the objective-c code to swift using CryptoSwift. I'm not sure how to use functions like: bzero, getCString, malloc in Swift.

+(NSData*)encryptData:(NSData*)data
{
    static NSString *key = @"BitCave012345678";
    char keyPtr[kCCKeySizeAES128+1];
    bzero(keyPtr, sizeof(keyPtr));

    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [data length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;

    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode,
                                          keyPtr,kCCKeySizeAES128,NULL,[data bytes],dataLength,
                                          buffer, bufferSize, &numBytesEncrypted);

    if(cryptStatus == kCCSuccess)
    {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

    free(buffer);

    return nil;
}

Does anyone has an idea how to satisfy arguments requiring pointers? I was trying using UnsafeMutablePointers and I also tried the code below, but I know it is completely wrong:

var key: NSString = "BitCave012345678"
        var keyPtr: Array<Character> = Array<Character>(count: 17, repeatedValue: "0")
        bzero(&keyPtr, 17*sizeof(Character))
        key.getCString(&keyPtr, maxLength: 17*sizeof(Character), encoding: NSUTF8StringEncoding)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Bart
  • 21
  • 5
  • Please never "outsource" relevant question information to somewhere behind a link, and definately not present source code as an image. – hlovdal Sep 21 '15 at 13:37
  • Did you have a look at existing Swift Q&A about CCCrypt? It seems to me that there are already a few examples. – Martin R Sep 21 '15 at 13:55
  • @MartinR Actually I found this: http://stackoverflow.com/questions/25754147/issue-using-cccrypt-commoncrypt-in-swift but I'm still not sure how to manage. – Bart Sep 21 '15 at 14:04
  • It is best to avoid using CryptoSwift, amoung other things it is over 1000 times slower than Common Crypto based implementations. Apple's Common Crypto is FIPS certified and as such has been well vetted, using CryptoSwift is taking a chance on correctness and security. – zaph Sep 21 '15 at 20:50

2 Answers2

3

Swift 2.0

It is not necessary to use bzero, getCString, malloc, here is an example that does not:

Add Security.framework to the project
Add #import to the bridging header.

// operation is either 'kCCEncrypt' or 'kCCDecrypt'
func testCrypt(data data:NSData, keyData:NSData, operation:Int) -> NSData? {
    let keyBytes = UnsafePointer<UInt8>(keyData.bytes)

    let dataLength = Int(data.length)
    let dataBytes  = UnsafePointer<UInt8>(data.bytes)

    let cryptData: NSMutableData! = NSMutableData(length: Int(dataLength) + kCCBlockSizeAES128)
    let cryptPointer = UnsafeMutablePointer<UInt8>(cryptData.mutableBytes)
    let cryptLength  = size_t(cryptData.length)

    let keyLength              = size_t(kCCKeySizeAES128)
    let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
    let options:   CCOptions   = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)

    var numBytesEncrypted :size_t = 0

    let cryptStatus = CCCrypt(CCOperation(operation),
        algoritm,
        options,
        keyBytes, keyLength,
        nil,
        dataBytes, dataLength,
        cryptPointer, cryptLength,
        &numBytesEncrypted)

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        cryptData.length = Int(numBytesEncrypted)

    } else {
        print("Error: \(cryptStatus)")
    }

    return cryptData;
}

Example usage:

let keyData     = "12345678901234567890123456789012".dataUsingEncoding(NSUTF8StringEncoding)
let messageData = "Don´t try to read this text. Top Secret Stuff".dataUsingEncoding(NSUTF8StringEncoding)
let encrypted = testCrypt(data:messageData!, keyData:keyData!, operation:kCCEncrypt)

Here is version in Swift Arrays of UInt8 with no NSData objects:

func testCrypt(data data:[UInt8], keyData:[UInt8], operation:Int) -> [UInt8]? {
    let keyBytes = UnsafeMutablePointer<UInt8>(keyData)

    let dataLength = data.count
    let dataBytes  = UnsafeMutablePointer<UInt8>(data)

    var cryptData = [UInt8](count:data.count+kCCBlockSizeAES128, repeatedValue:0)
    let cryptPointer = UnsafeMutablePointer<UInt8>(cryptData)
    let cryptLength  = size_t(cryptData.count)

    let keyLength              = size_t(kCCKeySizeAES128)
    let algoritm:  CCAlgorithm = UInt32(kCCAlgorithmAES128)
    let options:   CCOptions   = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)

    var numBytesEncrypted :size_t = 0

    let cryptStatus = CCCrypt(CCOperation(operation),
        algoritm,
        options,
        keyBytes, keyLength,
        nil,
        dataBytes, dataLength,
        cryptPointer, cryptLength,
        &numBytesEncrypted)

    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        cryptData.removeRange(numBytesEncrypted..<cryptData.count)

    } else {
        print("Error: \(cryptStatus)")
    }

    return cryptData;
}

Example usage:

let keyData     = Array("12345678901234567890123456789012".utf8)
let messageData = Array("Don´t try to read this text. Top Secret Stuff".utf8)
let encrypted   = testCrypt(data:messageData, keyData:keyData, operation:kCCEncrypt)
zaph
  • 111,848
  • 21
  • 189
  • 228
0

I know there are better solutions out there. But I needed legacy support (old DB, already encrypted) so I translated Barts Obj-C code to Swift 5 code. Maybe someone needs it too.

extension Data {

    func aesDecrypt() -> Data? {

        let myKey:String = "BitCave012345678"

        var keyPtr = [Int8](repeating: 0, count: kCCKeySizeAES128+1)
        myKey.getCString(&keyPtr, maxLength: keyPtr.count, encoding: String.Encoding.utf8)

        var numBytesDecrypted :size_t = 0
        let dataLength:Int = self.count
        let bufferSize: size_t = dataLength + kCCBlockSizeAES128
        let bufferDecrypt = malloc(bufferSize)
        let iv = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

        let result:CCCryptorStatus = CCCrypt(CCOperation(kCCDecrypt), CCAlgorithm(kCCAlgorithmAES128), CCOptions(kCCOptionPKCS7Padding), keyPtr, kCCKeySizeAES128, iv, self.bytes, self.count, bufferDecrypt, bufferSize, &numBytesDecrypted)

        if (result == kCCSuccess) {
            return Data(bytes: bufferDecrypt!, count: numBytesDecrypted)
        }

        free(bufferDecrypt)

        return nil
    }
}
Richard R
  • 873
  • 6
  • 20