2016-10-25 32 views
0
do { 
let JSONObject:[String:String] = 
[ 
"username" : "username", 
"password" : "Password", 
"domain": "domain" 
] 
let my64data:NSData = NSData(base64EncodedString:Credentials.SecretKey, options: NSDataBase64DecodingOptions(rawValue: UInt(0)))! 

let jsonData = try NSJSONSerialization.dataWithJSONObject(JSONObject, options: NSJSONWritingOptions.PrettyPrinted) 

let myString = String(data: jsonData, encoding: NSUTF8StringEncoding) 

    // let jsonString = AES1.encrypt(myString!, secretKey: Credentials.SecretKey, options:["iv":my64data]) 
    // print(" My Encrypted Json = \(jsonString)") 
    //    
    // let Decrypt = AES1.decrypt(jsonString, secretKey: Credentials.SecretKey, options: ["iv":my64data]) 
    //print(" My Decrypted Json = \(Decrypt)") 

let iv: Array<UInt8> = AES.randomIV(128/8) 
let salt: Array<UInt8> = AES.randomIV(128/8) 

let value = try! PKCS5.PBKDF2(password: Credentials.SecretKey.utf8.map({$0}), salt: salt, iterations: 1000, variant: .sha256).calculate() 
       value.toHexString() 

       _ = CryptoJS.mode.ECB() 
       _ = CryptoJS.pad.Iso97971() 
       _ = CryptoJS.pad.AnsiX923() 
       _ = CryptoJS.pad.Iso10126() 
       _ = CryptoJS.pad.ZeroPadding() 

       let encrypted : Array<UInt8> 

        encrypted = try AES(key: value, iv: iv, blockMode: .CBC, padding: PKCS7()).encrypt((myString?.utf8.map({$0}))!) 
        let decrypted = try AES(key: value, iv: iv, blockMode: .CBC, padding: PKCS7()).decrypt(encrypted) 

    //   let jsonString = AES1.encrypt(myString!, secretKey: String(value), options:["iv":iv.toHexString(),"mode":CryptoJS.mode().ECB,"padding":CryptoJS.pad().ZeroPadding]) 
       print(" My Encrypted Json = \(encrypted.toHexString())") 
    //    
    //   let pkcs = PKCS7() 
    //    
    //   let Decrypt = AES1.decrypt(jsonString, secretKey: String(value), options: ["iv":iv.toHexString(),"mode":CryptoJS.mode().ECB,"padding":pkcs]) 
       print(" My Decrypted Json = \(decrypted.toHexString())") 

       let myInputIV : String = String(iv.toHexString()) 
       let myInputSalt :String = String(salt.toHexString()) 

       let finalJSONObject:[String:String] = [ 

        "ciphertext" : "\(encrypted.toHexString())", 
        "iv" : "\(myInputIV)", 
        "salt": "\(myInputSalt)" 

       ] 

    print("Final Json Object = \(finalJSONObject)") 

       let requestURL: NSURL = NSURL(string:"<myURL>")! 
       print(requestURL) 
       let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL) 
       urlRequest.HTTPMethod = "POST" 
       urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") 
       urlRequest.HTTPBody = try!NSJSONSerialization.dataWithJSONObject(finalJSONObject, options:.PrettyPrinted) 

       let session = NSURLSession.sharedSession() 
       let task = session.dataTaskWithRequest(urlRequest, completionHandler:{ 
        data, response, error -> Void in 

        // Asynchronously call... 
        if (data != nil) { 

         print("Dataaa = \(data!)") 

         self.loginServiceResponse(data!) 

        }else{ 

         Singleton.SharedInstance.myAlert(alertTitle:Constants.SERVER_ERROR_TITLE, alertMessage: Constants.SERVER_ERROR_MESSAGE, alertButtonTitle:Constants.OK) 
         self.activityIndicator.stopAnimating() 

        } 


       }) 

       task.resume() 

      } catch { 
       print(error) 

      } 

我得到這個錯誤:CryptoSwift + CryptoJS作出錯誤的JSON在雨燕2.3

Error with Json Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}

+0

在郵遞員我得到了填充錯誤 – iPhone25

+0

最好避免使用CryptoSwift,其他的事情比通常的基於Crypto的實現慢500到1000倍。 Apple的Common Crypto已通過FIPS認證,並且經過充分審查,使用CryptoSwift正在考慮正確性和安全性。 – zaph

+0

使用[mcve]更新代碼,調整加密部分的輸入和輸出。首先得到簡單的加密工作,然後添加JSON,然後添加通信。在工作代碼上逐步構建,「大爆炸」方法很難調試。 – zaph

回答

0

要使用公共的密碼從斯威夫特

  1. 添加橋接報
  2. 添加#import <CommonCrypto/CommonCrypto.h>到頭。

該示例使用CBC模式並將加密數據與IV一起使用,這是一種通常用於處理IV的方法。

