3

Converting a string to a byte array and then changing back will sometimes wont return the same string:

RandomNumberGenerator gen = new RNGCryptoServiceProvider();
byte[] randomBytes = new byte[32];
gen.GetBytes(randomBytes);

In some cases (or any kind of encoding other than unicode):

randomBytes != Encoding.Unicode.GetBytes(Encoding.Unicode.GetString(randomBytes));

I'd like to know how to do this method and get the same result for sure. Thanks in advance

1
  • 2
    Are you actually using != to compare byte arrays? Commented Jan 9, 2019 at 14:06

2 Answers 2

2

Probably, you are not looking for a text encoding but a serialization format. Text encodings are meant for text. The bytes you are processing are random bytes.

Does Base64 (Convert.ToBase64String) work for you?

You could also jam the bytes into chars (new string(myBytes.Select(b => (char)b).ToArray())). This will produce unreadable strings that are prone to being mangled by other systems. Likely not the right path.

Sign up to request clarification or add additional context in comments.

4 Comments

Convert.ToBase64String returns a string. I need to convert the string to byte[] and back. I'm using the NetworkStream class to transmit strings and it requires a byte[].
@idotalker why use strings at all? You have bytes, you want bytes. Directly send the bytes. If your protocol is text-based, then you probably need to use bas64 to go to a string, then use an encoding such as UTF8 to go to bytes. This will work with random data. Without base64 it will not.
I think I might've been a little unclear. The example in this post is not the code I'm working with, I wrote it to show that Encoding.Unicode.GetBytes(Encoding.Unicode.GetString(randomBytes)) will sometimes be different from randomBytes. I have no desire to work with random data. My input is a string that I need to send with NetworkStream. Goes something like this: input(string) => encryption => Send (NetworkStream) and then Recieve (NetworkStream) => decryption => put string to use. The byte[] is going through fine but since Encoding changes it the decryption doesn't work.
Why can't you operate with bytes entirely? No strings at all. Encryption does not operate on text anyway. It operates on bytes. @idotalker My points do not depend on the data being random. My point is, if you have arbitrary bytes you cannot make text from them using an encoding.
1

Arbitrary byte array does not necessary encodes a valid Unicode string (see https://en.wikipedia.org/wiki/UTF-16 for details), e.g.

  byte[] before = new byte[] { 0xA6, 0xDD };
  byte[] after = Encoding.Unicode.GetBytes(Encoding.Unicode.GetString(before));

  if (!before.SequenceEqual(after))
    Console.Write(string.Join(Environment.NewLine,
      $"before: {string.Join(" ", before.Select(b => b.ToString("x2")))}",
      $"after:  {string.Join(" ", after.Select(b => b.ToString("x2")))}"));

Outcome:

before: a6 dd
after:  fd ff

If you want to generate these strings you can modify your code into

while (true) {
  using (RandomNumberGenerator gen = new RNGCryptoServiceProvider()) {
    byte[] randomBytes = new byte[32];
    gen.GetBytes(randomBytes);

    byte[] after = Encoding.Unicode.GetBytes(Encoding.Unicode.GetString(randomBytes));

    if (!randomBytes.SequenceEqual(after)) {
      Console.Write(string.Join(" ", randomBytes) + 
                    Environment.NewLine + 
                    string.Join(" ", after));

      break;
    }
  }
}

Possible outcome:

166 8 99 175 188 233 240 219 64 143 26 87 157 209 205 219 27 169 239 67 99 170 172 226 254 56 168 168 64 222 178 15
166 8 99 175 188 233 253 255 64 143 26 87 157 209 253 255 27 169 239 67 99 170 172 226 254 56 168 168 253 255 178 15
                     ^
                     Difference

Please, note that we should compare arrays with SequenceEqual.

If you want to encode an array, you can do it with a help of string.Join:

byte[] array = ...

// Something like "166 8 99 175 188 233 240 219 ... 64 222 178 15"
string encoded = string.Join(" ", array);

byte[] back = encoded
  .Split(' ')
  .Select(item => byte.Parse(item))
  .ToArray();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.