[英]Decrypting AES/CBC/PKCS5Padding in iOS
我有一個使用以下代碼在 Android 上加密的文件:
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESUtils {
private static final String IV_STRING = "123456789876543";
private String key = "mysecretkey12345";
public static byte[] encryptData(String key, byte[] byteContent) {
byte[] encryptedBytes = null;
try {
byte[] enCodeFormat = key.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
byte[] initParam = IV_STRING.getBytes();
IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
encryptedBytes = cipher.doFinal(byteContent);
} catch (Exception e) {
e.printStackTrace();
}
return encryptedBytes;
}
public static byte[] decryptData(String key, byte[] encryptedBytes) {
byte[] result = null ;
try {
byte[] sEnCodeFormat = key.getBytes();
SecretKeySpec secretKey = new SecretKeySpec(sEnCodeFormat, "AES");
byte[] initParam = IV_STRING.getBytes();
IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
result = cipher.doFinal(encryptedBytes);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
我嘗試使用 CommonCrypto 對 Swift 中的解密進行逆向工程,如下所示:
import CommonCrypto
let keyStr:String = "mysecretkey12345"
let ivStr:String = "123456789876543"
func aesDecrypt(data:NSData) -> Data? {
let k:NSData = keyStr.data(using: .utf8)! as NSData
let dbytes = data.bytes
let kbytes=k.bytes
if let keyData = keyStr.data(using: .utf8),
let cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
kbytes, keyLength,
ivStr,
dbytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
return (cryptData.copy() as! Data)
}
else {
return nil
}
}
return nil
}
我對加密很陌生,但從我的研究中我發現 CC 默認使用 CBC,而 PKCS7Padding 與 PKCS5Padding 基本相同。 但是,解密並沒有提供我期望的結果! swift 代碼來自各種來源,包括在 stackoverflow 上提出的許多解決方案。 主要問題是大多數示例使用 key 和 iv 作為數據,而我有字符串 - 不確定我的轉換會導致問題。 其次,許多只是簡單地轉換字符串消息,而我直接轉換數據(從文件) - 不應該影響它太多,實際上使代碼更簡單,避免數據->字符串轉換。 但既然它不起作用,我錯過了什么?
好吧,我想我找到了問題所在。 顯然,NSData.bytes 存在問題,應該使用UnsafeBytes。 此外,我的問題可能是 IV 不是數據的一部分,正如許多示例所假設的那樣,所以我在解密時錯過了 16 個字節。 以下代碼對我有用,希望對某人有所幫助!
func decrypt(data: Data) -> Data {
let key: Data = keyStr.data(using: .utf8) ?? Data()
let iv: Data = ivStr.data(using: .utf8) ?? Data()
if(keyStr.count == kCCKeySizeAES128){print("Key OKAY")} else {print("Key NOT okay")}
if(ivStr.count == kCCBlockSizeAES128){print("IV OKAY")} else {print("IV NOT okay")}
var buffer = Data(count: data.count)
var numberBytesDecrypted: Int = 0
let cryptStatus: CCCryptorStatus = key.withUnsafeBytes {keyBytes in
data.withUnsafeBytes {dataBytes in
buffer.withUnsafeMutableBytes {bufferBytes in iv.withUnsafeBytes {ivBytes in
CCCrypt( // Stateless, one-shot encrypt operation
CCOperation(kCCDecrypt), // op: CCOperation
CCAlgorithm(kCCAlgorithmAES128), // alg: CCAlgorithm
CCOptions(kCCOptionPKCS7Padding), // options: CCOptions
keyBytes.baseAddress, // key: the "password"
key.count, // keyLength: the "password" size
ivBytes.baseAddress, // iv: Initialization Vector
dataBytes.baseAddress!, // dataIn: Data to decrypt bytes
data.count, // dataInLength: Data to decrypt size
bufferBytes.baseAddress, // dataOut: decrypted Data buffer
data.count, // dataOutAvailable: decrypted Data buffer size
&numberBytesDecrypted // dataOutMoved: the number of bytes written
)}
}
}
}
if(cryptStatus == CCCryptorStatus(kCCSuccess)){
return buffer[..<numberBytesDecrypted]
} else {
print("Decryption failed")
return data
}
}
好吧,原來我的一個測試文件已損壞,我的解密一直有效。 這是一個沒有 withUnsafeBytes 的簡單版本:
func decrypt(data: Data) -> Data {
let key:Data = keyStr.data(using: .utf8)!
let iv:Data = ivStr.data(using: .utf8)!
var buffer = [UInt8](repeating: 0, count: data.count + kCCBlockSizeAES128)
var bufferLen: Int = 0
let status = CCCrypt(
CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
CCOptions(kCCOptionPKCS7Padding),
[UInt8](key),
kCCBlockSizeAES128,
[UInt8](iv),
[UInt8](data),
data.count,
&buffer,
buffer.count,
&bufferLen
)
if(status == kCCSuccess) {
return Data(bytes: buffer, count: bufferLen)}
else {
print("Decryption failed")
return data
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.