0

what i am trying to do is when a user registers the password gets encrypted, and the encrypted password gets saved in a database, and when the user logs in it should then decrypt the password to compare if the user entered the correct password, but when i try to decrypt its gives me a "Bad data" exception.

Please help guys. Here is my code:

protected void btnLogin_Click(object sender, EventArgs e)
{
    try
    {
        private Cryptography crypt = new Cryptography();
        var registerUser = new test.Model.User();
        registerUser.EmailAddress = txtEmail.Text;
        registerUser.Password = txtPassword.Text;
        //new test().Getbyusername(registerUser);
        new test().getbyemail(registerUser, crypt);
    }
    catch (Exception ex)
    {

    }
}

public void getbyemail(User user, Cryptography crypt)
{
    try
    {
        var repo = new UserRepository();
        var test = repo.GetEncryptedPasswrd(user);
        var o = repo.getPrivateKey(user.EmailAddress);
        crypt.privateKey = o;
        var j = repo.getpublicKey(user.EmailAddress);
        crypt.publicKey = j;
        decryptPassword(test, o, crypt);

    }
    catch (Exception ex)
    {

    }
}

public String decryptPassword(byte [] encryptedpassword, string privateKey, Cryptography cry)
{
    decrypted = cry.decrypt(encryptedpassword, privateKey);
   //return Encoding.ASCII.GetString(decrypted);
    return Encoding.ASCII.GetString(decrypted);

}

protected void btnRegister_Click(object sender, EventArgs e)
{
    Cryptography crypt = new Cryptography();
    var registerUser = new test.Model.User();
    registerUser.Name = txtName.Text;
    registerUser.Surname = txtSurname.Text;
    registerUser.EmailAddress = txtEmailAddress.Text;
    registerUser.Password = txtPassword.Text;
    registerUser.DateRegisterd = DateTime.Now;
    new test().RegisterUser(registerUser, crypt.privateKey, crypt.publicKey,crypt, encrypted);
}

public void RegisterUser(User user, string privateKey, string publicKey, Cryptography crypt, byte[] encrypted)
{
    try
    {
        var repo = new UserRepository();
        byte[] plainText = Encoding.ASCII.GetBytes(user.Password);
        encrypted = crypt.encrypt(plainText, crypt.publicKey);
        user.Password = Encoding.ASCII.GetString(encrypted);
        user.PrivateKey = crypt.privateKey;
        user.PublickKey = crypt.publicKey;
        repo.Add(user);
    }
    catch (Exception ex)
    {

    }
}

Thanks in advance.

Jalal Said
  • 15,906
  • 7
  • 45
  • 68
johnnie
  • 1,837
  • 5
  • 23
  • 36
  • 1
    Just as a sidenote, you generally don't want to encrypt passwords but hash them instead. See here for a more detailed explanation as to why: http://stackoverflow.com/questions/326699/difference-between-hashing-a-password-and-encrypting-it – Brandon Jul 21 '11 at 20:17
  • 7
    It should give you a 'BadIdeaException'. Don't encrypt and decrypt a user's password. Hash it and compare to the stored hash. –  Jul 21 '11 at 20:18
  • "BadIdeaException" :) . Good one . – Pit Digger Jul 21 '11 at 20:19
  • Listen to Brandon and Matthew. Another hint: Do not use empty exception catch blocks. You are not doing yourself a favor this way. You are basically swallowing any useful error information that could help you diagnose and fix the issue. – Paul Sasik Jul 21 '11 at 20:20
  • I just read your code - but unfortunatelly I don't get it... What kind of cryptography algorithm do you want to use? symmetric - asymetric? Why don't you use md5 hash or sha hashing algorithms for storing your users pwds. Personally I never crypt and decrypt password - the only time there is a plain text password appears when the user enters it in a password-field ... – Pilgerstorfer Franz Jul 21 '11 at 20:23

4 Answers4

3

As said above comment you should really hash it .

Still if you want to encrypt as you example don't decrypt password . Instead you should encrypt password from user and simply compare to database .

You can Consider this simple option to hash the password . http://davidhayden.com/blog/dave/archive/2004/02/16/157.aspx .

Pit Digger
  • 9,618
  • 23
  • 78
  • 122
  • thanks for the quick response guys, but won the hash value always be the same? – johnnie Jul 21 '11 at 20:25
  • If the passwords are the same, they will produce the same hash. A work around that is to use a unique salt per user. – vcsjones Jul 21 '11 at 20:31
  • Consider this article too for some more ideas on creating a salt . http://www.codeproject.com/KB/recipes/StoringPasswords.aspx . – Pit Digger Jul 21 '11 at 20:32
2

You should not be encrypting passwords. Encryption is a reversable process, so if someone were to steal the encryption key and the passwords, they could get the user's password.

Instead, you should hash the password, and compare the hashes. A hash is destructive - it is impossible to get the original data from a hash. When a user signs up, you store the hash. When they want to sign back in, you hash what they entered and compare the hashes in the database. A hash using an algorithm like SHA-256 can be done like this:

public string GetPasswordHash(string clearPassword)
{
    using (var hash = new System.Security.Cryptography.SHA256Managed())
    {
        var hashBytes = System.Text.Encoding.UTF8.GetBytes(clearPassword);
        return Convert.ToBase64String(hash.ComputeHash(hashBytes));
    }
}

This gets us a step further, but you should also use a salt as well to prevent attacks like Rainbow Tables. In addition, hashing it multiple times (say 10,000) helps prevent against against brute force attacks. 10,000 hashes is fast for the user logging in, but extremely slow trying to brute force.

vcsjones
  • 138,677
  • 31
  • 291
  • 286
0

there can be a security hole when you're able to decrypt the password. What you should do is encrypt the submitted password as well and compare the encrypted strings.

EDIT: thanks Matthew... that's what i meant...doh

the better question is why aren't you making full use of .net built in login control? You'll need to configure your web.config.

for best security. add the following in your membership provider settings in web.config

enablePasswordRetrieval="False" enablePasswordReset="True" passwordFormat="Hashed"

also add machinekey in

<system.web>

http://www.qualitydata.com/products/aspnet-membership/help/configuration/no-machinekey.aspx

robert
  • 1,523
  • 5
  • 19
  • 27
  • 2
    No, you should not encrypt it. You should hash it. Encryption by definition is reversible. –  Jul 21 '11 at 20:19
  • 2
    nonononononono; that solves little. You *hash* the original (with salt) and store only the hash. Then to test, you *hash* the input (with the same salt), and compare the hash. – Marc Gravell Jul 21 '11 at 20:19
0

I would start with writing a unit test that takes a password, encrypts it an immediately decrypts it.

Once you know that works, make a copy of the encrypted password, and test if you can make a successful roundtrip to the database. If that is binary, encoding it to hex or base64 might help.