Convert Int32 to char(s) representation - c#

I have some encrypting (and decrypting) functions that take any int value and return also any int value (it uses some xor operations with large prime numbers under the hood):
public interface IIntEncryption {
public int Encrypt(int value);
public int Decrypt(int encryptedValue);
}
Now I want to use it to encrypt string. My idea is to take each char from the string, convert it to int, encrypt with the function above and then convert back to char. The problem is that not every int value is valid character value afaik. So casting int to char won't work. So I am thinking that I will need to convert int to two valid characters somehow and then when decrypting convert each pair of two characters. So basically I am looking for following functions:
public interface IStringEncryption {
public string Encrypt(string str, IIntEncryption intEncryption);
public string Decrypt(string encryptedStr, IIntEncryption intEncryption);
}
I tried many ways but I can't figure out how to encrypt/decrypt array if integers into string representation. Finally I want it to be base64 encoded string.

I have some encrypting (and decrypting) functions that take any int value and return also any int value (it uses some xor operations with large prime numbers under the hood):
This is fine, assuming you are only doing this for fun/education. It is generally frowned upon creating your own encryption algorithms or implementations for anything where security is needed.
My idea is to take each char from the string, convert it to int, encrypt with the function above and then convert back to char
This would not be fine, or at least a very cumbersome way to do it. As you surmised you could fit two utf16 characters in a 32-bit int. But you will still have the same problem converting to a string again, since not all 16 bit values are valid utf16 characters.
A better solution would be to convert your string to a byte-array using some kind of encoding. You can then convert pairs of 4 bytes to int32s, encrypt, convert back to a byte array, and use something like base64 to convert the bytes back to a string.
This might sound a bit complicated, and it is. So most real implementations just work with byte-arrays directly, typically splitting them into some larger chunk-size internally.

Related

C# - Convert string of zeros and ones to a byte array or similar

I am getting a string of zeros and ones from a client API request. They are of a set length (28, in this case) and I want to convert them to a byte[] or something similar, with the goal of storing these in SQL via EF Core and later using bitwise operators to compare them.
I can't seem to wrap my head around this one. I'm seeing a lot of posts/questions about converting characters to byte arrays, or byte arrays to strings, neither of which is what I need.
I need a "00111000010101010" to become a literal binary 00111000010101010 I can use a ^ on.
Leading zeros would be fine if necessary, I think the length might be forced to be a multiple of 8?
You can binary string convert to an integer easily with this:
string source = "00111000010101010";
int number = Convert.ToInt32(source, 2); // The `2` is "base 2"
That gives: 28842.
Then you can go one step further an convert to a byte array, if needed.
byte[] bytes = BitConverter.GetBytes(number);

BigInteger.Parse() trouble reading in large numbers

