2015-06-23 61 views
3

我正在將Objective-C代碼轉換爲Swift。在這裏,我們發現CommonCrypto在Swift中不可用。如何將通用加密代碼從Objective-C轉換爲Swift?

因此,我使用映射在我令人興奮的Swift項目中執行module.map文件並訪問Common Crypto文件。我已經將下面的Objective-C代碼寫入Swift。

但我面臨的代碼轉換問題。下面我寫了兩種語言代碼。 請注意,此SWIFT代碼包含錯誤這並不完美。請幫我解決Swift語言代碼。

Objective-C代碼:

- (NSData *) hashKey:(NSString *)hash{ 
    unsigned char result[1000]; 
    const char *cStr = [hash UTF8String]; 
    CC_MD5(cStr, (CC_LONG)strlen(cStr), result); 

    for (int jval = 0, kval = 16; jval < 8;) { 
     result[kval++] = result[jval++]; 
    } 
    return [NSMutableData dataWithBytes:result length:24];; 
} 

- (NSData *) myEncrypt:(NSString *)encryptData{ 
    NSData *myKeyData = [self hashKey:MySecretKey]; 
    NSData *myRawData = [encryptData dataUsingEncoding:NSUTF8StringEncoding]; 

    size_t buffer_size   = [myRawData length] + kCCBlockSize3DES; 
    void* buffer     = malloc(buffer_size); 
    size_t num_bytes_encrypted = 0; 

    uint8_t iv[8] = { 56, 101, 63, 23, 96, 182, 209, 205}; 

    CCCryptorStatus Crypto_status = CCCrypt(kCCEncrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding, 
              [myKeyData bytes], 
              kCCKeySize3DES, 
              iv, 
              [myRawData bytes], 
              [myRawData length], 
              buffer, 
              buffer_size, 
              &num_bytes_encrypted); 

    if (Crypto_status == kCCSuccess){ 
     NSData *myResult = [NSData dataWithBytes:buffer length:num_bytes_encrypted]; 
     free(buffer); 
     return myResult; 
    } 
    else { 
     free(buffer); 
     return nil; 
    } 
} 


- (NSData *) myDecrypt:(NSData *)decryptData{ 

    NSUInteger mydata_len = [decryptData length]; 
    NSData *keyData = [self hashKey:MySecretKey]; 

    size_t buffer_size   = mydata_len + kCCBlockSizeAES128; 
    void* buffer     = malloc(buffer_size); 
    size_t num_bytes_encrypted = 0; 

    uint8_t iv[8] = { 56, 101, 63, 23, 96, 182, 209, 205}; 

    CCCryptorStatus decrypt_status = CCCrypt(kCCDecrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding, 
              [keyData bytes], 
              kCCKeySize3DES, 
              iv, 
              [decryptData bytes], 
              mydata_len, 
              buffer, 
              buffer_size, 
              &num_bytes_encrypted); 

    if (decrypt_status == kCCSuccess){ 
     NSData *myResult = [NSData dataWithBytes:buffer length:num_bytes_encrypted]; 
     free(buffer); 
     return myResult; 
    } 
    else { 
     free(buffer); 
     return nil; 
    } 

} 

Swift代碼:

func hashKey(hash:String) -> NSData{ 

    let digestLength = Int(CC_MD5_DIGEST_LENGTH) 
    let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLength) 
    var cStr = hash.cStringUsingEncoding(NSUTF8StringEncoding) 
    var strLen = CC_LONG(strlen(cStr!)) 

    CC_MD5(cStr!, strLen, result) 

    var kval = 16 

    for (var jval=0; kval==16; jval<8){ 
    result [kval++] = result[jval++] ***//Here We Got An Error: Cannot assign a value of type 'CUnsignedChar' to a value of type '[Int]'*** 

    } 

    return NSMutableData(bytes: result, length: 24) 
} 


func myEncrypt(encryptData:String) -> NSData?{ 

    var myKeyData : NSData = self.hashKey(MySecretKey) 
    var myRawData : NSData = encryptData.dataUsingEncoding(NSUTF8StringEncoding)! 

    var buffer_size : size_t = myRawData.length + kCCBlockSize3DES 
    var buffer = UnsafeMutablePointer<NSData>.alloc(buffer_size) 
    var num_bytes_encrypted : size_t = 0 

    var iv : [UInt8] = [56, 101, 63, 23, 96, 182, 209, 205] 

    let operation: CCOperation = UInt32(kCCEncrypt) 
    let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES) 
    let options: CCOptions = UInt32(kCCOptionPKCS7Padding) 
    let keyLength  = size_t(kCCKeySize3DES) 

    var Crypto_status: CCCryptorStatus = CCCrypt(operation, algoritm, options, myKeyData.bytes, keyLength, iv, 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) 
    return myResult 
}else{ 
    free(buffer) 
    return nil 
    } 

} 


func myDecrypt(decryptData : NSData) -> NSData?{ 

    var mydata_len : Int = decryptData.length 
    var keyData : NSData = self.hashKey(MySecretKey) 

    var buffer_size : size_t = mydata_len+kCCBlockSizeAES128 
    var buffer = UnsafeMutablePointer<NSData>.alloc(buffer_size) 
    var num_bytes_encrypted : size_t = 0 

    var iv : [UInt8] = [56, 101, 63, 23, 96, 182, 209, 205] 

    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, iv, 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) 
    return myResult 
}else{ 
    free(buffer) 
    return nil 

    } 
} 
+0

使用橋接頭的問題是什麼? –

+0

@iOSDev我也是這麼做的。但是,當解密時,我剛剛得到**零作爲解密文本。你能告訴我如何解密數據 –

回答

3
for (var jval=0; kval==16; jval<8){ 
    return [kval++] = result[jval++] ***//Here We Got An Error: Cannot assign a value of type 'CUnsignedChar' to a value of type '[Int]'*** 
} 

由於@Francisco筆記,這是不正確。你正試圖在循環中返回。這是一個明顯的錯字。你的意思是result[kval++]而不是return [kval++]

但還有另一個問題。您修改了for循環。它是:

for (int jval = 0, kval = 16; jval < 8;) { 

這是基本相同的斯威夫特:

for var jval = 0, kval = 0; jval < 8; { 
+0

+1謝謝,是這是我的錯誤,當我編碼粘貼在這裏。基本上不是這個參數的問題。這是非常簡單的轉換,但我無法弄清楚。 –

0

我不知道什麼是你想這樣做,但這樣的:

for (int jval = 0, kval = 16; jval < 8;) { 
     result[kval++] = result[jval++]; 
    } 

它不是比這一樣:

for (var jval=0; kval==16; jval<8){ 
    return [kval++] = result[jval++] 
    } 

我認爲你想做什麼是這樣的:

for (var jval=0; kval==16; jval<8){ 
    result[kval++] = result[jval++] 
    } 
你可以轉換CUnsignedChar任何情況下

(命名爲例子VAR)爲Int與此:

[String(var).toInt()!] 
+0

,謝謝你審查我的問題,是的,這是我的錯誤,當我在這裏粘貼代碼。其實這是愚蠢的錯誤,但我無法弄清楚。 –

1

雨燕2.0

添加Security.framework

#import <CommonCrypto/CommonCrypto.h> (in bridging header) 

樣品MD5方法:

func mac_md5(string string: String) -> (NSData?) { 
    let data = (dataString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData! 
    let result = NSMutableData(length: Int(CC_MD5_DIGEST_LENGTH))! 
    if (data.length > 0) { 
     CC_MD5(data.bytes, 
      CC_LONG(data.length), 
      UnsafeMutablePointer<UInt8>(result.mutableBytes)) 
    } 
    return result 
} 

測試:

let dataString = "Here is the data longer" 
var mac = mac_md5(string:dataString) as! NSMutableData 
print("mac: \(mac)") 

輸出:

mac: <e3b741ae cadf6725 03e3c95c 9d88a9a6> 

在問題末尾的代碼被複制的前8個字節在第一個16字節cr結束時吃一個24字節的3DES密鑰(又名2TDEA)。這主要體現在加密方法中實現DES和3DES兼容性的應用程序中。

樣品的編號:

mac.appendData(mac.subdataWithRange(NSMakeRange(0, 8))) 
println("mac: \(mac)") 

輸出:

mac: <e3b741ae cadf6725 03e3c95c 9d88a9a6 e3b741ae cadf6725> 

樣品3DES方法:

func testCrypt3DES(data data:NSData, keyData:NSData, ivData:NSData, operation:CCOperation) -> NSData? { 
    let keyBytes = UnsafePointer<UInt8>(keyData.bytes) 
    let ivBytes = UnsafePointer<UInt8>(ivData.bytes) 
    let dataLength = Int(data.length) 
    let dataBytes = UnsafePointer<UInt8>(data.bytes) 
    let cryptData: NSMutableData! = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES) 
    let cryptPointer = UnsafeMutablePointer<UInt8>(cryptData.mutableBytes) 
    let cryptLength = size_t(cryptData.length) 

    let keyLength    = size_t(kCCKeySize3DES) 
    let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES) 
    let options: CCOptions = UInt32(kCCOptionPKCS7Padding) 

    var numBytesEncrypted :size_t = 0 

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

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

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

    return cryptData; 

//測試代碼:

let keyString = "!Use a data key!" 
let keyData = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData! 

let ivString = "Use a iv" 
let ivData = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData! 

let message = "Don´t try to read this text. Top Secret Stuff" 
let data = (message as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData! 

print("data:   \(data)") 
if let encryptedData = testCrypt3DES(data:data, keyData:keyData, ivData:ivData, operation:UInt32(kCCEncrypt)) { 
    print("encryptedData: \(encryptedData)") 
    if let decryptedData = testCrypt3DES(data:encryptedData, keyData:keyData, ivData:ivData, operation:UInt32(kCCDecrypt)) { 
     print("decryptedData: \(decryptedData)") 
    } 
} 

輸出:

data:   <446f6ec2 b4742074 72792074 6f207265 61642074 68697320 74657874 2e20546f 70205365 63726574 20537475 6666> 
encryptedData: <b146c869 df2eec94 fd4656fd 02757e25 718cc32e 35c51907 31866a1c 99f8e2b9 de3ba203 41a49b0f 8fd5dc4c d7721333> 
decryptedData: <446f6ec2 b4742074 72792074 6f207265 61642074 68697320 74657874 2e20546f 70205365 63726574 20537475 6666> 
+1

我不認爲這是做原始代碼有奇怪的MD5 mangle(for循環複製8個字節到最後填充到24)。看起來你只是產生了16個字節(就像你知道的,一個正常的MD5)。 –

+0

的確,我將其視爲OP應該能夠實現的非加密操作。我通常會將操作分離爲原語而不是混合,這會降低可重用性。感謝提供修剪。 – zaph

+0

添加了將16字節md5擴展爲24字節2TDEA密鑰的代碼。 – zaph

0

使用Swiftify,我得到了下面的代碼:

func hashKey(hash: String) -> NSData { 
    var result: UInt8 
    let cStr: Character = hash.UTF8String() 
    CC_MD5(cStr, strlen(cStr), result) 
    for var jval = 0, kval = 16; jval < 8; { 
     result[kval++] = result[jval++] 
    } 
    return NSMutableData.dataWithBytes(result, length: 24) 
} 

func myEncrypt(encryptData: String) -> NSData { 
    var myKeyData: NSData = self.hashKey(MySecretKey) 
    var myRawData: NSData = encryptData.dataUsingEncoding(NSUTF8StringEncoding) 
    var buffer_size: size_t = myRawData.length() + kCCBlockSize3DES 
    var buffer: void = malloc(buffer_size) 
    var num_bytes_encrypted: size_t = 0 
    var iv: uint8_t = 56101632396182209205 
    var Crypto_status: CCCryptorStatus = CCCrypt(kCCEncrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding, myKeyData.bytes(), kCCKeySize3DES, iv, myRawData.bytes(), myRawData.length(), buffer, buffer_size, &num_bytes_encrypted) 

    if Crypto_status == kCCSuccess { 
    var myResult: NSData = NSData.dataWithBytes(buffer, length: num_bytes_encrypted) 
    free(buffer) 
    return myResult 
    } 
    else { 
    free(buffer) 
    return nil 
    } 
} 

func myDecrypt(decryptData: NSData) -> NSData { 
    var mydata_len: UInt = decryptData.length() 
    var keyData: NSData = self.hashKey(MySecretKey) 
    var buffer_size: size_t = mydata_len + kCCBlockSizeAES128 
    var buffer: void = malloc(buffer_size) 
    var num_bytes_encrypted: size_t = 0 
    var iv: uint8_t = 56101632396182209205 

    var decrypt_status: CCCryptorStatus = CCCrypt(kCCDecrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding, keyData.bytes(), kCCKeySize3DES, iv, decryptData.bytes(), mydata_len, buffer, buffer_size, &num_bytes_encrypted) 
    if decrypt_status == kCCSuccess { 
    var myResult: NSData = NSData.dataWithBytes(buffer, length: num_bytes_encrypted) 
    free(buffer) 
    return myResult 
    } 
    else { 
    free(buffer) 
    return nil 
    } 
} 
0

我想你使用CryptoSwift建議。它是用純粹的快速書寫的。