【问题标题】:How do I do a cross platform encryption method working in both IOS and android (AES encryption only..)?如何在 IOS 和 android 中使用跨平台加密方法(仅限 AES 加密..)?
【发布时间】:2017-06-06 04:21:04
【问题描述】:

我最近被分配了一项任务,即加密我在 swift 中传入 dataTaskWithRequest 的链接和参数。主要令人头疼的是它应该产生与 Android 平台相同的输出。 android 团队已经创建了一个使用 spring 来解密数据的后端。 java代码是这样的

类 AESencrp {

private static final String ALGO = "AES";
 private static final byte[] keyValue =
        new byte[]{'T', 'h', 'e', 'B', 'e', 's', 't',
                'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};

public static String encrypt(String Data) throws Exception {
    Key key = generateKey();
    Cipher c = Cipher.getInstance(ALGO);
    c.init(Cipher.ENCRYPT_MODE, key);
    byte[] encVal = c.doFinal(Data.getBytes());
    String encryptedValue = new BASE64Encoder().encode(encVal);
    return encryptedValue;
}

public static String decrypt(String encryptedData) throws Exception {
    Key key = generateKey();
    Cipher c = Cipher.getInstance(ALGO);
    c.init(Cipher.DECRYPT_MODE, key);
    byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
    byte[] decValue = c.doFinal(decordedValue);
    String decryptedValue = new String(decValue);

    return decryptedValue;
}

private static Key generateKey() throws Exception {
    Key key = new SecretKeySpec(keyValue, ALGO);
    return key;
}

} 我无法更改此处使用的方法并使用 swift 的内置加密方法。有没有办法在 swift 中进行 AES 加密,既高效又与 java 代码的输出相匹配

我试过了 - POD Cryptoswift

   do {

         let encrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .ECB).encrypt(inputBytes)
         let encrypted2: [UInt8] = try AES(key: key, iv: iv, blockMode: .ECB, padding: PKCS5).encrypt(inputBytes)


        let encryptedNSData = NSData(bytes: encrypted, length: encrypted.count)
        encryptedBase64 = encryptedNSData.base64EncodedStringWithOptions([])

        let encryptedNSData2 = NSData(bytes: encrypted2, length: encrypted2.count)
        encryPadded = encryptedNSData2.base64EncodedStringWithOptions([])


        let decrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .ECB).decrypt(encrypted)
        let result = String(bytes: decrypted, encoding: NSUTF8StringEncoding)!
        print("result\t\(result )")

    } catch {
        // some error
    }
JAVA CODE OUTPUT = "eJvkXYGzEjJ6RbYSp4a3OQ=="

SWIFT CODE OUTPUT = "9UiyETvuHTsN7eIo0HfQ+w=="

如您所见,两种输出都存在差异。这是为什么呢?

【问题讨论】:

  • 你有没有设法让它工作?我也在研究这个确切的问题。我的 java 代码虽然是服务器端的,但其他的都是一样的。
  • 是的,我做到了..我将在下面发布答案
  • 一个很好的跨平台解决方案也支持多种语言是RNCryptor。您还可以获得身份验证,如果需要,还可以获得密钥派生。
  • 我刚刚在stackoverflow.com/questions/40421146/… 中发布了一个可以接受的答案。

标签: java swift swift2 aes


【解决方案1】:

我通过使用 crypto swift 做到了这一点。您可以通过 CocoaPods 添加此 pod。建议您找到解决此问题的本地方法,因为加密 swift 可能会影响您的应用程序性能。反正我想不出除此之外的出路。

我使用的是 swift 2.3 。所以,如果您使用的是最新版本的swift,请转换代码

第 1 步:pod 'CryptoSwift', '0.5.2'(0.5.2 仅适用于 swift 2.3。)

第 2 步:创建字符串扩展名

//加密斯威夫特

