我最近被分配了一项任务,对我在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代码的输出相匹配?
我试过了
-荚隐雨燕
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=="
正如你所看到的,两种输出都有差异。这是为什么?
最佳答案
我是用密码斯威夫特做的。你可以通过椰子荚添加这个荚果。有人建议您找到一种本地方法来解决此问题,因为crypto swift可能会影响您的应用程序性能。无论如何,我想不出别的办法。
我用的是斯威夫特2.3。所以,如果您使用最新版本的swift,请转换代码
第1步:POD‘CryptoSwift’,‘0.5.2’(0.5.2仅适用于SWIFT 2.3。)
步骤2:创建字符串扩展名
//加密swift
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:最重要的是在两个平台上交叉检查所有方法的方式。一定要按照在另一个平台上完成的所有步骤操作。