如何在c#中的解密字符串在iOS中使用Rijndael加密 [英] How decrypt string in c# was encrypted in iOS using Rijndael

查看:153
本文介绍了如何在c#中的解密字符串在iOS中使用Rijndael加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用客观c和C#加密和解密字符串。两个都在本机代码工作正常,但当我尝试解密在c#中的字符串是在iOS中加密。我收到一些错误。



这是我在目标c中使用的代码

   - (NSData *)AES256EncryptWithKey:(NSString *)key Data:(NSData *)data 
{
char keyPtr [kCCKeySizeAES256 + 1]; //用于终止符的空间(未使用)

bzero(keyPtr,sizeof(keyPtr)); //填充零(用于填充)

[key getCString:keyPtr maxLength:sizeof(keyPtr)encoding:NSUTF8StringEncoding];

NSUInteger dataLength = [data length];

NSData * iv = [@abcdefghijklmnopqrstuvwxyz123456dataUsingEncoding:NSUTF8StringEncoding];

size_t bufferSize = dataLength + kCCBlockSizeAES128;

void * buffer = malloc(bufferSize);

size_t numBytesEncrypted = 0;

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,kCCAlgorithmAES128,kCCOptionPKCS7Padding,
keyPtr,kCCKeySizeAES256,
[iv bytes] / *初始化向量(可选)* /,
[数据字节],dataLength,/ * input * /
buffer,bufferSize,/ * output * /
& numBytesEncrypted);

if(cryptStatus == kCCSuccess)
{
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}

free(buffer); //释放缓冲区

return nil;
}

想知道如何在C# ivsize到32并使用RijndaelManaged()。我不使用盐&密码。
错误:类似填充无效,无法删除。
我试图设置填充太像PKCS7,无,零,但没有帮助解密。



可以帮助这个吗?



编辑:
我的C#代码

  public string DecryptString b $ b {
string result = null;
_encoder = new UTF8Encoding();
if(!string.IsNullOrWhiteSpace(encrypted)&&(encrypted.Length> = 32))
{
var messageBytes = Convert.FromBase64String
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));
}
}

返回结果;
}

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 0,buffer.Length);
cs.FlushFinalBlock();
result = stream.ToArray();
}

返回结果;
}


解决方案指定所有加密参数,C#代码隐式确定许多参数。



C#类 RijndaelManaged 允许明确指定参数,改变你的代码使用这些,特别是 BlockSize 128 ), KeySize 128 ),模式 CipherMode.CBC )和 Padding PaddingMode.PKCS7 )。 mode Padding 的默认值都可以。请参见 Rijndael管理文档



AES和Rijndael不相同,特别是AES仅使用128位(16字节)的块大小,Rijndael允许几个块大小。因此,需要为Rijndael指定128位的块大小。因此,iv也是128位(16字节)。
两者都支持128,192和256字节的加密密钥。



你可能最好使用 AESManaged RijndaelManaged 类。请参见 Aes管理文档



C#期望数据是Base64编码,iOS端不显示编码操作,确保是在iOS端完成。 p>

由于您使用iv,因此请确保您在两侧都使用CBC模式。在通用加密CBC模式是默认,确保CBC模式正在C#侧使用。



确保C#端使用PKCS#7或PKCS#5 padding,它们是等价的。看来PKCS#7是C#侧的默认值,所以这应该是OK的。



最好使用一个指定大小的键,而不是依赖默认填充。在通用加密中,密钥大小被明确指定,并且如果提供的密钥要短,则填空。 C#看起来像是通过提供的密钥确定密钥大小,在这种情况下,密钥是10字节,因此解密密钥可能默认为128位,并且密钥在内部用空值填充。在iOS上,您明确指定了256位的密钥大小。这是一个需要修复的不匹配。提供一个在iOS端指定的精确大小的键。



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



最后提供测试数据的十六进制转储,数据输出,iv和键加密呼叫,如果你需要更多的帮助。


I'm trying to encrypt and decrypt the string using objective c and C#. both are working fine in native code, but when I was try to decrypt string in c# was encrypted in iOS. I get some error.

This was the code I used in the objective 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()". I'm not using salt & password. 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.

can any one help this?

Edit: My C# code here

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. 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). The defaults for mode and Padding are OK. See 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. So one needs to specify a block size of 128 bits for Rijndael. Thus the iv is also 128 bits (16 bytes). Both support encryption keys of 128, 192 and 256 bytes.

You would probably be better off using the AESManaged class than the RijndaelManaged class. See AesManaged Documentation

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.

Since you are using an iv make sure you are using CBC mode on both sides. In Common Crypto CBC mode is the default, make sure CBC mode is being used on the C# side.

Make sure the C# side is using PKCS#7 or PKCS#5 padding, they are equivalent. It appears that PKCS#7 is the default on the C# side so this should be OK.

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. 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. On iOS you are explicitly specifying a key size of 256 bits. This is a mis-match that needs to be fixed. Supply a key that is the exact size specified on the iOS side.

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. The solution is to change the iOS code to prepend the iv to the encrypted code. Change the iv to be 16 bytes, the AES block size.

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.

这篇关于如何在c#中的解密字符串在iOS中使用Rijndael加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