Chrome Native messaging with C# Application - c#

I am trying to communicate with a C# app through chrome native messaging. I am totally new to C#. So I'll create a sample app through following code. How do I add this DisplayMessage function to display the incoming message in the UI?. I have used forms for this UI.
nativeMessage.exe
using System;
using System.IO;
using System.Windows.Forms;
namespace NativeMsgApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string message = txt_inputBox.Text;
label1.Text = "Send Message "+ message;
OpenStandardStreamOut(message);
}
private static string OpenStandardStreamIn()
{
//// We need to read first 4 bytes for length information
Stream stdin = Console.OpenStandardInput();
int length = 0;
byte[] bytes = new byte[4];
stdin.Read(bytes, 0, 4);
length = System.BitConverter.ToInt32(bytes, 0);
string input = "";
for (int i = 0; i < length; i++)
{
input += (char)stdin.ReadByte();
}
return input;
}
private static void OpenStandardStreamOut(string stringData)
{
//// We need to send the 4 btyes of length information
string msgdata = "{\"text\":\"" + stringData + "\"}";
int DataLength = msgdata.Length;
Stream stdout = Console.OpenStandardOutput();
stdout.WriteByte((byte)((DataLength >> 0) & 0xFF));
stdout.WriteByte((byte)((DataLength >> 8) & 0xFF));
stdout.WriteByte((byte)((DataLength >> 16) & 0xFF));
stdout.WriteByte((byte)((DataLength >> 24) & 0xFF));
//Available total length : 4,294,967,295 ( FF FF FF FF )
Console.Write(msgdata);
}
private static void DisplayMessage()
{
while (OpenStandardStreamIn() != null || OpenStandardStreamIn() != "")
{
OpenStandardStreamOut("Received to Native App: " + OpenStandardStreamIn());
OpenStandardStreamOut("Recieved: " + OpenStandardStreamIn());
}
}
}
}
The UI of the App

Related

C# why TCPListener load CPU

I found TCPListener code from here.
In MainWindow class Im starting server.
Then opening websocket from html page
let socket = new WebSocket("ws://192.168.1.149:1112");
Right after this CPU loads to 25% even if nothing sent to server. Further data sending to server going normal. What to do to prevent CPU load? Please help.
class TcpServer
{
public string ip;
public int port;
private Thread bgThread;
public void StartListen()
{
bgThread = new Thread(new ThreadStart(Start))
{
IsBackground = true
};
bgThread.Start();
}
public void Start()
{
TcpListener server = new TcpListener(IPAddress.Parse(ip), port);
server.Start();
TcpClient client = server.AcceptTcpClient();
NetworkStream stream = client.GetStream();
while (true)
{
while (!stream.DataAvailable) ;
while (client.Available < 3) ; // match against "get"
byte[] bytes = new byte[client.Available];
stream.Read(bytes, 0, client.Available);
string strbytes = Encoding.UTF8.GetString(bytes);
if(strbytes.StartsWith("GET"))
{
Console.WriteLine("=====Handshaking from client=====\n{0}", strbytes);
string swk = Regex.Match(strbytes, "Sec-WebSocket-Key: (.*)").Groups[1].Value.Trim();
string swka = swk + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
byte[] swkaSha1 = System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(swka));
string swkaSha1Base64 = Convert.ToBase64String(swkaSha1);
// HTTP/1.1 defines the sequence CR LF as the end-of-line marker
byte[] response = Encoding.UTF8.GetBytes(
"HTTP/1.1 101 Switching Protocols\r\n" +
"Connection: Upgrade\r\n" +
"Upgrade: websocket\r\n" +
"Sec-WebSocket-Accept: " + swkaSha1Base64 + "\r\n\r\n");
stream.Write(response, 0, response.Length);
}
else
{
bool mask = (bytes[1] & 0b10000000) != 0;
int msglen = bytes[1] - 128,
offset = 2;
if (msglen == 126)
{
msglen = BitConverter.ToUInt16(new byte[] { bytes[3], bytes[2] }, 0);
offset = 4;
}
else if (msglen == 127)
{
Console.WriteLine("TODO: msglen == 127, needs qword to store msglen");
}
if (msglen == 0)
Console.WriteLine("msglen == 0");
else if (mask)
{
try
{
byte[] decoded = new byte[msglen];
byte[] masks = new byte[4] { bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3] };
offset += 4;
for (int i = 0; i < msglen; ++i)
decoded[i] = (byte)(bytes[offset + i] ^ masks[i % 4]);
string text = Encoding.UTF8.GetString(decoded);
// other code
}
catch(Exception exc)
{
Console.WriteLine(exc.Message + "\n--------\n" + exc.StackTrace);
}
}
else
Console.WriteLine("mask bit not set");
}
}
}
}
private void startServer()
{
tcpserver = new TcpServer
{
ip = ipbox.Text,
port = 1112
};
tcpserver.StartListen();
}
startServer();
P.S: I have not to say anymore but SO says "It looks like your post is mostly code; please add some more details.". So: some words

Read arduino Serial.Write with C#

I have an Arduino that send on serial port some information revealed by analogical pin. Anyway, in the Arduino code (that I can not modify) is used Serial.write() instead of Serial.print() in order to print a buffer of char. As a consequence, if in my C# software I read the information with a "simple" ReadLine(), the data are incomprehensible. How can I read these type of data with C#?
It is the Arduino code:
#include <compat/deprecated.h>
#include <FlexiTimer2.h>
#define TIMER2VAL (1024/256) // 256Hz - frequency
volatile unsigned char myBuff[8];
volatile unsigned char c=0;
volatile unsigned int myRead=0;
volatile unsigned char mych=0;
volatile unsigned char i;
void setup() {
pinMode(9, OUTPUT);
noInterrupts();
myBuff[0] = 0xa5; //START 0
myBuff[1] = 0x5a; //START 1
myBuff[2] = 2; //myInformation
myBuff[3] = 0; //COUNTER
myBuff[4] = 0x02; //CH1 HB
myBuff[5] = 0x00; //CH1 LB
myBuff[6] = 0x02; //CH2 HB
myBuff[7] = 0x00; //CH2 LB
myBuff[8] = 0x01; //END
FlexiTimer2::set(TIMER2VAL, Timer2);
FlexiTimer2::start();
Serial.begin(57600);
interrupts();
}
void Timer2()
{
for(mych=0;mych<2;mych++){
myRead= analogRead(mych);
myBuff[4+mych] = ((unsigned char)((myRead & 0xFF00) >> 8)); // Write HB
myBuff[5+mych] = ((unsigned char)(myRead & 0x00FF)); // Write LB
}
// SEND
for(i=0;i<8;i++){
Serial.write(myBuff[i]);
}
myBuff[3]++;
}
void loop() {
__asm__ __volatile__ ("sleep");
}
And this is the C# method that read from serial port
public void StartRead()
{
msp.Open(); //Open the serial port
while (!t_suspend)
{
i++;
String r = msp.ReadLine();
Console.WriteLine(i + ": " + r);
}
}
EDIT: I would as output an array of string that correspond to the data of Arduino output. If I record everything as an array of byte, I have not the information about start and the end of the array.
I can edit the code as:
public void StartRead()
{
msp.Open(); //Open the serial port
ASCIIEncoding ascii = new ASCIIEncoding();
while (!t_suspend)
{
i++;
int r = msp.ReadByte();
String s = ascii.getString((byte)r); // here there is an error, it require an array byte[] and not a single byte
Console.WriteLine(i + ": " + r);
}
}
How I can have the same Arduino array value (but as a String) in my C# software, considering that the starting value is every time 0xa5 and the end is 0x01.
Arduino sends a telegram of several bytes. You can read it into a byte array:
byte[] telegram = byte[msp.BytesToRead];
msp.Read(telegram, 0, msp.BytesToRead);
To get the data from the byte array you have to interpret the bytes (See example below).
Of course you could create a string from the properties of the Telegram class:
class Telegram {
public Telegram(byte[] tel) {
// Check start bytes ( 0xa5, 0x5a );
Info = tel[2];
Counter = tel[3];
Channel1 = BitConverter.ToInt16(new byte[] { tel[5], tel[4] }, 0); // Switch lo/hi byte
Channel2 = BitConverter.ToInt16(new byte[] { tel[7], tel[6] }, 0);// Switch lo/hi byte
// check tel[8] == 1 for end of telegram
}
public int Info { get; private set; }
public int Counter { get; private set; }
public int Channel1 { get; private set; }
public int Channel2 { get; private set; }
}

real time server/client application in C++ and C#

I have a working chat -server application in C++ on a raspberry pi that listens for clients and sends messages from one client to the others and vice versa using pthreads in for loops. I am using C# as the clients.
The C# clients are sending and receiving data (single byte) to the RPi server continuously, and logging the times when they send and receive data.
Looking at the logged times, I can see that there is a delay of 100 ms or so between when one client sends and the second one receives the data. This kind of delay is unacceptable for my application. I need to get it under 15 ms consistently.
In my C++ program, the time delay between receiving and sending the byte back to the client is 1-2 ms.
I am not sure if there is a problem in how I have coded the C# clients or the C++ server. I upgraded my kernel with the RT PREEMPT patch but this has not affected the delay times.
If I put in a random delay on the order of seconds before sending a byte to the server in the C# program, then the delay times improve significantly - down to 1-2 ms.
Is there a way to optimize it so even when sending continuously, the delay times are very small? I can post the codes if needed.
**EDIT: Here is the server side code on the RPi.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string.h> // memset
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#include <vector>
#include <string>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <sys/time.h>
#include <sched.h>
#include <time.h>
#include <sys/mman.h>
using namespace std;
int BACKLOG;
#define IP_ADDR "192.168.137.99"
#define PORT "8888"
#define MAXLEN 1
#define MY_PRIORITY (49) /* we use 49 as the PRREMPT_RT use 50
as the priority of kernel tasklets
and interrupt handler by default */
#define MAX_SAFE_STACK (8*1024) /* The maximum stack size which is
guaranteed safe to access without
faulting */
#define NSEC_PER_SEC (1000000000) /* The number of nsecs per sec. */
static unsigned int cli_count = 0;
vector<int> cliarray;
vector<vector<unsigned long long> > data;
pthread_attr_t custom_sched_attr;
int fifo_max_prio, fifo_min_prio;
struct sched_param fifo_param;
void stack_prefault(void) {
unsigned char dummy[MAX_SAFE_STACK];
memset(dummy, 0, MAX_SAFE_STACK);
return;
}
void send_message(char *s, int sock){
int i;
for(i=0;i<BACKLOG;i++){
if(cliarray[i]){
if(cliarray[i] != sock){
send(cliarray[i], s, 1,0);
}
}
}
}
/* Send message to all clients */
void send_message_all(char *s){
int k;
for(k=0;k<BACKLOG;k++){
if(cliarray[k]){
send(cliarray[k], s, 1,0);
}
}
}
void *handle_conn(void *pnewsock)
{
int sock = *(int*)pnewsock;
char client_msg[MAXLEN];
int read_size;
struct timeval tv;
bool looprun = true;
int clientint;
vector<unsigned long long> row(4);
while(looprun ){
read_size = recv(sock, client_msg, 1, 0);
gettimeofday(&tv, NULL);
unsigned long long milliseconds_recv =(unsigned long long)(tv.tv_sec) * 1000 +(unsigned long long)(tv.tv_usec) / 1000;
clientint = int(*client_msg);
client_msg[read_size] = '\0';
/* cout << "length of client message: " << strlen(client_msg) << endl;
cout << "# bytes is : " << read_size << endl;
cout << clientint << " received" << endl;*/
send_message(client_msg,sock);
gettimeofday(&tv, NULL);
unsigned long long milliseconds_sent =(unsigned long long)(tv.tv_sec) * 1000 +(unsigned long long)(tv.tv_usec) / 1000;
row = {clientint, milliseconds_recv, milliseconds_sent, strlen(client_msg)};
data.push_back(row);
if (clientint == 100)
{
looprun = false;
break;
}
}
cout << "exit handle -conn " << endl;
pthread_exit(NULL);
}
int main (int argc, char **argv)
{
struct timespec t;
struct sched_param param;
int interval = 50000; /* 50us*/
/* Declare ourself as a real time task */
param.sched_priority = MY_PRIORITY;
if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
perror("sched_setscheduler failed");
exit(-1);
}
/* Lock memory */
if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
perror("mlockall failed");
exit(-2);
}
/* Pre-fault our stack */
stack_prefault();
int connfd =0, n = 0;
int *new_sock, sock;
struct addrinfo hints, *res;
int reuseaddr = 1; // True
// Get the address info
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(IP_ADDR, PORT, &hints, &res) != 0) {
perror("getaddrinfo");
exit (EXIT_FAILURE);
//return 1;
}
// Create the socket
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock == -1) {
perror("socket");
exit (EXIT_FAILURE);
// return 1;
}
// Enable the socket to reuse the address
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1) {
perror("setsockopt");
::close(sock);
exit (EXIT_FAILURE);
//shutdown(sock,2);
// return 1;
}
// Bind to the address
if (bind(sock, res->ai_addr, res->ai_addrlen) == -1) {
perror("bind");
::close(sock);
exit (EXIT_FAILURE);
//shutdown(sock,2);
//return 0;
}
freeaddrinfo(res);
// Listen
if (listen(sock, BACKLOG) == -1) {
perror("listen");
exit (EXIT_FAILURE);
// return 0;
}
cout << "Enter # clients: " ;
cin >> BACKLOG;
cout << "Enter name of text file (num clients - trial #).txt:" << endl;
string filename;
cin >> filename;
cout << "listening for connections" << endl;
// Main loop
// Main loop
bool running = true;
// Initialize clients
while (running)
{
size_t size = sizeof(struct sockaddr_in);
struct sockaddr_in their_addr;
int clilen = sizeof(their_addr);
int newsock = accept(sock, (struct sockaddr*)&their_addr, &size);
if (newsock == -1)
{
perror("accept");
exit (EXIT_FAILURE);
// return -1;
}
cli_count++;
printf("Got a connection from %s on port %d\n", inet_ntoa(their_addr.sin_addr), htons(their_addr.sin_port));
cliarray.push_back(newsock);
if (cli_count == BACKLOG)
{
cout << "Max clients reached" << endl;
running = false;
break;
}
}
ofstream frout("/home/pi/cplus/"+filename,ios::app);
frout << "recv \t" << "time recv (ms) \t" << "time sent (ms) \t" << "length of msg" << endl;
/* Send message to all clients that server is ready to accept data */
char r = char(cli_count);
char *mesg = &r;
send_message_all(mesg);
cout << "length of mesg: " << strlen(mesg) << endl;
//pthread_t from_ard_t, *ptr;
pthread_attr_init(&custom_sched_attr);
pthread_attr_setinheritsched(&custom_sched_attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&custom_sched_attr, SCHED_FIFO);
fifo_max_prio = sched_get_priority_max(SCHED_FIFO);
fifo_param.sched_priority = fifo_max_prio;
pthread_attr_setschedparam(&custom_sched_attr, &fifo_param);
pthread_t *ptr;
ptr =static_cast<pthread_t*>(malloc(sizeof(pthread_t)*cli_count));
int i;
for (i=0;i<BACKLOG;i++)
{
if (pthread_create(&ptr[i], &custom_sched_attr, handle_conn, (void *)&cliarray[i]) != 0)//was newsock
{
fprintf(stderr, "Failed to create thread\n");
exit (EXIT_FAILURE);
}
}
/*if (pthread_create(&from_ard_t, NULL, from_ard, NULL)!=0)
{
fprintf(stderr, "Failed to create thread\n");
}*/
//pthread_join(from_ard_t, NULL);
cout << "Created threads" << endl;
for(i = 0; i < BACKLOG; i++)
{
pthread_join(ptr[i], NULL);
}
cout << "joined send/recv threads" << endl;
close(sock);
/* array for timestamp data */
int numrows = data.size();
for (int k = 0; k < numrows; k++)
{
for (int j = 0; j < 4; j++)
{
frout << data[k][j] << "\t";
}
frout << endl;
}
}
C# client code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.IO;
//make command line possible to save time info in file
namespace sockclient_cs
{
public class Program
{
private System.Object lockThis = new System.Object();
const int MAXLEN = 1;
public bool recvrun = true;
StringBuilder sb = new StringBuilder();
public NetworkStream stream;
string fnrecv;
string fnsend;
public int clicount;
DateTime centuryBegin = new DateTime(1970, 1, 1);
Random rndseed;
public Program(NetworkStream streamer, int clinum, string pathsend, string pathrecv, Random rand)
{
stream = streamer;
clicount = clinum;
fnrecv = pathrecv;
fnsend = pathsend;
rndseed = rand;
}
public void SendData()
{
int[] numarray = new int[] { 70, 80, 90, 100, 60, 50, 40, 30}; // coressponds to %, A, P, _, d
bool looprun = true;
while (looprun)
{
int rnd1 = rndseed.Next(0, numarray.Length);
byte[] writebyte = new byte[] { BitConverter.GetBytes(numarray[rnd1])[0] };
int delay = rndseed.Next(2000,6000);
Thread.Sleep(delay);
Array.Reverse(writebyte);
stream.Write(writebyte, 0, writebyte.Length);
DateTime currentDate = DateTime.Now;
long elapsedTicks = currentDate.Ticks - centuryBegin.Ticks;
Decimal milliseconds = elapsedTicks / (Decimal)TimeSpan.TicksPerMillisecond;
using (StreamWriter sw = File.AppendText(fnsend))
{
sw.WriteLine(numarray[rnd1] + "\t" + milliseconds + "\n");
}
Console.Write("sent: " + numarray[rnd1] + "\n");
if (numarray[rnd1] == 100)
{
looprun = false;
break;
}
}
}
public void ReceiveData()
{
bool recvrun = true;
int numenders = 0;
while (recvrun)
{
String responseData = String.Empty;
byte[] bb = new byte[1]; //1 byte of data coming in
ASCIIEncoding ascii = new ASCIIEncoding();
int bytes;
bytes = stream.Read(bb, 0, bb.Length);
DateTime currentDate = DateTime.Now;
long elapsedTicks = currentDate.Ticks - centuryBegin.Ticks;
Decimal milliseconds = elapsedTicks / (Decimal)TimeSpan.TicksPerMillisecond;
int numback = BitConverter.ToInt16(new byte[] { bb[0], 0x00 }, 0);
using (StreamWriter sw = File.AppendText(fnrecv))
{
sw.WriteLine(numback + "\t" + milliseconds + "\n");
}
//responseData = ascii.GetString(bb, 0, bytes);
Console.WriteLine("Received: " + bb[0] + "\n");
if (numback == 100)
{
numenders++;
if (numenders == clicount-1)
{
recvrun = false;
break;
}
}
}
Console.Write("Exiting receive");
}
}
public class Simple
{
public static void Main()
{
Console.Write("Enter name of recv data file (ex. cli1recv_1.txt):\n");
string recvfile = Console.ReadLine();
string pathrecv = #"C:\Users\Neha\Documents\Ayaz Research\" + recvfile;
Console.Write("Enter name of send data file (ex. cli4send_1.txt):\n");
string sendfile = Console.ReadLine();
string pathsend = #"C:\Users\Neha\Documents\Ayaz Research\" + sendfile;
using (StreamWriter sw = File.CreateText(pathrecv))
{
sw.WriteLine("Received \t Recv time (ms) \n");
}
using (StreamWriter sw = File.CreateText(pathsend))
{
sw.WriteLine("Sent \t Sent time (ms) \n");
}
//SerialPort Serial1 = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
Random seed = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
try
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting...");
tcpclnt.Connect("192.168.137.99", 8888); //address of RPi on arbitrary non privileged port
Console.WriteLine("Connected");
NetworkStream stream = tcpclnt.GetStream();
/*Receive the welcome from server */
String responseData = String.Empty;
Byte[] bb = new byte[2]; //1 byte of data coming in
ASCIIEncoding ascii = new ASCIIEncoding();
int bytes = stream.Read(bb, 0, bb.Length);
int numback = BitConverter.ToInt16(new byte[] { bb[0], 0x00 }, 0);
Console.Write("Received initial message from server: " + bb[0] + "\n");
/*byte[] writebyte = new byte[] { BitConverter.GetBytes(82)[0] };
Console.Write("writebyte length is " + writebyte.Length + "\n");
Array.Reverse(writebyte);
stream.Write(writebyte, 0, writebyte.Length);
bytes = stream.Read(bb, 0,bb.Length);
// convert to string info
Console.Write("reading byte length is " + bb.Length + "\n");
responseData = ascii.GetString(bb, 0, bytes);
Console.WriteLine("bb[0] is: " + bb[0] + "and bb[1] is: " + bb[1] + "\n");
int numback = BitConverter.ToInt16(new byte[] { bb[0], 0x00 }, 0);
Console.WriteLine("Received: " + responseData + "\n");
Console.WriteLine("Received: " + numback + "\n");*/
Program clientObject = new Program(stream,numback,pathsend, pathrecv, seed);
//non loop format - for cppserv
ThreadStart sending = new ThreadStart(clientObject.SendData);
Thread sendThread = new Thread(sending);
sendThread.Start();
ThreadStart receiving = new ThreadStart(clientObject.ReceiveData);
Thread recvThread = new Thread(receiving);
recvThread.Start();
sendThread.Join();
recvThread.Join();
tcpclnt.Close();
}
catch (Exception e)
{
Console.WriteLine("Error...." + e.StackTrace);
}
}
}
}
Here is what Client 2 is sending to Client 1 and the timestamp.
Sent Sent time (ms)
70 1467720189893.1576
80 1467720189912.1587
60 1467720189926.1595
60 1467720189937.1602
50 1467720189949.1608
60 1467720189959.1614
40 1467720189969.162
100 1467720190006.1641
Here is what Client 1 is receiving from Client 2 and the timestamp.
Received Recv time (ms)
70 1467720190016.1647
80 1467720190063.1674
60 1467720190079.1683
60 1467720190109.17
50 1467720190126.171
60 1467720190137.1716
40 1467720190149.1723
100 1467720190161.173
Turn off the Nagle algorithm at the sender
Socket.NoDelay = true

Sending Long integer values from Arduino and receiving them from C# app?

As title gives it away I am trying to just send Long integer values from arduino and receiving it from my C# application.
My Arduino code is
void setup()
{
Serial.begin(9600);
}
long n;
byte b[4];
void loop()
{
n=500;
for (int i=0; i<10; i++)
{
n = n+20;
IntegerToBytes(n, b);
for (int i=0; i<4; ++i)
{
Serial.write((int)b[i]);
}
delay(1000);
}
}
void IntegerToBytes(long val, byte b[4])
{
b[3] = (byte )((val >> 24) & 0xff);
b[2] = (byte )((val >> 16) & 0xff);
b[1] = (byte )((val >> 8) & 0xff);
b[0] = (byte )((val) & 0xff);
}
And related C# code is
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
if (mySerial.IsOpen)
{
int bytes = mySerial.BytesToRead;
byte[] byte_buffer = new byte[4];
mySerial.Read(byte_buffer, 0, 4);
if (bytes == 4)
{
SerialConverted_LONGValue = BitConverter.ToInt32(byte_buffer, 0);
}
}
}
After I debug the code it just writes the received value to a textbox. I can see just one value, and if any chance, it changes couple of times, as well.
What is wrong with my long to byte[] and byte[] to long conversion?
BitConverter does a straight map. It does not know about endianess. Change the order of assignment from 3, 2, 1, 0 to 0, 1, 2, 3.

