開放式封裝慣例的數位簽章架構

 

DavidMelzer 和 Andrey Shur
Microsoft Corporation

2006 年 9 月

適用於:
   OPC 數位簽章架構
   W3C XML 數位簽章標準
   Microsoft .NET 3.0 Framework

摘要:討論 OPC 數位簽章架構、提供套件元件和支援服務的概觀,以及簽署原則及其實作的範例。 (12 個列印頁面)

目錄

簡介
OPC 數位簽章架構的元件
   XML 數位簽章標準
   代表封裝中的數位簽章
   簽署元件和關聯性
封裝簽章的程式設計支援
   簽署套件元件和關聯性
   驗證憑證和簽章
應用程式簽署原則
   XPS 文件
   XPS 簽章的程式設計支援
參考資料

簡介

Open Packaging Conventions (OPC 所指定的封裝模型) 描述封裝、元件和關聯性。 套件會保存部分,以保存內容和資源。 關聯性的定義是將封裝連接到元件,以及連接封裝中的各種元件。

本文討論 OPC 數位簽章架構、提供套件元件和支援服務的概觀,以及簽署原則及其實作的範例。

簽署架構包含代表數位簽章的基礎結構,以及用來建立和驗證簽章的服務。 簽署架構可讓 W3C XML 數位簽章標準套用至封裝元件和關聯性。

使用簽署架構時,套件型格式的擁有者會定義並實作其格式特有的「簽署原則」。 原則會指定如何簽署及驗證特定格式的整數內容,並說明簽章如何用於不同的工作流程。 事實上,針對單一格式,可能會有數個原則定義在檔生命週期的不同階段使用。

封裝型格式的簽署原則是以簽署元件和關聯性來表示,而且可能還有其他檔特性 (,例如驗證預定的顯示裝置、色彩深度或應用程式版本) 。 簽署原則會指定要簽署的檔元件,以及如果有的話,要保留未簽署的檔元件。 例如,您可以實作簽署原則,以允許將新元件和關聯性新增至套件,或者如果新元件或簽章新增至封裝,原則可能會導致簽章失效。

本文假設熟悉 開放式封裝慣例規格 和 W3C 建議 XML 簽章語法和處理

OPC 數位簽章架構的元件

XML 數位簽章標準

封裝的簽署架構會使用 XML 數位簽章標準,如 W3C 建議 XML 簽章語法和處理中所定義。 此建議會指定產生和儲存數位簽章的 XML 語法和處理規則。

標準會定義 XML 簽章專案類型、架構和一致性需求,以簽署和驗證任何類型的數位資源。 架構也會定義參考資源及指定簽章相關演算法的元素。

數位簽章的功能

數位簽章可用來判斷簽署的內容在簽署後是否已變更。 簽章包含根據已知演算法雜湊的內容資訊清單,並在建立時儲存在簽章中。 若要判斷內容是否已變更,則會重新建立已簽署內容的雜湊,並與簽章內儲存的雜湊進行比較。

數位簽章也可用來識別內容的簽署者。 簽署者的身分識別是由與簽章相關聯的憑證來表示。 憑證可以內嵌在簽章中,或可在其他地方使用。

數位簽章不會「鎖定」檔,或造成檔 (加密,但可能已經加密) 。 簽署之後,檔內容會保持不變。 數位簽章不會防止非預期的取用者檢視已簽署的內容。

代表封裝中的數位簽章

應用程式會使用指定的元件和關聯性組態,將數位簽章併入套件中。

簽署架構會使用封裝命名空間中的元素和屬性,其中由 XML 數位簽章標準所允許。 封裝命名空間中定義的簽章元素支援擴充標準的套件特定功能,而不會與它衝突。 For a summary of the additions, see the section "Modifications to the XML Digital Signature Specification" of the OPC Specification.

為簽署架構定義的封裝元件是原始元件、XML 簽章元件和憑證元件。 每個都有定義完善的內容類型。 定義完善的關聯性類型可用來連接封裝中的簽章元件,如 OPC 規格的附錄 H、「標準命名空間和內容類型」中所指定。

