MembershipProvider.ValidateUser password encoding implementations - encryption

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

Related

Store data securely in memory (password based encryption)

I have to store the key into memory. So as security concern we can not store the cryptographic key into the memory directly, We need to store the key in Encrypted way. So the idea is we store the key in encrypted manner and at the time of crypto operation, just decrypt the key and use it and dispose the key.
So we are using Password based encryption(PBE) define in BouncyCastle c# version Example code.
The problem in code is that the password is fix here. I have to generate the password at run time.
Steps to Store the Key:
Generate password
Create temporary key to encrypt the key(secure data)
Save into memory
Steps to perform Crypto operation:
Generate password
Create temporary key to decrypt the key(secure data)
perform crypto operation
Dispose the key(secure data)
Here is an idea so the password can be never stored unencrypted outside local vars:
using System;
using System.Security;
using System.Security.Cryptography;
using System.Text;
private string _SecureKey;
public bool MemorizePassword { get; set; }
public string Password
{
get
{
if ( _Password.IsNullOrEmpty() ) return _Password;
var buf = Encoding.Default.GetBytes(_Password);
ProtectedMemory.Unprotect(buf, MemoryProtectionScope.SameProcess);
return Encoding.Default.GetString(Decrypt(buf, _SecureKey.ToString()));
}
set
{
if ( !MemorizePassword )
{
_Password = "";
return;
}
CreateSecureKey();
if ( value.IsNullOrEmpty() )
_Password = value;
else
{
var buf = Encrypt(Encoding.Default.GetBytes(value), _SecureKey.ToString());
ProtectedMemory.Protect(buf, MemoryProtectionScope.SameProcess);
_Password = Encoding.Default.GetString(buf);
}
}
}
private void CreateSecureKey()
{
_SecureKey = new SecureString();
foreach ( char c in Convert.ToBase64String(CreateCryptoKey(64)) )
_SecureKey.AppendChar(c);
_SecureKey.MakeReadOnly();
}
static public byte[] CreateCryptoKey(int length)
{
if ( length < 1 ) length = 1;
byte[] key = new byte[length];
new RNGCryptoServiceProvider().GetBytes(key);
return key;
}
static public byte[] Encrypt(byte[] data, string password)
{
return Encrypt(data, password, DefaultCryptoSalt);
}
static public byte[] Decrypt(byte[] data, string password)
{
return Decrypt(data, password, DefaultCryptoSalt);
}
static public string Encrypt(string str, string password, byte[] salt)
{
if ( str.IsNullOrEmpty() ) return str;
PasswordDeriveBytes p = new PasswordDeriveBytes(password, salt);
var s = Encrypt(Encoding.Default.GetBytes(str), p.GetBytes(32), p.GetBytes(16));
return Convert.ToBase64String(s);
}
static public string Decrypt(string str, string password, byte[] salt)
{
if ( str.IsNullOrEmpty() ) return str;
PasswordDeriveBytes p = new PasswordDeriveBytes(password, salt);
var s = Decrypt(Convert.FromBase64String(str), p.GetBytes(32), p.GetBytes(16));
return Encoding.Default.GetString(s);
}
static public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
if ( data == null ) return data;
using ( MemoryStream m = new MemoryStream() )
{
var r = Rijndael.Create().CreateEncryptor(key, iv);
using ( CryptoStream c = new CryptoStream(m, r, CryptoStreamMode.Write) )
c.Write(data, 0, data.Length);
return m.ToArray();
}
}
static public byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{
if ( data == null ) return data;
using ( MemoryStream m = new MemoryStream() )
{
var r = Rijndael.Create().CreateDecryptor(key, iv);
using ( CryptoStream c = new CryptoStream(m, r, CryptoStreamMode.Write) )
c.Write(data, 0, data.Length);
return m.ToArray();
}
}
Example of salt specific to your app (use any random value between 0 and 255):
byte[] DefaultCryptoSalt = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

AES 256 Encryption Decryption,

