【问题标题】:Deriving public / key pair from passphrase从密码中派生公钥/密钥对
【发布时间】:2015-09-26 14:25:39
【问题描述】:

按照此处提供的答案: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
    }
}

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

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

【问题讨论】:

    标签: c# encryption encryption-asymmetric


    【解决方案1】:

    经过一番摸索,我决定生成一个随机的 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 公钥和 RSA 私钥,通过使用密码和 salt 派生 AES 密钥,使用 AES 加密
    2. 加密数据涉及:
      1. 生成随机 AES 密钥
      2. 使用该 AES 密钥加密数据
      3. 使用发起者的 RSA 私钥生成加密数据的 RSA 签名
      4. 通过 RSA 使用目标的公共 RSA 密钥加密随机 AES 密钥来授予对数据的访问权限

    这让我可以存储所有核心信息:

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

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

    解密也比较简单:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-13
      • 2012-07-13
      • 1970-01-01
      • 2017-10-28
      • 1970-01-01
      相关资源
      最近更新 更多