我正在尝试使用目标c和C#加密和解密字符串。两者在本机代码中工作正常,但当我尝试解密c#中的字符串时,在iOS中加密。我收到了一些错误。
这是我在目标c中使用的代码
- (NSData *)AES256EncryptWithKey:(NSString *)key Data: (NSData *) data
{
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];
NSUInteger dataLength = [data length];
NSData *iv = [@"abcdefghijklmnopqrstuvwxyz123456" dataUsingEncoding:NSUTF8StringEncoding];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
[iv bytes] /* initialization vector (optional) */,
[data bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess)
{
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer); //free the buffer;
return nil;
}
想要知道如何在C#中解密,我给出的blockize是256,ivsize到32并使用了“RijndaelManaged()”。我没有使用盐和盐密码。 错误:类似“填充无效且无法删除”。 我试图设置padding也像PKCS7,none,zero但没有任何帮助解密。
任何人都可以帮忙吗?
编辑: 我的C#代码在这里
public string DecryptString(string encrypted)
{
string result = null;
_encoder = new UTF8Encoding();
if (!string.IsNullOrWhiteSpace(encrypted) && (encrypted.Length >= 32))
{
var messageBytes = Convert.FromBase64String(encrypted);
using (var rm = new RijndaelManaged())
{
rm.BlockSize = _blockSize;
rm.Key = _encoder.GetBytes("mykey_here");
rm.IV = _encoder.GetBytes("abcdefghijklmnopqrstuvwxyz123456"); ;
rm.Padding = PaddingMode.Zeros;
var decryptor = rm.CreateDecryptor(rm.Key, messageBytes.Take(_ivSize).ToArray());
result = _encoder.GetString(Transform(messageBytes.Skip(_ivSize).ToArray(), decryptor));
}
}
return result;
}
protected byte[] Transform(byte[] buffer, ICryptoTransform transform)
{
byte[] result;
using (var stream = new MemoryStream())
using (var cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
cs.Write(buffer, 0, buffer.Length);
cs.FlushFinalBlock();
result = stream.ToArray();
}
return result;
}
答案 0 :(得分:4)
iOS(Common Crypto)明确指定所有加密参数,C#代码隐式确定许多参数。在尝试实现互操作性时,这些隐式参数在简化使用时会出现问题。
C#类RijndaelManaged
允许显式指定参数,更改代码以使用这些参数,特别是BlockSize
(128
),KeySize
(128
) ,Mode
(CipherMode.CBC
)和Padding
(PaddingMode.PKCS7
)。 mode
和Padding
的默认值均可。见RijndaelManaged Documentation
AES和Rijndael不相同,特别是AES仅使用128位(16字节)的块大小,而Rijndael允许多个块大小。因此,需要为Rijndael指定128位的块大小。因此,iv也是128位(16字节)。 两者都支持128,192和256字节的加密密钥。
使用AESManaged
类可能比RijndaelManaged
类更好。见AesManaged Documentation
C#端希望数据为Base64编码,iOS端不显示编码操作,请确保在iOS端完成。
由于您使用的是iv,请确保您在两侧都使用CBC模式。在Common Crypto中,CBC模式是默认模式,确保在C#端使用CBC模式。
确保C#端使用PKCS#7或PKCS#5填充,它们是等效的。似乎PKCS#7是C#端的默认值,所以这应该没问题。
最好使用完全符合指定大小的密钥,而不是依赖于默认填充。在Common Crypto中,显式指定密钥大小,如果提供的密钥为short,则填充空值。 C#看起来像是通过提供的密钥确定密钥大小,在这种情况下密钥是10个字节,因此解密密钥可能默认为128位,密钥在内部用空值填充。在iOS上,您明确指定密钥大小为256位。这是一个需要修复的不匹配。提供一个在iOS端指定的确切大小的密钥。
最后有iv,C#代码希望iv加在加密数据之前,但iOS代码没有提供。解决方案是更改iOS代码以将iv添加到加密代码之前。将iv更改为16字节,即AES块大小。
如果您需要更多帮助,最后在加密通话之前和之后提供测试数据的十六进制转储,数据输出,iv和密钥。