简体   繁体   English

如何使用Rijndael在iOS中加密c#中的解密字符串

[英]How decrypt string in c# was encrypted in iOS using Rijndael

I'm trying to encrypt and decrypt the string using objective c and C#. 我正在尝试使用目标c和C#加密和解密字符串。 both are working fine in native code, but when I was try to decrypt string in c# was encrypted in iOS. 两者在本机代码中工作正常,但当我尝试解密c#中的字符串时,在iOS中加密。 I get some error. 我收到一些错误。

This was the code I used in the objective c 这是我在目标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;
}

In want to know how to decrypt in C#, I give blocksize is 256, ivsize to 32 and used "RijndaelManaged()". 想要知道如何在C#中解密,我给出的blockize是256,ivsize为32,并使用了“RijndaelManaged()”。 I'm not using salt & password. 我没有使用salt和密码。 Error: something like "Padding is invalid and cannot be removed." 错误:类似“填充无效且无法删除”。 I tried to set padding too like PKCS7, none, zero but nothing help to decrypt. 我试图设置padding也像PKCS7,none,zero但没有任何帮助解密。

can any one help this? 任何人都可以帮忙吗?

Edit: My C# code here 编辑:我的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 (Common Crypto) explicitly specifies all encryption parameters, the C# code implicitly determines many parameters. iOS(Common Crypto)明确指定所有加密参数,C#代码隐式确定许多参数。 These implicit parameters while simplifying usage are problematic when trying to achieve interoperability. 在尝试实现互操作性时,这些隐含参数在简化使用时会出现问题。

The C# class RijndaelManaged allows explicitly specifying parameter, change your code to use these, in particular BlockSize ( 128 ), KeySize ( 128 ), Mode ( CipherMode.CBC ) and Padding ( PaddingMode.PKCS7 ). C#类RijndaelManaged允许显式指定参数,更改您的代码以使用它们,特别是BlockSize128 ), KeySize128 ), ModeCipherMode.CBC )和PaddingPaddingMode.PKCS7 )。 The defaults for mode and Padding are OK. modePadding的默认值都可以。 See RijndaelManaged Documentation 请参阅RijndaelManaged Documentation

AES and Rijndael are not the same, in particular AES uses only a block size of 128 bits (16 bytes) and Rijndael allows several block sizes. AES和Rijndael不相同,特别是AES仅使用128位(16字节)的块大小,而Rijndael允许多个块大小。 So one needs to specify a block size of 128 bits for Rijndael. 因此,需要为Rijndael指定128位的块大小。 Thus the iv is also 128 bits (16 bytes). 因此,iv也是128位(16字节)。 Both support encryption keys of 128, 192 and 256 bytes. 两者都支持128,192和256字节的加密密钥。

You would probably be better off using the AESManaged class than the RijndaelManaged class. 使用AESManaged类可能比RijndaelManaged类更好。 See AesManaged Documentation 请参阅AesManaged文档

The C# side expects the data to be Base64 encoded, the iOS side does not show that encoding operation, make sure that is being done on the iOS side. C#端期望数据为Base64编码,iOS端不显示编码操作,确保在iOS端完成。

Since you are using an iv make sure you are using CBC mode on both sides. 由于您使用的是iv,请确保您在两侧都使用CBC模式。 In Common Crypto CBC mode is the default, make sure CBC mode is being used on the C# side. 在Common Crypto中,CBC模式是默认模式,请确保在C#端使用CBC模式。

Make sure the C# side is using PKCS#7 or PKCS#5 padding, they are equivalent. 确保C#端使用PKCS#7或PKCS#5填充,它们是等效的。 It appears that PKCS#7 is the default on the C# side so this should be OK. 似乎PKCS#7是C#端的默认值,所以这应该没问题。

It is best to use a key of exactly the size specified and not rely on default padding. 最好使用完全符合指定大小的密钥,而不是依赖于默认填充。 In Common Crypto the key size is explicitly specified and null padded if the supplied key is to short. 在Common Crypto中,显式指定密钥大小,如果提供的密钥为short,则填充空值。 The C# looks like it is determining the key size by the supplied key, in this case the key is 10 bytes so the decryption key probably defaults to 128 bits and the key is being internally padded with nulls. C#看起来像是通过提供的密钥确定密钥大小,在这种情况下密钥是10个字节,因此解密密钥可能默认为128位,密钥在内部用空值填充。 On iOS you are explicitly specifying a key size of 256 bits. 在iOS上,您明确指定密钥大小为256位。 This is a mis-match that needs to be fixed. 这是一个需要修复的不匹配。 Supply a key that is the exact size specified on the iOS side. 提供一个在iOS端指定的确切大小的密钥。

Finally there is the iv, the C# code expects the iv to be prepended to the encrypted data but the iOS code is not providing that. 最后是iv,C#代码期望iv加在加密数据之前,但iOS代码没有提供。 The solution is to change the iOS code to prepend the iv to the encrypted code. 解决方案是更改iOS代码以将iv添加到加密代码之前。 Change the iv to be 16 bytes, the AES block size. 将iv更改为16字节,即AES块大小。

Finally provide hex dumps of the test data in, data out, iv and key just prior to and after the encryption call if you need more help. 如果需要更多帮助,最后在加密调用之前和之后提供测试数据的十六进制转储,数据输出,iv和密钥。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM