从密码短语中派生公钥/密钥对

时间:2015-09-26 02:59:27

标签: 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
    }
}

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

我这样做是因为我不必将私钥存储在任何地方,这是一个安全考虑因素并且有助于实现可移植性,因为密钥可以在任何提供相同密码的机器上获得(和盐) - 最初是独一无二的,随机的。)

1 个答案:

答案 0 :(得分:0)

经过一番搜索后,我决定继续生成随机RSA密钥对,然后使用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公钥和通过使用密码和盐派生AES密钥使用AES加密的RSA私钥
  2. 加密数据涉及:
    1. 生成随机AES密钥
    2. 使用该AES密钥加密数据
    3. 使用发起者的RSA私钥生成加密数据的RSA签名
    4. RSA使用目标公共RSA密钥加密随机AE​​S密钥,授予对数据的访问权。
  3. 这允许我存储所有核心信息:

    1. 公钥
    2. 初始化矢量
    3. 加密私钥
    4. 几乎我想要的地方,因为实际破解私钥需要密码。

      解密也相对简单:

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