I am currently converting a legacy ASP.NET 1.1 application into a .NET 4 MVC 3 application.
I am looking at the password encryption and a routine was written in the old code to use the MD5CryptoServiceProvider.
private string EncryptText(string szText)
{
try
{
UTF8Encoding objEncoder = new UTF8Encoding();
MD5CryptoServiceProvider objMD5Hasher = new MD5CryptoServiceProvider();
Byte[] btHashedDataBytes = objMD5Hasher.ComputeHash(objEncoder.GetBytes(szText));
string szReturn = objEncoder.GetString(btHashedDataBytes);
objEncoder = null;
objMD5Hasher = null;
return szReturn;
}
catch
{
return "";
}
}
I have written a quick .NET 4 console application and copied this function so I can do a comparison against the current passwords in the database (to make sure the MD5 function still gives me the same output)
string encTxt = encryptor.EncryptText("fbloggsPass12345");
using (SqlConnection conn = new SqlConnection("Server=server;Database=db;User Id=sa;Password=1111;"))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "UPDATE SiteUsers SET Token = '" + encTxt + "' WHERE PKey = 10";
if (cmd.ExecuteNonQuery() > 0)
Console.WriteLine("Updated");
else
Console.WriteLine("Failed");
}
conn.Close();
}
Console.ReadLine();
However the password in the database is currently !?MGF+&> and the output I am getting is ���!?��MGF�+&��> which when I store in the database converts to ???!???MGF?+&??>
Which I can see is almost the same, but why am I getting the ? characters
This is the first problem, at least:
string szReturn = objEncoder.GetString(btHashedDataBytes);
You're trying to use the hash as if it were UTF-8-encoded text. It's not - it's just arbitrary binary data.
If you need to convert arbitrary binary data to text, you should use something like Base64 (e.g. Convert.ToBase64String) or hex.
(Additionally, I would strongly advise you not to "handle" exceptions in the way you're doing so at the moment. Why would you want to hide problems like that? And why are you setting variables to null just before they go out of scope anyway?)
Oh, and please don't include values directly in your SQL like that - use parameterized SQL instead.
Finally, I would use a different hashing algorithm these days, particularly for passwords. Can you not use an off-the-shelf system for authentication, which is actually developed by security experts? Security is difficult: we'd all be better off leaving it to the relatively few people who know how to do it right :) See comments for more suggestions.
The standard technique for low impact upgrading is using the old hash as input for the new hashing scheme. This works pretty well with normal MD5 hashes.
Unfortunately for you, you were sending the binary hash through a non binary safe encoding (UTF8). This replaced every second character by 0xFFFD, effectively halving the output size to 64 bits. This weakens an upgraded scheme considerably but not fatally.
I'd upgrade the existing hashes to PBKDF2(legacyHash, salt), then on user login replace the hash with a new hash PBKDF2(password, salt) that doesn't depend on the legacy scheme. After a few months trigger a password reset for all users who did not login yet, getting rid of the legacy hash based passwords.
For the new scheme, I'd go with PBKDF2-SHA-1 which is implemented in the Rfc2898DeriveBytes Class. Use sufficient iterations, at least 10000.
Related
I have to face a new little project. It will have about 7 or 9 tables, the biggest of them will grow by a max rate of 1000 rows a month.
I thought about SQLite as my db... But i will need to protect the db in case anybody wants to change data from the db
My main question is:
Is it possible password protect a sqlite db as you would do on access?
The development would be on C#, but I'm searching something free.
You can password protect a SQLite3 DB. Before doing any operations, set the password as follows.
SQLiteConnection conn = new SQLiteConnection("Data Source=MyDatabase.sqlite;Version=3;");
conn.SetPassword("password");
conn.Open();
then next time you can access it like
conn = new SQLiteConnection("Data Source=MyDatabase.sqlite;Version=3;Password=password;");
conn.Open();
This wont allow any GUI editor to view your data. Some editors can decrypt the DB if you provide the password. The algorithm used is RSA.
Later if you wish to change the password, use
conn.ChangePassword("new_password");
To reset or remove password, use
conn.ChangePassword(String.Empty);
You can use the built-in encryption of the sqlite .net provider (System.Data.SQLite). See more details at http://web.archive.org/web/20070813071554/http://sqlite.phxsoftware.com/forums/t/130.aspx
To encrypt an existing unencrypted database, or to change the password of an encrypted database, open the database and then use the ChangePassword() function of SQLiteConnection:
// Opens an unencrypted database
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3");
cnn.Open();
// Encrypts the database. The connection remains valid and usable afterwards.
cnn.ChangePassword("mypassword");
To decrypt an existing encrypted database call ChangePassword() with a NULL or "" password:
// Opens an encrypted database
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3;Password=mypassword");
cnn.Open();
// Removes the encryption on an encrypted database.
cnn.ChangePassword(null);
To open an existing encrypted database, or to create a new encrypted database, specify a password in the ConnectionString as shown in the previous example, or call the SetPassword() function before opening a new SQLiteConnection. Passwords specified in the ConnectionString must be cleartext, but passwords supplied in the SetPassword() function may be binary byte arrays.
// Opens an encrypted database by calling SetPassword()
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3");
cnn.SetPassword(new byte[] { 0xFF, 0xEE, 0xDD, 0x10, 0x20, 0x30 });
cnn.Open();
// The connection is now usable
By default, the ATTACH keyword will use the same encryption key as the main database when attaching another database file to an existing connection. To change this behavior, you use the KEY modifier as follows:
If you are attaching an encrypted database using a cleartext password:
// Attach to a database using a different key than the main database
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3");
cnn.Open();
cmd = new SQLiteCommand("ATTACH DATABASE 'c:\\pwd.db3' AS [Protected] KEY 'mypassword'", cnn);
cmd.ExecuteNonQuery();
To attach an encrypted database using a binary password:
// Attach to a database encrypted with a binary key
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3");
cnn.Open();
cmd = new SQLiteCommand("ATTACH DATABASE 'c:\\pwd.db3' AS [Protected] KEY X'FFEEDD102030'", cnn);
cmd.ExecuteNonQuery();
Use SQLCipher, it's an opensource extension for SQLite that provides transparent 256-bit AES encryption of database files. http://sqlcipher.net
You can encrypt your SQLite database with the SEE addon. This way you prevent unauthorized access/modification.
Quoting SQLite documentation:
The SQLite Encryption Extension (SEE) is an enhanced version of SQLite that encrypts database files using 128-bit or 256-Bit AES to help prevent unauthorized access or modification. The entire database file is encrypted so that to an outside observer, the database file appears to contain white noise. There is nothing that identifies the file as an SQLite database.
You can find more info about this addon in this link.
One option would be VistaDB. They allow databases (or even tables) to be password protected (and optionally encrypted).
If you use FluentNHibernate you can use following configuration code:
private ISessionFactory createSessionFactory()
{
return Fluently.Configure()
.Database(SQLiteConfiguration.Standard.UsingFileWithPassword(filename, password))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<DBManager>())
.ExposeConfiguration(this.buildSchema)
.BuildSessionFactory();
}
private void buildSchema(Configuration config)
{
if (filename_not_exists == true)
{
new SchemaExport(config).Create(false, true);
}
}
Method UsingFileWithPassword(filename, password) encrypts a database file and sets password.
It runs only if the new database file is created. The old one not encrypted fails when is opened with this method.
I know this is an old question but wouldn't the simple solution be to just protect the file at the OS level? Just prevent the users from accessing the file and then they shouldn't be able to touch it. This is just a guess and I'm not sure if this is an ideal solution.
Why do you need to encrypt the database? The user could easily disassemble your program and figure out the key. If you're encrypting it for network transfer, then consider using PGP instead of squeezing an encryption layer into a database layer.
I'm using ASP.NET Core 3.1, with some custom logic that reuses ASP.NET Core Identity's UserManager<TUser> class. I want to reuse its ability to GenerateUserTokenAsync(...), the same type of token also used in e.g. e-mail confirmations. For my application's purpose, I need to know the maximum length for generated tokens.
I've done the following research:
UserManager<TUser>.GenerateUserTokenAsync(...) calls GenerateAsync on the injected provider
in my case that is the DataProtectorTokenProvider<TUser> which will generate tokens like this:
var ms = new MemoryStream();
var userId = await manager.GetUserIdAsync(user);
using (var writer = ms.CreateWriter())
{
writer.Write(DateTimeOffset.UtcNow);
writer.Write(userId);
writer.Write(purpose ?? "");
string stamp = null;
if (manager.SupportsUserSecurityStamp)
{
stamp = await manager.GetSecurityStampAsync(user);
}
writer.Write(stamp ?? "");
}
var protectedBytes = Protector.Protect(ms.ToArray());
return Convert.ToBase64String(protectedBytes);
So the basic calculation for length of the memory stream would be:
27 characters for DateTimeOffset.UtcNow
36 characters for the user id (string representation of a GUID)
20 characters for my specific "purpose" string
36 characters for the security stamp (string representation of a GUID)
---- +
119 characters in total
In the code snippet this gets Protected and then converted ToBase64String
When I casually tested this on my local machine, I got an encrypted string of 352 characters. How could I predict that the 119 input characters would become 352 characters when encrypted? And worse, my app runs actually in production on an Azure App Service where Azure's DPAPI should kick in, possibly with different encryption than on localhost?
Can I in any way predict what the maximum length of the generated User Tokens will be on Azure App Services? I'm happy to include a margin of error, but am clueless what that would need to be.
By default DPAPI uses AES-256-CBC as encryption algorithm unless you change it via UseCryptographicAlgorithms. As per default algo, the calculation would go like this for your case:
Since it's AES 256, it would work with 32 bytes block. So with CBC padding, you output becomes ((119/32) + 1) * 32 + 16 (IV) = 144. After base64, it becomes 192.
So, having it 352 brings up the question is the stamp really 36 in your case?
36 characters for the security stamp (string representation of a GUID)
Also, in deployed environment, make sure to store data protection key outside app since each instance of the app service needs to point to the same key.
I am not sure if I can decrypt passwords with c#, that i stored in a mysql database. I encrypted these passwords in php using PASSWORD_BCRYPT.
And if it is possible how can I do it? Sorry but i'm a beginner and I didn't find any help on the internet. This is the piece of code I used to encrypt my passwords.
$passwort = $con->real_escape_string($_POST['passwort']);
$hash = password_hash($passwort, PASSWORD_BCRYPT);
After reading the comments I tried doing so in c# but it always says wrong password
string email = textBox1.Text;
string password = textBox2.Text;
string passwordHash = BCrypt.Net.BCrypt.HashPassword(password);
MessageBox.Show(passwordHash);
MySqlConnection conn = new MySqlConnection("datasource=127.0.0.1;port=3306;username=root;password=CIAO6CIAO6;database=kontoprogramm");
int i = 0;
conn.Open();
MySqlCommand cmd = new MySqlCommand("select KLPPassword from tklassenlehrpersonen where KLPEmail = '" + email + "' and KLPPassword = '" + passwordHash + "'", conn);
cmd.ExecuteNonQuery();
DataTable dt = new DataTable();
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(dt);
i = Convert.ToInt32(dt.Rows.Count.ToString());
if (i == 0)
{
MessageBox.Show("Falsche Email oder Kennwort!");
}
else
{
MessageBox.Show("Angemeldet!");
}
Can somebody please help me?
You cannot search for a hash in the database, because of the salt, instead search by username only and take the stored hash for verification. This answer shows how to do it in PHP, though the principle is the same.
And don't escape the user input before calling password_hash() this calls for trouble.
First of all, you cannot decrypt, only if you effort to troubleshooting and hack the password decryption, for example, using Brute Force technique etc, because finally result from PHP by password_hash function is generates a hashed password, hash result. By the hash primary concept, cannot be reversible, but been comparable.
You may compare password hashs using PHP function password_verify (comparing stored hash from database with the inputed password from your C# Application). If your requirement is really decrypt, it's need to change the focus of your post, re-think to troubleshooting and hack the password decryption, for example, using Brute Force technique etc.
Now, let's go to solution: you have two ways:
a) Create an PHP WebService parameterized with the "Clear Text" as input parameter, and get the output result as a encrypted text password; the core of Web Service (in PHP) uses the password_hash with PASSWORD_BCRYPT option, to encrypt. After, your C# code consumes the encrypted data and compare this output hash with stored hash from Database; however, this alternative needs to invest many efforts in security at WebServer and WebService layers. For example, your C# code consuming this PHP Web Service as code bellow:
WebClient webclient = new WebClient();
webclient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webclient_DownloadStringCompleted);
webclient.DownloadStringAsync(new Uri("http://ws.phpurl.com/?password=stackoverflow#12345"));
void webclient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
string phpWsEncryptedPass = e.Result;
string databaseEncryptedPass = //TO DO: query Database
//using WHERE statement,
//parsing 'phpWsEncryptedPass' as parameter;
}
b) OR, download the binaries of the respective PHP version for Windows that you work'on, understand these DLLs methods using a DLL Reflector application (for example dotPeek) and use C# Interop features to import the DLL thta have the password_hash and password_verify to consume this in your C# code; you need to make efforts to open the DLL, to get the correctly methods declaration. Note: this way is suggest because the Core of PHP writted in C/C++ and a C# code can be consume the DLL of PHP for Windows binaries, this code bellow has an example to do this:
[DllImport(#"C:\ProgramFiles\PHP\php_mbstring.dll", CharSet = CharSet.Unicode)]
internal static extern IntPtr password_hash(string clearTextpassword, int option)
[DllImport(#"C:\ProgramFiles\PHP\php_mbstring.dll", CharSet = CharSet.Unicode)]
internal static extern bool password_verify(string clearTextpassword, string hash)
That's all.
I trying to Decrypt password in visual studio 2010 using C-Sharp language but i m stuck on this error i try all the solution which was provided on this side but my error not resolved how i encrypt password can anybody tell me using MD5 my code is,Now it gives another error "String reference not set to an instance of a String.*Parameter name: s" What can i do i cant understand .I m newbie on C#*.I dont know what can i do if i waste your time then sorry to all.
public string PasswordDecrypt(string sQueryString)
{
byte[] buffer;
TripleDESCryptoServiceProvider loCryptoClass = new
TripleDESCryptoServiceProvider();
MD5CryptoServiceProvider loCryptoProvider = new MD5CryptoServiceProvider();
try
{
buffer = Convert.FromBase64String(sQueryString);
loCryptoClass.Key = loCryptoProvider.ComputeHash(ASCIIEncoding.ASCII.GetBytes(sQueryString));
loCryptoClass.IV = lbtVector;
return ASCIIEncoding.ASCII.GetString(loCryptoClass.CreateDecryptor().TransformFinalBlock(buffer, 0, buffer.Length));
}
catch (Exception ex)
{
throw ex;
}
finally
{
loCryptoClass.Clear();
loCryptoProvider.Clear();
loCryptoClass = null;
loCryptoProvider = null;
}
}
The code relevant to your question is this:
string sQueryString = txtPassword.Text;
byte[] buffer = Convert.FromBase64String(sQueryString);
Create a test case for this, containing the data as is entered when you get the error. Perhaps your users don't input their password as base64.
I think you are confused about what to do for password security. Passwords don't get encrypted, they get hashed. That's kind of a one-way-encryption. The same password will always result in the same hash, but different passwords are allowed to generate the same hash, so it's impossible to decrypt it from hash to password.
While that doesn't sound useful at first, the point is that you never actually store the password, encrypted or not. You store the hash value of the password. That way you know when someone enters a password, it gets hashed and matches the stored hash, it's the correct password... without ever knowing what the password was.
So you cannot decrypt a hash. You simply hash your input and compare with an earlier hash from the correct password.
Please note that you should also google Salting hashes, a technique for lowering the attack surface of hashes once the data store was breached and the hash is known to potential attackers.
I'm developing an ASP.NET MVC application in which I want to encrypt a short string on the server, using C#, and send it to the client-side.
Then on the client-side it will be decrypted through Javascript code.
Any thoughts on how to implement this?
Do you know of a simple encryption algorithm (doesn't have to be bullet-proof secure) that can be easily translated from C# to Javascript or vice-versa?
NOTE: I could do this entirely in C# and do the decryption through Ajax, but I'd prefer not to do it this way, as I want to reduce website traffic as much as possible.
What about a simple XOR Cipher?
These two implementations are fully compatible:
Simple XOR Encryption (C#)
JavaScript XOR Encryption
It sounds like you want an obfuscation or encoding, not encryption. Base64 encoding should work well here. The result will look nothing like an email address, and the encoding process is fast.
In C#, you can use:
string emailAddress = "abc#example.com";
string encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(emailAddress));
And you can use this JavaScript function to decode it:
function Base64Decode(encoded) {
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
do {
enc1 = keyStr.indexOf(encoded.charAt(i++));
enc2 = keyStr.indexOf(encoded.charAt(i++));
enc3 = keyStr.indexOf(encoded.charAt(i++));
enc4 = keyStr.indexOf(encoded.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
} while (i < encoded.length);
return output;
}
The C# application encodes the string abc#example.com into YWJjQGV4YW1wbGUuY29t, and the JavaScript version will decode YWJjQGV4YW1wbGUuY29t back into abc#example.com.
The System.Security.Cryptography has a bunch of symetric (and asymetric) encrytion algorithms ready to use. (For something super secure use aes)
You should be able to find matching Javascript implementation for most (here are a few aes implementations in JS)
http://www.movable-type.co.uk/scripts/aes.html
http://www.hanewin.net/encrypt/aes/aes.htm
Note: If you are planning to use private key based encryption then keep in mind, your web page is going to have the key embedded in it and that means that it all becomes kind of pointless cause anyone with access to the page can do the decryption, at best you would be making the life of the screen scrapers a little bit harder. If making screen scrapers life harder is your goal you could just use an obsfucation algorithm. Any trivial implementation would make very impractical for screen scrapers that do not have a javascript engine:
Eg.
function samObsfucated()
{
return("s" + "a" + "m" + "#" + "s" + "." + "com");
}
Then onload populate your email fields with the output of these functions.
Javascript encryption has a really good use case for software that stores passwords for users ala clipperz
In terms of the simplest thing that could possibly work, it seems that you want a simple form of obfuscation, rather than anything really secure.
Rot-13 might be enough, provided that you're dealing with an audience with ASCII email addresses. If you need to support Unicode, then you might need something slightly more sophisticated.
Can you use HTTPS to encrypt all traffic between the client and server? This is probally the most secure method that you will find.
Very Simple Functions,
function Encrypt(value)
{
var result="";
for(i=0;i<value.length;i++)
{
if(i<value.length-1)
{
result+=value.charCodeAt(i)+10;
result+="-";
}
else
{
result+=value.charCodeAt(i)+10;
}
}
return result;
}
function Decrypt(value)
{
var result="";
var array = value.split("-");
for(i=0;i<array.length;i++)
{
result+=String.fromCharCode(array[i]-10);
}
return result;
}