[英]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.