[英]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 密钥的正式验证。 可以导入密钥:
不能保证参数在内容方面被验证以保持一致性(例如,在私钥的情况下,模数可能不等于 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.