如何在 C# 应用程序中保护私钥(三重 DES)? [英] How to Secure Private key(of Triple DES) in C# application?

查看:79
本文介绍了如何在 C# 应用程序中保护私钥(三重 DES)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

工具:OS-Windows 7 64 位,Visual Studio 2012,4.5 .NET Framework.语言:C#.

Tool : OS-Windows 7 64bit, Visual Studio 2012, 4.5 .NET Framework. Language : C#.

我创建了一个控制台应用程序.在这个应用程序中,我使用了数据加密算法(DES-对称算法)来加密和解密数据.

I have created one console application. In this application I have used Data Encryption Algorithm (DES- Symmetric Algorithm) to encrypt and decrypt data.

现在在这种方法中,使用私钥或秘密密钥.我想从客户端/黑客那里保护这个密钥.我怎样才能保护它?

Now in this approach, Private or secrete key is used. I want to secure this key from client/Hack. How can I secure it?

现在我已将 KEY 存储到注册表中,并在需要时从注册表中读取该密钥以进行加密和解密.但是从注册表中,任何像你们这样知识渊博的开发人员都可以轻松读取密钥.

For now I have stored KEY to the registry, And read that key from registry to encryption and decryption when required. But from registry any knowledgeable developer like you guys can easily read key.

下面是我的 DES 算法代码(我从 MSDN 得到这个代码):

Below is my DES algorithm code(I got this code from MSDN):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace DES_Encrypt_Decrypt
{
    public class Program
    {
        static void Main(string[] args)
        {
            var text = "This is Plain Text";

            var encryptedText = CryptoGraphyExample.EncryptPlainTextToCipherText(text);
            var decryptedText = CryptoGraphyExample.DecryptCipherTextToPlainText(encryptedText);

            Console.WriteLine("Passed Text = " + text);
            Console.WriteLine("EncryptedText = " + encryptedText);
            Console.WriteLine("DecryptedText = " + decryptedText);

            Console.ReadLine();
        }
    }

    public class CryptoGraphyExample
    {
        private const string _securityKey = "MyComplexKey";
        // This is my secret key and I want to secure it to the client machine. 


        public static string EncryptPlainTextToCipherText(string PlainText)
        {                
            byte[] toEncryptedArray = UTF8Encoding.UTF8.GetBytes(PlainText);

            MD5CryptoServiceProvider objMD5CryptoService = new MD5CryptoServiceProvider();

            byte[] securityKeyArray = objMD5CryptoService.ComputeHash(UTF8Encoding.UTF8.GetBytes(_securityKey));

            objMD5CryptoService.Clear();

            var objTripleDESCryptoService = new TripleDESCryptoServiceProvider();

            objTripleDESCryptoService.Key = securityKeyArray;

            objTripleDESCryptoService.Mode = CipherMode.ECB;

            objTripleDESCryptoService.Padding = PaddingMode.PKCS7;

            var objCrytpoTransform = objTripleDESCryptoService.CreateEncryptor();

            byte[] resultArray = objCrytpoTransform.TransformFinalBlock(toEncryptedArray, 0, toEncryptedArray.Length);

            objTripleDESCryptoService.Clear();

            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }

        public static string DecryptCipherTextToPlainText(string CipherText)
        {
            byte[] toEncryptArray = Convert.FromBase64String(CipherText);

            MD5CryptoServiceProvider objMD5CryptoService = new MD5CryptoServiceProvider();

            byte[] securityKeyArray = objMD5CryptoService.ComputeHash(UTF8Encoding.UTF8.GetBytes(_securityKey));

            objMD5CryptoService.Clear();

            var objTripleDESCryptoService = new TripleDESCryptoServiceProvider();

            objTripleDESCryptoService.Key = securityKeyArray;

            objTripleDESCryptoService.Mode = CipherMode.ECB;

            objTripleDESCryptoService.Padding = PaddingMode.PKCS7;

            var objCrytpoTransform = objTripleDESCryptoService.CreateDecryptor();

            byte[] resultArray = objCrytpoTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            objTripleDESCryptoService.Clear();

            return UTF8Encoding.UTF8.GetString(resultArray);
        }
    }
}

推荐答案

你可以看看我的另一个答案:

You can have a look at another answer of mine:

或者你可以考虑从密码生成一个密钥,你可以用它来加密密钥本身:

Or you can consider generating a key from a password, which you can use to encrypt the key itself:

无论如何,您不应再使用 DES,因为它不再足够安全.如果您别无选择,三重 DES 也可以.我建议使用 AES 密钥大小为 256 位(如果您需要安全对称算法).

Either way, you should not use DES any longer as it is not secure enough any more. Triple-DES is okay if you have no other option. I recommend to use AES with a key size of 256 bit if you require a secure symmetric algorithm.

在之前的 Documentation Beta - "stackoverflow.com/documentation",,我添加了一些附加信息(.Net Framework -> 加密/加密).由于测试版处于离线状态,我将在此处提供此信息:

