You do realize that strings in the C#/.Net/CLR world are UTF-16 encoded Unicode, right?
http://en.wikipedia.org/wiki/UTF-16
Only those characters at code points in the Basic Multilingual Plance (ranges U+0000– U+D7FF and U+E000–U+FFFF) are represented as a single 16-bit character.
Your random XORing of characters results in random stuff that won't round trip: it will either be invalid UTF-16 or a surrogate pair.
That's your problem.
If you want to encode things like this, try this:
- Use the encoding of choice to create a
byte[]
from your string to be encoded. - XOR that.
- Convert the resulting
byte[]
ciphertext into a Base64-encoded string usingConvert.ToBase64String()
.
To decode it, reverse the process:
- Convert the Base64-encoded string into a
byte[]
usingConvert.FromBase64String()
. - XOR that
- Convert the resulting plaintext
byte[]
back into a C#/.Net string using the same encoding you used in the first place.
Edited To Note:
Just for fun...
A test case:
MyNotVerySecureCrypto crypto = new MyNotVerySecureCrypto("cat" ) ; string plainText = "The quick brown fox jumped over the lazy dog." ; string cipherText = crypto.Encrypt(plainText) ; string plainText1 = crypto.Decrypt(cipherText) ; Debug.Assert(plainText.Equals(plainText1,StringComparison.Ordinal));
To test this code:
public class MyNotVerySecureCrypto { private byte[] Key { get ; set ; } private Encoding Encoding { get ; set ; } public MyNotVerySecureCrypto( string key , Encoding encoding ) { this.Encoding = encoding ; this.Key = Encoding.GetBytes(key).Where( b => b != 0 ).ToArray() ; return ; } public MyNotVerySecureCrypto( string key ) : this ( key , Encoding.UTF8 ) { return ; } public string Encrypt( string plainText ) { int i = 0 ; byte[] octets = Encoding .GetBytes(plainText) .Select( b => (byte) (b^Key[(++i)%Key.Length]) ) .ToArray() ; string cipherText = Convert.ToBase64String(octets) ; return cipherText ; } public string Decrypt( string cipherText ) { int i = 0 ; byte[] octets = Convert .FromBase64String(cipherText) .Select( b => (byte) (b^Key[(++i)%Key.Length]) ) .ToArray() ; string plainText = Encoding.GetString( octets ) ; return plainText ; } }