public void EncryptFile()
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "JPEG Files (*.jpeg)|*.jpeg|PNG Files (*.png)|*.png|All files (*.*)|*.*";
dialog.InitialDirectory = #"C:\";
dialog.Title = "Please select an image file to encrypt.";
if (dialog.ShowDialog() == DialogResult.OK)
{
byte[] ImageBytes = File.ReadAllBytes(dialog.FileName);
foreach (byte X in ImageBytes)
{
//How can I take byte "X" and add a numerical value to it?
}
}
}
So, I'm trying to encrypt an image file by just converting it to byte[] array and then adding a numerical value to each byte.
How can I add a numerical value to a byte?
You just add it. The problem is that you can't modify the value in your foreach loop there. You actually want a for loop:
for(int k = 0; k < ImagesBytes.Length; k++){
ImageBytes[k] = (byte) (ImageBytes[k] + 5); // needs a cast
}
byte is a value type, which means it's always copied when it's returned. Consequently, you can only add a value to the local byte value inside your foreach, pretty much like changing the value of a byte argument inside a function won't change the value outside the function (unless, of course, you used the ref keyword).
You can't use a foreach for this task. Use a regular for loop:
for(int i = 0; i < ImageBytes.Length; i++)
ImageBytes[i] += MyNumericValue;
You need to use modulo (specifically modulo 256) addition, so that the operation is reversible. Alternatively you could use a bitwise operation, XOR is a common choice.
Modulo 256 operation is simple to implement for bytes, you just need to cast the result, as in:
ImageBytes[k] = (unsigned byte) ((unsigned byte) ImageBytes[k] + x)
Beware however that such "encryption" is rather weak. A way to improve the strength of such encryption is to add a distinct value for each byte, for example by taking the added value in a circular buffer (i.e. with a sequence which eventually repeats itself). A better way, still may use the values readily decoded as part of the operands.
Question: Why not just use one of the built in crypto streams in .NET?
If you don't want to do that, assuming that you are going to want to use the image in some way after you obscure the bits of it, I would look at doing a custom stream class and just modify the bytes are the come in.
There is a great end to end walk through here Custom Transform Streams (and the rotate stream would be a better faster way to solve your problem of obscuring the image file). This also gets rid of the overflow issues with adding to a byte.
Related
what I wanted to make is a if statement which checks if the variable which has a offset in it is equal to the base stream length and if it is, it will break.
here is what I have:
//open.FileName is Test.txt which doesn't have the number 123 (aka "7B")
user_input = "123";
BinaryReader br = new BinaryReader(File.OpenRead(open.FileName));
for (int i = 0; i <= br.BaseStream.Length; i++)
{
if (i == br.BaseStream.Length) //for some reason this doesn't work. why?
{
br.Close();
operation_Info.Text = operation_Fail;
break;
}
br.BaseStream.Position = i;
string Locate = br.ReadInt32().ToString();
if (Locate == user_input)
{
br.Close();
operation_Info.Text = operation_Success;
break;
}
}
For some reason it ignores the if and tries to check for 123 again but gives the error System.IO.EndOfStreamException: 'Unable to read beyond the end of the stream.' sins its already at the end of the file. why doesnt the if work?
Change your 'if' statement to:
if (i == br.BaseStream.Length - 3)
The reason it is failing is because you attempt to read 4 bytes with the ReadInt32() method when you are less than 4 bytes from the end of the stream.
Your if statement is unnecessary. You should just change your loop variable so that it only goes to br.BaseStream.Length - 3 instead.
Also, if your text file has the actual string "123" then using ReadInt32 will not work like you think it will. The string "123" is represented by the bytes 0x31 0x32 0x33. Depending on what character appears before it or after it will affect the value that ReadInt32 returns.
For example, if the string has a space before it, then the bytes will be 0x20313233 and the value returned by ReadInt32 will be 858927392 and if there is a space after the 123, the bytes will be 0x31323320 and the returned value will be 540226097.
If you're searching for the numeric value of 123, then the bytes will be 0x7B000000 in the file. The BinaryReader will read them using Big Endian order (assuming Windows).
You should research Big Endian, Little Endian, and how strings and numbers are represented in binary in a file.
I am trying to read a binary file (.bin) and convert the resources of the file into a matrix. The code I use to get the file is here.
using (BinaryReader Reader = new BinaryReader(File.Open(string.Format("{0}{1}.bin", DefaultFilePath, "MyBinaryFile"), FileMode.Open)))
{
//the code to convert binary to AxB matrix here.
byteArray = Reader.ReadBytes(100000);
float myFloat = System.BitConverter.ToSingle(byteArray, 0);
}
I need to write a piece of code which can convert the resources of a binary file into a AxB matrix. From the code above, you can see that I convert binary file into Byte[], then to float, but I am stuck in here.
In Matlab, you can read .bin file easily and get the AxB array such as in this link.
How can I proceed?
If the file is just a long list of 32-bit floats, you already got the first value converter correctly. Now you just need to do the rest by adding a loop and incrementing the second argument for ToSingle by 4 each time.
Or, since you're already using a BinaryReader you could just use its ReadSingle method in a loop. If you want a two-dimensional matrix, using a multidimensional array might be a good idea.
// In reality you might want to figure out the array size based on the file size
float[,] floatArray = new float[5000, 32];
using (BinaryReader reader = new BinaryReader(File.Open(string.Format("{0}{1}.bin", DefaultFilePath, "MyBinaryFile"), FileMode.Open)))
{
for (x = 0; x < floatArray.GetLength(0); x++)
{
for (y = 0; y < floatArray.GetLength(1); y++)
floatArray[x, y] = reader.ReadSingle();
}
}
Note: you might need to flip things around depending on whether your data file and desired memory representation is row-major or column-major.
Also remember that multidimensional arrays are contiguous in memory, so if your file is huge, you might run into problems processing it.
I am wrestling with a particular issue and like to ask for guidance on how I can achieve what I seek. Given the below function, a variable length string is used as input which produces a 4-byte Hex chunk equivalent. These 4-byte chunks are being written to an XML file for storage. And that XML file's schema cannot be altered. However, my issue is when the application which governs the XML file sorts the 4-byte chunks in the XML file. The result, is when I read that same XML file my string is destroyed. So, I'd like a way to "tag" each 4-byte chunk with some sort of identifier that I can in my decoder function inspite of the sorting that may have been done to it.
Encoding Function (Much of which was provided by (Antonín Lejsek)
private static string StringEncoder(string strInput)
{
try
{
// instantiate our StringBuilder object and set the capacity for our sb object to the length of our message.
StringBuilder sb = new StringBuilder(strInput.Length * 9 / 4 + 10);
int count = 0;
// iterate through each character in our message and format the sb object to follow Microsofts implementation of ECMA-376 for rsidR values of type ST_LongHexValue
foreach (char c in strInput)
{
// pad the first 4 byte chunk with 2 digit zeros.
if (count == 0)
{
sb.Append("00");
count = 0;
}
// every three bytes add a space and append 2 digit zeros.
if (count == 3)
{
sb.Append(" ");
sb.Append("00");
count = 0;
}
sb.Append(String.Format("{0:X2}", (int)c));
count++;
}
// handle encoded bytes which are greater than a 1 byte but smaller than 3 bytes so we know how many bytes to pad right with.
for (int i = 0; i < (3 - count) % 3; ++i)
{
sb.Append("00");
}
// DEBUG: echo results for testing.
//Console.WriteLine("");
//Console.WriteLine("String provided: {0}", strInput);
//Console.WriteLine("Hex in 8-digit chunks: {0}", sb.ToString());
//Console.WriteLine("======================================================");
return sb.ToString();
}
catch (NullReferenceException e)
{
Console.WriteLine("");
Console.WriteLine("ERROR : StringEncoder has received null input.");
Console.WriteLine("ERROR : Please ensure there is something to read in the output.txt file.");
Console.WriteLine("");
//Console.WriteLine(e.Message);
return null;
}
}
For Example : This function when provided with the following input "coolsss" would produce the following output : 0020636F 006F6C73 00737300
The above (3) 8 digit chunks would get written to the XML file starting with the first chunk and proceeding onto the last. Like so,
0020636F
006F6C73
00737300
Now, there are other 8-digit chunks in the XML file which were not created by the function above. This presents an issue as the Application can reorder these chunks among themselves and the others already present in the file like so,
00737300
00111111
006F6C73
00000000
0020636F
So, can you help me think of anyway to add a tag of some sort or use some C# Data Structure to be able to read each chunk and reconstruct my original string despite the the reordering?
I appreciate any guidance you can provide. Credit to Antonín Lejsek for his help with the function above.
Thank you,
Gabriel Alicea
Well, I am reluctant to suggest this as a proposed solution because it feels a bit too hackish for me.
Having said that; I suppose you could leverage the second byte as an ordinal so you can track the chunks and "re-assemble" the string later.
You could use the following scheme to track your chunks.
00XY0000
Where the second byte XY could be split up into two 4-bit parts representing an ordinal and a checksum.
X = Ordinal
Y = 16 % X
When reading the chunks you can split up the second byte into two words just like above and verify that the checksum aligns for the ordinal.
This solution does introduce a 16 character constraint on string length unless you eliminate the checksum and use the entire byte as an ordinal for which you can increase your string lengths to 256 characters.
I've been trying to get my program to replace unicode in a binary file.
The user would input what to find, and the program would find and replace it with a specific string if it can find it.
I've searched around, but there's nothing I can find to my specifics, what I would like would be something like:
string text = File.ReadAllText(path, Encoding.Unicode);
text = text.Replace(userInput, specificString);
File.WriteAllText(path, text);
but anything that works in a similar manner should suffice.
Using that results in a file that is larger and unusable, though.
I use:
int var = File.ReadAllText(path, Encoding.Unicode).Contains(userInput) ? 1 : 0;
if (var == 1)
{
//Missing Part
}
for checking if the file contains the user inputted string, if it matters.
This can work only in very limited situations. Unfortunately, you haven't offered enough details as to the nature of the binary file for anyone to know if this will work in your situation or not. There are a practically endless variety of binary file formats out there, at least some of which would be rendered invalid if you modify a single byte, many more of which could be rendered invalid if the file length changes (i.e. data after your insertion point is no longer where it is expected to be).
Of course, many binary files are also either encrypted, compressed, or both. In such cases, even if you do by some miracle find the text you're looking for, it probably doesn't actually represent that text, and modifying it will render the file unusable.
All that said, for the sake of argument let's assume your scenario doesn't have any of these problems and it's perfectly okay to just completely replace some text found in the middle of the file with some entirely different text.
Note that we also need to make an assumption about the text encoding. Text can be represented in a wide variety of ways, and you will need to use the correct encoding not just to find the text, but also to ensure the replacement text will be valid. For the sake of argument, let's say your text is encoded as UTF8.
Now we have everything we need:
void ReplaceTextInFile(string fileName, string oldText, string newText)
{
byte[] fileBytes = File.ReadAllBytes(fileName),
oldBytes = Encoding.UTF8.GetBytes(oldText),
newBytes = Encoding.UTF8.GetBytes(newText);
int index = IndexOfBytes(fileBytes, oldBytes);
if (index < 0)
{
// Text was not found
return;
}
byte[] newFileBytes =
new byte[fileBytes.Length + newBytes.Length - oldBytes.Length];
Buffer.BlockCopy(fileBytes, 0, newFileBytes, 0, index);
Buffer.BlockCopy(newBytes, 0, newFileBytes, index, newBytes.Length);
Buffer.BlockCopy(fileBytes, index + oldBytes.Length,
newFileBytes, index + newBytes.Length,
fileBytes.Length - index - oldBytes.Length);
File.WriteAllBytes(filename, newFileBytes);
}
int IndexOfBytes(byte[] searchBuffer, byte[] bytesToFind)
{
for (int i = 0; i < searchBuffer.Length - bytesToFind.Length; i++)
{
bool success = true;
for (int j = 0; j < bytesToFind.Length; j++)
{
if (searchBuffer[i + j] != bytesToFind[j])
{
success = false;
break;
}
}
if (success)
{
return i;
}
}
return -1;
}
Notes:
The above is destructive. You may want to run it only on a copy of the file, or prefer to modify the code so that it takes an addition parameter specifying the new file to which the modification should be written.
This implementation does everything in-memory. This is much more convenient, but if you are dealing with large files, and especially if you are on a 32-bit platform, you may find you need to process the file in smaller chunks.
I have here a code where i set up a byte[1] to fill with a random byte which i then need to have this random generated byte from array [0] into a single byte to be able to compare it. (x is either 16 or 32, z is always staring with 0)
byte compareByte = 0x00;
byte[] rndByte = new byte[1];
byte[] buffer = new byte[x];
Random rnd = new Random();
for (int i = 0; i < dalmatinerRound.Length; i++)
{
while (z != x)
{
Application.DoEvents();
rnd.NextBytes(rndByte);
compareByte = (byte) rndByte[0];
if (compareByte == dalmatinerRound[i])
{
buffer[z] = compareByte;
z++;
if (z == x)
{
string str = Encoding.ASCII.GetString(buffer);
textPass.Text = str;
}
}
}
}
The problem is that compareByte is everytime "A". Regardless of how often i trie. Or even if i use the random byte to compare like:
if (rndByte[0] == dalmatinerRound[i])
it also returns "A". I can't get the byte from offset 0x00 of the array into a single byte.
But when i do some test and use:
string str = Encoding.ASCII.GetString(rndByte);
textPass.Text = str;
then it works and i get everytime a other letter.
To be more clear. This code will generate a Random passwort in length of 16 or 32 diggis. The dalmatinerRound is a Array of bytes in length of 101 contaning Alphabetical letters, lower and upper case, 0-9 and also !"§$%&/()=?*+}][{
thanks
Why not just use (byte)rnd.Next(0, 256)? In any case, rnd.NextBytes works just fine, and you get the first byte by using rndByte[0] just the way you did. In other words, the error must be somewhere else, not in the random generator or reading the byte value. Is this really the code, or have you made some changes? In any case, your code seems incredibly complicated and wasteful. You should probably just use your array of allowable values (no need to have it a byte array, chars are more useful) and use rnd.Next(0, dalmatinerRound.Length); to get a random allowed character.
What your code actually does is that it loops until you get a "random" byte... which is equal to (byte)'A'. Your loops are all wrong. Instead, you can use this:
StringBuilder pwd = new StringBuilder(wantedLength);
for (var i = 0; i < wantedLength; i++)
pwd.Append(dalmatinerRound[rnd.Next(0, dalmatinerRound.Length)]);
And there you have your random password :)
This expects that dalmatinerRound is an array of strings, which is quite useful anyway, so you should do that.
You're looping over the array of eligible characters, I assume starting "ABC...", and for each of those doing something. With your while loop you're trying to generate a count of x bytes in your buffer, but you don't stop until this is done - you never get a chance to increment i until you finish filling up the buffer.
You're also generating a random byte and only adding it to your buffer if it happens to be the current "candidate" character in dalmatinerRound. So the buffer sloooowly fills up with "A" characters. Then once this is full, the next time i is incremented, the while loop immediately exits, so no other characters are tried.
You should instead loop over the character index i in the target buffer, generating one random character in each iteration - just think how you would go about this process by hand.
It looks like your for loop is in the wrong place. Currently, the whole password is generated on the first (and presumably the only) iteration of the for loop. That means your comparison only ever compares the random byte to the first entry in dalmatinerRound, which is presumably the letter A.
You need to put the for loop inside the while loop, so that each random byte gets compared to every element of dalmatinerRound. (Make sure you put the loop after you generate the random byte!)
As a side note, there are much better ways of generating what you need. Since you have an array of all valid characters, you could just pick a random element from that to get a password digit (i.e. generate a random number between 0 and the length of the array).