簡體   English   中英

驗證分離的簽名(* .p7s文件)和X509Certificate2

[英]Verify detached signature (*.p7s files) and X509Certificate2

我在我的方法中收到一個XML文檔作為字符串參數。 XML文檔是:

<Document>
    <ZipContainer> Zip_File_In_Base64 </ZipContainer>
    <X509Certificate> Certificate_In_Base64 </X509Certificate>
</Document>

從這個字符串中我提取了base64格式的ZIP文件和base64格式的X509Certificate2證書。 ZIP文件包含:

  • 將ZIP文件的內容描述為XML的文件(文件packageDescription.xml );

  • 包含已傳輸文檔內容的文件(例如, *.doc文件);

  • 內容為分離數字簽名的文件( *.p7s文件 - 分離的數字簽名);

從歸檔應該提取簽名的簽名文件(分離的數字簽名可能不止一個)。 分離的數字簽名存儲在擴展名為.p7s文件中。 必須完成每個簽名以檢查其與數字簽名的協議,用戶使用該簽名登錄到門戶。

必須包括兩個步驟:

  1. 請參閱方法certificateValidator() (請參閱下面的此方法):這是一個分離的簽名,包含在.p7s文件中,其中包含相應的簽名文件,這些*。 P7S-文件。
    例如:一對相關文件: ZayavUL_3594c921f545406d9b8734bbe28bf894.doc_1.p7s
    ZayavUL_3594c921f545406d9b8734bbe28bf894.doc

  2. 請參閱方法certificateValidator() :這將使用從XML文檔輸入字符串中提取的證書來驗證文件.p7s中的證書。

問題

  1. 方法signatureValidator (請參閱下面的此方法)當前未使用文件.p7s分離簽名。 我試過了,但沒有成功。 如何正確驗證.p7s文件的分離簽名.p7s包含相應的文件?

  2. 在方法certificateValidator (請參閱下面的此方法)中,如何驗證從.p7s文件中提取的證書與從Base64格式的輸入字符串中提取的證書的一致性?

  3. 代碼行foreach (X509Certificate2 x509 in signCms.Certificates) { } ---> Certificates Collection始終為空。 為什么?

輸入參數

  • Dictionary <string, byte[]> dictP7SFiles (key - 文件名* .p7s,value - 字節數組,表示* .p7s文件)

  • Dictionary <string, byte[]> dictNotP7SFiles (key - 使用* .p7s文件中的分離簽名簽名的文件的名稱,value - 字節數組,表示文件)

  • X509Certificate2 userCertX509 - 證書對象,從輸入的xml文檔中提取(其格式為Base64)

以下是測試驗證步驟的實施(參見上面的這2個步驟):

private bool certificateValidator(Dictionary<string, byte[]> dictP7SFiles, 
    Dictionary<string, byte[]> dictNotP7SFiles, X509Certificate2 userCertX509)
{
  bool isValid = false;           
  try
  {               
    foreach (KeyValuePair<string, byte[]> pair in dictP7SFiles)
    {
      ContentInfo contentInfo = new ContentInfo(pair.Value);
      SignedCms signCms = new SignedCms(contentInfo, true);                   

      if (signCms.Certificates.Count != 0)
      {
        //Certificates Collection always is empty. Why?
        foreach (X509Certificate2 x509 in signCms.Certificates)
        {
          if ((x509.SerialNumber != userCertX509.SerialNumber) 
              || (x509.Thumbprint != userCertX509.Thumbprint))
          {
            isValid = false;
            return isValid;
          }
        }

        isValid = true;
        return isValid;
      }
    }
  }
  catch (Exception ex)  
  {
    //here process exception code
  }           

  return isValid;
}



private bool signatureValidator(Dictionary<string, byte[]> dictP7SFiles, 
    Dictionary<string, byte[]> dictNotP7SFiles, X509Certificate2 userCertX509)
{
  bool isValid = false;
  try
  {              
    byte[] data = dictP7SFiles["ZayavUL_3594c921f545406d9b8734bbe28bf894.doc"];
    byte[] publicKey;
    byte[] signature;
    object hasher = SHA1.Create(); // Our chosen hashing algorithm.
    // Generate a new key pair, then sign the data with it:
    using (var publicPrivate = new RSACryptoServiceProvider())
    {
      signature = publicPrivate.SignData(data, hasher);
      publicKey = publicPrivate.ExportCspBlob(false); // get public key
    }
    // Create a fresh RSA using just the public key, then test the signature.
    using (var publicOnly = new RSACryptoServiceProvider())
    {
      publicOnly.ImportCspBlob(publicKey);

      isValid = publicOnly.VerifyData(data, hasher, signature); // Return True

      //isValid = ByteArrayCompare(dictP7SStreams["ZayavUL_3594c921f545406d9b8734bbe28bf894.doc_1.p7s"], signature);

      byte[] p7sDetachedSignature = File.ReadAllBytes(@"D:\ZayavUL_3594c921f545406d9b8734bbe28bf894.doc_1.p7s");
      isValid = ByteArrayCompare(p7sDetachedSignature, signature);
    }                
  }
  catch (Exception)
  {
    //here process exception code
  }

  return isValid;    
}

你做錯的主要是重新生成 CMS和簽名。 您應該解析 CMS消息,然后在驗證期間指示外部內容。

  1. 如何正確驗證.p7s文件的分離簽名是否包含相應的文件?

在SO上查看以下Java代碼 ,了解如何驗證簽名; C#應該使用相同的體系結構,因此應該以類似的方式工作。

  1. 在方法certificateValidator(請參閱下面的此方法)中,如何驗證從.p7s文件中提取的證書與從Base64格式的輸入字符串中提取的證書的一致性?

解碼base 64證書並執行證書的鏈驗證和驗證。 您想要執行多少驗證(例如,檢查生效日期 )取決於您。

  1. 代碼行foreach(X509Certificate2 x509 in signCms.Certificates){} ---> Certificates Collection始終為空。 為什么?

在構建新的CMS結構時,您根本沒有放入一個。


你當然也不應該重新生成簽名。 通常,在驗證期間您不會擁有私鑰,並且算法可能與CMS文檔中使用的算法不匹配。 此外,即使它會,簽名生成也不總是確定性的(您可能會得到不同的簽名值)。

暫無
暫無

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

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