Presently I am attempting to do this challenge (http://cryptopals.com/sets/1/challenges/1) and I am having some trouble completing the task in C#. I can not seem to parse the number into a big integer.
So code looks like below:
string output = "";
BigInteger hexValue = BigInteger.Parse("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6");
output = Convert.ToBase64String(hexValue.ToByteArray());
Console.WriteLine(hexValue);
Console.WriteLine(output);
Console.ReadKey();
return "";
And at present the problem I am getting is when I run the program it fails with the error
System.FormatException: 'The value could not be parsed.' and I am not entirely sure why.
So, what is the appropriate way to get a large integer from a string into a BigInt?
The initial problem
The BigInteger.Parse method expects the value to be decimal, not hex. You can "fix" that by passing in NumberStyles.HexNumber.
The bigger problem with using BigInteger for this
If you're just trying to convert a string of hex digits into bytes, I would avoid using BigInteger at all. For one thing, you could end up with problems if the original byte array started with zeroes, for example. The zeroes wouldn't be in the resulting byte array. (Sample input: "0001" - you want to get two bytes out, but you'll only get one, after persuading it to parse hex.)
Even if you don't lose any information, the byte[] you receive from BigInteger.ToByteArray() isn't what you were probably expecting. For example, consider this code, which just converts the data to byte[] and back to hex via BitConverter:
BigInteger bigInt = BigInteger.Parse("1234567890ABCDEF", NumberStyles.HexNumber);
byte[] bytes = bigInt.ToByteArray();
Console.WriteLine(BitConverter.ToString(bytes));
The output of that is "EF-CD-AB-90-78-56-34-12" - because BigInteger.ToByteArray returns the data in little-endian order:
The individual bytes in the array returned by this method appear in little-endian order. That is, the lower-order bytes of the value precede the higher-order bytes.
That's not what you want - because it means the last part of the original string is the first part of the byte array, etc.
Avoiding BigInteger altogether
Instead, parse the data directly to a byte array, as in this question, or this one, or various others. I won't reproduce the code here, but it's simple enough, with different options depending on whether you're trying to create simple source code or an efficient program.
General advice on conversions
In general it's a good idea to avoid intermediate representations of data unless you're absolutely convinced that you won't lose information in the process - as you would here. It's fine to convert the hex string to a byte array before converting the result to base64, because that's not a lossy transformation.
So your conversions are:
String (hex) to BigInteger: lossy (in the context of leading 0s being significant, as they are in this situation)
BigInteger to byte[]: not lossy
byte[] to String (base64): not lossy
I'm recommending:
String (hex) to byte[]: not lossy (assuming you have an even number of nybbles to convert, which is generally a reasonable assumption)
byte[] to String (base64): not lossy
Use NumberStyles.HexNumber:
BigInteger.Parse("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6",
NumberStyles.HexNumber,
CultureInfo.InvariantCulture);
If your number is supposed to be always positive, add a leading zero to your string.
The problem is that the input is not decimal but hexadecimal, therefore you need to pass an additional parameter for parsing:
BigInteger number = BigInteger.Parse(
hexString,
NumberStyles.AllowHexSpecifier);

Change string to Byte Array without conversion

I have a JSON formatted object, and the byte array is coming through as a string. I need to change that string to a byte array, but without converting the char's.
static byte[] GetBytes(string str)
{
return str.Select(Convert.ToByte).ToArray();
}
The above code half solves the issue, unfortunately it's still converting each char to it's respective byte.
For completness, here is my string
"PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMDEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQvc3RyaWN0LmR0ZCI+PGh0bWw+PGhlYWQ+PE1FVEEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTE2Ij48dGl0bGU+Q2l2aWwgUHJvY2VkdXJlIGluIE1hZ2lzdHJhdGVzJyBDb3VydHM8L3RpdGxlPjxsaW5rIHR5cGU9InRleHQvY3NzIiByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii4uL1N0eWxlcy9CV0NvbW1vbi5jc3MiPjxsaW5rIHR5cGU9InRleHQvY3NzIiByZWw9InN0eWxlc2hlZXQiIGhyZWY9Ii4uL1N0eWxlcy9TaXRlQ29tbW9uLmNzcyI+PHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0iLi4vc2NyaXB0cy9qcXVlcnktMS42LjIubWluLmpzIj48L3NjcmlwdD48c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSIuLi9zY3JpcHRzL3BvcHVwLmpzIj48L3NjcmlwdD48c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSIuLi9zY3JpcHRzL2hvdmVyYm94LmpzIj48L3NjcmlwdD48c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSIuLi9TY3JpcHRzL2pxdWVyeS5wcmludEVsZW1lbnQuanMiPjwvc2NyaXB0PjwvaGVhZD48Ym9keSBvbmxvYWQ9ImlmKHBhcmVudC5zZXRUb29scylwYXJlbnQuc2V0VG9vbHMoKSI+PGRpdiBpZD0iY29udGVudCI+PHAgY2xhc3M9IkdlbmVyYXRvci1IZWFkaW5nIj5Db250ZW50czwvcD48cCBjbGFzcz0iR2VuZXJhdG9yLUl0ZW0iIHN0eWxlPSJtYXJnaW4tbGVmdDoxNXB0Ij48YSBocmVmPSIjIiBvbmNsaWNrPSJsb2FkQ29udGVudCgnLi4vMWInLCBmYWxzZSk7Ij5DaXZpbCBQcm9jZWR1cmU8L2E+PC9wPjxwIGNsYXNzPSJHZW5lcmF0b3ItSXRlbSIgc3R5bGU9Im1hcmdpbi1sZWZ0OjE1cHQ7Y29sb3I6IzAwMjY3RjttYXJnaW4tdG9wOjEycHQiPjxiPsKgwqA8aW1nIHN0eWxlPSJib3JkZXI6MCIgd2lkdGg9IjgiIGhlaWdodD0iOSIgc3JjPSIuLi9SZXNvdXJjZXMvSW1hZ2VzL2Fycm93cy5naWYiIGFsdD0iIj7CoMKgQ2l2aWwgUHJvY2VkdXJlIGluIE1hZ2lzdHJhdGVzJyBDb3VydHM8L2I+PC9wPjxwIGNsYXNzPSJHZW5lcmF0b3ItSXRlbSIgc3R5bGU9Im1hcmdpbi1sZWZ0OjQ1cHQ7Y29sb3I6IzAwMjY3RjttYXJnaW4tYm90dG9tOjEycHQiPjxiPkF1dGhvcnFxcTogPC9iPkVkaXRvcnM6IERSIEhhcm1zLCBBZHZvY2F0ZSBvZiB0aGUgSGlnaCBDb3VydCwgTWVtYmVyIG9mIHRoZSBQcmV0b3JpYSBCYXI7IEYgU291dGh3b29kLiBGb3JtZXIgQ29udHJpYnV0b3JzOiBJIHZhbiBkZXIgV2FsdCwgQWR2b2NhdGUgb2YgdGhlIEhpZ2ggQ291cnQsIE1lbWJlciBvZiB0aGUgUHJldG9yaWEgQmFyOyBDIExvdXcsIEFkdm9jYXRlIG9mIHRoZSBIaWdoIENvdXJ0LCBNZW1iZXIgb2YgdGhlIFByZXRvcmlhIEJhcjsgQnJlbmRhIE5ldWtpcmNoZXIsIEFkdm9jYXRlIG9mIHRoZSBIaWdoIENvdXJ0LCBNZW1iZXIgb2YgdGhlIFByZXRvcmlhIEJhcjsgSkEgRmFyaXMsIFByb2Zlc3NvciBvZiBMYXcsIFVuaXZlcnNpdHkgb2YgU291dGggQWZyaWNhPGJyPjxiPkxhc3QgVXBkYXRlZDogPC9iPk9jdG9iZXIgMjAxMyAtIFNJIDMyLiBQcm9kdWN0IGRldmVsb3BlcjogQ3JhaWdlbiBTdXJhamxhbGw8L3A+PHA+PGJyPjxicj48L3A+PHA+PGJyPjxicj48L3A+PC9kaXY+PGRpdiBpZD0iY29udGV4dE1lbnUiPjwvZGl2PjwvYm9keT48c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+dHJ5e3dpbmRvdy5wYXJlbnQuc2V0RnJhbWVIZWlnaHQoIE1hdGgubWF4KE1hdGgubWF4KGRvY3VtZW50LmJvZHkuc2Nyb2xsSGVpZ2h0LCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsSGVpZ2h0KSwgTWF0aC5tYXgoZG9jdW1lbnQuYm9keS5vZmZzZXRIZWlnaHQsIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5vZmZzZXRIZWlnaHQpLCBNYXRoLm1heChkb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodCwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudEhlaWdodCkpKTt9Y2F0Y2goZSl7fTwvc2NyaXB0PjwvaHRtbD4="
I need to change that to a byte array, such as
['P','C','F'] etc, without converting each char to it's respective byte
This is not and edit of: How do I get a consistent byte representation of strings in C# without manually specifying an encoding?
In that question, the string is being converted. It's literally in the title that I do not want to convert
Assuming this is your actual problem description:
I have a base64-encoded string, that I wish to convert to a byte array where each single byte contains the ASCII code for one character from the base64 string.
Then you can very easily do that:
byte[] characterBytes = Encoding.ASCII.GetBytes(input);
Because the characters used in a base64 string are all below Unciode code point 127, they all can be represented in a single byte obtained through Encoding.ASCII.
In fact, if that is your actual problem description, that'd make this question a duplicate of C# Convert a string to ASCII bytes.

Convert Byte[64] array to minimum length string

I have try to generate unlock key like XXXX-XXXX-XXXX or simply small length string or Hexstring. I am using RSA algorithm to encrypt and decrypt the Key. I got some long string like
Q65g2+uiytyEUW5SFsiI/c5z9NSxyuU2CM1SEly6cAVv9PdTpH81XaWS8lITcaTZ4IjdmINwhHBosvt5kdg==
when I convert the byte array (array size is 64 byte) using the below convert method.
Convert.ToBase64String(bytes);
My requirement is to generate the minimal length Key. Is there any way to convert the Byte array (array size is 64 byte) to minimal length and I need that back to byte array or any other suggestions (to minimize the string length) would be helpful.
I have tried to convert the output string to Hex decimal, but the output is too long than the string.
You may want to take a look at What is the most efficient way to encode an arbitrary GUID into readable ASCII (33-127)? There the Base 85 encoding is discussed which is used to compress PDF files.
Though, the difference between Base64 and Base85 in your case is 8 characters.
You can safely remove trailing '==' in Base64 string because it is used for alignment and will always be there for 64-byte values (Of course you will have to add these characters back to decode the string).
Since you mention you want users to be able to type in the string,
there will be an inverse correlation between easy-of-use from point of view of users and the length of string.
Even typing a Base64 string is prone to lot of errors. Base32 strings are much easier to type, but correspondingly the length will increase.
If the users can Copy-Paste the key, then the above is moot and there should not be any valid reason why the length of the string should be as small as possible.
Obviously, you can only fit a certain amount of data into a fixed number of characters. You have pretty much maxed out the limit with base64 already which gives you 6 bits per byte.
Therefore you need to reduce the amount of data that needs to be stored. Can you reduce the key length? You could use a 96 bit key (by always leaving all other bytes zero). That would require 16 base64 characters which is much better.
It seems you don't need much security against brute forcing. So you can reduce the key size even further.

Using C#, what is the most efficient method of converting a string containing binary data to an array of bytes

While there are 100 ways to solve the conversion problem, I am focusing on performance.
Give that the string only contains binary data, what is the fastest method, in terms of performance, of converting that data to a byte[] (not char[]) under C#?
Clarification: This is not ASCII data, rather binary data that happens to be in a string.
UTF8Encoding.GetBytes
I'm not sure ASCIIEncoding.GetBytes is going to do it, because it only supports the range 0x0000 to 0x007F.
You tell the string contains only bytes. But a .NET string is an array of chars, and 1 char is 2 bytes (because a .NET stores strings as UTF16). So you can either have two situations for storing the bytes 0x42 and 0x98:
The string was an ANSI string and contained bytes and is converted to an unicode string, thus the bytes will be 0x00 0x42 0x00 0x98. (The string is stored as 0x0042 and 0x0098)
The string was just a byte array which you typecasted or just recieved to an string and thus became the following bytes 0x42 0x98. (The string is stored as 0x9842)
In the first situation on the result would be 0x42 and 0x3F (ascii for "B?"). The second situation would result in 0x3F (ascii for "?"). This is logical, because the chars are outside of the valid ascii range and the encoder does not know what to do with those values.
So i'm wondering why it's a string with bytes?
Maybe it contains a byte encoded as a string (for instance Base64)?
Maybe you should start with an char array or a byte array?
If you realy do have situation 2 and you want to get the bytes out of it you should use the UnicodeEncoding.GetBytes call. Because that will return 0x42 and 0x98.
If you'd like to go from a char array to byte array, the fastest way would be Marshaling.. But that's not really nice, and uses double memory.
public Byte[] ConvertToBytes(Char[] source)
{
Byte[] result = new Byte[source.Length * sizeof(Char)];
IntPtr tempBuffer = Marshal.AllocHGlobal(result.Length);
try
{
Marshal.Copy(source, 0, tempBuffer, source.Length);
Marshal.Copy(tempBuffer, result, 0, result.Length);
}
finally
{
Marshal.FreeHGlobal(tempBuffer);
}
return result;
}
There is no such thing as an ASCII string in C#! Strings always contain UTF-16. Not realizing this leads to a lot of problems. That said, the methods mentioned before work because they consider the string as UTF-16 encoded and transform the characters to ASCII symbols.
/EDIT in response to the clarification: how did the binary data get in the string? Strings aren't supposed to contain binary data (use byte[] for that).
If you want to go from a string to binary data, you must know what encoding was used to convert the binary data to a string in the first place. Otherwise, you might not end up with the correct binary data. So, the most efficient way is likely GetBytes() on an Encoding subclass (such as UTF8Encoding), but you must know for sure which encoding.
The comment by Kent Boogaart on the original question sums it up pretty well. ;]

Categories

Resources