AES:使用CCCrypt()方法加密,使用C#解密,输出错误
本文关键字:使用 解密 输出 错误 加密 方法 CCCrypt AES | 更新日期: 2023-09-27 18:25:57
使用CCCrypt()
方法加密,然后在C#中解密。但是输出与原始纯文本不同。
密钥长度为256位,IV是默认值。
主要代码如下所示:
// Encrypt
{
// the key is 32 bytes (256 bits).
Byte iv[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, // Operation
kCCAlgorithmAES128, // Algorithm
kCCOptionPKCS7Padding, // Option
keyPtr, // key
kCCKeySizeAES256, // key length
iv, /* initialization vector (optional) */
[self bytes], // plain text
dataLength, /* input */
buffer,
bufferSize, /* output */
&numBytesEncrypted); //dataOutMove
if (cryptStatus == kCCSuccess) {
NSData *encryptedData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
NSString *encryptedString = [encryptedData base64Encoding];
}
// Decrypted
{
byte[] _key1 = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
public static string AESDecrypt(string encryptedString, string key)
{
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = _key1;
aes.Key = Encoding.UTF8.GetBytes(key);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// Convert Base64 strings to byte array
byte[] src = System.Convert.FromBase64String(encryptedString);
// decryption
using (ICryptoTransform decrypt = aes.CreateDecryptor())
{
byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length);
return Encoding.UTF8.GetString(dest);
}
}
}
编辑:我发现原因是keyPtr
。在加密过程中,我很早就这样处理密钥:
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) [key
getCString:keyPtr maxLength:sizeof(keyPtr)
encoding:NSUTF8StringEncoding];
现在,我修改这些代码如下:
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger keyLength = [keyData length];
Byte *keyPtr= (Byte *)malloc(keyLength);
memcpy(keyPtr, [keyData bytes], keyLength);
然后我得到了正确的输出。虽然问题已经解决了,但我真的不知道以前的版本出了什么问题。
Crypto被设计成即使有一个小错误也会严重失败。您需要明确地检查键是否逐字节相同(检查字节,而不是字符)。IVs也是如此。您正在CBC模式下解码。您确定加密处于CBC模式吗;它没有在代码中明确设置。填充也是如此。您确定加密方法使用的是PKCS7吗?
一般来说,不要依赖默认设置,而是在代码中明确设置它们。
最后一点,您是否使用了相同的字节<->两边的字符转换。同样,最好明确说明您正在使用的内容。例如,UTF-8文本可能附带一个UTF-8转换将忽略的初始BOM,但不同的转换将包含在字节中。
我在审查的一些代码时遇到了同样的问题,其中由CCCrypt加密并由另一个工具解密的数据没有产生相同的明文。我将其追踪到未能正确生成密钥。是这条线:
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
如果"key"的CString版本比kCCKeySizeAES256字节长,那么key:getCString将返回"NO"(因为它不适合提供的缓冲区),并且不会接触keyPtr指向的缓冲区,从而产生一个实际上全是NUL字节的密钥(来自bzero函数)。
使用[key-dataUsingEncoding]的替换代码不会遇到这个问题,因为它将创建一个与存储字符串所需大小一样大的NSData对象。然而,它会遇到密钥不够大的问题,除非你能保证传入的密钥足够长。
不建议使用纯文本键。如果您有一个纯文本"passphrase",那么使用Key派生函数将其转换为二进制序列。"黄金标准"是PBKDF2,但即使是SHA2-256也比纯文本要好。SHA2-256将为您提供32个字节。(SHA-1不够,因为它只有20个字节)。