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);
}
Related
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.
I am decrypting a message in C#, this message is encrypted in PHP using below code:-
public function __construct($sEncryptionKey)
{
$this->link = mcrypt_module_open('tripledes', '', 'ecb', '');
$this->sInitializationVector = mcrypt_create_iv(mcrypt_enc_get_iv_size($this->link), MCRYPT_RAND);
$this->iKeySize = mcrypt_enc_get_key_size($this->link);
$sEncryptionKey = substr(md5($sEncryptionKey), 0, $this->iKeySize);
mcrypt_generic_init($this->link, $sEncryptionKey, $this->sInitializationVector);
}
public function encrypt($sDataToEncrypt)
{
return base64_encode(mcrypt_generic($this->link, $sDataToEncrypt));
}
And I am using below decryption function in c# for decryption:-
public 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));
hashmd5.Clear();
}
else
{
keyArray = UTF8Encoding.UTF8.GetBytes(key);
}
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
var strValue = UTF8Encoding.UTF8.GetString(resultArray);
return UTF8Encoding.UTF8.GetString(resultArray);
}
I tried with few changes and getting below results:-
1.) PaddingMode.PKCS7 with no hashing = "Specified key is not a valid size for this algorithm."
2.) PaddingMode.PKCS7 with hashing = "Bad Data."
3.) PaddingMode.Zeros with no hashing = "Specified key is not a valid size for this algorithm."
4.) PaddingMode.Zeros with hashing = "�8�f����q6IGs�" some unknown characters
I think 4'th one will work, but not sure what I am doing wrong.
Found a solution, need to do changes in MD5 hashing, below are whole code if someone stuck in same situation :-
public string Decrypt(string toDecrypt, string key, bool useHashing)
{
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
byte[] keyArray;
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
string keyArrayStr = "";
if (useHashing)
{
MD5 md5 = MD5CryptoServiceProvider.Create();
byte[] dataMd5 = md5.ComputeHash(Encoding.Default.GetBytes(key));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < dataMd5.Length; i++)
sb.AppendFormat("{0:x2}", dataMd5[i]);
keyArrayStr = sb.ToString().Substring(0, tdes.Key.Length);
keyArray = UTF8Encoding.UTF8.GetBytes(keyArrayStr);
}
else
{
keyArray = UTF8Encoding.UTF8.GetBytes(key);
}
tdes.Key = keyArray;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
var strValue = UTF8Encoding.UTF8.GetString(resultArray);
return UTF8Encoding.UTF8.GetString(resultArray);
}
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);
}
}
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.
in a case i need to decrypt texts with diffrent keys
i also need to genreate valid keys in code behind.
i am using this line to generate a key.
var key = Encoding.UTF8.GetString(TripleDES.Create().Key);
but can't use that key in this method. it says "Specified key is not a valid size for this algorithm"
how can i fix this situation?
public class CryptoHelper
{
public string Encrypt(string toEncrypt, string key)
{
var toEncryptArray = Encoding.UTF8.GetBytes(toEncrypt);
var keyArray = Encoding.UTF8.GetBytes(key);
var tdes = new TripleDESCryptoServiceProvider { Key = keyArray, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
var cTransform = tdes.CreateEncryptor();
var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public string Decrypt(string cipherString, string key)
{
var toEncryptArray = Convert.FromBase64String(cipherString.Replace(' ', '+'));
var keyArray = Encoding.UTF8.GetBytes(key);
var tdes = new TripleDESCryptoServiceProvider { Key = keyArray, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
var cTransform = tdes.CreateDecryptor();
var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
return Encoding.UTF8.GetString(resultArray);
}
}
If you write a little test, your problem becomes obvious,
var failures = ParallelEnumerable.Range(0, 10000).Count(i =>
{
var keyBefore = TripleDES.Create().Key;
var keyAfter = Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(keyBefore));
return !keyBefore.SequenceEqual(keyAfter);
});
In my testing, every attempted roundtrip fails. This confirms Damien's comment.
There's no guarantee that the bytes generated for a key can be safely
round-tripped into a string by acting as if they're a valid UTF-8
sequence.
The keyAfter is (almost) always somewhat expanded, sometimes doubled in length. In fact, I'm unable to fluke a key that is round trippable, this may have something to do with avoiding weak keys.
However, if i try
var failures = ParallelEnumerable.Range(0, 10000).Count(i =>
{
var keyBefore = TripleDES.Create().Key;
var keyAfter = Convert.FromBase64String(Convert.ToBase64String(keyBefore));
return !keyBefore.SequenceEqual(keyAfter);
});
failures always equals 0, as expected. So, there is a simple solution.