簡體   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