Decryption logic is missing something can you please assist.
Output is not completely decrypted.
Java Encryption Logic:
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException {
try {
String in ="This is a text message";
byte[] input = in.toString().getBytes("utf-8");
String ENCRYPTION_KEY = "RW50ZXIgS2V5IEhlcmU=";
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] thedigest = md.digest(ENCRYPTION_KEY.getBytes("UTF-8"));
// SecretKeySpec skc = new SecretKeySpec(thedigest, "AES/ECB/PKCS5Padding");
SecretKeySpec skc = new SecretKeySpec(thedigest, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skc);
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
ctLength += cipher.doFinal(cipherText, ctLength);
// String query = Base64.encodeToString(cipherText, Base64.DEFAULT);
String query = new String(java.util.Base64.getEncoder().encode(cipherText));
System.out.println("query " + query);
// String query = new String(encode(cipherText), StandardCharsets.ISO_8859_1);
} catch(UnsupportedEncodingException e) { // TODO Auto-generated catch block
e.printStackTrace();
}
}
Nodejs Decryption Logic:
let crypto = require('crypto');
var decipher = crypto.createDecipher('aes-256-ecb', "RW50ZXIgS2V5IEhlcmU=");
decipher.setAutoPadding(false);
console.log(decipher.update("EncyptedText", 'base64', 'utf8') + decipher.final('utf8'));

Ruby OpenSSL::Cipher::CipherError (key not set)

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 ?)

Encryption / decryption for j2me app with AES 128 encryption using sha256 hashing

