[英]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.