【发布时间】:2015-11-09 19:36:49
【问题描述】:
我有一个 iOS 应用程序,它发送加密数据,然后在 C# 中解密。我检查了十六进制密钥和接收到的数据是否相同,但我仍然得到 Bad PKCS7 padding。长度 0 无效。
我的 Objective-C 调用是
+(NSData*) encryptData: (NSData*) data
key: (NSString*) key
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[data bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer); //free the buffer;
return nil;
}
我的 keysize 是 256,blocksize 是 128,padding 是 pkcs7,IV 是 null,mode 是 CBC(默认)。
我要解密的 C# 代码是
using (MemoryStream memoryStream = new MemoryStream(outputBytes))
{
AesManaged algo = GetCryptoAlgorithm(GetRawBrokerKey());
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, algo.CreateDecryptor(), CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(cryptoStream))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
private static AesManaged GetCryptoAlgorithm()
{
return GetCryptoAlgorithm(null);
}
private static AesManaged GetCryptoAlgorithm(byte[] key)
{
AesManaged algorithm = new AesManaged();
//set the mode, padding and block size
algorithm.Padding = PaddingMode.PKCS7;
algorithm.Mode = CipherMode.CBC;
algorithm.KeySize = 256;
algorithm.BlockSize = 128;
if (key != null)
{
algorithm.Key = key;
}
algorithm.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
return algorithm;
}
我尝试使用 C# 进行加密,并使用相同的密钥查看不同的十六进制输出。
c# encryption - 42AC7494606333309287768F47DFB35B
static byte[] EncryptStringToBytes_Aes(string plainText, byte[] key)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
byte[] encrypted;
AesManaged algorithm = new AesManaged();
//set the mode, padding and block size
algorithm.Padding = PaddingMode.PKCS7;
algorithm.Mode = CipherMode.CBC;
algorithm.KeySize = 256;
algorithm.BlockSize = 128;
if (key != null)
{
algorithm.Key = key;
}
algorithm.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = algorithm.CreateEncryptor();
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
string hex = BitConverter.ToString(encrypted);
Console.WriteLine("c# encryption - " + hex.Replace("-", ""));
// Return the encrypted bytes from the memory stream.
return encrypted;
}
有什么想法可能会出错吗?我认为,我似乎正在遵循有关模式和 IV 的默认值的所有在线建议。
【问题讨论】:
-
Hex 在加密/解密调用之前转储 Objective-C 和 C++ 中的参数(密钥和数据),您应该会发现问题。如果是字符串,则可能存在关键问题。另一个明显的区别是传递数据与流的指针。调用没有明显错误。
-
我在 c# 中的十六进制值是加密的有效载荷十六进制 - DB1FB055E7961F6D2648110B1A8854CA 密钥十六进制 - 708B797DDB28D167CCC19F71ED2920447C743B9BFD5B878FA5CA7A0FC35659E4
-
我在 Objective-C 中的十六进制值是 --key hex = 加密数据 hex =对不起,我犯了一个愚蠢的错误,填充是在未加密的数据上,所以可能没有填充错误。随机数据无法转换为 unicode 字符串,所以使用 Base64 编码或 hex 编码。除了 Base64 编码之外,不需要密钥字符串。
标签: c# objective-c encryption interop aes