views:

1870

answers:

5

I am doing RSA encryption and I have to split my long string into small byte[] and encrypt them. I then combine the arrays and convert to string and write to a secure file.

Then encryption creates byte[128]

I use this the following to combine:

public static byte[] Combine(params byte[][] arrays)
{
    byte[] ret = new byte[arrays.Sum(x => x.Length)];
    int offset = 0;
    foreach (byte[] data in arrays)
    {
        Buffer.BlockCopy(data, 0, ret, offset, data.Length);
        offset += data.Length;
    }
    return ret;
}

When I decrypt I take the string, convert it to a byte[] array and now need to split it to decode the chunks and then convert to string.

Any ideas?

Thanks

EDIT:

I think I have the split working now however the decryption fails. Is this because of RSA keys etc? At TimePointA it encrypts it, then at TimePointB it tries to decrypt and it fails. The public keys are different so not sure if that is the issue.

A: 

Why do you need to break the string into variable length chunks? Fixed-length chunks, or no chunks at all, would simplify this a lot.

Matt Howells
RSA will not encrypt a byte[1024]
Jon
+2  A: 

When you decrypt, you can create one array for your decrypt buffer and reuse it:

Also, normally RSA gets used to encrypt a symmetric key for something like AES, and the symmetric algorithm is used to encrypt the actual data. This is enormously faster for anything longer than 1 cipher block. To decrypt the data, you decrypt the symmetric key with RSA, followed by decrypting the data with that key.

byte[] buffer = new byte[BlockLength];
// ASSUMES SOURCE IS padded to BlockLength
for (int i = 0; i < source.Length; i += BlockLength)
{
    Buffer.BlockCopy(source, i, buffer, 0, BlockLength);
    // ... decode buffer and copy the result somewhere else
}

Edit 2: If you are storing the data as strings and not as raw bytes, use Convert.ToBase64String() and Convert.FromBase64String() as the safest conversion solution.

Edit 3: From his edit:

private static List<byte[]> splitByteArray(string longString)
{
    byte[] source = Convert.FromBase64String(longString);
    List<byte[]> result = new List<byte[]>();

    for (int i = 0; i < source.Length; i += 128)
    {
        byte[] buffer = new byte[128];
        Buffer.BlockCopy(source, i, buffer, 0, 128);
        result.Add(buffer);
    }
    return result;
}
280Z28
Not sure what BlockLength is
Jon
It's whatever size you need to split the array into. :) Also check the added 2nd paragraph.
280Z28
I'm using System.Text.Encoding.Unicode
Jon
If your data includes particular byte sequences, it will interfere with the UTF-16 conversions. Use the base-64 conversions or directly serialize the byte arrays if you want to make sure they work properly.
280Z28
Thanks for the tip. Will use base 64. I have posted my code. It successfully splits the byte[] but comes up with a bad data exception when decrypting
Jon
Your code is note returning the byte[128] as it was after encoding for example my first byte[] after encoding was 47,89,142. Afther converting from base 64 then splitting the arryays into 128 the first byte[] is 95,219,47
Jon
@Jon, you were using it in a way I wasn't expecting. See my update.
280Z28
Yup I just spotted that before I came back here! Thanks. That does seem to put it back in the state it was after the encoding however I am still getting BadData exception when decrypting which is weird
Jon
+1  A: 

I'd say something like this would do it:

        byte[] text = Encoding.UTF8.GetBytes(longString);
        int len = 128;

        for (int i = 0; i < text.Length; )
        {
            int j = 0;
            byte[] chunk = new byte[len];
            while (++j < chunk.Length && i < text.Length)
            {
                chunk[j] = text[i++];
            }
            Convert(chunk); //do something with the chunk
        }
Matt Jacobsen
The Buffer.* API calls as given in the accepted answer are better.
Matt Jacobsen
A: 

"the public keys are different"?

You encrypt with a private key, and decrypt with the public key that corresponds to the private key.

Anything else will give you gibberish.

Will
I have it working by setting RSA.FromXmlString(key) when encoding and then decoding I do the same. This seems to work however that key is in my code which can't be secure?
Jon
Right, its not secure.To be secure, you have to understand security. Asking on Stackoverflow is not where you're going to get to grasp even the basics. Go by "The Code Book" by Simon Singh. Its very approachable and fun read, and after you've got through it you'll start to understand the fundementals.
Will
Oh, and you don't use the same key for encrypting and decrypting. You encrypt with a "public" key, and decrypt with the matching "private" key.
Will
Thanks will take a look. Although time is precious and at the moment that works albeit explicitly keeping the encode/decode key in code. Where else do you keep it and then do you encrypt that? Vicious circle.
Jon
"Oh, and you don't use the same key for encrypting and decrypting." - Do you have a C# RSA example?
Jon
Buy or borrow a proper book written by professionals. Then apply the knowledge and understanding you gain to writing programs.There is no copy-n-paste shortcut that will serve you kindly.
Will
A: 

why not use a framework instead of doing the byte-stuff yourself?

http://www.codinghorror.com/blog/archives/001275.html

Sander