數位簽章原始部分

數位簽章來源部分是流覽套件中簽章的起點。 數位簽章來源部分是以使用 數位簽章來源 關聯性的套件根目錄為目標。 多個簽章元件可以從 Origin 元件設為目標。 如果套件中沒有簽章,則不會顯示 Origin 元件。

數位簽章 XML 簽章元件

數位簽章 XML 簽章元件包含 W3C 數位簽章標準以及封裝命名空間中定義的標記。 這些元件是以數位簽章來源元件 XML 為目標,並具有 數位簽章 關聯性。

數位簽章憑證部分

識別簽署者所需的 X.509 憑證,如果放在封裝中,可能內嵌在 XML 簽章元件中,或儲存在個別的憑證元件中。 選擇性憑證元件是以具有數位簽章憑證關聯性的 XML 簽章 元件為目標。 憑證元件可以在多個簽章元件之間共用。

自訂簽章元件

簽署架構允許自訂 (應用程式特定) 簽章元件,但不允許處理。 保存 XML 簽章以外的簽章形式的簽章元件必須由自訂內容類型識別。 此外,與自訂關聯性類型的關聯性必須用來以數位簽章來源元件中的元件為目標。

簽署元件和關聯性

XML 數位簽章標準允許簽署可定址的資源,而套件是元件。 簽署架構可讓您簽署元件。 封裝中儲存在關聯性元件中的關聯性可以一次簽署,也可以指定一部分的關聯性來進行簽署。

元件的內容類型會連同元件內容一起簽署,以確保有效簽署套件中的元件將如預期般使用或轉譯。 因為內容類型不是可定址的資源,所以會採用套件特定的方法來簽署內容類型值。 簽署封裝時,每個已簽署元件的內容類型會儲存在參考已簽署元件的 URI 查詢元件中。 取用套件時,OPC 數位簽章架構會使用內容類型值,以確保在簽署元件之後,元件的內容型別尚未變更。

當關聯性部分整體簽署時,該元件中定義的所有關聯性都會經過簽署。 為了支援允許套件的某些內容變更而不使簽章失效的簽署原則,簽署架構會提供簽署指定關聯性的機制。 若要簽署指定的關聯性,簽署架構會使用特殊轉換,關聯性轉換 (請參閱 轉換演算法) 。

關聯性轉換會建立只包含指定關聯性集合的關聯性元件。 取得的關聯性部分用於簽署和簽章驗證期間。

封裝簽章的程式設計支援

若要簽署和驗證簽章,應用程式可以使用 .NET 3.0 類別 PackageDigitalSignatureManager在 System.IO.Packaging命名空間中定義的套件特定類別,以System.Security.Cryptography.Xml命名空間中定義的 Microsoft .NET 3.0 Framework 數位簽章類別為基礎。

PackageDigitalSignatureManager類別用於建立和驗證簽章,並將簽章基礎結構放在套件中。 簽章是以 PackageDigitalSignature 類別為基礎的物件來表示。

簽署套件元件和關聯性

應用程式會根據其簽署原則定義要簽署的元件和關聯性清單。 應用程式接著會呼叫 PackageDigitalSignatureManager.Sign () 方法來建立簽章,並將簽章基礎結構新增至套件。

下列範例程式碼示範簽署套件中的所有元件,但關聯性元件除外、簽署源自封裝根目錄的所有現有關聯性,以及內嵌用於登入 XML 簽章元件的憑證。 範例程式碼假設一開始套件中沒有任何簽章存在,而且在驗證之前只會套用一個簽章。

開始簽署程式

若要開始使用套件中的簽章,請先建立 PackageDigitalSignatureManager,如下所示。

    // Open the package.
    Package package = Package.Open(filename);

    // Create the PackageDigitalSignatureManager
      PackageDigitalSignatureManager dsm =
        new PackageDigitalSignatureManager(package);

憑證內嵌選項

