TripleDESCryptoService - "Wrong data" - c#

when I try do decrypt my encrypted key I receive an error saying that it's wrong data / inaccurate data. Tried to search around for a while without any result. This is both the encryption code and decryption code. The indata is a MAC-Address for encryption, and indata for decryption is read from textfile.
public string encryptMAC(string indata)
{
byte[] resultCrypt;
UTF8Encoding utf8 = new UTF8Encoding();
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
byte[] encrypt = utf8.GetBytes(indata);
try
{
ICryptoTransform encryptor = tdes.CreateEncryptor();
resultCrypt = encryptor.TransformFinalBlock(encrypt, 0, encrypt.Length);
}
finally
{
tdes.Clear();
}
return Convert.ToBase64String(resultCrypt);
}
public string decryptMAC(string indata)
{
byte[] resultDecrypt;
UTF8Encoding utf8 = new UTF8Encoding();
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
byte[] decrypt = Convert.FromBase64String(indata);
try
{
ICryptoTransform decryptor = tdes.CreateDecryptor();
resultDecrypt = decryptor.TransformFinalBlock(decrypt, 0, decrypt.Length);
}
catch (CryptographicException ex)
{
Console.WriteLine(ex);
}
finally
{
tdes.Clear();
}
return utf8.GetString(decrypt);
}

TripleDESCryptoServiceProvider will generate a key for you. If you don't set it yourself or retrieve it during encryption, then you will not be able to decrypt the ciphertext.
I suggest that you add a key to your methods and use the same one for encryption and decryption:
public string encryptMAC(string indata, byte[] key)
{
byte[] resultCrypt;
UTF8Encoding utf8 = new UTF8Encoding();
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
tdes.Key = key;
byte[] encrypt = utf8.GetBytes(indata);
try
{
ICryptoTransform encryptor = tdes.CreateEncryptor();
resultCrypt = encryptor.TransformFinalBlock(encrypt, 0, encrypt.Length);
}
finally
{
tdes.Clear();
}
return Convert.ToBase64String(resultCrypt);
}
public string decryptMAC(string indata, byte[] key)
{
byte[] resultDecrypt = new byte[0];
UTF8Encoding utf8 = new UTF8Encoding();
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
tdes.Key = key;
byte[] decrypt = Convert.FromBase64String(indata);
try
{
ICryptoTransform decryptor = tdes.CreateDecryptor();
resultDecrypt = decryptor.TransformFinalBlock(decrypt, 0, decrypt.Length);
}
catch (CryptographicException ex)
{
Console.WriteLine(ex);
}
finally
{
tdes.Clear();
}
return utf8.GetString(resultDecrypt);
}
Keep in mind that DES has a small set of weak keys, so you should use TripleDESCryptoServiceProvider to generate a key for you which will filter out those weak keys. You can generate a valid key by (new TripleDESCryptoServiceProvider()).Key.

Related

RijndaelManaged "padding is invalid and cannot be removed"

