简体   繁体   中英

Data protection / encryption on Azure websites?

I'm trying to encrypt some data to store in a user cookie from a website deployed on Azure.

I tried looking at the DataProtection APIs in System.Security but they all seem to need a machine or user scope, which doesn't work when deployed to Azure.

Then I tried using the AesCryptoServiceProvider and storing the key in my Web.config, but I get this error:

CryptographicException: The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating.

I was reading up on the error and apparently you need to tweak an IIS setting, which doesn't work for Azure.

I also tried looking at the DataProtection Asp.NET Core package but it brought in a whole lot of new packages and the docs mentioned needing to store crypto information in a local folder; which again doesn't seem like it would work on Azure without a dedicated machine.

What's the right way to protect/unprotect data on an Azure website?

Turns out it was only the DataProtection API that was throwing the error. AesManaged and AesCryptoServiceProvider both still work in Azure. Here is what I ended up using:

private const string AesKey = "206283c07cbfda1c0c126ef56d78ba9a0aeb53a06cd65f10bd3a9cb9a68e3fe1";

public static byte[] Encrypt(byte[] toEncrypt)
{
    byte[] encrypted;

    var aes = new AesCryptoServiceProvider();
    aes.Key = StringToByteArray(AesKey);

    // Create a new IV for each item to encrypt
    aes.GenerateIV();
    byte[] iv = aes.IV;

    using (var encrypter = aes.CreateEncryptor(aes.Key, iv))
    using (var cipherStream = new MemoryStream())
    {
        using (var cryptoStream = new CryptoStream(cipherStream, encrypter, CryptoStreamMode.Write))
        using (var binaryWriter = new BinaryWriter(cryptoStream))
        {
            // Prepend unencrypted IV to data
            cipherStream.Write(iv, 0, iv.Length);
            binaryWriter.Write(toEncrypt);
            cryptoStream.FlushFinalBlock();
        }

        encrypted = cipherStream.ToArray();
    }

    return encrypted;
}

public static byte[] EncryptFromString(string toEncrypt)
{
    return Encrypt(Encoding.UTF8.GetBytes(toEncrypt));
}

public static byte[] Decrypt(byte[] toDecrypt)
{
    var aes = new AesCryptoServiceProvider();
    aes.Key = StringToByteArray(AesKey);

    // Pull out the unencrypted IV first
    byte[] iv = new byte[16];
    Array.Copy(toDecrypt, 0, iv, 0, iv.Length);

    using (var encryptedMemoryStream = new MemoryStream())
    {
        using (var cryptoStream = new CryptoStream(encryptedMemoryStream, aes.CreateDecryptor(aes.Key, iv), CryptoStreamMode.Write))
        using (var binaryWriter = new BinaryWriter(cryptoStream))
        {
            // Decrypt Cipher Text from Message
            binaryWriter.Write(
                toDecrypt,
                iv.Length,
                toDecrypt.Length - iv.Length
            );
        }

        return encryptedMemoryStream.ToArray();
    }
}

public static string DecryptToString(byte[] toDecrypt)
{
    return Encoding.UTF8.GetString(Decrypt(toDecrypt));
}

public static string ByteArrayToString(byte[] array)
{
    StringBuilder hex = new StringBuilder(array.Length * 2);
    foreach (byte b in array)
    {
        hex.AppendFormat("{0:x2}", b);
    }

    return hex.ToString();
}

public static byte[] StringToByteArray(string hex)
{
    int charCount = hex.Length;
    byte[] bytes = new byte[charCount / 2];
    for (int i = 0; i < charCount; i += 2)
    {
        bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    }

    return bytes;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM