简体   繁体   English

IOS 中的 AES 解密未给出确切结果

[英]AES Decryption in IOS not giving the exact result

Im trying to Decrypt my file in IOS.我试图在 IOS 中解密我的文件。 the file is encrypted with AES in C# application.该文件在 C# 应用程序中使用 AES 加密。

this is my IOS Decryption Method :这是我的 IOS 解密方法:

- (NSData *)AES128Operation:(CCOperation)operation key:(NSString *)key iv:(NSString *)iv
{
    NSLog(@"inside AES128Operation");
    char keyPtr[kCCKeySizeAES128 + 1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    char ivPtr[kCCBlockSizeAES128 + 1];
    bzero(ivPtr, sizeof(ivPtr));
    if (iv) {
        [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
    }

    NSUInteger dataLength = [self length];
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(operation,
                                          kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          keyPtr,
                                          kCCBlockSizeAES128,
                                          ivPtr,
                                          [self bytes],
                                          dataLength,
                                          buffer,
                                          bufferSize,
                                          &numBytesEncrypted);

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

And the way im using it :我使用它的方式:

NSString *strKey = MyKey;
NSString *strIv = MyIV;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *pathLocal_encrypted = [documentsDir stringByAppendingPathComponent:@"encrypted.file"];

NSData *data_encrpted = [[NSFileManager defaultManager] contentsAtPath:pathLocal_encrypted];

NSData *decryptedData = [data_encrpted AES128DecryptedDataWithKey:strKey iv:strIv];

IV is a 8 Byte Vector. IV 是一个 8 字节向量。 The final decrypted file is unreadable or badly decrypted.最终解密的文件无法读取或解密错误。 i also tried Encrypt/Decrypt inside ios application with "AES128Operation" method on some test file and it works well but dont know why it cant decrypt the C# encrypted file.我还尝试在 ios 应用程序中使用“AES128Operation”方法对某些测试文件进行加密/解密,它运行良好,但不知道为什么它无法解密 C# 加密文件。

The Decryption Works well in C# with this code (same file , Same iv , Same ,Key):解密在 C# 中使用此代码运行良好(相同的文件,相同的 iv ,相同的,密钥):

    static byte[] GetBytes(string str)
    {
        byte[] bytes = new byte[str.Length * sizeof(char)];
        System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }

    private static byte[] DecryptBytes(SymmetricAlgorithm alg, byte[] message)
    {
        if ((message == null) || (message.Length == 0))
        {
            return message;
        }
        using (var stream = new MemoryStream())
        {
            using (var decryptor = alg.CreateDecryptor())
            using (var encrypt = new CryptoStream(stream, decryptor, CryptoStreamMode.Write))
            {
                encrypt.Write(message, 0, message.Length);
                encrypt.FlushFinalBlock();
            }
            return stream.ToArray();
        }
    }
                path = openFileDialog1.FileName;
                byte[] encMessage = StreamFile(path);
                byte[] decMessage; 

                byte[] rkey = GetBytes(Mykey);
                byte[] riv = GetBytes(MyIv);
                using (var rijndael = new RijndaelManaged())
                {
                    rijndael.Key = rkey;
                    rijndael.IV = riv;
                    decMessage = DecryptBytes(rijndael, encMessage);
                }

due to answer suggestion ive tried this one to but still no hope :由于回答建议,我尝试了这个,但仍然没有希望:

    NSData *key = [NSData dataWithData:[strKey dataUsingEncoding:NSUTF8StringEncoding]];
    NSData *iv = [NSData dataWithData:[strIv dataUsingEncoding:NSUTF8StringEncoding]];
    NSData *decryptedData = [self doCipher:data_encrpted iv:iv key:key context:kCCDecrypt];

and the new function :和新功能:

- (NSData *)doCipher:(NSData *)dataIn
                  iv:(NSData *)iv
                 key:(NSData *)symmetricKey
             context:(CCOperation)encryptOrDecrypt
{

    CCCryptorStatus ccStatus   = kCCSuccess;
    size_t          cryptBytes = 0;    // Number of bytes moved to buffer.
    NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

    ccStatus = CCCrypt( encryptOrDecrypt,
                       kCCAlgorithmAES128,
                       kCCOptionPKCS7Padding,
                       symmetricKey.bytes,
                       kCCKeySizeAES128,
                       iv.bytes,
                       dataIn.bytes,
                       dataIn.length,
                       dataOut.mutableBytes,
                       dataOut.length,
                       &cryptBytes);


        NSLog(@"CCCrypt status: %d", ccStatus);


    dataOut.length = cryptBytes;
    NSLog(@"CCCrypt ataOut.length: %d", dataOut.length);
    return dataOut;
}

this is the encryption\\decryption setting inside C# :这是 C# 中的加密\\解密设置:

   public RijndaelManaged GetRijndaelManaged(string secretKey, string iv)
    {
        var keyBytes = new byte[16];
        var secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
        Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));

        var ivBytes = new byte[16];
        var secretIvBytes = Encoding.UTF8.GetBytes(iv);
        Array.Copy(secretIvBytes, ivBytes, Math.Min(ivBytes.Length, secretIvBytes.Length));

        return new RijndaelManaged
        {
            Mode = CipherMode.CBC,
            Padding = PaddingMode.PKCS7,
            KeySize = 128,
            BlockSize = 128,
            Key = keyBytes,
            IV = ivBytes
        };
    }

    public byte[] Encrypt(byte[] plainBytes, RijndaelManaged rijndaelManaged)
    {
        return rijndaelManaged.CreateEncryptor()
            .TransformFinalBlock(plainBytes, 0, plainBytes.Length);
    }

    public byte[] Decrypt(byte[] encryptedData, RijndaelManaged rijndaelManaged)
    {
        return rijndaelManaged.CreateDecryptor()
            .TransformFinalBlock(encryptedData, 0, encryptedData.Length);
    }

The iv for AES is the same as the block size: 128 bits (16 bytes), the question states: "IV is a 8 Byte Vector" which is incorrect. AES 的 iv 与块大小相同:128 位(16 字节),问题指出:“IV 是 8 字节向量”,这是不正确的。

Since you are using an iv the mode should be CBC but the code specifies kCCOptionECBMode , remove this, the default on iOS (Common Crypto) is CBC mode.由于您使用的是 iv 模式应该是 CBC 但代码指定了kCCOptionECBMode ,删除它,iOS(通用加密)上的默认值是 CBC 模式。

Note that RijndaelManaged defaults to CBC mode and PKCS#7 padding.请注意, RijndaelManaged默认为 CBC 模式和 PKCS#7 填充。 But the key size if not explicitly set is determined by length of the key supplied and is null padded to a supported key length.但是,如果未明确设置,密钥大小由所提供密钥的长度决定,并填充为支持的密钥长度。 It is better to explicitly set this, in RijndaelManaged use the KeySize parameter (in bits).最好明确设置它,在RijndaelManaged使用KeySize参数(以位为单位)。

The block size for AES is 128 bits but RijndaelManaged supports several block sizes, AESManaged is a better choice for AES encryption. AES 的块大小为 128 位,但RijndaelManaged支持多种块大小, AESManaged是 AES 加密的更好选择。 This is probably not a problem.这可能不是问题。 It is better to explicitly set this, in RijndaelManaged use the BlockSize parameter with the value 128.最好明确设置它,在RijndaelManaged使用值为 128 的BlockSize参数。

As documentation says for C# default mode (AesManaged.Mode Property):正如文档所说的 C# 默认模式(AesManaged.Mode 属性):

 One of the enumeration values that specifies the block cipher mode to use for encryption. The default is CBC.

So, in ios you also must decrypt data with CBC mode.因此,在 ios 中,您还必须使用 CBC 模式解密数据。

Remove kCCOptionECBMode from your decryption code从你的解密代码中删除 kCCOptionECBMode

As for padding:至于填充:

Property Value Type: System.Security.Cryptography.PaddingMode One of the enumeration values that specifies the type of padding to apply.属性值类型:System.Security.Cryptography.PaddingMode 指定要应用的填充类型的枚举值之一。 The default is PKCS7.默认为 PKCS7。

So, check your decryption code for correct params因此,请检查您的解密代码以获取正确的参数

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

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