How to implement hashing between Oracle, SQL Server, and ASP.NET - asp.net

I need to get some sensitive data from an Oracle server to a SQL Server for use in my ASP.NET website. Lets say its passwords. Our security guys say that these passwords need to be secured every step of the way. My website needs to be able to compare user input to these passwords. These passwords must be transferred from the Oracle server to SQL Server at night and can only be used on SQL Server during the day.
The best solution I can come up with is that we need to hash the passwords on Oracle and pass the hashes to SQL Server (lets assume the connection between the two is secure, because that's not my job :P ). Then my ASP.NET web application needs to be able to implement the exact same hashing on user input so we can compare the input hash to the database hash.
So my question is: how can I hash something using the same algorithm/key/salt on Oracle and .NET? I know how to use the .NET hashing functions, but I'm not sure what I can use in Oracle that would be comparable... I could potentially pass them in plain text from ASP.NET to SQL Server and hash them there if that's easier, but lets call that "Plan B".

Your datastore should be storing hashed values, on the asp.net side you'll need to implement an md5 function to convert strings to the hash, and then compare against the hashed value in your db.
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_obtool.htm#i1003449
Oracle does have the ability to use MD5 hash, which you can pass to SQL server and implement, as well as ASP.net.
SQL Server md5
http://www.lazerwire.com/2011/10/ms-sql-md5-hash.html
ASP.net MD5
public string CalculateMD5Hash(string input)
{
// step 1, calculate MD5 hash from input
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);
// step 2, convert byte array to hex string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
return sb.ToString();
}

Related

AES-256 best practices implementation

I'm reversing an app but I'm not very expert of the AES algorithm.
The application gives the user the opportunity to make an offline login.
The user is asked to provide his username and password
This is the function that is used to store the info of the user
public void EncryptLoginInfo(string username, byte[] secretShared, byte[] salt)
{
byte[] random = calc.GenerateRandomBytes();
byte[] array = aes.Encrypt(secretShared, random);
OfflineLogin loginInfo = new OfflineLogin()
{
Username = username,
SecretShared = array,
Iv = random,
Salt = salt
};
this._userCredentials.StoreOfflineLoginData(username, loginInfo);
}
And this are the info that are stored inside an internal config file of the app. In the example below, the password passed to the encryptLoginInfo is 123
Username: not_important
SecretShared: 4KVrjy1cQVWYpWF7aolpMS0HzhKyFf+9VXauQrXoXVUbf0bGXIDOLDJuSVhYoFo2
Iv:yil4nn02IoKsOnX5KXVsDg==
Salt: 5kJio2VQEqjomHRdQMqRVJ0zkBsmqi8K3NypC2VWJk4
If the user want to make an offline login, he is asked to provide username and his password.
Question: Is this algo safe? If an attacker is able to obtain SecretShared+Iv+Salt is he able to recover the password of the user (that in this specific example is 123)
This is the decrypt function
public void DencryptLoginInfo(OfflineLogin loginInfo)
{
byte[] array = aes.Decrypt(loginInfo.SecretShared, loginInfo.Iv);
loginInfo.SecretShared = array;
loginInfo.Iv = (byte[]) null;
}
Are you able to spot any security issues in this implementation? The algo used should be AES-256.. Are you able to implement a POC in python to decrypt the PASSWORD given SecretShared+Iv+Salt?
According to your comment, your goal is to authenticate the user. For that we use password base key derivation functions on the password. Often people refer to this as "hashing passwords", which is unfortunate terminology because "hashing" can mean anything. But the main point is that we do not encrypt passwords, instead we send them through a one-way function that is designed to be slow. The slow speed deters brute force attacks.
You do not need an IV to do this. Instead, your app should be deriving a salt and and using a password based key derivation function (sometimes referred to as a "password hashing" algorithm: you will have to excuse that the industry has made a mess out of the terminology on this topic). You can find guidance on this all over the web. But I suggest you have a read of point 4 in Top 10 Developer Crypto Mistakes to see common pitfalls in implementing this.
Don't use openssl to convert a password into a key (or password hash)! The algorithm in openssl is weak. Openssl's EVP_BytesToKey() fails to meet the requirements of slow speed, meaning that it is easy to brute force your key from your password.
The proper solution to this problem is to use an algorithm such as bcrypt or pbkdf2 (Java implementations can be found without much effort) to derive a "hash" from the password. You then verify that the user typed in the password correctly by re-doing the same computation with the user entered password and the salt that was stored for this password. If they match, access is granted, otherwise access is denied.
Note that if this app interacts with a server, normally you do password verification on the server side. If your app does not interact with a server, then you may have a good reason to do it on the device. I don't know what your app does, so I cannot tell you what is right or wrong for you.
A great reference for doing this properly is How to Safely Store Your Users' Passwords in 2016 .

Decrypt by key not working ASP.NET sql command

I have the following problem:
I have encrypted a column in my SQL Database by using a Symmetric Key. Now I have the encrypted value in the database and when I open the key and execute the query:
SELECT Convert(varchar, DECRYPTBYKEY(ColumnName)) as ClientSecret
FROM dbo.Sample
In Management Studio query editor it is ok and it returns the decrypted value.
But when I try to execute the same thing as a SqlCommand from my ASP.NET application it returns null.
Code:
string query = "SELECT Convert(varchar, DECRYPTBYKEY(ColumnName)) as ClientSecret FROM dbo.Sample";
var con = ConfigurationManager.ConnectionStrings["connectionName"].ConnectionString;
using (SqlConnection connection = new SqlConnection(con))
{
SqlCommand command = new SqlCommand(query, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
//the value of client secret here is null
var readerTest = reader["ClientSecret"];
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
My questions are the following:
First, why this does not work?
Second, is there a better way to decrypt the value of the column in the application (not by asking the server to do it) by using its encryption algorithm?
The only explanation that makes sense is that you already have the key open in SQL Server Management Studio since DecryptByKey requires the symmetric key to be open prior to decryption. To check which keys are open, execute the sql below just prior to selecting the data.
select * from sys.openkeys
If your intent is to combine opening the key with decrypting the data, then DECRYPTBYKEYAUTOCERT would be a good function to use. If you want to encrypt and decrypt data at the client instead of the server, you should look at SQL Server 2016 Always Encrypted. Be careful how it is configured because using deterministic encryption with a data set having low cardinality could result in the ability for a bad actor to create a hash table to indirectly decrypt the data. Also, generally clients are more prone to attack than servers.

How to encrypt data in sql server 2012 or sql server 2008 r2?

I want to encrypt the username and password both in sql tables . is it useful(if any method for data encryption in Sql Server) or i should apply for the Encryption and Decryption keys from front end.
till now i m using encryption and decryption from the front end using HttpUtility and base 64 method .
Column-level encryption (aka cell-level encryption) was introduced in SQL Server 2005 and is available in all editions of SQL Server, including the free SQL Server Express edition. To use cell-level encryption, the schema must be changed to varbinary, then reconverted to the desired data type. This means the application must be changed to support the encryption-decryption operation; in addition, it can affect performance. Encryption of the database occurs at the page level, but when those pages are read to buffer pool, they're decrypted. Data can be encrypted using a passphrase, an asymmetric key, a symmetric key, or a certificate. The supported algorithms for column-level encryption are AES with 128,196,256 bit keys and 3DES. To learn more about column-level encryption
For Information Please Read This article http://technet.microsoft.com/en-us/library/ms179331.aspx
You can use the PWDENCRYPT and PWDCOMPARE like # Paresh J in his comment during new user Insertion use PWDENCRYPT like
Declare #Uname Varchar(250)='User2'
Declare #Pwd Varchar(250)='password'
Declare #UserTbl Table
(
id int identity(1,1),
Uname Varbinary(250),
Pwd Varbinary(250)
)
Insert Into #UserTbl(Uname,Pwd)
select PWDENCRYPT(#Uname),PWDENCRYPT(#Pwd)
and during the login of that user use PWDCOMPARE like
Declare #UnameEncr Varbinary(max)
Declare #PwdEncrypt Varbinary(max)
Select #UnameEncr=Uname,#PwdEncrypt=Pwd from #UserTbl where id=1
Select LoginMessage=Case When PWDCOMPARE(#Uname,#UnameEncr)=1
and PWDCOMPARE(#Pwd,#PwdEncrypt)=1
Then 'Correct Username / Password'
else 'Incorrect Username / Password' end

Hashing using SHA1 as inner-most hash in a chain

A client program (over which I have no control) is authenticating by sending me a password, hashed as SHA1(password).
I'm reluctant to store the password hashed using only SHA1 in my database, so I'm proposing to store passwords in the database hashed as SHA256(SHA1(password)) (where the password is hashed over multiple iterations using PBKDF-2 or something similar).
My question is: is there anything insecure about the inner-most hash using SHA1 in this scenario? I realise that the probability of collisions will be increased, but since this is just for storing passwords in the database I don't think I need to be concerned about that. Is there anything else that I'm missing?
Consider adding a salt which is unique-per-row before doing the final encryption. Example:
Lets say that you receive W6ph5Mm5Pz8GgiULbPgzG37mj9g= (a SHA1'd encryption of "password"). That is associated with a User, who should have a unique key, such as a UserID and/or UserName.
My suggestion - to avoid collision - would be to do a conversion of the Bytes to a Base64String (in C# this would be Convert.ToBase64String( byteVariable ) - then concatenate onto the string the user's unique-ID (making the new string something like:
W6ph5Mm5Pz8GgiULbPgzG37mj9g=+103 (where I added +103 to reflect the user's ID) - then apply your SHA256 algorithm. This will produce: mNXRjWsKJ7V+BHbAuwJJ7neGT+V1IrLQSQXmb4Vv1X8= - which you can store in your database. A SHA256 hash - which eliminates the collisions from the less-safe SHA1 algorithm.
And - since you are using 1-way encryption - when you go to check whether the password is valid in the future, you simply append the user's ID again before checking.
If the client always sends you the same password, simply SHA1 hashed, then the SHA1 hash output is the password, to all intents and purposes. Treat it and store it the same way you would any other password, such as by using PBKDF2, SCrypt, or BCrypt.

Convert ASP.NET Membership Passwords from Encrypted to Hashed

I've developed a website that uses ASP.NET membership. Based on comments from previous sites, I decided to encrypt passwords so they could be recovered for users who forgot them.
However, the new site (which now has over 500 registered users) has brought me some criticism that the industry standard is really to hash passwords.
However, after a fairly extensive search, I have been unable to find anything about how to convert existing users' passwords from encrypted to hashed.
I know I can change the web.config file, and new users' passwords will use the new format. But it does nothing to update the existing users.
Note: I previously asked a similar question but mostly just got a debate about which is better, encrypted or hashed. I'm past that discussion but I've been unable to find a way to convert them without losing the hundreds of users already registered.
it seems you already know how to decrypt the passwords and change the web.config file, but you're stuck with how to implement the rest of the process.
using ILSpy, here's how to generate the salt for each user:
byte[] array = new byte[16];
new RNGCryptoServiceProvider().GetBytes(array);
return Convert.ToBase64String(array);
once you have the salt, here's how to generate the password:
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] array = Convert.FromBase64String(salt);
byte[] array2 = new byte[array.Length + bytes.Length];
Buffer.BlockCopy(array, 0, array2, 0, array.Length);
Buffer.BlockCopy(bytes, 0, array2, array.Length, bytes.Length);
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) {
return Convert.ToBase64String(sha1.ComputeHash(array2));
}
where pass is the plain-text password you calculated, and salt is the string calculated in the first code snippet above. the default algorithm is SHA1, if you're wondering why it's being used.
since this is a one-time process, i would write a HTTP handler to manually update the database during a short, scheduled maintenance period - hopefully you have that luxury. (obviously make a backup and test first). you need to update the following fields in the aspnet_Membership table:
Password - calculated above
PasswordFormat - 1
PasswordSalt - calculated above
never had to do anything like this, but hopefully that will get you started :)
IMHO, Greg's response (and the associated comments) on your previous question (Changing passwordFormat from Encrypted to Hashed) is the way to go. Essentially, you want to:
Add a hashed membership provider
Loop through all of the encrypted password users,
For each one decrypt the password, create the hash, store it, delete the encrypted version from the database, and move on.
When you are done, all of the encrypted password users should be converted to hashed.
Maybe I'm missing something here, but it should be pretty simple. Create a process to decrypt the password, then salt accordingly and store the hash of the salt + user's decrypted password in the database. Obviously you don't want to be hashing the user's encrypted password. Don't forget to store the salt too.

Resources