I have to use encryption / decryption mechanism for a j2me application and lots of searching I found that Bouncy Castle is most suitable for j2me apps.
Below are the steps that I follow to perform encryption:
Get a string needed to create a hash key using sha256 algorithm;
With that hash key perform AES-128 encryption for a plain text.
Below is the sample code. It is using key and IV (Initialization Vector) for encryption key generation. Is it same as sha256 hashing?
static String strEnc = "String for encryption";
final static String strPassword = "2345678978787878"; // AES 128 -
String encrypted;
public static String strEncResult;
public static String strDcrResult;
public static String keyStr;
String dcrtpt;
String enc1;
//Key key;
/*public static byte[] getSHA256(String key) {
SHA256Digest digester = new SHA256Digest();
byte[] retValue = new byte[digester.getDigestSize()];
digester.update(key.getBytes(), 0, key.length());
digester.doFinal(retValue, 0);
System.out.println("retValue === "+retValue);
return retValue;
}*/
public static byte[] cipherData(PaddedBufferedBlockCipher cipher,
byte[] data) throws Exception {
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
int actualLength = length1 + length2;
byte[] result = new byte[actualLength];
System.arraycopy(outBuf, 0, result, 0, result.length);
return result;
}
public static byte[] decrypt(byte[] cipher, byte[] key, byte[] iv)
throws Exception {
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(
new CBCBlockCipher(new AESEngine()));
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key),
iv);
aes.init(false, ivAndKey);
return cipherData(aes, cipher);
}
public static byte[] encrypt(byte[] plain, byte[] key, byte[] iv)
throws Exception {
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(
new CBCBlockCipher(new AESEngine()));
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key),
iv);
aes.init(true, ivAndKey);
return cipherData(aes, plain);
}
public static String encryptMe(String plain){
byte[] plainStr = plain.getBytes();
byte[] keyStr = strPassword.getBytes();//getSHA256(strPassword);
byte[] ivStr = strPassword.getBytes();//getSHA256(strPassword);
try {
byte[] encBytes = encrypt(plainStr, keyStr,
ivStr);
byte[] encbase = Base64.encode(encBytes);
strEncResult = new String(encbase, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return strEncResult;
}
public static String decryptMe(String encrtptedStr){
try {
byte[] dcrByte = Base64.decode(encrtptedStr.getBytes());
byte[] dec = decrypt(dcrByte, strPassword.getBytes()/*getSHA256(strPassword)*/,
strPassword.getBytes()/*getSHA256(strPassword)*/);
strDcrResult = new String(dec, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return strDcrResult;
}
protected void destroyApp(boolean unconditional)
throws MIDletStateChangeException {
}
protected void pauseApp() {
}
protected void startApp() throws MIDletStateChangeException {
byte[] enc;
try {
enc = encrypt(strEnc.getBytes(), /*getSHA256(strPassword)*/strPassword.getBytes(),
/*getSHA256(strPassword)*/strPassword.getBytes());
byte[] encbase = Base64.encode(enc);
encrypted = new String(encbase, "UTF-8");
enc1= encryptMe ("String for encryption");
System.out.println("Encrypted is:" + encbase + "/// "+enc1);
} catch (Exception e) {
e.printStackTrace();
}
byte[] decbase = Base64.decode(encrypted.getBytes());
byte[] dec;
try {
dec = decrypt(decbase, /*getSHA256(strPassword)*/strPassword.getBytes(),
/*getSHA256(strPassword)*/strPassword.getBytes());
dcrtpt = decryptMe(enc1);
System.out.println("Decrypted file is:" + new String(dec, "UTF-8")+"///"+dcrtpt);
} catch (Exception e) {
e.printStackTrace();
}
}
i got it worked!!. i have used sha256 for secret key generation and took first 16 digit for AES 128 encryption. i am getting correct encrypted and decrypted data when it is 16 or below 16 string. if it is above 16 char string i am getting 16 char with some unwanted characters. (Eg: abcdefghijklmnop5#�D�!�&M�\~C��) can anybody help me to sort this issue. please see below for code
public static String getSHA256(String key) {
SHA256Digest digester = new SHA256Digest();
byte[] retValue = new byte[digester.getDigestSize()];
digester.update(key.getBytes(), 0, key.length());
digester.doFinal(retValue,0);
byteToStr = new String(Hex.encode(retValue));
System.out.println("byteToStr === " + byteToStr);
byteToStr = byteToStr.substring(0, 16);
System.out.println("byteToStr after subString === " + byteToStr);
return byteToStr;
}
public static byte[] cipherData(BufferedBlockCipher cipher, byte[] data)
throws Exception {
int minSize = cipher.getOutputSize(data.length);
System.out.println("min Size = "+minSize);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
System.out.println("length1 = "+length1 +"/ length2 = "+length2);
int actualLength = length1 + length2;
System.out.println("actualLength = "+actualLength);
byte[] result = new byte[actualLength];
System.arraycopy(outBuf, 0, result, 0, result.length);
return result;
}
public static byte[] decrypt(byte[] cipher, byte[] key/* , byte[] iv */)
throws Exception {
/*
* PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher( new
* CBCBlockCipher(new AESEngine())); CipherParameters ivAndKey = new
* ParametersWithIV(new KeyParameter(key), iv); aes.init(false,
* ivAndKey); return cipherData(aes, cipher);
*/
BufferedBlockCipher aes = new PaddedBufferedBlockCipher(
new CBCBlockCipher(new AESEngine()));
KeyParameter secretKey = new KeyParameter(key);
aes.init(false, secretKey);
return cipherData(aes, cipher);
}
public static byte[] encrypt(byte[] plain, byte[] key/* , byte[] iv */)
throws Exception {
/*
* PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher( new
* CBCBlockCipher(new AESEngine())); CipherParameters ivAndKey = new
* ParametersWithIV(new KeyParameter(key), iv);
*/
BufferedBlockCipher aes = new PaddedBufferedBlockCipher(
new CBCBlockCipher(new AESEngine()));
KeyParameter secretKey = new KeyParameter(key);
aes.init(true, secretKey);
return cipherData(aes, plain);
}
public static String encryptMe(String plain) {
byte[] plainStr = plain.getBytes();
byte[] keyStr = getSHA256(key).getBytes();
// byte[] ivStr = iv.getBytes();//
System.out.println("key str = "+Strings.fromByteArray(keyStr));
try {
byte[] encBytes = encrypt(plainStr, keyStr/*
* , ivStr
*/);
strEncResult= Base64.toBase64String(encBytes);
//strEncResult = new String(encbase);
} catch (Exception e) {
e.printStackTrace();
}
return strEncResult;
}
public static String decryptMe(String cipherText) {
try {
byte[] dcrByte = Base64.decode(cipherText);
byte[] dec = decrypt(dcrByte, getSHA256(key).getBytes()/*
* ,iv.getBytes
* ()
*/);
strDcrResult = Strings.fromByteArray(dec);
} catch (Exception e) {
e.printStackTrace();
}
return strDcrResult;
}

Datatype of encrypted password

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

Resources