簡體   English   中英

在不同的機器上生成並簽署證書 C#

[英]Generate and sign certificate in different machines C#

我需要生成用於代理之間安全通信的證書。 每個代理都會生成一個證書,並且必須將其發送到另一台機器上的系統 CA 進行簽名(並由其他代理信任)。 我正在使用 C# 和以下代理代碼執行此操作:

 //generate certificate
        ECDsa elipticCurveNistP256Key = ECDsa.Create(ECCurve.CreateFromValue("1.2.840.10045.3.1.7")); // nistP256 curve
        CertificateRequest certificateRequest = new CertificateRequest("CN=" + agentId, elipticCurveNistP256Key, HashAlgorithmName.SHA256);
        certificateRequest.CertificateExtensions.Add(
            new X509BasicConstraintsExtension(false, false, 0, false));
        certificateRequest.CertificateExtensions.Add(
            new X509KeyUsageExtension(
                X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation,
                false));

        // Add the SubjectAlternativeName extension
        var sanBuilder = new SubjectAlternativeNameBuilder();
        sanBuilder.AddIpAddress(IPAddress.Parse(agentIpAddress));
        certificateRequest.CertificateExtensions.Add(sanBuilder.Build());

        certificateRequest.CertificateExtensions.Add(
            new X509EnhancedKeyUsageExtension(
                new OidCollection
                {
                    new Oid("1.3.6.1.5.5.7.3.8")
                },
                true));

        certificateRequest.CertificateExtensions.Add(
            new X509SubjectKeyIdentifierExtension(certificateRequest.PublicKey, false));

以及以下 CA 系統的代碼:

  X509Certificate2 signedCertificate = certificateRequest.Create(
            caCertificatePFX,
            DateTimeOffset.UtcNow.AddDays(-1),
            DateTimeOffset.UtcNow.AddDays(30),
            new byte[] {1, 2, 3, 4});

當然,我也使用代碼在我這里沒有顯示的機器之間進行通信。 但我至少有兩個問題:

  1. 我希望將證書生成和簽名完全分開,但即使進行了大量嘗試,這也是我能夠開始工作的唯一代碼。 如果我沒記錯的話,這段代碼在 CA 系統上創建了證書,這不是理想的場景(CA 可以訪問代理私鑰),但如果我沒有找到更好的,我可以接受。

  2. 第二個問題是,即使我接受了第一個問題,我仍然需要將 CertificateRequest 對象從一台機器發送到另一台機器,並且 CertificateRequest 是不可序列化的。 我找到了 CreateSigningRequest() 方法,它“創建一個 ASN.1 DER 編碼的 PKCS#10 CertificationRequest 值,表示當前對象的狀態。” 但是我還沒有找到一種方法讓它再次成為 CertificateRequest 對象,以便我可以運行 CA 系統代碼。

有誰知道我怎么能做到這一點? 希望將證書生成和證書簽名完全分開,但如果不可能至少創建 CertificateRequest 對象。

我正在運行 .Net Framework 4.7.2,我需要維護它才能使用以前開發的 Windows 窗體。

謝謝

正如您所指出的,沒有辦法讀回 PKCS#10 請求。 這主要是因為缺少太多東西才能成為“OK”證書頒發機構,因此擁有閱讀器只會導致許多“壞”證書頒發機構。 (由於您的 CA 不支持吊銷,因此它也是一個“壞”CA,但您正在使用短期證書來緩解這種情況。)

PKCS#10 請求包含:

  • 一個數據格式版本
  • 一個名字(大概是請求者想要的名字)
  • 一個公鑰
  • 屬性
    • 請求的擴展名出現在這里(EKU、主題備用名稱等)
  • 簽名,證明請求者擁有私鑰。

如果您不使用數據格式,則數據格式版本無關緊要,並且簽名對於“封閉”頒發者(僅向直接已知方頒發證書的 CA)來說並不重要。 因此,您只需要傳輸公鑰和請求所需的任何其他數據(查看您當前的代碼、代理 ID 和 IP 地址)。

唯一棘手的部分是發送公鑰……但是使用 .NET Core 3.0+,您可以將所有密鑰規范化為它們的 SubjectPublicKeyInfo 格式:

byte[] spki = elipticCurveNistP256Key.ExportSubjectPublicKeyInfo();

雖然PublicKey類型擁有 ImportSubjectPublicKeyInfo 方法會非常聰明,但這還沒有發生。 對於通用解析,您想嘗試所有主要的密鑰類型,但由於您是另一側的封閉 CA,您可以先驗地知道它是 ECDSA:

using (ECDsa clientPub = ECDsa.Create())
{
    clientPub.ImportSubjectPublicKeyInfo(transmittedSpki, out _);

    // the rest of your code goes here.
}

我強烈建議使用 CA 軟件來簽署證書請求。 時期。

任何擁有 CA 代碼的嘗試都會使解決方案在許多方面變得不可靠、脆弱和容易出錯。 有多種選擇,從 Microsoft ADCS (Windows) 和 EJBCA (Windows/Linux) 開始。 任何其他設計都將是糟糕的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM