I am trying to use AesCryptoServiceProvider to achieve the same encryption mechanism as Aes.
Here is my AesCryptoServiceProvider version of it:
public string version1(string plainText, string encryptionKey, string initializationVector)
{
AesCryptoServiceProvider provider = new AesCryptoServiceProvider
{
BlockSize = 128,
Padding = PaddingMode.PKCS7,
Key = Convert.FromBase64String(encryptionKey),
IV = Encoding.UTF8.GetBytes(initializationVector)
};
byte[] buffer = Encoding.ASCII.GetBytes(plainText);
byte[] encrypted = provider.CreateEncryptor().TransformFinalBlock(buffer, 0, buffer.Length);
return Convert.ToBase64String(encrypted);
}
And here is the Aes version of it:
public string version2(string plainText, string encryptionKey, string initializationVector)
{
byte[] clearBytes = Encoding.UTF8.GetBytes(plainText);
byte[] encryptedBytes;
byte[] iv = Encoding.UTF8.GetBytes(initializationVector);
using (Aes aes = Aes.Create())
{
aes.BlockSize = 128;
aes.Padding = PaddingMode.PKCS7;
aes.Key = Convert.FromBase64String(encryptionKey);
aes.IV = iv;
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
encryptedBytes = ms.ToArray();
}
}
byte[] ivEncryptedBytes = new byte[iv.Length + encryptedBytes.Length];
Buffer.BlockCopy(iv, 0, ivEncryptedBytes, 0, iv.Length);
Buffer.BlockCopy(encryptedBytes, 0, ivEncryptedBytes, iv.Length, encryptedBytes.Length);
return Convert.ToBase64String(ivEncryptedBytes);
}
When I encrypt the same string using version1 and version2 they came out to be different. Any idea on how these two methods are different and how I can make version1 produces the same encrypted string as version2? (p.s. I am rather new to encryption so sorry if the answer is obvious) Thanks!
As #MichaelFehr pointed out, version2 only has the initialization vector and the encrypted bytes concatenated together before converting the bytes back to string. I have tested that if I concatenate the string the same way as version2 in version1, the result string will become the same.
Related
With an AES key that I retrieve from a Key Vault I'm trying to decrypt a blob file. But I keep getting:
System.Security.Cryptography.CryptographicException: Specified key is
not a valid size for this
I'm trying to reverse engineer a python decrypt situation and this suggests to me that the value I'm retrieving from the key vault is a hex string or at least should be stored as hexstrings in a bytearray.
Python:
aes_key= bytes.fromhex(aes_key)
So because I get it from my configuration with var keyStringValue = _configuration.GetValue<string>("the-key-i-want"); I first convert to a bytearray to be able to convert it to hexstring. And then put it in a bytearray again.
//Where I convert my Keyvault keyStringValue to a hexString encoded bytearray
byte[] tempBytes = utf8.GetBytes(keyStringValue);
var hexString = BitConverter.ToString(tempBytes);
hexString = hexString.Replace("-", "").ToLower();
int NumberChars = hexString.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
byte[] pass = bytes;
I pass the pass variable to my decrypt function which looks like this:
var crypto = new AesCryptographyService();
var decryptedData = crypto.Decrypt(postSplitByteArray, pass, iv)
And finally my decrypt:
public class AesCryptographyService
{ public byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{
using var aes = Aes.Create();
aes.Padding = PaddingMode.Zeros;
aes.Mode = CipherMode.CBC;
aes.Key = key;
aes.IV = iv;
using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
{
return PerformCryptography(data, decryptor);
}
}
private byte[] PerformCryptography(byte[] data, ICryptoTransform cryptoTransform)
{
using (var ms = new MemoryStream())
using (var cryptoStream = new CryptoStream(ms, cryptoTransform, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
return ms.ToArray();
}
}
The hexstring is 128 characters long. And the resultant bytearray 64. Now I know that the array should only be 32 bytes big. But I can't see the point of just cutting my key to size. Nor do I get a properly decrypted result. This bugs me since the python function seems to be doing the same as I am.
cipher = AES.new(aes256_key, AES.MODE_CBC, iv)
decrypted_data = cipher.decrypt(encrypted_data).decode('utf-8')
PS. I verified with an online converter that the conversion from string to hexstring is going well.
The solution was to not first convert my string into a bytearray and then do a hexstring conversion.
The string in the keyvault was already a "hexstring"
So getting rid of this.
byte[] tempBytes = utf8.GetBytes(keyStringValue);
var hexString = BitConverter.ToString(tempBytes);
hexString = hexString.Replace("-", "").ToLower();
And from
var keyStringValue = _configuration.GetValue<string>("the-key-i-want")
pass that to the hexstring conversion
private static byte[] FromHex(string keyStringValue)
{
int NumberChars = keyStringValue.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(keyStringValue.Substring(i, 2), 16);
return bytes;
}
And Bob is your uncle.
I am trying to port an existing .net encryption code to ruby. But stuck with the key not set error.
Bellow is the .net code to encrypt a string.
private static string Encrypt(string strToEncrypt, string saltValue, string password)
{
using (var csp = new AesCryptoServiceProvider())
{
ICryptoTransform e = GetCryptoTransform(csp, true, saltValue, password);
byte[] inputBuffer = Encoding.UTF8.GetBytes(strToEncrypt);
byte[] output = e.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
string encrypted = Convert.ToBase64String(output);
return encrypted;
}
}
private static ICryptoTransform GetCryptoTransform(AesCryptoServiceProvider csp, bool encrypting, string saltValue, string password)
{
csp.Mode = CipherMode.CBC;
csp.Padding = PaddingMode.PKCS7;
var passWord = password;
var salt = saltValue;
//a random Init. Vector. just for testing
String iv = "e675f725e675f123";
var spec = new Rfc2898DeriveBytes(Encoding.UTF8.GetBytes(passWord), Encoding.UTF8.GetBytes(salt), 1000);
byte[] key = spec.GetBytes(16);
csp.IV = Encoding.UTF8.GetBytes(iv);
csp.Key = key;
if (encrypting)
{
return csp.CreateEncryptor();
}
return csp.CreateDecryptor();
}
I have used Ruby's OpenSSL::PKCS5 library to generate key and OpenSSL::Cipher to encrypt using AES algorithm like bellow.
def aes_encrypt(input_string)
cipher = OpenSSL::Cipher.new('AES-128-CBC')
cipher.encrypt
key = encryption_key
iv = cipher.random_iv
cipher.update(input_string) + cipher.final
end
def encryption_key
OpenSSL::PKCS5.pbkdf2_hmac_sha1(PASSWORD, SALT, 1000, 16)
end
Can anyone let know where I am missing? (Padding ?)
I want to encrypt my password and store to my DB, SQL Server 2008 R2.
For that I took the password from text box and encrypted using proper function and want to store in back end.
Tell me which datatype I have to use for encrypted password column.
Namespace:
using System.Security.Cryptography;
Encrypt Function:
public static string Encrypt(string Message)
{
string Password = Message;
byte[] Results;
System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Password));
TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
TDESAlgorithm.Key = TDESKey;
TDESAlgorithm.Mode = CipherMode.ECB;
TDESAlgorithm.Padding = PaddingMode.PKCS7;
byte[] DataToEncrypt = UTF8.GetBytes(Message);
try
{
ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
}
finally
{
TDESAlgorithm.Clear();
HashProvider.Clear();
}
return Convert.ToBase64String(Results);
}
Decrypt Function:
public static string Decrypt(string Message)
{
string Password = Message;
byte[] Results;
System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Password));
TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
TDESAlgorithm.Key = TDESKey;
TDESAlgorithm.Mode = CipherMode.ECB;
TDESAlgorithm.Padding = PaddingMode.PKCS7;
byte[] DataToDecrypt = Convert.FromBase64String(Message);
try
{
ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
}
finally
{
TDESAlgorithm.Clear();
HashProvider.Clear();
}
return UTF8.GetString(Results);
}
How to use??
For Encrypt:
string encryptpassword=Encrypt(txtPassword.Text.Trim());
For Decrypt:
string decryptpassword=Decrypt(txtPassword.Text.Trim());
NOTE : txtPassword is a textbox where you can enter a password
I want to encrypt mail id. The encrypted mail id should not contain special characters.
I send mail from console app. In console app I encode the mail id and attach it in link that will perform my click counts. In the web app I am decoding the mail id passed. So if encrypted mail id contains special character it is disturbing my link.
I am using following:
string EncryptedEmailId;
string EncryptionKey = "MAKV2SPBNI99212";
byte[] EmailIdEncrypt = Encoding.Unicode.GetBytes(InvEmail);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdbEncrypt = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdbEncrypt.GetBytes(32);
encryptor.IV = pdbEncrypt.GetBytes(16);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
csEncrypt.Write(EmailIdEncrypt, 0, EmailIdEncrypt.Length);
csEncrypt.Close();
}
EncryptedEmailId = Convert.ToBase64String(msEncrypt.ToArray());
}
}
individualContent = individualContent.Replace("[MailId]", EncryptedEmailId);
With the hint given by Nipun I got the answer.
a) Convert String to Hex
public static string ConvertStringToHex(String input, System.Text.Encoding encoding)
{
Byte[] stringBytes = encoding.GetBytes(input);
StringBuilder sbBytes = new StringBuilder(stringBytes.Length * 2);
foreach (byte b in stringBytes)
{
sbBytes.AppendFormat("{0:X2}", b);
}
return sbBytes.ToString();
}
b) Convert Hex to String
public static string ConvertHexToString(String hexInput, System.Text.Encoding encoding)
{
int numberChars = hexInput.Length;
byte[] bytes = new byte[numberChars / 2];
for (int i = 0; i < numberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(hexInput.Substring(i, 2), 16);
}
return encoding.GetString(bytes);
}
Sample usage code
string testString = "MIKA#?&^";
string hex = ConvertStringToHex(testString, System.Text.Encoding.Unicode);
string normal = ConvertHexToString(hex, System.Text.Encoding.Unicode);
Debug.Assert(testString.CompareTo(normal) == 0, "They are not identical");
Have a look at: http://www.nullskull.com/faq/834/convert-string-to-hex-and-hex-to-string-in-net.aspx
You will need to try different Algo for the same
Try anyof the below methods and see if it works for you?
This won't be working you as you are using Console App, but can try other one.
string EncryptedText = FormsAuthentication.HashPasswordForStoringInConfigFile("YourPlainText", "MD5");
Or, you may use the following encryption and decryption algorithm:
using System.IO;
using System.Text;
using System.Security.Cryptography;
/// <summary>
/// Summary description for Pass
/// </summary>
public class CryptoSystem
{
public string plainText;
public string passPhrase = "Pas5pr#se";
public string saltValue = "s#1tValue";
public string hashAlgorithm = "MD5";
public int passwordIterations = 2;
public string initVector = "#1B2c3D4e5F6g7H8";
public int keySize = 256;
public string Encrypt(string plainText)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);
byte[] keyBytes = password.GetBytes(keySize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
string cipherText = Convert.ToBase64String(cipherTextBytes);
return cipherText;
}
public string Decrypt(string cipherText)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);
byte[] keyBytes = password.GetBytes(keySize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
string plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
return plainText;
}
}
Try out Hexadecimal as well
http://www.string-functions.com/string-hex.aspx
To code follow this link
Convert string to hex-string in C#
byte[] ba = Encoding.Default.GetBytes("sample");
var hexString = BitConverter.ToString(ba);
I'm implementing the ValidateUser method on a custom MembershipProvider class. I've seen quite a few examples of this, I'm looking for some guidance on how to properly encode/hash/encrypt my passwords. I'm no crypto expert, and I'm a little anxious about straying from the default implementation. Should I just copy the relevant source code from the SqlMembershipProvider or will any of these work?
http://mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx
public override bool ValidateUser(string username, string password)
{
if(string.IsNullOrEmpty(password.Trim())) return false;
string hash = EncryptPassword(password);
User user = _repository.GetByUserName(username);
if (user == null) return false;
if (user.Password == hash)
{
User = user;
return true;
}
return false;
}
protected string EncryptPassword(string password)
{
// Produses an MD5 hash string of the password
//we use codepage 1252 because that is what sql server uses
byte[] pwdBytes = Encoding.GetEncoding(1252).GetBytes(password);
byte[] hashBytes = System.Security.Cryptography.MD5.Create().ComputeHash(pwdBytes);
return Encoding.GetEncoding(1252).GetString(hashBytes);
}
ASP.NET membership salt?
public string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Encoding.Unicode.GetBytes(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
ASP.NET membership salt?
private const int ITERATIONS = 10000;
private const int SALT_SIZE = 32;
private const int HASH_SIZE = 32;
public void SaltAndHashPassword(string password, out byte[] salt, out byte[] hash)
{
Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(password, SALT_SIZE, ITERATIONS);
salt = rdb.Salt;
hash = rdb.GetBytes(HASH_SIZE);
}
ASP.NET membership salt?
internal string GenerateSalt()
{
byte[] buf = new byte[16];
(new RNGCryptoServiceProvider()).GetBytes(buf);
return Convert.ToBase64String(buf);
}
internal string EncodePassword(string pass, int passwordFormat, string salt)
{
if (passwordFormat == 0) // MembershipPasswordFormat.Clear
return pass;
byte[] bIn = Encoding.Unicode.GetBytes(pass);
byte[] bSalt = Convert.FromBase64String(salt);
byte[] bAll = new byte[bSalt.Length + bIn.Length];
byte[] bRet = null;
Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
if (passwordFormat == 1)
{ // MembershipPasswordFormat.Hashed
HashAlgorithm s = HashAlgorithm.Create("SHA1");
// Hardcoded "SHA1" instead of Membership.HashAlgorithmType
bRet = s.ComputeHash(bAll);
}
else
{
bRet = EncryptPassword(bAll);
}
return Convert.ToBase64String(bRet);
}
Download BCrypt.Net. As opposed to typica SHA hashing, which is too fast making anything encrypted with it easy to brute force. BCrypt is slower due to a configurable work factor, so whilst imperceptable to the user, when trying to brute force 700m keys a second, you simply can't.
Once you have bcrypt all you need to do to hash is:
...
private static readonly int BCRYPT_WORK_FACTOR = 10;
string hashedPassword = BCrypt.Net.BCrypt.HashPassword(account.HashedPassword, BCRYPT_WORK_FACTOR);
...
and to check a password:
bool matched = BCrypt.Net.BCrypt.Verify(password, match.HashedPassword))
More info here: http://www.danharman.net/2011/06/25/encrypting-hashing-passwords-for-your-website/
I use next:
var salt = Encoding.UTF8.GetBytes(this.Name);
var bytes = Encoding.UTF8.GetBytes(password);
return Convert.ToBase64String(new HMACSHA1(salt).ComputeHash(bytes));