Simple Byte Encryption Not Working - c#

When the message is decrypted, the characters are one less than the original. Example: H Will be G
I have tried to debug the code by printing out values and all goes well until trying to divide by 100000 and multiplying by the date
Here is the code I used:
I didn't include the Main Method Here
public static string encrypt(string input)
{
string final;
string date = DateTime.Now.Date.ToShortDateString().ToString();
var datetime = int.Parse(date.Replace("/", ""));
List<int> semi = new List<int>();
var bytes = Encoding.UTF8.GetBytes(input.ToCharArray());
for (int i = 0; i < bytes.Length; i++)
{
int y = bytes[i] * datetime / 100000;
semi.Add(y);
Console.WriteLine(y);
}
Console.WriteLine(string.Join("", bytes));
final = string.Join(":", semi.ToArray()) + ":" + date;
return final;
}
public static string decrypt(string input)
{
string final;
string[] raw = input.Split(':');
int date = int.Parse(raw[raw.Length - 1].Replace("/",""));
var dump = new List<string>(raw);
dump.RemoveAt(raw.Length - 1);
string[] stringbytes = dump.ToArray();
List<byte> bytes = new List<byte>();
for (int i = 0; i < stringbytes.Length; i++)
{
int x = int.Parse(stringbytes[i]);
Console.WriteLine(x);
x = x * 100000 / date;
byte finalbytes = Convert.ToByte(x);
bytes.Add(finalbytes);
}
Console.WriteLine(string.Join("", bytes.ToArray()));
Console.WriteLine(date);
var bytearray = bytes.ToArray();
final = Encoding.UTF8.GetString(bytearray);
return final;
}

It's likely a rounding error from integer division. when doing integer math it is very possible that ((x * date / 100000) * 100000 / date) != x, in fact the only time it will be == x is when date % 100000 == 0.
Fix the rounding errors introduced by your int division and it should fix your problem.
P.S. I would also be very hesitant to call this "encryption", there is no secret key, all the information required to decrpt the message is in the message itself. You are only relying on the fact that the algorithm is secret which is practically impossible to do with C#. I would rather call what you are doing "Encoding", because to decode something that is encoding all you need to know is the algorithm.

You are using the low precision datatype int to store the result of the division. I have changed the type to double and it works
public static string encrypt(string input)
{
string final;
string date = DateTime.Now.Date.ToString("MMddyyyy");
var datetime = int.Parse(date);
List<double> semi = new List<double>();
var bytes = Encoding.UTF8.GetBytes(input);
for (int i = 0; i < bytes.Length; i++)
{
double y = bytes[i] * datetime / 100000;
semi.Add(y);
Console.WriteLine(y);
}
Console.WriteLine(string.Join("", bytes));
final = string.Join(":", semi.ToArray()) + ":" + date;
return final;
}
public static string decrypt(string input)
{
string final;
string[] raw = input.Split(':');
int date = int.Parse(raw[raw.Length - 1].Replace("/", ""));
var dump = new List<string>(raw);
dump.RemoveAt(raw.Length - 1);
string[] stringbytes = dump.ToArray();
List<byte> bytes = new List<byte>();
for (int i = 0; i < stringbytes.Length; i++)
{
var x = double.Parse(stringbytes[i]);
Console.WriteLine(x);
x = x * 100000 / date;
byte finalbytes = Convert.ToByte(x);
bytes.Add(finalbytes);
}
Console.WriteLine(string.Join("", bytes.ToArray()));
Console.WriteLine(date);
var bytearray = bytes.ToArray();
final = Encoding.UTF8.GetString(bytearray);
return final;
}
Here is a fully working console app http://ideone.com/Rjc13A

I believe this is a number truncation issue. In your decrypt method, the division will actually create a double instead of an int - If you do the math it turns out to have decimal places. Since x is an integer it will be cutt-off.
The following should work:
for (int i = 0; i < stringbytes.Length; i++)
{
var x = double.Parse(stringbytes[i]);
Console.WriteLine(x);
x = Math.Round((x * 100000) / date,0);
byte finalbytes = Convert.ToByte(x);
bytes.Add(finalbytes);
}
Also, as a side note why are you creating your own encryption algorithm? Could you not use one that already exists?

Related

C# i use Modbus/TCP to get Data, Data type is 「LReal」. i want turn to double

i use Modbus/TCP to get data, data type is LReal.
but i want LReal to int.
this is my data.
staic_13 data is 「4.232」
but i get [80] 16400 [81]-2098 [82] -9962 [83] -30933.
i don't know how turn to double
Based on this experimental Python code,
>>> x = [16400, -2098, -9962, -30933]
>>> struct.unpack(">d", struct.pack(">4h", *x))
(4.242,)
it looks like you'd need to concatenate those 4 16-byte integers in big-endian format, then interpret those 8 bytes as a single big-endian double.
In .NET 6 (see this fiddle):
using System.Buffers.Binary;
using System;
short[] values = {16400, -2098, -9962, -30933};
byte[] buf = new byte[values.Length * sizeof(short)];
for (int i = 0; i < values.Length; i++)
{
BinaryPrimitives.WriteInt16BigEndian(buf.AsSpan(i * sizeof(short)), values[i]);
}
double result = BinaryPrimitives.ReadDoubleBigEndian(buf);
Console.WriteLine(result);
In .NET 4 (see this fiddle):
using System;
public class Program
{
public static void Main()
{
short[] values = {16400, -2098, -9962, -30933};
byte[] buf = new byte[8];
for (int i = 0; i < 4; i++)
{
byte[] sh_buf = BitConverter.GetBytes(values[i]);
if(BitConverter.IsLittleEndian) {
// Flip the bytes around if we're little-endian
buf[(3 - i) * 2] = sh_buf[0];
buf[(3 - i) * 2 + 1] = sh_buf[1];
} else {
buf[i * 2] = sh_buf[0];
buf[i * 2 + 1] = sh_buf[1];
}
}
double result = BitConverter.ToDouble(buf, 0);
Console.WriteLine(result);
}
}

Reverse binary representation of int (only significant bits)

I'm trying to write a program for reversing numbers in binary. For instance, the binary representation of 13 is 1101, and reversing it gives 1011, which corresponds to number 11 right?
Here's my code:
static void Main(string[] args)
{
Console.WriteLine("Enter a Number");
int numb = int.Parse(Console.ReadLine());
int reverse = 0;
while (numb > 0)
{
int rem = numb % 10;
reverse = (reverse * 10) + rem;
numb = numb / 10;
}
Console.WriteLine("Reverse number={0}", reverse);
Console.ReadLine();
}
By this code I only get the numbers to reverse (13 -> 31)...
The input should contain a single line with an integer N, 1≤N≤1000000000 and I want my output in one line with one integer, the number I want to get by reversing the binary representation of N.
Something like that
// 13 = 1101b
int value = 13;
// 11 = 1011b
int result = Convert.ToInt32(new String(
Convert.ToString(value, 2)
.Reverse()
.ToArray()), 2);
Explanation:
Convert.ToString(value, 2) returns value in binary representation ("1101")
Reverse().ToArray() - reverse the string ('1','0','1','1') as sequence of characters and converts to array char[].
new String(...) constructs string "1011" from array of char
finally, Convert.ToInt32(..., 2) convert binary representation back to int
You can use Convert.ToString and Convert.ToInt32 methods, where 2 means binary:
int numb = int.Parse(Console.ReadLine());
var reversedString = Convert.ToString(numb, 2).ReverseString();
var result = Convert.ToInt32(reversedString, 2);
...
public static string ReverseString(this string s)
{
char[] arr = s.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}
A fun excercise would be doing this without using the string conversion.
I have very little experience with bit twiddling so there is probably a faster and better way of doing this, but this seems to work:
public static IEnumerable<bool> ToBinary(this int n)
{
for (int i = 0; i < 32; i++)
{
yield return (n & (1 << i)) != 0;
}
}
public static int ToInt(this IEnumerable<bool> b)
{
var n = 0;
var counter = 0;
foreach (var i in b.Trim().Take(32))
{
n = n | (i ? 1 : 0) << counter;
counter++
}
return n;
}
private static IEnumerable<bool> Trim(this IEnumerable<bool> list)
{
bool trim = true;
foreach (var i in list)
{
if (i)
{
trim = false;
}
if (!trim)
{
yield return i;
}
}
}
And now you'd call it like this:
var reversed = n.ToBinary().Reverse().ToInt();

ElGamal C# implementation

I want to implement ElGamal encryption. I need this for my school work but when I want do decryption the last step is always 0 cause of (b/Math.Pow(a,x))%primenumber is always less then 1.
Here is the keys generation:
public void GenerateKey() {
this.x = 3;
this.prvocislo = PrimeGen.findPrimes(29).Max(); //prime number
this.g = this.prvocislo % 12;
this.y = Convert.ToInt32(Math.Pow(this.g, this.x) % this.prvocislo);
this.k = 23;//601}
Here is encrypt function:
public string Encrypt(string word) {
List<string> words = new List<string>();
words = PrimeGen.SplitToArray(word, 2);
string encrypted="";
string sss = PrimeGen.GetStringFromBytes(PrimeGen.GetBytesFromInt(PrimeGen.GetIntFromBytes(PrimeGen.GetBytesFromString("ah")))); //returns ah so conversion works
foreach (string s in words)
{
int a = Convert.ToInt32(Math.Pow(g,k) % prvocislo);
int b = Convert.ToInt32((Math.Pow(y, k) * PrimeGen.GetIntFromBytes(PrimeGen.GetBytesFromString(s))) % prvocislo);
string aS = PrimeGen.GetStringFromBytes(PrimeGen.INT2LE(a + posun));
string bS = PrimeGen.GetStringFromBytes(PrimeGen.INT2LE(b + posun));
encrypted = encrypted + aS + bS;
}
return encrypted;
}
Here is my decrypt function:
public string Decrypt(string ElgamalEncrypted) {
string decrypted = "";
for (int i = 0; i < ElgamalEncrypted.Length; i = i + 2) {
string aS = ElgamalEncrypted.Substring(i, 2);
string bS = ElgamalEncrypted.Substring(i + 2, 2);
int a = PrimeGen.GetIntFromBytes(PrimeGen.GetBytesFromString(aS)) - posun;
int b = PrimeGen.GetIntFromBytes(PrimeGen.GetBytesFromString(bS)) - posun;
if(b==0) b=1;
if (a == 0) a = 1;
decrypted=decrypted+PrimeGen.GetStringFromBytes(PrimeGen.GetBytesFromInt(Convert.ToInt32(((b/Math.Pow(a,x))%prvocislo))));
}
return decrypted;
}
You're using Math.Pow(base, exponent) % modulus for modular exponentiation. That doesn't work because floating points can't represent the large integers crypto needs. Use System.Numerics.BigInteger.ModPow(base, exponent, modulus) instead.
The division probably doesn't work because you use integer division, instead of multiplying with the modular multiplicative inverse of the right side.

String to byte array

I have to convert a string to byte (16 bit) in JavaScript. I can do this in .net in following code but I have to change this for old classic asp App which uses JavaScript.
string strShared_Key = "6fc2e550abc4ea333395346123456789";
int nLength = strShared_Key.Length;
byte[] keyMAC = new byte[nLength / 2];
for (int i = 0; i < nLength; i += 2)
keyMAC[i / 2] = Convert.ToByte(strShared_Key.Substring(i, 2), 16);
This is the JavaScript function but doesn't return same out put as above .net code.
function String2Bin16bit(inputString) {
var str = ""; // string
var arr = []; // byte array
for (var i = 0; i < inputString.length; i += 2) {
// get chunk of two characters and parse to number
arr.push(parseInt(inputString.substr(i, 2), 16));
}
return arr;
}
You want parseInt(x, 16) which will read x as a number and parse it as such bearing in mind that it's in base 16.
var str = "aabbcc"; // string
var arr = []; // byte array
for(var i = 0; i < str.length; i += 2) {
arr.push(parseInt(str.substr(i, 2), 16)); // get chunk of two characters and parse to number
}

Quickest Method to Reverse in String in C#.net

I'm currently writing a quick solution for Euler Problem #4 where one must find the largest palindromic number from the product of two 3-digit numbers.
To identify if a number is palindromic, you would obviously compare a reverse of the number with the original.
Since C# doesn't have a built in String.Reverse() method, what is the quickest way to reverse a string?
I will be testing all the suggested solution in a loop with 100,000,000 iterations. The correct answer will be given to the person who submitted the fastest solution.
I will be testing the solution in a C#.Net 3.5 console application
Wouldn't reversing the number be faster?
// unchecked code, don't kill me if it doesn't even compile.
ulong Reverse(ulong number) {
ulong result = 0;
while (number > 0) {
ulong digit = number % 10;
result = result * 10 + digit;
number /= 10;
}
return result;
}
A you want to compare a number with its reverse it may be faster to reverse the number using division rather than converting it to a string. I still need to test the speed of it.
private static int Reverse(int num) {
int res = 0;
while (num > 0) {
int rm ;
num = Math.DivRem(num, 10, out rm);
res = res * 10 + rm;
}
return res;
}
EDIT:
DivRem was about 1% faster than division and module in my computer.
A speed optimization is exit if the last digit is 0:
private static int Reverse(int num) {
int res = 0;
int rm;
num = Math.DivRem(num, 10, out rm);
//Some magic value or return false, see below.
if (rm == 0) return -1 ;
res = res * 10 + rm;
while (num > 0) {
num = Math.DivRem(num, 10, out rm);
res = res * 10 + rm;
}
return res ;
}
Making the method return a bool was slightly slower than comparing to a bool in a loop in my computer, but I don't understand why. Please test in your computer.
Multiplication and bit-shifing should be faster than division but probably are not precise enough. EDIT: using long seems be precise enough.
private static int FastReverse(int num) {
int res = 0;
int q = (int)((214748365L * num) >> 31);
int rm = num - 10 * q;
num = q;
if (rm == 0) return -1;
res = res * 10 + rm;
while (num > 0) {
q = (int)((214748365L * num) >> 31);
rm = num - 10 * q;
num = q;
res = res * 10 + rm;
}
return res;
}
(214748365L * num) >> 31 is equal to i / 10 until 1,073,741,829 where 1 / 10 gives 107374182 and the multiplication + binary shifting gives 107374183.
I think it might be faster to do the comparison in-place. If you reverse the string, you've got to:
Instantiate a new string object (or StringBuffer object)
Copy the data (in reverse) from the first string to the new string
Do your comparison.
If you perform the comparison in place, you do only the last step. An even then, your comparison is only half the string (or half - 0.5, in the event of an odd number of characters). Something like the following should work:
static bool IsPalindromic(string s){
int len = s.Length;
int half = len-- >> 1;
for(int i = 0; i < half; i++)
if(s[i] != s[len - i])
return false;
return true;
}
EDIT:
Although this answers the OP's question, the solutions offered by ggf31416 and configurator solve the OP's real need about 30% faster, by my tests. configurator's solution is a tiny bit faster than ggf31416's, if you convert it to a static method and use ints instead of ulongs (but much slower, otherwise).
Incidentally, running through these examples to solve the problem the OP mentions (finding the largest palindromic product of any two three-digit numbers) with the simple (perhaps naïve) loop below:
for(int i = 100; i < 1000; i++)
for(int j = i; j < 1000; j++) // calculations where j < i would be redundant
...
yields the following results on my machine:
IsPalindromic(product.ToString()) took 0.3064174 seconds.
ggf31416Reverse(product) == product took 0.1933994 seconds.
configuratorReverse(product) == product took 0.1872061 seconds.
Each produces the correct result of 913 * 993 = 906609.
Performance: Fastest string reversing algorithms... (final results)
string test = "ABC";
string reversed = new String(test.ToCharArray().Reverse().ToArray());
public static String Reverse(string input) {
var length = input.Length;
var buffer = new char[length];
for ( var i= 0; i < input.Length; i++ ) {
buffer[i] = input[(length-i)-1];
}
return new String(buffer);
}
EDIT: Doh! Forgot to halve the length for perf :)
The fastest way I have found to reverse a string in C# is with the following code. It's faster reading in 32bits at a time instead of a char's length of 16bits.
In debug mode, it is faster until you get to about 93 characters. Anything longer than that Array.Reverse() is faster. Using a release build and running outside of the IDE, this method will blow Array.Reverse() out of the water at any string length.
char[] MyCharArray = MyString.ToCharArray();
UIntStringReverse(ref MyCharArray); //Code to reverse is below.
string ReversedString = new string(MyCharArray);
private static unsafe void UIntStringReverse(ref char[] arr)
{
uint Temp;
uint Temp2;
fixed (char* arrPtr = &arr[0])
{
uint* p, q;
p = (uint*)(arrPtr);
q = (uint*)(arrPtr + arr.LongLength - 2);
if (arr.LongLength == 2)
{
Temp = *p;
*p = ((Temp & 0xFFFF0000) >> 16) | ((Temp & 0x0000FFFF) << 16);
return;
}
while (p < q)
{
Temp = *p;
Temp2 = *q;
*p = ((Temp2 & 0xFFFF0000) >> 16) | ((Temp2 & 0x0000FFFF) << 16);
*q = ((Temp & 0xFFFF0000) >> 16) | ((Temp & 0x0000FFFF) << 16);
p++;
q--;
}
}
}
try this too:
http://weblogs.sqlteam.com/mladenp/archive/2006/03/19/9350.aspx
string Reverse(string s)
{
return new string(s.ToCharArray().Reverse().ToArray());
}
Using ggf31416's FastReverse function, here is the solution to Project Euler's Problem #4 which completes on my computer in 47ms.
using System;
using System.Diagnostics;
namespace Euler_Problem_4
{
class Program
{
static void Main(string[] args)
{
Stopwatch s = new Stopwatch();
s.Start();
int t = 0;
for (int i = 999; i > 99; i--)
{
for (int j = i; j > 99; j--)
{
if (i*j == FastReverse(i*j))
{
if (i * j > t)
{
t = i * j;
}
}
}
}
Console.WriteLine(t);
s.Stop();
Console.WriteLine("{0}mins {1}secs {2}ms", s.Elapsed.Minutes, s.Elapsed.Seconds, s.Elapsed.Milliseconds);
Console.ReadKey(true);
}
private static int FastReverse(int num)
{
int res = 0;
int q = (int)((214748365L * num) >> 31);
int rm = num - 10 * q;
num = q;
if (rm == 0) return -1;
res = res * 10 + rm;
while (num > 0)
{
q = (int)((214748365L * num) >> 31);
rm = num - 10 * q;
num = q;
res = res * 10 + rm;
}
return res;
}
}
}
The Stopwatch class needs reset after each run. the code below has been corrected
var d = s.ToCharArray();
Array.Reverse(d);
return s == new string(d);
using System;
using System.Diagnostics;
namespace longeststring_codegolf
{
class Program
{
static void Main(string[] args)
{
int t = 0, v = 0;
var sw = new Stopwatch();
sw.Start();
for (int i = 999; i > 99; i--)
for (int j = 999; j > 99; j--)
if ((v = i * j) > t && IsPalindromicMine(v.ToString()))
t = v;
sw.Stop();
var elapsed = sw.Elapsed;
var elapsedMilliseconds = sw.ElapsedMilliseconds;
var elapsedTicks = sw.ElapsedTicks;
Console.WriteLine("Ticks: " + elapsedTicks.ToString());//~189000
Console.WriteLine("Milliseconds: " + elapsedMilliseconds.ToString()); //~9
sw = Stopwatch.StartNew();
for (int i = 999; i > 99; i--)
for (int j = 999; j > 99; j--)
if ((v = i * j) > t && IsPalindromic(v.ToString()))
t = v;
sw.Stop();
var elapsed2 = sw.Elapsed;
var elapsedMilliseconds2 = sw.ElapsedMilliseconds;
var elapsedTicks2 = sw.ElapsedTicks;
Console.WriteLine("Ticks: " + elapsedTicks2.ToString());//~388000
Console.WriteLine("Milliseconds: " + elapsedMilliseconds2.ToString());//~20
}
static bool IsPalindromicMine(string s)
{
var d = s.ToCharArray();
Array.Reverse(d);
return s == new string(d);
}
static bool IsPalindromic(string s)
{
int len = s.Length;
int half = len-- >> 1;
for (int i = 0; i < half; i++)
if (s[i] != s[len - i])
return false;
return true;
}
}
}

Categories

Resources