0

I am implementing compatible binary file encryption/decryption between .NET and Objective-C apps. I am using RNCryptor package on Objective-C side. As far as I reached, I am able to encrypt/decrypt strings, but file encryption is troubling me. The problem is, when I read file and encrypt its data and write it to a file, it doesn't decrypt in .NET app. If I calculate Base64 string of encrpted data and decrypt that in .NET - creating byte array from Base64 string and decrypt with same login as of file, it decrypts. Is there any difference between writing encrypted data to file in Objective C and .NETCryptoStream?

Or am I missing something basic? Code for encrypting file in objective C is :-

  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);
}

Decrypting

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

always works but file doesn't decrypt.

user2319247
  • 88
  • 1
  • 9

2 Answers2

1

Update:

RNEncryptor actually is a high level encryption api for doing aes right, while it has an adhoc ciphertext format it is the typcial construction. To match your dotnet code with it's on adhoc format, you will have to use RNCryptor keyForPassword:salt:settings: with RNCryptorKeyDerivationSettings matching your Rfc2898DeriveBytes. Such as:

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

And use RNCryptorEngine for your aes encryption, and layout the ciphertext matching your adhoc .net format.

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

This is assuming the plaintext is already in the right format too

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

You may just want to use iOS's built-in CCCryptor directly at this point rather than RNCryptor if you need to make the plaintext format too (i'm guessing you do).

Advisory:

for the benefit of others who come across this question, there are security issues with the with the poster's .net ciphertext construction, don't use it.

Previous Answer:

RNCryptor does authenticated encryption.

It should actually be compatible with my code from: Modern Examples of Symmetric Authenticated Encryption of a string (C#)

Then to decrypt, what was produced with RNEncryptor, use:

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

The nonSecretPayloadLength is to 2, so that it will skip the RNEncryptor Header's version/option.

Community
  • 1
  • 1
jbtule
  • 31,383
  • 12
  • 95
  • 128
0

Base64 encoding needs input size to be multiple of 3 (it transforms each 3 bytes to 4 chars). If it is not, it adds padding ('=' symbols), which will not be processed in stream.

Nickolay Olshevsky
  • 13,706
  • 1
  • 34
  • 48
  • Sorry but I don't understand your point. May be my ques is not so clear. The base64 string of the encrypted data from Obj-C code is being decrypted correctly in .NET, but if the same data is inside a file (NSOutPutStream) and I copy that file on my windows machine and try to decrypt the file,it doesn't decrypt. I can add the .NET decrypt method if you want to see. – user2319247 Sep 03 '13 at 11:33
  • If I correctly understand your code, problem is in [encodedText appendString:[data base64EncodingWithLineLength:0]]; If data chunk sizes will not be multiple of 3, output stream will contain incorrectly base64-encoded data. – Nickolay Olshevsky Sep 03 '13 at 13:17