【问题标题】:CryptoStream in .NET does not decrypt encrypted file from objective-C.NET 中的 CryptoStream 不会解密来自 Objective-C 的加密文件
【发布时间】:2013-09-06 13:32:21
【问题描述】:

我正在.NET and Objective-C apps 之间实现兼容的二进制文件加密/解密。我在Objective-C 端使用RNCryptor 包。据我所知,我可以encrypt/decrypt 字符串,但文件加密让我很困扰。问题是,当我读取文件并加密其数据并将其写入文件时,它不会在.NET app 中解密。如果我计算加密数据的 Base64 字符串并在 .NET 中解密它 - 从 Base64 字符串创建字节数组并使用与文件相同的登录名解密,它会解密。 将加密数据写入Objective C and .NETCryptoStream?中的文件有什么区别

或者我错过了一些基本的东西? 在目标 C 中加密文件的代码是:-

  RNEncryptor *encryptor = [[RNEncryptor alloc] initWithSettings:kRNCryptorAES256Settings
                                                          password:password
                                                           handler:^(RNCryptor *cryptor, NSData *data) {
                                                               @autoreleasepool
                                                               {
                                                                   NSLog(@"6length of out data %d",[data length]);

                                                                   [encodedText appendString:[data base64EncodingWithLineLength:0]];
                                                                   [outputStream write:data.bytes maxLength:data.length];

                                                                   dispatch_semaphore_signal(semaphore);

                                                                   data = nil;
                                                                   if (cryptor.isFinished)
                                                                   {

                                                                       [outputStream close];
                                                                       NSLog(@"my encryptedText  %@",encodedText);
                                                                       encryptionError = cryptor.error;
                                                                       // call my delegate that I'm finished with decrypting
                                                                   }
                                                               }
                                                           }];
    encryptor.filesize=[attrs fileSize];
    while (inputStream.hasBytesAvailable)
    {
        @autoreleasepool
        {
            uint8_t buf[blockSize];
            NSUInteger bytesRead = [inputStream read:buf maxLength:blockSize];
            if (bytesRead > 0)
            {
                NSData *data = [NSData dataWithBytes:buf length:bytesRead];

            }
                total = total + bytesRead;
                [encryptor addData:data];

                dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            }
        }
    }

    [inputStream close];

    [encryptor finish];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}

解密

[encodedText appendString:[data base64EncodingWithLineLength:0]];

始终有效,但文件无法解密。

【问题讨论】:

    标签: .net objective-c encryption cryptography aes


    【解决方案1】:

    更新:

    RNEncryptor 实际上是用于正确执行 aes 的高级加密 api,虽然它具有 adhoc 密文格式,但它是典型的构造。要将您的 dotnet 代码与它的 adhoc 格式匹配,您必须使用 RNCryptor keyForPassword:salt:settings:RNCryptorKeyDerivationSettings 匹配您的 Rfc2898DeriveBytes。如:

       {
        .keySize = kCCKeySizeAES256,
        .saltSize = 16,
        .PBKDFAlgorithm = kCCPBKDF2,
        .PRF = kCCPRFHmacAlgSHA1,
        .rounds = 1000
       }
    

    并使用 RNCryptorEngine 进行 aes 加密,并布置与您的 adhoc .net 格式匹配的密文。

    | IV (16 bytes) | Password Salt (16 bytes) | Ciphertext |
    

    这是假设明文也已经是正确的格式

    | message length (8 bytes) | const tag of some sort (8 bytes) | message | sha256 hash of message (32 bytes) |
    

    如果您也需要制作纯文本格式,此时您可能只想直接使用 iOS 的内置 CCCryptor 而不是 RNCryptor(我猜您会这样做)。

    建议:

    为了其他遇到此问题的人的利益,发帖者的 .net 密文结构存在安全问题,请勿使用。

    上一个答案

    RNCryptor 进行经过身份验证的加密。

    它实际上应该与我的代码兼容: Modern Examples of Symmetric Authenticated Encryption of a string (C#)

    然后解密,使用 RNEncryptor 生成的内容,使用:

    var plainText = AESThanHmac.SimpleDecryptWithPassword(encryptedMessage, password, nonSecretPayloadLength: 2);
    

    nonSecretPayloadLength 是 2,因此它会跳过 RNEncryptor Header 的版本/选项。

    【讨论】:

    • @user2319247 已更新,我认为这应该为您指明正确的方向。
    • 谢谢@jbtule,我今天要试试这个,很快就会回来。
    【解决方案2】:

    Base64 编码需要输入大小为 3 的倍数(它将每 3 个字节转换为 4 个字符)。如果不是,则添加填充('=' 符号),不会在流中处理。

    【讨论】:

    • 对不起,我不明白你的意思。可能是我的问题不是很清楚。来自 Obj-C 代码的加密数据的 base64 字符串在 .NET 中被正确解密,但如果相同的数据位于文件 (NSOutPutStream) 中,并且我将该文件复制到我的 Windows 机器上并尝试解密该文件,它不会'不要解密。如果你想看,我可以添加 .NET 解密方法。
    • 如果我正确理解您的代码,问题出在 [encodedText appendString:[data base64EncodingWithLineLength:0]];如果数据块大小不是 3 的倍数,则输出流将包含错误的 base64 编码数据。
    猜你喜欢
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 2014-01-13
    • 1970-01-01
    • 2012-03-03
    • 2016-07-28
    • 1970-01-01
    相关资源
    最近更新 更多