In the former Documentation Beta - "stackoverflow.com/documentation", I had added some additional information (.Net Framework -> Encryption / Cryptography). Since Beta is offline, I will provide this information here:

根据密码/随机 SALT 创建密钥(在 C# 中)

using System;
using System.Security.Cryptography;
using System.Text;

public class PasswordDerivedBytesExample
{
    public static void Main(String[] args)
    {
        // Get a password from the user.
        Console.WriteLine("Enter a password to produce a key:");

        byte[] pwd = Encoding.Unicode.GetBytes(Console.ReadLine());

        byte[] salt = CreateRandomSalt(7);

        // Create a TripleDESCryptoServiceProvider object.
        TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();

        try
        {
            Console.WriteLine("Creating a key with PasswordDeriveBytes...");

            // Create a PasswordDeriveBytes object and then create
            // a TripleDES key from the password and salt.
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(pwd, salt);

            // Create the key and set it to the Key property
            // of the TripleDESCryptoServiceProvider object.
            tdes.Key = pdb.CryptDeriveKey("TripleDES", "SHA1", 192, tdes.IV);

            Console.WriteLine("Operation complete.");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        finally
        {
            // Clear the buffers
            ClearBytes(pwd);
            ClearBytes(salt);

            // Clear the key.
            tdes.Clear();
        }

        Console.ReadLine();
    }

    #region Helper methods

    /// <summary>
    /// Generates a random salt value of the specified length.
    /// </summary>
    public static byte[] CreateRandomSalt(int length)
    {
        // Create a buffer
        byte[] randBytes;

        if (length >= 1)
        {
            randBytes = new byte[length];
        }
        else
        {
            randBytes = new byte[1];
        }

        // Create a new RNGCryptoServiceProvider.
        RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();

        // Fill the buffer with random bytes.
        rand.GetBytes(randBytes);

        // return the bytes.
        return randBytes;
    }

    /// <summary>
    /// Clear the bytes in a buffer so they can't later be read from memory.
    /// </summary>
    public static void ClearBytes(byte[] buffer)
    {
        // Check arguments.
        if (buffer == null)
        {
            throw new ArgumentNullException("buffer");
        }

        // Set each byte in the buffer to 0.
        for (int x = 0; x < buffer.Length; x++)
        {
            buffer[x] = 0;
        }
    }

    #endregion
}

此示例取自 MSDN.

这是一个控制台演示,它展示了如何基于用户定义的密码创建安全密钥,以及如何基于加密随机生成器创建随机 SALT.

It is a console demo, and it shows how to create a secure key based on a user-defined password, and how to create a random SALT based on the cryptographic random generator.

注意事项:

  • 内置函数 PasswordDeriveBytes 使用标准的 PBKDF1 算法从密码生成密钥.默认情况下,它使用 100 次迭代来生成减缓蛮力攻击的密钥.随机生成的 SALT 进一步加强了密钥.

  • The built-in function PasswordDeriveBytes uses the standard PBKDF1 algorithm to generate a key from the password. Per default, it uses 100 iterations to generate the key to slow down brute force attacks. The SALT generated randomly further strenghens the key.

函数 CryptDeriveKey 使用指定的散列算法(此处为SHA1")将 PasswordDeriveBytes 生成的密钥转换为与指定加密算法(此处为TripleDES")兼容的密钥.本例中的密钥大小为 192 字节,初始化向量 IV 取自三重 DES 加密提供者

The function CryptDeriveKey converts the key generated by PasswordDeriveBytes into a key compatible with the specified encryption algorithm (here "TripleDES") by using the specified hash algorithm (here "SHA1"). The keysize in this example is 192 bytes, and the initialization vector IV is taken from the triple-DES crypto provider

通常,此机制用于通过密码保护更强的随机生成的密钥,从而对大量数据进行加密.您还可以使用它来提供不同用户的多个密码以访问相同的数据(由不同的随机密钥保护).

Usually, this mechanism is used to protect a stronger random generated key by a password, which encrypts large amount of data. You can also use it to provide multiple passwords of different users to give access to the same data (being protected by a different random key).

遗憾的是,CryptDeriveKey 目前不支持 AES.请参阅此处.注意:作为一种变通方法,您可以创建一个随机 AES 密钥来加密要使用 AES 保护的数据,并将 AES 密钥存储在使用 CryptDeriveKey 生成的密钥的 TripleDES-Container 中.但这限制了 TripleDES 的安全性,没有利用 AES 较大的密钥大小,并创建了对 TripleDES 的依赖.

Unfortunately, CryptDeriveKey does currently not support AES. See here. NOTE: As a workaround, you can create a random AES key for encryption of the data to be protected with AES and store the AES key in a TripleDES-Container which uses the key generated by CryptDeriveKey. But that limits the security to TripleDES, does not take advantage of the larger keysizes of AES and creates a dependency to TripleDES.

这篇关于如何在 C# 应用程序中保护私钥(三重 DES)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