AES加密CBC模式與隨機IV(SWIFT 3.0)

的IV被前綴到加密數據

aesCBC128Encrypt將創建一個隨機IV和:從已棄用的文檔部分

實施例加密代碼前綴。
aesCBC128Decrypt將在解密期間使用前綴IV。

輸入是數據,鍵是數據對象。如果需要的話,如Base64等編碼形式轉換爲和/或在調用方法中。

密鑰的長度應該正好是128位(16字節),192位(24字節)或256位(32字節)。如果使用其他密鑰大小,則會引發錯誤。

PKCS#7 padding默認設置。

這個例子需要公共的密碼
這是需要有一個橋接報的項目:
#import <CommonCrypto/CommonCrypto.h>
添加Security.framework到項目中。

這是例子,而不是產品代碼。

enum AESError: Error { 
    case KeyError((String, Int)) 
    case IVError((String, Int)) 
    case CryptorError((String, Int)) 
} 

// The iv is prefixed to the encrypted data 
func aesCBCEncrypt(data:Data, keyData:Data) throws -> Data { 
    let keyLength = keyData.count 
    let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256] 
    if (validKeyLengths.contains(keyLength) == false) { 
     throw AESError.KeyError(("Invalid key length", keyLength)) 
    } 

    let ivSize = kCCBlockSizeAES128; 
    let cryptLength = size_t(ivSize + data.count + kCCBlockSizeAES128) 
    var cryptData = Data(count:cryptLength) 

    let status = cryptData.withUnsafeMutableBytes {ivBytes in 
     SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, ivBytes) 
    } 
    if (status != 0) { 
     throw AESError.IVError(("IV generation failed", Int(status))) 
    } 

    var numBytesEncrypted :size_t = 0 
    let options = CCOptions(kCCOptionPKCS7Padding) 

    let cryptStatus = cryptData.withUnsafeMutableBytes {cryptBytes in 
     data.withUnsafeBytes {dataBytes in 
      keyData.withUnsafeBytes {keyBytes in 
       CCCrypt(CCOperation(kCCEncrypt), 
         CCAlgorithm(kCCAlgorithmAES), 
         options, 
         keyBytes, keyLength, 
         cryptBytes, 
         dataBytes, data.count, 
         cryptBytes+kCCBlockSizeAES128, cryptLength, 
         &numBytesEncrypted) 
      } 
     } 
    } 

    if UInt32(cryptStatus) == UInt32(kCCSuccess) { 
     cryptData.count = numBytesEncrypted + ivSize 
    } 
    else { 
     throw AESError.CryptorError(("Encryption failed", Int(cryptStatus))) 
    } 

    return cryptData; 
} 

// The iv is prefixed to the encrypted data 
func aesCBCDecrypt(data:Data, keyData:Data) throws -> Data? { 
    let keyLength = keyData.count 
    let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256] 
    if (validKeyLengths.contains(keyLength) == false) { 
     throw AESError.KeyError(("Invalid key length", keyLength)) 
    } 

    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 { 
     throw AESError.CryptorError(("Decryption failed", Int(cryptStatus))) 
    } 

    return clearData; 
} 

實例:

let clearData = "clearData".data(using:String.Encoding.utf8)! 
let keyData = "keyData89".data(using:String.Encoding.utf8)! 
print("clearData: \(clearData as NSData)") 
print("keyData:  \(keyData as NSData)") 

var cryptData :Data? 
do { 
    cryptData = try aesCBCEncrypt(data:clearData, keyData:keyData) 
    print("cryptData: \(cryptData! as NSData)") 
} 
catch (let status) { 
    print("Error aesCBCEncrypt: \(status)") 
} 

let decryptData :Data? 
do { 
    let decryptData = try aesCBCDecrypt(data:cryptData!, keyData:keyData) 
    print("decryptData: \(decryptData! as NSData)") 
} 
catch (let status) { 
    print("Error aesCBCDecrypt: \(status)") 
} 

示例輸出:

clearData: <636c6561 72446174 61303132 33343536> 
keyData:  <6b657944 61746138 39303132 33343536> 
cryptData: <92c57393 f454d959 5a4d158f 6e1cd3e7 77986ee9 b2970f49 2bafcf1a 8ee9d51a bde49c31 d7780256 71837a61 60fa4be0> 
decryptData: <636c6561 72446174 61303132 33343536> 

注:
與CBC模式示例代碼的一個典型問題是,它離開隨機的創建和共享IV給用戶。這個例子包括生成IV,在加密數據前加上前綴,並在解密期間使用前綴IV。這使臨時用戶免於CBC mode所需的細節。

爲了安全,加密的數據也應該有認證,這個示例代碼沒有規定爲了小,並且允許其他平臺更好的互操作性。

還缺少的是從密碼中得到密鑰的關鍵推導,建議使用PBKDF2是將文本密碼用作密鑰材料。

要獲得穩健的生產就緒多平臺加密代碼,請參見RNCryptor