MD5 encode and decode [closed] - c#

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a function md5_encode
public string MD5_encode(string str_encode)
{
MD5 md5Hash = MD5.Create();
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(str_encode));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
i can't decode it. I search in internet and found something like that
public static string Encrypt(string toEncrypt, bool useHashing)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
// Get the key from config file
string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
//System.Windows.Forms.MessageBox.Show(key);
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.PKCS7;
ICryptoTransform cTransform = tdes.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
tdes.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
but i don't know that code work, Someone help me, decode function MD5_encode(string str_encode) or show me detail about different MD5_encode(string str_encode) and Encrypt(string toEncrypt, bool useHashing)
tks a lot for any help :)

MD5_encode uses MD5 (a cryptographic hash function) to generate a hash. The name is misleading as it isn't an encoding. A hash generate a value of a fixed size independent of the input, and cryptographic hash are especially designed not to be reversible.
Encrypt uses Triple DES to encrypt the input using as key either a value stored in the settings or the hash of this value.
You can decrypt the result of Encrypt using tdes.CreateDecryptor after removing the Base64 encoding.
PS: 3DES is old, you should use something more recent like AES
PS: ECB is insecure in a lot of cases, you should at least use CBC with a random IV.

Although MD5 is susceptible to a number of attacks that prove otherwise, MD5 is a hashing method. Hashes are designed to be one-way only. Just imagine if all of the hashing algorithms in the world today allowed anyone to easily get the original data from the hash data! Eeeeek!

Related

Why to create a derived password of 256 bytes and later get bytes from result?