憑證可以表示為內嵌在簽章本身的字串、封裝中的個別部分,或是封裝外部的資源。 如果要將憑證放在封裝內,應用程式會指定如何使用 PackageDigitalSignature.CertificateOption 屬性的內嵌選項來保存憑證。 建立 PackageDigitalSignatureManager 類別之後,會設定憑證的內嵌選項,如下列範例程式碼所示。

    //Specify that the certificate is embedded in the signature held
    //in the XML Signature part.

    //Certificate embedding options include:
    // InSignaturePart – Certificate is embedded in the signature.
    // InCertificatePart – Certificate is embedded in a 
    //                     separate certificate part

    dsm.CertificateOption =
        CertificateEmbeddingOption.InSignaturePart;

帶正負號的元件清單

要簽署的元件清單是使用定址元件的 URI 來指定。 在此範例中,除了使用 PackUriHelper.IsRelationshipPartUri () 方法篩選掉的關聯性元件之外,封裝中的所有元件都會簽署。

    //Initialize a list to hold the part URIs to sign.

    System.Collections.Generic.List<Uri> partsToSign =
        new System.Collections.Generic.List<Uri>();

    //Add each part to the list, except relationships parts.
    foreach (PackagePart packagePart in package.GetParts())
    {
        if (!PackUriHelper.IsRelationshipPartUri(packagePart.Uri))
      partsToSign.Add(packagePart.Uri);
  }

帶正負號的關聯性清單

使用關聯性轉換簽署個別關聯性。 如此一來,簽署關聯性即可將新的關聯性新增至套件,而不會使簽章失效。

建立將在簽署時使用的 PackageRelationshipSelector 物件清單,即可選取關聯性進行簽署。 PackageRelationshipSelector 物件可以依關聯性類型建立為群組, (如開放式封裝慣例) 的一節中所定義,或透過指定關聯性識別碼個別建立,如下列範例所示。

     //Create list of selectors for the list of relationships

     List<PackageRelationshipSelector> relationshipSelectors = 
          new List<PackageRelationshipSelector>();

     //Create one selector for each package-level relationship, based on id

  foreach (PackageRelationship relationship in package.GetRelationships())
            {
                relationshipSelectors.Add(new
                    PackageRelationshipSelector(relationship.sourceUri, 
                    PackageRelationshipSelectorType.Id, relationship.Id));
            }

使用PackageRelationshipSelectorType.Id建立PackageRelationshipSelector時,將會選取具有指定唯一識別碼的一個關聯性來進行簽署。 使用 PackageRelationshipSelectorType.Type建立選取器時,會選取具有指定類型的所有關聯性以進行簽署。 如果稍後將相同類型的關聯性新增至封裝,簽章將會失效。

建立 Certificate 物件

簽署之前,系統會藉由具現化 System.Security.Cryptography.X509Certificates.X509Certificates.X509Certificate2 類型的物件來取得有效的 X.509 憑證。 此物件會在簽署時傳遞至 PackageDigitalSignatureManager.Sign () 方法。 如需建立憑證物件的詳細資訊,請參閱 System.Security.Cryptography.X509Certificates 命名空間。

套用簽章

建立要簽署的元件和關聯性清單並取得憑證物件之後,應用程式會呼叫 PackageDigitalSignatureManager.Sign () 方法。

     //Sign package using components created above

     PackageDigitalSignature signature = dsm.Sign(partsToSign, 
          x509Certificate, relationshipSelectors);

     //After signing, close the package.
     //The signature will be persisted in the package.
     package.Close();

呼叫 Sign () 方法時,會產生雜湊並儲存在簽章資訊清單中,並建立簽章元件。 如果套件中已有簽章基礎結構,如果允許) ,則會新增新的簽章元件 (。 如果套件中還沒有基礎結構, Sign () 方法會建立基礎結構,並將它放在套件中。

驗證憑證和簽章

應用程式可以驗證憑證或簽章。 在驗證簽章之前,應該先驗證憑證。 代表 封裝中簽章的 物件 PackageDigitalSignature具有屬性 「Signer」,會傳回用於建立該簽章的憑證,如果憑證位於封裝中。 如果憑證未內嵌在套件中,應用程式會從應用程式已知的位置取得憑證。

PackageDigitalSignatureManager.VerifyCertificate () 方法可用來驗證取得的憑證、檢查憑證結構、到期日和鏈結狀態。 如需鏈結狀態的詳細資訊,請參閱 .NET Framework 類別庫中的X509ChainStatusFlag 列舉

應用程式開發人員可以使用憑證狀態來支援其簽署原則。 例如,應用程式可以指定只接受在特定日期之後發出的憑證。

PackageDigitalSignatureManager.VerifySignatures () 方法可用來驗證套件中的所有簽章。 這個方法只會驗證簽章,而不是與簽章相關聯的憑證。

下列範例程式碼可用來驗證簽署範例中封裝中放置的憑證和簽章。 範例程式碼假設尚未將其他簽章新增至套件。

    // Open the package.

    Package package = Package.Open(filename);

    // Create the PackageDigitalSignatureManager

    PackageDigitalSignatureManager dsm =
        new PackageDigitalSignatureManager(package);

    // Verify the collection of certificates in the package (one, in this case)

        foreach(PackageDigitalSignature signature in pdsm.Signatures)
        {
        if(PackageDigitalSignatureManager.VerifyCertificate(signature.Signer)
            != X509ChainStatusFlags.NoError)
              {
                // Application-specific code for error handling 
                // or certificate validation 
              }
        }
 
   // For this example, if all certificates are valid,
   // verify all signatures in the package.
 
    VerifyResult vResult = dsm.VerifySignatures(false);
    Console.WriteLine("Result " + vResult.ToString());

    // Close the package.

    package.Close();

應用程式簽署原則

使用封裝格式的應用程式會在簽署架構中定義自己的原則。 原則取決於格式的專案類型和工作流程需求。 在本節中,會針對一個 Microsoft 套件型格式描述簽署原則:XPS 檔案格式。

XPS 文件

XPS 檔案格式是以開放式封裝慣例為基礎,如 XML 紙張規格中所指定。 XML 檔規格會定義簽署 XPS 檔的原則。 在該原則中,有可支援應用程式功能或工作流程的簽署選項。

XPS 檔套件的簽署原則

XPS 檔的簽署原則描述必須簽署的元件和關聯性集合,以便驗證內容。 作為此原則的一部分,應用程式可能會建立簽章,選擇性地包含與內容連續的特定元件組合,例如 CoreProperties 元件。 簽署這些元件可防止變更這些元件,而不會使簽章失效。 此外,應用程式可以選擇性地簽署簽章中附加至數位簽章來源元件的關聯性部分,禁止將新簽章新增至檔,而不會使簽章失效。

若要讓簽章有效,XPS 檔簽署原則會要求籤章中包含特定部分和關聯性。 無法簽署無法辨識的部分或關聯性。 驗證簽章時,應用程式必須確認已簽署所有必要的元件和關聯性。

要簽署的 XPS 檔元件

下表包含必須在所有 XPS 檔中簽署的元件清單,以及選擇性簽署的元件。 對於關聯性,XPS 簽署原則會指定以必要元件為目標 (關聯性) 的必要關聯性一律使用 OPC 定義的關聯性轉換來簽署。 如果元件已簽署,則目標為它的關聯性也必須簽署。

元件類型 原則
FixedDocumentSequence 元件 必須簽署
FixedDocument 元件 必須簽署
DocumentStructure 元件 必須簽署
SignatureDefinitions 元件 必須簽署
FixedPage 元件 必須簽署
所需的資源元件 (,例如字型、影像) 必須簽署
StoryFragments 元件 必須簽署
縮圖元件 必須簽署
CoreProperties 元件 選擇性簽署
數位簽章來源部分 選擇性簽署
數位簽章憑證部分 選擇性簽署
PrintTicket 元件 選擇性簽署
DiscardControl 元件 選擇性簽署

For more information about the XPS signing policy, see the section "XPS Document Package Features: Digital Signatures: Signing Rules" in the XML Paper Specification.

標記相容性簽署原則

XML 檔規格說明在 XPS 檔中包含替代內容的方法:標記相容性。 替代內容會放在標記相容性命名空間的專案內。 根據原則,除非簽署應用程式會將所有內容替代專案辨識為對等專案,否則無法有效簽署具有標記相容性元素和屬性的 XPS 檔。 只有包含可辨識之元素和屬性的 XPS 檔才能簽署或驗證。

副署

多個簽章可以套用至 XPS 檔的內容。 例如,代表法律合約的內容可能需要數位人員套用其簽章,指出已簽署的內容和簽署者的身分識別。

新增簽章一律會在附加至數位簽章原始元件的關聯性元件內建立新的關聯性。 若要將新簽章新增至 XPS 檔,而不使現有簽章失效,此關聯性部分必須維持未簽署 (,雖然關聯性的子集可能會簽署) 。 如果簽章中包含關聯性部分,該簽章將會由所有後續套用的簽章失效。

驗證 XPS 簽章

除了定義簽章建立之外,XPS 簽署原則也會指定如何驗證簽章是否有效。 此原則會定義簽章的有效狀態,其中包含不符合規範、中斷、可疑且有效,如下表所示。

簽章狀態 已簽署所有必要的元件和關聯性? 簽章只包含已辨識的內容? 已簽署內容的雜湊已驗證? 已辨識已簽署的標記相容性內容? 憑證有效?
不相容

YES

n/a

n/a

n/a

n/a

n/a

n/a

n/a

破碎 YES YES n/a n/a
可疑 YES

YES

YES

YES

YES

YES

YES

n/a

有效 YES YES YES YES YES

XPS 檢視器會顯示可疑且中斷的 XPS 簽章,以及有效的 XPS 簽章。 未列舉不符合規範的簽章。

XPS 簽章的程式設計支援

使用 XPS Document 時,應用程式可以使用 XpsDigitalSignature 類別中的方法。 此類別是以 PackageDigitalSignature 類別為基礎,並包含遵循 XPS 數位簽章規格中所指定演算法和需求的方法。 簽署和驗證方法會確認已簽署 XPS 檔的所有必要元件和關聯性。

簽署 XPS 檔

XpsDocument.SignDigitally () 方法是用來簽署 XPS 檔。 在呼叫 方法之前,應用程式必須具有 X.509 憑證,可以使用 System.Security.Cryptography.X509Certificates.X509Certificate2物件取得。

     // Open the XPS Document

     XpsDocument document = new XpsDocument(dstContainer,
          FileAccess.ReadWrite);

     // Obtain the certificate object from a file

     X509Certificate certificate =
          509Certificate.CreateFromCertFile(certFilename);

     // Create the signature and add it to the document using
     // the OPC Signing Framework

     document.SignDigitally(certificate, true, 
          XpsDigSigPartAlteringRestrictions.None);

XpsDigSigPartAlteringRestrictions 可用來根據簽署原則指定簽章的其他限制。 此參數會指定是否要從簽章中排除 CoreMetadata 和/或 SignatureOrigin 元件。 然後,您可以稍後修改排除的元件,而不會使簽章失效。 例如,從簽章排除 CoreMetadata 元件可讓應用程式變更某些文件屬性,而不會使簽章失效。

PrintTicketDiscardControl元件會從SignDigitally () 方法所建立的簽章中排除,不過這些元件可能會選擇性地以應用程式特定的方式簽署。

驗證 XPS 檔簽章

一或多個簽章可以與 XPS 檔一起儲存。 簽章可以從 XpsDocument.Signatures 屬性取得。 每個簽章都是以 XpsDigitalSignature 物件的實例表示。

在下列範例中,只會驗證集合中的第一個簽章。

     // Open the XPS Document.

     // Obtain the first enumerated signature.

     foreach (XpsDigitalSignature digitalSignature in
              document.Signatures)
     { 
          // Verify the signature object, if present.

          if (digitalSignature.Verify() ==
     System.IO.Packaging.PackageDigitalSignature.VerifyResult.Success)
          {
         //Signature is valid
          }
     }

參考資料