func AES_EncryptionKey() -> String {
    let date = NSDate()
    let calender = NSCalendar.currentCalendar()
    let components = calender.components([.Day,.Month,.Year], fromDate: NSDate())
    let year = components.year
    var day = String(components.day)
    var month = String(components.month)
    if day.characters.count == 1 {
        day = "0\(String(day))"
    }
    if month.characters.count == 1 {
        month = "0\(String(month))"
    }
    //Mark: Please change the key as per your requirment! I am using a dynamic key now  rather the one specified in question . i.e It changes everday
    let secretKey = "\(String(day))20\(month)u\(String(year))e"
    return secretKey

}


func AESencrypt() throws -> String  {

    //Mark: You have to do the same thing in Android too. If u skip this here skip in android too
    let secretKeyTest = AES_EncryptionKey().toBase64()!



    let inputBytes: [UInt8] = Array(self.utf8)
    let key:        [UInt8] = Array(secretKeyTest.utf8) //16
    let iv:         [UInt8] = Array("0000000000000000".utf8)  //16

    var encryptedBase64 = ""
    do
    {
        let encrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .ECB).encrypt(inputBytes)
        let encryptedNSData = NSData(bytes: encrypted, length: encrypted.count)
        encryptedBase64 = encryptedNSData.base64EncodedStringWithOptions([])

        //Mark: You have to do the same thing in Android too. If u skip this here skip in android too
        encryptedBase64=encryptedBase64.toBase64()!

        //Mark: Follow the same blockMode in both platform. ECB Mode is not recommended. I did it in ECB cuz it was already done in other platform
        let decrypted: [UInt8] = try AES(key: key, iv: iv, blockMode: .ECB).decrypt(encrypted)
        let result = String(bytes: decrypted, encoding: NSUTF8StringEncoding)!
        print("result\t\(result )")
    }
    catch
    {
        print("FAIL ENCRYPT")
    }
    print("encryptedBase64: \(encryptedBase64)")

    return encryptedBase64

}

func AESdecrypt() throws -> String {
    var decryptedString = "NIL"
    let secretKeyTest = AES_EncryptionKey().toBase64()!

    let key:        [UInt8] = Array(secretKeyTest.utf8) //16
    let iv:         [UInt8] = Array("0000000000000000".utf8)  //16

    //Step1
    let encryptedData = self.dataUsingEncoding(NSUTF8StringEncoding)!
    if let base64Decoded_ = NSData(base64EncodedData: encryptedData, options:  NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
    {

        if var stringBase64 = String(data:base64Decoded_, encoding: NSUTF8StringEncoding)
        {
            //Step2
            let encryptedDataSecond = stringBase64.dataUsingEncoding(NSUTF8StringEncoding)!
            let base64DecodedSecond_ = NSData(base64EncodedData: encryptedDataSecond, options:  NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
            //Step3
            let encrypted = Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>(base64DecodedSecond_!.bytes), count: base64DecodedSecond_!.length))
            do
            {
                let decryptedData = try AES(key: key, iv: iv, blockMode: .ECB).decrypt(encrypted)
                decryptedString = String(bytes: decryptedData, encoding: NSUTF8StringEncoding)!
                print("decryptedString: \(decryptedString)")
                print("ALL DECRYPTED")

            }
            catch
            {
                print("FAIL DECRYPT")
            }
        }
    }


    return decryptedString


}



func fromBase64() -> String? {
    guard let data = NSData(base64EncodedString: self, options: NSDataBase64DecodingOptions(rawValue: 0)) else {
        return nil
    }

    return String(data: data, encoding: NSUTF8StringEncoding)
}

func toBase64() -> String? {
    guard let data = self.dataUsingEncoding(NSUTF8StringEncoding) else {
        return nil
    }

    return data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
}}

第 3 步:最重要的是在两个平台上交叉检查所有方法的方式。一定要按照在另一个平台上完成的所有步骤..

【讨论】:

  • 最好避免使用 CryptoSwift,除此之外,它比基于 Common Crypto 的实现慢 500 到 1000 倍。 Apple 的 Common Crypto 已通过 FIPS 认证,因此经过严格审查,使用 CryptoSwift 在正确性和安全性方面是有机会的。
猜你喜欢
  • 2012-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-03
  • 1970-01-01
  • 1970-01-01
  • 2020-04-30
  • 1970-01-01
相关资源
最近更新 更多