繁体   English   中英

如何验证 RSA 公钥?

[英]How to validate an RSA public key?

如果我收到一个 PEM 编码的密钥,我可以像这样导入它:

    using var rsa = new RSACryptoServiceProvider(2048);
    rsa.ImportFromPem(keyString.AsSpan());
    // do stuff with it

然而, ImportFromPem的文档声明它将不加区别地接受四种密钥类型:PUBLIC KEY、PRIVATE KEY、RSA PRIVATE KEY、RSA PUBLIC KEY,并且“不支持或格式错误的 PEM 编码对象将被忽略”。

如果我想验证 1) 我收到的是公钥而不是私钥,并且 2) 它是有效的公钥而不是“不受支持或格式错误的 PEM 编码 object”,我将如何 go 这样做?

使用发布的代码成功导入也意味着对 RSA 密钥的正式验证。 可以导入密钥:

  • 如果它是 RSA 密钥。
  • 如果密钥包含 RSA 支持的标签之一(即 PUBLIC KEY (SPKI)、RSA PUBLIC KEY (public PKCS#1)、PRIVATE KEY (PKCS#8)、RSA PRIVTE KEY (private PKCS#1))。
  • 如果正文包含有效(Base64 编码)ASN.1/DER。
  • 如果 label 与正文中包含的密钥一致(按类型(公共/私有)和格式(PKCS#1/PKCS#8/SPKI))。

不能保证参数在内容方面被验证保持一致性(例如,在私钥的情况下,模数可能不等于 p 和 q 的乘积)。 除其他事项外,这取决于平台(例如 Windows 或 Unix)。 因此,如果需要保证参数的验证,则必须显式验证参数。
通过使用ExportParameters()导出RSA 参数然后验证它们,可以显式验证参数。 这与私钥相关,其中参数相互依赖,因此可以测试这些一致性(例如,模数是否等于两个素数的乘积)。 公钥没有这样的一致性检查。
由于这个问题是关于公钥的,因此不需要检查私钥(也可以省略)。

对于以这种方式导入的密钥,可以使用PublicOnly来检查它是私钥还是公钥。

这使得为 RSA 密钥验证创建逻辑变得相对容易,例如:

using System.Numerics;
using System.Security.Cryptography;
...
private static void ImportPublicKey(string key)
{
    using var rsa = new RSACryptoServiceProvider();
    try
    {
        rsa.ImportFromPem(key.AsSpan());
        if (rsa.PublicOnly)
        {
            Console.WriteLine("Public RSA key");
        }
        else
        {
            // Explicit check of the consistency of the parameters for private keys, for example N = p*q
            var rsaParams = rsa.ExportParameters(true);
            BigInteger m = new BigInteger(rsaParams.Modulus, true, true);
            BigInteger p = new BigInteger(rsaParams.P, true, true);
            BigInteger q = new BigInteger(rsaParams.Q, true, true);
            Console.WriteLine("Private RSA key - params " + (p*q==m ? "consistent" : "not consistent"));
        }
    }
    catch
    {
        Console.WriteLine("Invalid or inconsistent RSA key");
    }
}

首先,这取决于您为什么要验证公钥。 你不应该期望对手故意发送错误的密钥。 如果他们可以做到这一点,他们可以简单地向您发送错误的密钥。 为防止出现这种情况,您需要一种更好的方式来管理密钥,例如在公钥基础设施或 PKI 中使用证书。

太好了,顺便说一下,我想指出所有定义的 PEM 密钥都包含一个公钥。 RSA PUBLIC KEY是 PKCS#1 定义的公钥, RSA PRIVATE KEY是 PKCS#1 私钥。 但是,私钥的定义也包含了公共指数 同样, PUBLIC KEY是一个SubjectPublicKeyInfo结构,而PRIVATE KEY是一个 PKCS#8 定义的私钥。 两者都在内部包含PKCS#1 密钥结构,因此包含公钥。

也许你怀疑实例中的公钥没有被替换。 如果我正确阅读了文档,那当然是一个可能的选择(尽管 Microsoft 文档的质量通常是有问题的)。 在这种情况下,您可能想要验证模数是否更改了值。 模数特定于每个密钥对,并且包含在公钥和私钥中。 您可以使用ExportParameters(false).Modulus访问模数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM