Encrypting in Unity, decrypting in Node.js - c#

I am trying to send some data from Unity to Node.js express server and vice versa.
Here is my Unity code in C#:
public string Encrypt(string toEncrypt, string key, bool useHashing)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
if (useHashing){
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
}
else {
keyArray = UTF8Encoding.UTF8.GetBytes(key);
}
var tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
//tdes.Mode = CipherMode.CBC; // which is default
//tdes.Padding = PaddingMode.PKCS7; // which is default
ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
Dictionary<string, string> data = new Dictionary<string, string>();
data.Add("Test01", "Tanmoy");
data.Add("Test02", "Mitra");
string json = Json.Serialize(data);
byte[] postData = Encoding.UTF8.GetBytes(Encrypt(json, "12345", true));
StartCoroutine(HttpPost("test", postData, delegate(string requestError, IDictionary rData) {
cb(null,rData);
}));
And here is my Node.js code:
var alg = 'des-ede3-cbc';
var key = new Buffer('123456789012345678901234', 'utf-8');
var iv = new Buffer(m_strApiPass, 'base64');
var encrypted = new Buffer(reqString, 'base64');
var decipher = crypto.createDecipheriv(alg, key, iv);
var decoded = decipher.update(encrypted, 'binary', 'ascii');
decoded += decipher.final('ascii');
I am getting this error:
TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
What I have noticed, in C#, I got following string,
pySqIdAiJpDOW7XkOQDoblLOtZ382J1G1F1UE16W0Ulg+x5X0Bocjg==
but when I send this string to Node.js, it becomes:
pySqIdAiJpDOW7XkOQDoblLOtZ382J1G1F1UE16W0Ulg x5X0Bocjg
What could the issue be?

The reason is simple: the returned ciphertext consists of random looking bytes to any observer. This means that there are bytes in there which do not map to a character. The information within those bytes is lost.
If you require a string during transmission, base 64 encode your ciphertext instead, and decode it again at the receiving side.

Related

Encryption and Decryption in C# using MD5CryptoServiceProvider

I have a service named CryptoService which inherit the interface ICryptoService that consist of 2 method Crypto Decrypto function.
Encryption of a string is Working but the Decryption of hash result will return my key instead of the Decrypted string.
Here is my encryption code :
private string _salt = "*1234567890!##$%^&*()14344*";
private string Crypto(string text)
{
var hashmd5 = new MD5CryptoServiceProvider();
byte[] toEncryptArray = Encoding.UTF8.GetBytes(_salt);
byte[] keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(_salt));
hashmd5.Clear();
TripleDesProvider.Key = keyArray;
TripleDesProvider.Mode = CipherMode.ECB;
TripleDesProvider.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = TripleDesProvider.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
My decryption code :
private string Decrypto(string text)
{
try
{
var hashmd5 = new MD5CryptoServiceProvider();
byte[] toEncryptArray = Convert.FromBase64String(text);
byte[] keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(_salt));
hashmd5.Clear();
TripleDesProvider.Key = keyArray;
TripleDesProvider.Mode = CipherMode.ECB;
TripleDesProvider.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = TripleDesProvider.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
TripleDesProvider.Clear();
return Encoding.UTF8.GetString(resultArray);
//return Encoding.UTF8.GetString(resultArray);
}
catch
{
return string.Empty;
}
}
provided here the screenshot in action.
here are the references of my codes I found in the internet
https://www.codeproject.com/Articles/14150/Encrypt-and-Decrypt-Data-with-C
This cannot work. A hash, such as MD5, is one-way. You cannot get the original text from the hash value.
If your crypto service runs on the same machine, I suggest using the Data Protection class.
Your toEncryptArray in Encrypto gets the value _salt. You meant text.
So, good news, your decryption works.

C# FromBase64String fail due to unknown UNICODE

I have an encrypted database in which the strings are values like the below:
ùœ¢Qa³•ù¼?-pJ´’ˆò»Æ8-skYIÞµ§¬†Œ‚„Šç
ù¢=~Òñ€Ï?-pJ´’ˆò»Æ8-skYIÞµ§¬†Œ‚„Šç
XwÚûùÖP^opJ´’ˆò»Æ8-skYIÞµ§¬†Œ‚„Šç
ö‘±_|Çúùß^_f9´’ˆò»Æ8-skYIÞµ§¬†Œ‚„Šç
I'm trying different ways to dencrypt the information (it's a simmetric encryption and I have the key, but I don't know the algorithm, more detail here How to decrypt a string encrypted by V FoxPro)
When I tried different ways to dencrypt using C#.NET in an step I get àn error saying that "the string has a non-base64 character" in the following line:
Convert.FromBase64String(input)
Where input is a string similar to the one I share above.
How Can I receive an string like that from DB in order to work with that in C#?
I normally use something like this:
public static class EncryptDecryptString
{
public static string Encrypt(string input, string key)
{
byte[] inputArray = UTF8Encoding.UTF8.GetBytes(input);
TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
tripleDES.Key = UTF8Encoding.UTF8.GetBytes(key);
tripleDES.Mode = CipherMode.ECB;
tripleDES.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tripleDES.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length);
tripleDES.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string Decrypt(string input, string key)
{
byte[] inputArray = Convert.FromBase64String(input);
TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
tripleDES.Key = UTF8Encoding.UTF8.GetBytes(key);
tripleDES.Mode = CipherMode.ECB;
tripleDES.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tripleDES.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length);
tripleDES.Clear();
return UTF8Encoding.UTF8.GetString(resultArray);
}
}

Invalid length for Convert.FromBase64String

So I'm trying to decrypt an encrypted string, it encrypts fine, and sometimes decrypts it if I'm lucky enough but usually the string length is too long.. firstly here is the code where I called the decryption method
decrypted = Decrypt(recieved, getString(anarchyAes.Key));
addToChat(decrypted);
recieved is just the encrypted string, and the other parameter is the decryption key. Here is the Decrypt method..
public static string Decrypt(string cipherString, string securityKey)
{
var key = securityKey;
var keyArray = Encoding.UTF8.GetBytes(key);
var tdes = new TripleDESCryptoServiceProvider
{
Key = keyArray,
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
};
var cTransform = tdes.CreateDecryptor();
var toEncryptArray = Convert.FromBase64String(cipherString);
var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
return Encoding.UTF8.GetString(resultArray);
}
It fails when it does
var toEncryptArray = Convert.FromBase64String(cipherString);
When the string is more than 7 characters giving the error, invalid length for a 64 base string. I'm wondering how I could possibly fix this, any insight is appreciated.
Encrpytion code:
public static string Encrypt(string toEncrypt, string securityKey)
{
var key = securityKey;
var keyArray = Encoding.UTF8.GetBytes(key);
var tdes = new TripleDESCryptoServiceProvider
{
Key = keyArray,
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
};
var cTransform = tdes.CreateEncryptor();
var toEncryptArray = Encoding.UTF8.GetBytes(toEncrypt);
var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}

C# encryption in DES

I have a key which is in hex as 1C19D5ED8D88DC40 and the data in hex as 041164DFFFFE7FF7.
I am supposed to do DES encryption to obtain the encrypted value in hex as B652FF1BA23C279B. i struggled a lot with all possible encrypting methods of DES but couldn't get the exact value. I found it in this link I passed the binary values of the above hex as input and got the desired.
Help with C# code to get the above value.
public static string Encrypt(string Data,string Key)
{
byte[] key = Encoding.ASCII.GetBytes(Key);
// byte[] iv = Encoding.ASCII.GetBytes("password");
byte[] data = Encoding.ASCII.GetBytes(Data);
byte[] enc = new byte[0];
TripleDES tdes = TripleDES.Create();
//tdes.IV = iv;
tdes.Key = key;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform ict = tdes.CreateEncryptor();
enc = ict.TransformFinalBlock(data, 0, data.Length);
return Bin2Hex(enc);
}
// my bin2hex implementation
static string Bin2Hex(byte[] bin)
{
StringBuilder sb = new StringBuilder(bin.Length * 2);
foreach (byte b in bin)
{
sb.Append(b.ToString("x").PadLeft(2, '0'));
}
return sb.ToString();
}

tripledes encryption not yielding same results in PHP and C#

When I encrypt with C# I get arTdPqWOg6VppOqUD6mGITjb24+x5vJjfAufNQ4DN7rVEtpDmhFnMeJGg4n5y1BN
static void Main(string[] args)
{
Encoding byteEncoder = Encoding.Default;
String key = "ShHhd8a08JhJiho98ayslcjh";
String message = "Let us meet at 9 o'clock at the secret place.";
String encryption = Encrypt(message, key, false);
String decryption = Decrypt(encryption , key, false);
Console.WriteLine("Message: {0}", message);
Console.WriteLine("Encryption: {0}", encryption);
Console.WriteLine("Decryption: {0}", decryption);
}
public static string Encrypt(string toEncrypt, string key, bool useHashing)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
if (useHashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
}
else
keyArray = UTF8Encoding.UTF8.GetBytes(key);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string Decrypt(string toDecrypt, string key, bool useHashing)
{
byte[] keyArray;
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
if (useHashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
}
else
keyArray = UTF8Encoding.UTF8.GetBytes(key);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return UTF8Encoding.UTF8.GetString(resultArray);
}
When I encrypt with PHP I get: arTdPqWOg6VppOqUD6mGITjb24+x5vJjfAufNQ4DN7rVEtpDmhFnMVM+W/WFlksR
<?php
$key = "ShHhd8a08JhJiho98ayslcjh";
$input = "Let us meet at 9 o'clock at the secret place.";
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
echo base64_encode($encrypted_data);
?>
I don't know enough about cryptography to figure out why. Any ideas? Thanks.
Peter is right. PHP just pads with zeros, while you're using PKCS#7 in the C# code. Here's some code that should do it right:
function pkcs7_pad($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
$input = pkcs7_pad("Let us meet at 9 o'clock at the secret place.", 16);
Alternatively, you should be able to put this in your C# code:
tdes.Padding = PaddingMode.Zeros;
and also have it work (albeit slightly less securely).
I don't know PHP, and neither have I analysed your C# code carefully, but as most of the encrypted string is the same maybe the padding of the data is the difference? Maybe PHP uses another mode than the PaddingMode.PKCS7 used in the C# code? (This would have been a comment if I could comment...)
As a side note: if you are using ECB then you do not need an IV. Actually, using ECB is most of the time a security hazard, so you really need to use something else, e.g. CBC, which uses an IV. The IV is a random, non-secret value with the same size than the cipher block size (8 bytes for 3DES). A new IV must be created for each message, and the decrypting party must know the IV that the encrypting party used. In practice, the IV is sent along with the encrypted message.

Categories