如何使用Rijndael在iOS中对C#中的解密字符串进行加密

我正在尝试使用目标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#中解密时,我给blocksize设置为256,将ivsize设置为32,然后使用“ RijndaelManaged()”.我不使用盐&密码.
错误:类似“填充无效且无法删除”之类的信息.
我试图像PKCS7一样设置填充,没有,为零,但没有帮助解密.

有人可以帮忙吗?

编辑:
我的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;
}

解决方法:

iOS(通用加密)显式指定所有加密参数,C#代码隐式确定许多参数.当试图实现互操作性时,这些隐式参数在简化用法的同时存在问题.

C#类RijndaelManaged允许显式指定参数,更改代码以使用它们,尤其是BlockSize(128),KeySize(128),Mode(CipherMode.CBC)和Padding(PaddingMode.PKCS7).模式和填充的默认设置为OK.查看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模式.在“通用加密”中,CBC模式是默认设置,请确保在C#端使用CBC模式.

确保C#端正在使用PKCS#7或PKCS#5填充,它们是等效的.似乎PKCS#7是C#上的默认设置,因此应该可以.

最好使用完全指定大小的密钥,而不要依赖默认填充.在Common Crypto中,密钥大小是明确指定的,如果提供的密钥较短,则将填充null. C#看起来像是通过提供的密钥来确定密钥大小,在这种情况下,密钥为10个字节,因此解密密钥可能默认为128位,并且该密钥在内部填充为空.在iOS上,您明确指定了256位的密钥大小.这是不匹配的问题,需要解决.提供一个与iOS端指定的大小完全相同的密钥.

最后是iv,C#代码希望iv放在加密数据的前面,但iOS代码没有提供.解决方案是更改iOS代码以将iv放在加密代码之前.将iv更改为16字节,即AES块大小.

最后,如果需要更多帮助,请在加密调用之前和之后提供十六进制的测试数据输入,数据输出,iv和密钥转储.

上一篇:c#-获取Wi-Fi配置文件信息


下一篇:我如何才能使CSharp / .NET与PHP加密的字符串“玩得很好”?