I have found an example that uses AES encrypt to encrypt text. The code is this:
public static string Encrypt(string PlainText, string Password,
string Salt = "Kosher", string HashAlgorithm = "SHA1",
int PasswordIterations = 2, string InitialVector = "OFRna73m*aze01xY",
int KeySize = 256)
{
if (string.IsNullOrEmpty(PlainText))
return "";
byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText);
PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
RijndaelManaged SymmetricKey = new RijndaelManaged();
SymmetricKey.Mode = CipherMode.CBC;
byte[] CipherTextBytes = null;
using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes))
{
using (MemoryStream MemStream = new MemoryStream())
{
using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write))
{
CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
CryptoStream.FlushFinalBlock();
CipherTextBytes = MemStream.ToArray();
MemStream.Close();
CryptoStream.Close();
}
}
}
SymmetricKey.Clear();
return Convert.ToBase64String(CipherTextBytes);
}
My question is: how is the key for the AES algorithm generated? These 2 lines:
PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
First, it creates a derived key of 256 bytes, and later, create a key getting pseudo random bytes of this derived key. It has to be divided by 8 because the AES algorithm need 128, 182 or 256 bits, not bytes. In this case, how derived key is 256 bytes, the key for AES will be 256 bits.
But why does it do that? Wouldn't it better create the derived key with the needed length, not 256 bytes but 256 bits (256 bytes / 8)? So It wouldn't be needed to create a new key taken the 1/8 bytes of the derived key.
Also, the getBytes() method, in the description of the method, it says it returns pseudo-random key bytes. So doesn't it do the AES key would be different in each case? How to generate again the AES key from decryption if it is pseudo random key bytes?
Thanks.
First, it creates a derived key of 256 bytes
Where? I don't see any 256-byte key being created.
and later, create a key getting pseudo random bytes of this derived key. It has to be divided by 8 because the AES algorithm need 128, 182 or 256 bits, not bytes
Yes, the function input of KeySize (which should be keySize by normal C# naming conventions) is in bits, but GetBytes wants an input in bytes. x / 8 is one of the three right answers for that conversion ((x + 7) / 8 is another, and x & 7 == 0 ? x / 8 : throw new ArgumentException(nameof(x)) is the third)
But why does it do that? Wouldn't it better create the derived key with the needed length, not 256 bytes but 256 bits (256 bytes / 8)? So It wouldn't be needed to create a new key taken the 1/8 bytes of the derived key.
It would be good to do that. But since it is already doing that, there's no "better" to be had.
Also, the getBytes() method, in the description of the method, it says it returns pseudo-random key bytes. So doesn't it do the AES key would be different in each case? How to generate again the AES key from decryption if it is pseudo random key bytes?
I have to make a pedantic point: There is no getBytes method. C# is a case-sensitive language, and the method name is GetBytes.
pseudorandom: noting or pertaining to random numbers generated by a definite computational process to satisfy a statistical test.
PasswordDeriveBytes is an implementation of PBKDF1 (except it continues beyond the limits of PBKDF1), which is a deterministic algorithm. Given the same inputs (password, seed, iteration count, pseudo-random function (hash algorithm)) the same output is produced. Change any of the inputs slightly, and the output is significantly different.
Rfc2898DeriveBytes (an implementation of PBKDF2) is also a deterministic, but chaotic, algorithm.
So you produce the same answer again in either of them (but not across them) by giving all the same inputs.
When using password-based encryption (PKCS#5) the flow is
Pick a PRF
Pick an iteration count
Generate a random salt
Write down these choices
Apply these three things, plus the password to generate a key
Encrypt the data
Write down to the encrypted data
When decrypting one
Read the PRF
Read the iteration count
Read the salt
Apply these three things, plus the password to generate a key
Read the encrypted data
Decrypt it
Party on
While this code is doing that part right, the IV and Salt should not be ASCII (or UTF8) strings, they should be "just bytes" (byte[]). If they need to be transported as strings then they should be base64, or some other "arbitrary" binary-to-text encoding.

What does the output of Rfc2898DeriveBytes depend on and how should the salt be treated?

public string Encrypt(string Code)
{
string result = string.Empty;
byte[] encryptResult = null;
var CodeInByte = Encoding.ASCII.GetBytes(Code);
try
{
using (MemoryStream memo = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = KeySize;
AES.BlockSize = BlockSize;
var key = new Rfc2898DeriveBytes(CodeInByte, salt, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var encrypt = new CryptoStream(memo, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
encrypt.Write(CodeInByte, 0, CodeInByte.Length);
encrypt.Close();
}
encryptResult = memo.ToArray();
}
}
result = Convert.ToBase64String(encryptResult);
return result;
}
catch (Exception err)
{
MsgCode = 99;
MsgDesc = err.Message;
return string.Empty;
}
}
It's just a simple AES encrypting method from string
The point I want to ask, when generating the key, at
var key = new Rfc2898DeriveBytes(CodeInByte, salt, 1000);
is the key generated from inputted string, or it's just a random generated byte array?
and, is the salt needs to be static or not
As the documentation on MSDN suggests:
Rfc2898DeriveBytes takes a password, a salt, and an iteration count, and then generates keys through calls to the GetBytes method.
In other words, it will derive bytes using the input parameters you give it. If you give it different parameters, the derived key will be different. If you give it the same parameters, it will generate the same bytes.
Symmetrical encryption algorithms (such as AES) require a fixed length key - 16 bytes in this case for AES128. However, you don't want to mandate that passwords are fixed length as this makes them much easier to attack. You also might want much longer keys than a feasible password - AES256 would require a 32byte key, for example. Finally, passwords tend to be alphanumeric and perhaps have some symbols, whereas an encryption key is made up of bytes that can range from 0x00-0xFF, if you made the encryption key a 32 character ASCII password, then you'd reduce the range quite considerably as the printable ASCII character range is much smaller than 0x00-0xFF.
For this reason, you want to derive the encryption key from a given password in such a way that you get a strong key of the exact length you require. That's where Rfc2898DeriveBytes comes in.

Encrypting with DES with user input password

I'm still studying cryptography. I'm trying to create a simple static function in C# that encrypts string to DES (with a Base64 ouput). I learned that DES use 8-Byte as its key. I want the user to input string of any length, use it as the key to encrypt the message, then convert it to Base64. Example is in this site.
public static string EncryptDES(string phrase, string key)
{
string encrypted = "";
byte[] phraseBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(phrase);
byte[] keyBytes = System.Text.Encoding.UTF8.GetBytes(key);
System.Security.Cryptography.MD5CryptoServiceProvider hashMD5Provider
= new System.Security.Cryptography.MD5CryptoServiceProvider();
System.Security.Cryptography.DESCryptoServiceProvider provider
= new System.Security.Cryptography.DESCryptoServiceProvider();
provider.Mode = System.Security.Cryptography.CipherMode.CBC;
System.Security.Cryptography.ICryptoTransform transform
= provider.CreateEncryptor(keyBytes, keyBytes);
System.Security.Cryptography.CryptoStreamMode mode
= System.Security.Cryptography.CryptoStreamMode.Write;
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
System.Security.Cryptography.CryptoStream cryptoStream
= new System.Security.Cryptography.CryptoStream(memStream, transform, mode);
cryptoStream.Write(phraseBytes, 0, phraseBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] encryptedMessageBytes = new byte[memStream.Length];
memStream.Position = 0;
memStream.Read(encryptedMessageBytes, 0, encryptedMessageBytes.Length);
encrypted = System.Convert.ToBase64String(encryptedMessageBytes);
return (encrypted);
} // private static string EncryptDES(string phrase, string key) { }
Then call it like this in Main:
SimpleEncryption.EncryptDES("A message regarding some secure 512-bit encryption", "AnUltimatelyVeryVeryLongPassword");
When a user inputs a random number of string length (whether greater than or less than 8 characters), a cryptographic exception always happens in this line:
System.Security.Cryptography.ICryptoTransform transform = provider.CreateEncryptor(keyBytes, keyBytes);
It says Specified key is not a valid size for this algorithm.
Removing parts of the key to fit in the length of 8 characters (with or without hashing) doesn't seems to be a secure solution (there might be a high rate of collision).
How can I implement DES (not 3DES) with a user input string?
You need to generate a hash from the user's password and take only 8 bytes to use as your key.
var fullHash = hashMD5Provider.ComputeHash(System.Text.Encoding.ASCII.GetBytes(key));
var keyBytes = new byte[8];
Array.Copy(fullHash , keyBytes, 8);
Your question expressed concern about hash collisions from throwing away part of the hash; yes, that certainly does increase the risk, but (assuming your hash algorithm is good) you're no worse off than if you just used a hash algorithm that only produced 8 bytes to begin with. A good hash algorithm should distribute the entropy evenly.

How to encrypt a guid into equal length string in C#?

I need to encrypt a guid and the encrypted string length should be 32 char max, not more than that. Please suggest me an encryption method available in C# for that.
I was using AES in CFB mode, as in Code Project, but that is producing 64 char long.
Well, a GUID is inherently 16 bytes of data... so that's what you should encrypt. That's a single block in AES. As per Reid's comment, the exact size of the output will depend on how you've configured things, but to convert the result into text, you'll probably want to use base64 if you need ASCII text with a fairly minimal size.
Base64 allows you to use 24 bytes to produce a 32 character result - so you should try different padding/cipher modes until you find one where the output is 24 bytes or less, if this 32 character requirement is a "hard" one (and you need ASCII; if you don't need ASCII then there's a lot more room to play...)
If a GUID is 16 bytes (I'll take that as a given) then you can simply do a single AES ECB mode encrypt without padding of the plaintext (i.e. the GUID). You can then convert to hexadecimals. That will with 100% certainty result in a 32 character result.
Note that ECB does not use an IV, which means that you can distinguish different GUID's from each other (as each GUID will be mapped to exactly one ciphertext). But the ciphertext should otherwise simply be identical to the security of the used block cipher and key.
public class EncryptGUI
{
private Aes aes;
public EncryptGUI (byte[] key)
{
aes = Aes.Create ();
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.None;
aes.Key = key;
}
public String encryptUID (byte[] guid)
{
ICryptoTransform aesDecryptor = aes.CreateDecryptor ();
byte[] result = aesDecryptor.TransformFinalBlock (guid, 0, guid.Length);
return ToHex (result);
}
public static string ToHex (byte[] data)
{
StringBuilder hex = new StringBuilder (data.Length * 2);
foreach (byte b in data)
hex.AppendFormat ("{0:x2}", b);
return hex.ToString ();
}
public static void Main (string[] args)
{
byte[] key = new byte[16];
EncryptGUI main = new EncryptGUI (key);
byte[] guid = new byte[16];
Console.Out.WriteLine (main.encryptUID (guid));
}
}

How to retrieve IV from an Encrypted string, then decrypt that string using AES128

I know very little about Encryption, but my goal is to essentially decrypt strings. I have been given the AES(128) key.
However, I must retrieve the IV from the Encrypted string, which is the first 16 bits.
Heres the doc for salesforce for more information (if what i explained was incorrect)
Encrypts the blob clearText using the specified algorithm and private
key. Use this method when you want Salesforce to generate the
initialization vector for you. It is stored as the first 128 bits (16
bytes) of the encrypted blob
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_restful_crypto.htm (encryptWithManagedIV)
For Retrieving the IV I've tried something like this (I don't believe it's right though):
public string retrieveIv()
{
string iv = "";
string input = "bwZ6nKpBEsuAKM8lDTYH1Yl69KkHN1i3XehALbfgUqY=";
byte[] bytesToEncode = Encoding.UTF8.GetBytes(input);
for(int i = 0; i <= 15; i++){
iv += bytesToEncode[i].ToString(); ;
}
return iv;
}
(Just ignore the fact that the input is hardcoded and not parameterized; easier for testing purposes)
Then use the Best answer from this question to decrypt the string
The IV shouldn't be expressed as a string - it should be as a byte array, as per the AesManaged.IV property.
Also, using Encoding.UTF8 is almost certainly wrong. I suspect you want:
public static byte[] RetrieveIv(string encryptedBase64)
{
// We don't need to base64-decode everything... just 16 bytes-worth
encryptedBase64 = encryptedBase64.Substring(0, 24);
// This will be 18 bytes long (4 characters per 3 bytes)
byte[] encryptedBinary = Convert.FromBase64String(encryptedBase64);
byte[] iv = new byte[16];
Array.Copy(encryptedBinary, 0, iv, 0, 16);
return iv;
}

Categories

Resources