I'm trying to create methods for very strong Rijndael 256 string encryption that I can use for passwords but I get an error saying Padding is invalid and cannot be removed. when I read the CryptoStream and get the decrypted string. Here are my encrypt and decrypt methods:
private string AES256EncryptString(string key, string plainText)
{
try
{
using (RijndaelManaged rijndael = new RijndaelManaged())
{
rijndael.KeySize = 256;
rijndael.BlockSize = 128;
rijndael.Key = Encoding.UTF8.GetBytes(key);
rijndael.GenerateIV();
rijndael.Mode = CipherMode.CBC;
rijndael.Padding = PaddingMode.PKCS7;
ICryptoTransform encryptor = rijndael.CreateEncryptor(rijndael.Key, rijndael.IV);
MemoryStream memoryStream = new MemoryStream();
memoryStream.Write(rijndael.IV, 0, rijndael.IV.Length);
CryptoStream crypoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
crypoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
crypoStream.FlushFinalBlock();
crypoStream.Close();
byte[] encryptedBytes = memoryStream.ToArray();
memoryStream.Close();
string encryptedText = Convert.ToBase64String(encryptedBytes);
return encryptedText;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return null;
}
}
private string AES256DecryptString(string key, string encryptedText)
{
try
{
using (RijndaelManaged rijndael = new RijndaelManaged())
{
rijndael.KeySize = 256;
rijndael.BlockSize = 128;
rijndael.Key = Encoding.UTF8.GetBytes(key);
byte[] encryptedTextBytes = Encoding.UTF8.GetBytes(encryptedText);
byte[] iv = new byte[16];
Array.Copy(encryptedTextBytes, iv, iv.Length);
rijndael.IV = iv;
rijndael.Mode = CipherMode.CBC;
rijndael.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);
MemoryStream memoryStream = new MemoryStream();
byte[] encryptedTextWithoutIVBytes = new byte[encryptedTextBytes.Length - iv.Length];
Array.Copy(encryptedTextBytes, 16, encryptedTextWithoutIVBytes, 0, encryptedTextWithoutIVBytes.Length);
memoryStream.Write(encryptedTextWithoutIVBytes, 0, encryptedTextWithoutIVBytes.Length);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
StreamReader streamReader = new StreamReader(cryptoStream);
string decryptedText = streamReader.ReadToEnd();
cryptoStream.FlushFinalBlock();
cryptoStream.Close();
memoryStream.Close();
return decryptedText;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
return null;
}
}
As you can see I add the initialization vector before the encrypted string before adding the encrypted bit because I know that IVs should be random and I've seen this is a good strategy to use. I make sure to remove the IV before decrypting.
Is there a way to fix this without changing the padding mode (I've seen that PKCS7 padding is very secure)?
Problems:
You should use a proper password-based KDF for passwords and similar low-entropy keys. .NET has the Rfc2898DeriveBytes (PBKDF2) class to make this relatively easy.
You are not base64 decoding your ciphertext in your decryptor. Instead of
byte[] encryptedTextBytes = Encoding.UTF8.GetBytes(encryptedText);
you should have
byte[] encryptedTextBytes = Convert.FromBase64String(encryptedText);
You need to reset the position of the MemoryStream after you populate it with ciphertext bytes. After
memoryStream.Write(encryptedTextWithoutIVBytes, 0, encryptedTextWithoutIVBytes.Length);
you need to insert
memoryStream.Seek(0, SeekOrigin.Begin);

TRIPLE DES ECB Encryption RUBY

I have a sample code in .NET C# which I need to convert to RUBY.
public static string Encrypt(string pstrText)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(pstrText);
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(secKey));
hashmd5.Clear();
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);
tdes.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
I have tried using OPENSSL:CIPHER and got thus far -
def encrypt data
secret = "******************"
md5 = Digest::MD5.hexdigest(secret)
des = OpenSSL::Cipher::Cipher.new 'DES-EDE3'
des.encrypt
des.key = md5
update_value = des.update(data)
up_final = update_value + des.final
puts Base64.encode64(up_final).gsub(/\n/, "")
end
The results in C# and RUBY do not match. Where am I going wrong?

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.

PHP Triple DES encryption and compatible C# decryption

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);
}

"Padding is invalid and cannot be removed" -Whats wrong with this code?

Every time I run this and encrypt, the output is variable, and when I attempt to decrypt
I get "Padding is invalid and cannot be removed." Been fighting with this for a day or two now and I am at a loss.
private static string strIV = "abcdefghijklmnmo"; //The initialization vector.
private static string strKey = "abcdefghijklmnmoabcdefghijklmnmo"; //The key used to encrypt the text.
public static string Decrypt(string TextToDecrypt)
{
return Decryptor(TextToDecrypt);
}
private static string Encryptor(string TextToEncrypt)
{
//Turn the plaintext into a byte array.
byte[] PlainTextBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(TextToEncrypt);
//Setup the AES providor for our purposes.
AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();
aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);
aesProvider.BlockSize = 128;
aesProvider.KeySize = 256;
aesProvider.Padding = PaddingMode.PKCS7;
aesProvider.Mode = CipherMode.CBC;
ICryptoTransform cryptoTransform = aesProvider.CreateEncryptor(aesProvider.Key, aesProvider.IV);
byte[] EncryptedBytes = cryptoTransform.TransformFinalBlock(PlainTextBytes, 0, PlainTextBytes.Length);
return Convert.ToBase64String(EncryptedBytes);
}
private static string Decryptor(string TextToDecrypt)
{
byte[] EncryptedBytes = Convert.FromBase64String(TextToDecrypt);
//Setup the AES provider for decrypting.
AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();
aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);
aesProvider.BlockSize = 128;
aesProvider.KeySize = 256;
aesProvider.Padding = PaddingMode.PKCS7;
aesProvider.Mode = CipherMode.CBC;
ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor(aesProvider.Key, aesProvider.IV);
byte[] DecryptedBytes = cryptoTransform.TransformFinalBlock(EncryptedBytes, 0, EncryptedBytes.Length);
return System.Text.Encoding.ASCII.GetString(DecryptedBytes);
}
}
You need to set the BlockSize and the KeySize before you set the Key and the IV. Additionally you should probably be generating a random IV for each message and note that ICryptoTransform implements IDisposable so these objects should be disposed.

Categories