c# - 从密码短语派生公钥/ key 对

标签 c# encryption encryption-asymmetric

按照此处提供的答案:https://crypto.stackexchange.com/questions/1662/how-can-one-securely-generate-an-asymmetric-key-pair-from-a-short-passphrase

我已经开始走以下道路:

public static void DeriveKeyPair(string pass, byte[] salt)
{
    using (var derived = new Rfc2898DeriveBytes(pass, salt, 10000))
    {
        var randomNum = new Random(BitConverter.ToInt32(derived.GetBytes(4), 0));
        // Can't seem to find an asymmetric implementation that I can supply the seed to
    }
}

忽略返回类型不会做任何有用的事情这一事实,我遇到的大问题是我似乎找不到可以播种或提供种子数的非对称加密提供程序发电机到。

我这样做是为了不必将私钥存储在任何地方,这是一种安全考虑并有助于可移植性,因为可以在提供相同密码(和盐 - 最初是独特且随机)。

最佳答案

经过一番探索后,我决定生成随机 RSA key 对,然后使用 AES 对称加密私钥。

这引导我采用以下两种方法:

public static byte[] EncryptData(string pass, byte[] salt, byte[] encryptedPrivateKey, byte[] targetPublicKey,
    byte[] iv, byte[] data)
{
    using (var rfc = new Rfc2898DeriveBytes(pass, salt, IterationCount))
    {
        using (var aes = new AesCryptoServiceProvider())
        {
            aes.KeySize = AesKeySize;
            aes.Key = rfc.GetBytes(aes.KeySize / 8);
            aes.IV = iv;

            using (var dec = aes.CreateDecryptor(aes.Key, aes.IV))
            {
                using (var ms = new MemoryStream(encryptedPrivateKey))
                {
                    using (var cs = new CryptoStream(ms, dec, CryptoStreamMode.Read))
                    {
                        var privKey = new byte[RsaKeySize];
                        cs.Read(privKey, 0, privKey.Length);
                        return RsaEncrypt(targetPublicKey, data);
                    }
                }
            }
        }
    }
}

public static byte[] DecryptData(string pass, byte[] salt, byte[] encryptedPrivateKey, byte[] iv, byte[] data)
{
    using (var rfc = new Rfc2898DeriveBytes(pass, salt, IterationCount))
    {
        using (var aes = new AesCryptoServiceProvider())
        {
            aes.KeySize = AesKeySize;
            aes.Key = rfc.GetBytes(aes.KeySize/8);
            aes.IV = iv;

            using (var dec = aes.CreateDecryptor(aes.Key, aes.IV))
            {
                using (var ms = new MemoryStream(encryptedPrivateKey))
                {
                    using (var cs = new CryptoStream(ms, dec, CryptoStreamMode.Read))
                    {
                        var privKey = new byte[RsaKeySize];
                        cs.Read(privKey, 0, privKey.Length);
                        return RsaDecrypt(privKey, data);
                    }
                }
            }
        }
    }
}

RSA 还不够。

本质上,RSA 只能加密较小的数据 than the key size

在我的新方案中:

  1. 用户身份是 RSA 公钥和 RSA 私钥,该私钥已通过使用密码和盐派生 AES key 进行 AES 加密
  2. 加密数据涉及:
    1. 生成随机 AES key
    2. 使用该 AES key 加密数据
    3. 使用发起者的 RSA 私钥生成加密数据的 RSA 签名
    4. 通过 RSA 使用目标的 RSA 公钥对随机 AES key 进行加密来授予对数据的访问权限

这允许我存储所有核心信息:

  1. 公钥
  2. 初始化向量
  3. 加密私钥

几乎是我想要的,因为实际破解私钥需要密码。

解密也相对简单:

  1. 接收传入数据
  2. RSA 根据声称的发件人的 RSA 公钥对其进行验证
  3. 从派生密码 + salt AES key 解密接收者的 RSA 私钥
  4. 解密访问 key (嵌入/托管 AES key )
  5. 使用提供的 key 解密收到的数据

关于c# - 从密码短语派生公钥/ key 对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32793186/

相关文章:

c# - 如何在 screwturn wiki 中测试运行插件

.net - 为什么 SHA512Managed 不符合 FIPS 标准?

java - 如何生成用于 64 位公钥加密的 key 对

c# - ActionFilterAttribute 重定向到带参数的操作方法

c# - 使用 RTSP over TCP 进行流式传输

c# - 如何在应用程序启动时立即显示光标?

php - 我可以在 NodeJS 中生成 key 对,使用公钥在 PHP 中加密数据,然后在 NodeJS 中解密吗?

sql - INT 列的 Postgres 数据加密

ruby - 从 Ruby 打开 RSA 私钥

c# - .NET 4.0 中大量的私钥加密