开发者

ASP MVC: E-mail Verification (Encrypting the activation link)

Okay i'm a little bit stuck on how to solve this problem.

When a user registers. I want to send him a link so that he can verify hes email address.

But i have troubles generating the link.

I've already written the controller to acce开发者_开发百科pt the links with the correct keys. i only have no idea on how to generate the activation keys.

So when the user registers i'll send him a link by mail like this:

Your activation link is : http://site.com/user/verify?key=keyhere

Now i have created this method (called by the controller/action) to handle the key in the link:

 public string Verify(string value)
    {
        String email = Decrypt(value);

        user u = gebRep.GetUsers().WithEmail(email).SingleOrDefault();
        if (u != null)
        {
            u.emailValid = true;
            userReppository.Save();
        }

        return "Invallid validation value!";
    }

Now my problem is I have no idea on how to encrypt and decrypt the email into some sort of key (url friendly) So i can mail it with the link and can use it to verify the email.

I need some kind of (not to complicated but secure) way to encrypt the email into a urlfriendly key.

Tyvm


You could use something like Rijndael encryption to encrypt the user's e-mail address as the verification key, then when they click the link you simply decrypt the verification code with your private encryption key to retrieve the e-mail address and activate the appropriate user. With this technique you would not need to store any extra data about the user for account activation and you'd still have an encrypted, very hard to guess value as the verification code.

Here's an example of Rijndael encryption with C#.

In case you aren't familiar with it, with Rijndael encryption you have a private key that only you know, which is used as the encryption key for your data. So long as you know the encryption key you can always decrypt whatever you have encrypted.

The additional beauty of this technique is that it also makes it easy to have an expiring link. Say for example you want a 24 hour password reset link, so you send the user a link with a verification code in it, but rather than storing data about the verification code and its expiration date in your system, encrypt the user's e-mail and an expiration date and send that as the verification code. So basically, you could encrypt a value like, 1272746267|14 where first part is the link expiration timestamp and the second value is the user's ID in the system. Upon decrypting and parsing out the timestamp you can make the decision right there whether or not the link is still valid. The only drawback I see to this approach is possibly the length of the encrypted string, but seeing as you're sending it in an e-mail that shouldn't matter too much.

Here's a quick example:

Key: a1b2c3d4e5f6h7i8
Value: 1272746267|14

Encrypted: wxtVC1u5Q7N9+FymCln3qA==
Decrypted: 1272746267|14

Be sure to throw a Url.Encode() on the encrypted value before linking it, as it can contain some unfriendly characters like slashes.


It may easier to not use any encryption and make things a bit more simple.

Create a new Guid for the link (and save this with the user) then just verify the user when the link is called


The way I would do this is simply generate a largish-random number for the "key" and then store a mapping in your database between activation key and email.


This is what I use. Short and easy.

private string GetNewValidationCode()
{
    long i = 1;
    foreach (byte b in Guid.NewGuid().ToByteArray())
    {
        i *= ((int)b + 1);
    }
    return string.Format("{0:x}", i - DateTime.Now.Ticks);
}

Result looks like this: 8e85a8a078884bbc


Encrypt, Decrypt using AES. Please find example below:

class AesExample
    {
        public static void Main()
        {
            try
            {

                string original = "Here is some data to encrypt!";

                // Create a new instance of the AesManaged
                // class.  This generates a new key and initialization 
                // vector (IV).
                using (AesManaged myAes = new AesManaged())
                {

                    // Encrypt the string to an array of bytes.
                    string encrypted = EncryptPasswordAes(original, myAes.Key, myAes.IV);

                    // Decrypt the bytes to a string.
                    string roundtrip = DecryptPasswordAes(encrypted, myAes.Key, myAes.IV);

                    //Display the original data and the decrypted data.
                    Console.WriteLine("Original:   {0}", original);
                    Console.WriteLine("Encrypted: {0}", encrypted);
                    Console.WriteLine("Round Trip: {0}", roundtrip);

                    Console.ReadLine();
                }

            }
            catch (Exception e)
            {
                Console.WriteLine("Error: {0}", e.Message);
            }
        }
        static string EncryptPasswordAes(string plainText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");
            byte[] encrypted;
            // Create an AesManaged object
            // with the specified key and IV.
            using (AesManaged aesAlg = new AesManaged())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {

                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }


            // Return the encrypted bytes from the memory stream.
            return Convert.ToBase64String(encrypted);

        }

        static string DecryptPasswordAes(string encryptedString, byte[] Key, byte[] IV)
        {
            //Convert cipher text back to byte array
            byte[] cipherText = Convert.FromBase64String(encryptedString);
            //  Byte[] cipherText = System.Text.Encoding.UTF8.GetBytes(encryptedString);
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an AesManaged object
            // with the specified key and IV.
            using (AesManaged aesAlg = new AesManaged())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }

            }

            return plaintext;

        }
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