2016-10-25 52 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