从密码短语构建私有CngKey(ECDH_P384)

时间:2016-11-25 20:49:47

标签: c# encryption cng

上下文:VS 2015 winforms,Windows 7,使用SecurityDriven Inferno库。

我正在编写一个离线应用程序,该应用程序生成要作为电子邮件附件发送的加密文件(因此不在客户端 - 服务器上下文中使用)。这些文件首先使用Inferno(ETM_Transform)加密,然后与(有时,重置密码)另一个文件一起发送,处理DHM密钥交换。

每个用户的公钥存储在由应用程序创建和保留的数据表中,允许在密钥交换过程中快速访问。但是,对于私钥,我的问题是用户(包括我自己)更愿意从密码中重新创建私钥,从而无需隐藏密钥,从而提高了安全性和可移植性。所以我需要从存储的公钥和散列密码短语中构建一个密钥。

这是一种合理的方法,或者对于这种特定的背景,这可能是更好的方法吗?

这是一个非常简短的代码示例,它抛出异常:"不支持请求的操作"。我该如何继续将数据导入密钥?

    internal static void CreateKey(string passPhrase)
    {
        byte[] keyType = new byte[] { 0x45, 0x43, 0x4B, 0x34 };
        byte[] keyLength = new byte[] { 0x30, 0x0, 0x0, 0x0 };            

        CryptoRandom cr = new CryptoRandom(); // rng used for this example
        byte[] prKey = cr.NextBytes(48); // salt+hash passphrase and pass it to the private key part
        byte[] pbKey = cr.NextBytes(96); // the public part, if I understand the format correctly for a cngkey using ECDH_P384
        byte[] blob = Utils.Combine(keyType, keyLength); // same as concat
        blob = Utils.Combine(blob, pbKey, prKey);

        CngKey key = CngKey.Import(blob, CngKeyBlobFormat.EccPrivateBlob);                        
    }

2 个答案:

答案 0 :(得分:2)

您无法随机生成公钥。公钥是根据私钥(和曲线)计算的,您可能会收到一个错误:a)公共X与私钥的预期不匹配,以及b)Y坐标不正确给定X坐标。

您需要从所选私钥计算公钥的值。据我所知,.Net和Windows CNG都没有公开这种功能。

答案 1 :(得分:1)

CngKey DHM blob有一个特定的格式,包括一个标题 - 它不仅仅是一个随机字节数组。您缺少该标头,这就是您获得例外的原因。很高兴您得到例外,因为您尝试做的事情在概念上是错误的。 ECDH_P384并非设计为每个随机私钥组合都是有效/适当的私钥。您不应手动生成CngKey - 将CngKey代留给相应的CngKey方法。

另一方面,

curve25519 设计用于任何随机私钥有效。您可以查看重新发布或重新实现Minilock