C# Base64 encoding / decoding fails when using custom encrypted password

Im currently writing a program that is encrypting a password (using a custom method), and then encoding the password to Base64 using the To/FromBase64Transform classes. The problem is, when i encode my encrypted password, I am unable to decode it back to its proper encrypted state. The Base64Helper class is just a wrapper for the To/FromBase64Transform classes.
My Test Code:
static void Main(string[] args)
{
bool Worked = false;
string Password = "testing";
Console.WriteLine("Password: " + Password);
// == Encode then decode 64 test. DecPass64 should equal password == //
// Encodes to Base64 using ToBase64Transform
string EncPass64 = Base64Helper.EncodeString(Password);
// Decodes a Base64 string using FromBase64Transform
string DecPass64 = Base64Helper.DecodeString(EncPass64);
// Test if base 64 ecoding / decoding works
Worked = (Password == DecPass64);
Console.WriteLine();
Console.WriteLine("Base64 Pass Encoded: " + EncPass64);
Console.WriteLine("Base64 Pass Decoded: " + DecPass64);
Console.WriteLine("Base64 Encode to Base64 Decode Worked? : " + Worked); // True
// gspassenc uses XOR to switch passwords back and forth between encrypted and decrypted
string GsEncodedPass = gspassenc(Password);
string GsDecodedPass = gspassenc(GsEncodedPass);
Worked = (Password == GsDecodedPass);
// GsDecodedPass should equal the original Password
Console.WriteLine();
Console.WriteLine("GsPass Encoded: " + GsEncodedPass);
Console.WriteLine("GsPass Decoded: " + GsDecodedPass);
Console.WriteLine("GsEncode to GsDecode Worked? : " + Worked); // True
// Bas64 encode the encrypted password. Then decode the base64. B64_GsDecodedPass should equal
// the GsEncoded Password... But it doesn't for some reason!
string B64_GsEncodedPass = Base64Helper.EncodeString(GsEncodedPass);
string B64_GsDecodedPass = Base64Helper.DecodeString(B64_GsEncodedPass);
Worked = (B64_GsDecodedPass == GsEncodedPass);
// Print results
Console.WriteLine();
Console.WriteLine("Base64 Encoded GsPass: " + B64_GsEncodedPass);
Console.WriteLine("Base64 Decoded GsPass: " + B64_GsDecodedPass);
Console.WriteLine("Decoded == GS Encoded Pass? : " + Worked); // False
// Stop console from closing till we say so
Console.Read();
}
private static int gslame(int num)
{
int c = (num >> 16) & 0xffff;
int a = num & 0xffff;
c *= 0x41a7;
a *= 0x41a7;
a += ((c & 0x7fff) << 16);
if (a < 0)
{
a &= 0x7fffffff;
a++;
}
a += (c >> 15);
if (a < 0)
{
a &= 0x7fffffff;
a++;
}
return a;
}
private static string gspassenc(string pass)
{
int a = 0;
int num = 0x79707367; // gspy
int len = pass.Length;
char[] newPass = new char[len];
for (int i = 0; i < len; ++i)
{
num = gslame(num);
a = num % 0xFF;
newPass[i] = (char)(pass[i] ^ a);
}
return new String(newPass);
}
And the result is:
Any help will be much appreciated!
UPDATE: Here is my Base64Helper Class:
class Base64Helper
{
public static string DecodeString(string encoded)
{
return Encoding.ASCII.GetString(Convert.FromBase64String(encoded));
}
public static string EncodeString(string decoded)
{
return Convert.ToBase64String(Encoding.ASCII.GetBytes(decoded));
}
}
It's because of the way you are interfering with the Unicode "Chars" of the string with the encoding algorithm and then constructing a String using those "Chars" which then might not form a valid Unicode stream.
When converting from your String to a Byte array and back again, you need to decide which encoding to use....and you can't arbitrarily change the byte stream (via your encryption routine) and expect it to produce a valid string when being converted back.
I've modified your code to show some string to byte[] conversion steps...you can adjust these depending on your need.
static void Main(string[] args)
{
bool Worked = false;
string Password = "testing";
Console.WriteLine("Password: " + Password);
// == Encode then decode 64 test. DecPass64 should equal password == //
// Encodes to Base64 using ToBase64Transform
string EncPass64 = Base64Helper.EncodeString(Password);
// Decodes a Base64 string using FromBase64Transform
string DecPass64 = Base64Helper.DecodeString(EncPass64);
// Test if base 64 ecoding / decoding works
Worked = (Password == DecPass64);
Console.WriteLine();
Console.WriteLine("Base64 Pass Encoded: " + EncPass64);
Console.WriteLine("Base64 Pass Decoded: " + DecPass64);
Console.WriteLine("Base64 Encode to Base64 Decode Worked? : " + Worked); // True
// gspassenc uses XOR to switch passwords back and forth between encrypted and decrypted
byte [] passwordbytes = Encoding.UTF8.GetBytes(Password);
byte [] bytes_GsEncodedPass = gspassenc(passwordbytes);
string GsEncodedPass = Encoding.UTF8.GetString(bytes_GsEncodedPass);
byte[] bytes_GsDecodedPass = gspassenc(bytes_GsEncodedPass);
string GsDecodedPass = Encoding.UTF8.GetString(bytes_GsDecodedPass);
Worked = (Password == GsDecodedPass);
// GsDecodedPass should equal the original Password
Console.WriteLine();
Console.WriteLine("GsPass Encoded: " + GsEncodedPass);
Console.WriteLine("GsPass Decoded: " + GsDecodedPass);
Console.WriteLine("GsEncode to GsDecode Worked? : " + Worked); // True
// Bas64 encode the encrypted password. Then decode the base64. B64_GsDecodedPass should equal
// the GsEncoded Password... But it doesn't for some reason!
string B64_GsEncodedPass = Convert.ToBase64String(bytes_GsEncodedPass);
byte []bytes_B64_GsDecodedPass = Convert.FromBase64String(B64_GsEncodedPass);
string B64_GsDecodedPass = Encoding.UTF8.GetString(bytes_B64_GsDecodedPass);
Worked = (B64_GsDecodedPass == GsEncodedPass);
// Print results
Console.WriteLine();
Console.WriteLine("Base64 Encoded GsPass: " + B64_GsEncodedPass);
Console.WriteLine("Base64 Decoded GsPass: " + B64_GsDecodedPass);
Console.WriteLine("Decoded == GS Encoded Pass? : " + Worked); // False
// Stop console from closing till we say so
Console.Read();
}
private static int gslame(int num)
{
int c = (num >> 16) & 0xffff;
int a = num & 0xffff;
c *= 0x41a7;
a *= 0x41a7;
a += ((c & 0x7fff) << 16);
if (a < 0)
{
a &= 0x7fffffff;
a++;
}
a += (c >> 15);
if (a < 0)
{
a &= 0x7fffffff;
a++;
}
return a;
}
private static byte[] gspassenc(byte [] pass)
{
int a = 0;
int num = 0x79707367; // gspy
int len = pass.Length;
byte[] newPass = new byte[len];
for (int i = 0; i < len; ++i)
{
num = gslame(num);
a = num % 0xFF;
newPass[i] = (byte)(pass[i] ^ a);
}
return newPass;
}
}

Categories