オープン パッケージ化規則のデジタル署名フレームワーク

 

David Meltzer と Andrey Shur
Microsoft Corporation

2006 年 9 月

適用対象:
   OPC Digital Signing Framework
   W3C XML デジタル署名標準
   Microsoft .NET 3.0 Framework

概要: OPC Digital Signing Framework について説明し、パッケージ コンポーネントとサポート サービスの概要と、署名ポリシーとその実装の例について説明します。 (12ページ印刷)

内容

はじめに
OPC Digital Signing Framework のコンポーネント
   XML デジタル署名標準
   パッケージでのデジタル署名の表し方
   署名パーツとリレーションシップ
パッケージ署名のプログラミング サポート
   署名パッケージのパーツとリレーションシップ
   証明書と署名の確認
アプリケーション署名ポリシー
   XPS ドキュメント
   XPS 署名のプログラミング サポート
リファレンス

はじめに

Open Packaging Conventions (OPC) で指定されたパッケージ モデルでは、パッケージ、パーツ、およびリレーションシップについて説明します。 パッケージには、コンテンツとリソースを保持するパーツが保持されます。 リレーションシップは、パッケージをパーツに接続し、パッケージ内のさまざまなパーツを接続するために定義されます。

この記事では、OPC Digital Signing Framework について説明します。パッケージ コンポーネントとサポート サービスの概要と、署名ポリシーとその実装の例について説明します。

署名フレームワークには、デジタル署名を表すインフラストラクチャと、署名を作成および検証するためのサービスが含まれています。 署名フレームワークを使用すると、W3C XML デジタル署名標準をパッケージ パーツとリレーションシップに適用できます。

署名フレームワークを使用して、パッケージ ベースの形式の所有者は、その形式に固有の "署名ポリシー" を定義して実装します。 ポリシーでは、特定の形式の不可欠なコンテンツに署名して検証する方法を指定し、さまざまなワークフローで署名がどのように使用されるかを具体化します。 実際、1 つの形式では、ドキュメントのライフサイクルのさまざまな段階で使用するために複数のポリシーが定義されている場合があります。

パッケージ ベースの形式の署名ポリシーは、署名パーツとリレーションシップ、および場合によっては他のドキュメント特性 (目的のディスプレイ デバイスの検証、色深度、アプリケーションのバージョンなど) で表されます。 署名ポリシーでは、署名するドキュメント コンポーネントと署名されていないドキュメント コンポーネント (存在する場合) を指定します。 たとえば、新しいパーツとリレーションシップをパッケージに追加できるように署名ポリシーを実装したり、新しいパーツまたは署名をパッケージに追加した場合に署名が無効になる可能性があります。

この記事では、 Open Packaging Conventions Specification と W3C Recommendation XML-Signature Syntax and Processing に精通していることを前提としています。

OPC Digital Signing Framework のコンポーネント

XML デジタル署名標準

パッケージの署名フレームワークでは、W3C Recommendation XML-Signature Syntax and Processing で定義されている XML Digital Signature Standard が使用されます。 この推奨事項では、デジタル署名を生成および格納するための XML 構文と処理規則を指定します。

標準では、あらゆる種類のデジタル リソースの署名と検証のための XML 署名要素の種類、スキーマ、および準拠要件が定義されています。 スキーマでは、リソースを参照し、署名関連のアルゴリズムを指定するための要素も定義されます。

デジタル署名の機能

デジタル署名を使用して、署名されたコンテンツが署名されてから変更されたかどうかを判断できます。 シグネチャには、既知のアルゴリズムに従ってハッシュされ、作成時に署名に格納されるコンテンツのマニフェストが含まれています。 コンテンツが変更されたかどうかを判断するために、署名されたコンテンツのハッシュが再作成され、署名内に格納されているハッシュと比較されます。

デジタル署名を使用して、コンテンツの署名者を識別することもできます。 署名者の ID は、署名に関連付けられている証明書によって表されます。 証明書は、署名に埋め込まれているか、他の場所で使用できます。

デジタル署名では、ドキュメントが "ロック" されたり、暗号化されたりすることはありません (ただし、既に暗号化されている可能性があります)。 ドキュメントの内容は、署名後も変更されません。 デジタル署名は、署名されたコンテンツが意図しないコンシューマーによって表示されるのを防ぐものではありません。

パッケージでのデジタル署名の表し方

アプリケーションは、パーツとリレーションシップの指定された構成を使用して、パッケージにデジタル署名を組み込みます。

署名フレームワークは、XML Digital Signature 標準で許可されているパッケージ名前空間の要素と属性を使用します。 パッケージ名前空間で定義されているシグネチャ要素は、矛盾することなく標準を拡張するパッケージ固有の機能をサポートします。 追加の概要については、OPC 仕様の「XML デジタル署名仕様の変更」セクションを参照してください。

署名フレームワークに定義されているパッケージ パーツは、配信元パーツ、XML 署名パーツ、および証明書パーツです。 それぞれに適切に定義されたコンテンツ タイプがあります。 適切に定義されたリレーションシップの種類は、OPC 仕様の付録 H「標準名前空間とコンテンツ タイプ」で指定されているように、パッケージ内の署名パーツを接続するために使用されます。

デジタル署名の配信元パーツ

Digital Signature Origin パーツは、パッケージ内の署名間を移動するための開始点です。 Digital Signature Origin パーツは、 Digital Signature Origin リレーションシップを使用してパッケージ ルートから対象とされます。 Origin パーツから複数の Signature パーツをターゲットにすることができます。 パッケージに署名がない場合、Origin パーツは存在しません。

デジタル署名 XML 署名パーツ

デジタル署名 XML 署名パーツには、W3C Digital Signature 標準およびパッケージ名前空間で定義されているマークアップが含まれています。 パーツは、デジタル 署名リレーションシップを 持つデジタル署名の配信元パーツ XML を対象とします。

デジタル署名証明書パーツ

署名者を識別するために必要な X.509 証明書は、パッケージに配置されている場合は、XML 署名パーツ内に埋め込んだり、別の証明書パーツに格納したりできます。 省略可能な証明書パーツは、 デジタル署名証明書 リレーションシップを持つ XML 署名パーツを対象とします。 証明書パーツは、複数の署名パーツ間で共有できます。

カスタム署名パーツ

カスタム (アプリケーション固有) 署名パーツは、署名フレームワークによって許可されますが、処理されません。 XML 署名以外の署名の形式を保持する署名パーツは、カスタム コンテンツ タイプで識別する必要があります。 さらに、カスタム リレーションシップの種類を持つリレーションシップを使用して、デジタル署名の配信元パーツからパーツをターゲットにする必要があります。

署名パーツとリレーションシップ

XML Digital Signature 標準では、アドレス指定可能なリソースの署名が可能です。これはパッケージのパーツです。 署名フレームワークでは、パーツの署名が有効になります。 リレーションシップ パーツに格納されているパッケージ内のリレーションシップは、一度にすべて署名することも、リレーションシップのサブセットを署名用に指定することもできます。

有効に署名されたパッケージ内のパーツが意図したとおりに使用またはレンダリングされるように、パーツのコンテンツ タイプがパーツ コンテンツと共に署名されます。 コンテンツ タイプはアドレス指定可能なリソースではないので、パッケージ固有のアプローチでコンテンツ タイプの値に署名します。 パッケージが署名されると、署名された各パーツのコンテンツ タイプが、署名されたパーツを参照する URI のクエリ コンポーネントに格納されます。 パッケージを使用すると、OPC Digital Signing Framework はコンテンツ タイプの値を使用して、パーツのコンテンツ タイプがパーツの署名後に変更されていないことを確認します。

リレーションシップ パーツが全体として署名されると、そのパーツで定義されているすべてのリレーションシップが署名されます。 署名を無効にせずにパッケージの一部のコンテンツを変更できるようにする署名ポリシーをサポートするために、署名フレームワークには、指定されたリレーションシップに署名するためのメカニズムが用意されています。 指定したリレーションシップに署名するために、署名フレームワークは特別な変換であるリレーションシップ変換を使用します (「 変換アルゴリズム」を参照)。

リレーションシップ変換では、指定されたリレーションシップ のセットのみを含むリレーションシップ パーツが作成されます。 取得したリレーションシップ パーツは、署名と署名の検証中に使用されます。

パッケージ署名のプログラミング サポート

署名に署名して検証するために、アプリケーションでは .NET 3.0 クラス PackageDigitalSignatureManager を使用できます。 System.IO.Packaging 名前空間で定義されているパッケージ固有のクラスは、System.Security.Cryptography.Xml名前空間で定義されている Microsoft .NET 3.0 Framework のデジタル署名クラスに基づいて構築されます。

PackageDigitalSignatureManager クラスは、署名の作成と検証、およびパッケージへの署名インフラストラクチャの配置に使用されます。 署名は、 PackageDigitalSignature クラスに基づくオブジェクトによって表されます。

署名パッケージのパーツとリレーションシップ

アプリケーションは、署名ポリシーに従って署名するパーツとリレーションシップの一覧を定義します。 次に、アプリケーションは PackageDigitalSignatureManager.Sign() メソッドを呼び出して署名を作成し、署名インフラストラクチャをパッケージに追加します。

次のサンプル コードは、リレーションシップ パーツを除くパッケージ内のすべてのパーツに署名し、パッケージ ルートからのすべての既存のリレーションシップに署名し、XML 署名パーツの署名に使用される証明書を埋め込む方法を示しています。 サンプル コードでは、最初にパッケージに署名が存在しないことを前提としており、検証の前に適用される署名は 1 つだけです。

署名プロセスの開始

パッケージ内の署名の操作を開始するには、次に示すように、まず 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 オブジェクトは、リレーションシップの種類 (Open Packaging Conventions の 「Standard Namespaces and Content Types」で定義されている) で定義されているグループとして作成することも、次のサンプルのようにリレーションシップ ID を指定して個別に作成することもできます。

     //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 を作成すると、指定された一意の ID を持つ 1 つのリレーションシップが署名用に選択されます。 PackageRelationshipSelectorType.Type を使用してセレクターを作成すると、指定した型を持つすべてのリレーションシップが署名用に選択されます。 同じ型のリレーションシップが後でパッケージに追加されると、署名は無効になります。

証明書オブジェクトの作成

署名する前に、有効な X.509 証明書を取得するには、 System.Security.Cryptography.X509Certificates.X509Certificate2 型のオブジェクトをインスタンス化します。 このオブジェクトは、署名時に 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();

アプリケーション署名ポリシー

パッケージ ベースの形式を使用するアプリケーションは、署名フレームワークの一部として独自のポリシーを定義します。 ポリシーは、形式の要素の種類とワークフロー要件によって決まります。 このセクションでは、署名ポリシーについて、1 つの Microsoft パッケージベースの形式 (XPS ドキュメント形式) について説明します。

XPS ドキュメント

XPS ドキュメント形式は、 XML Paper Specification で指定されている Open Packaging Conventions に基づいています。 XML Paper Specification では、XPS ドキュメントに署名するためのポリシーが定義されています。 そのポリシー内には、アプリケーションの機能またはワークフローをサポートするために使用できる署名オプションがあります。

XPS ドキュメント パッケージの署名ポリシー

XPS ドキュメントの署名ポリシーでは、コンテンツを検証できるように署名する必要がある一連のパーツとリレーションシップについて説明します。 このポリシーの一部として、アプリケーションは、必要に応じて、CoreProperties パーツなどのコンテンツに付属する特定のパーツの組み合わせを含む署名を作成できます。 これらのパーツに署名すると、署名を無効にせずに変更できなくなります。 さらに、アプリケーションは必要に応じて署名のデジタル署名の配信元パーツに添付されたリレーションシップ パーツに署名し、署名を無効にせずに新しい署名をドキュメントに追加することを禁止できます。

署名を有効にするために、XPS ドキュメント署名ポリシーでは、特定のパーツとリレーションシップが署名に含まれている必要があります。 認識できない部分やリレーションシップは署名できません。 署名を確認する場合、アプリケーションでは、必要なすべてのパーツとリレーションシップが署名されていることを確認する必要があります。

署名する XPS ドキュメント パーツ

次の表に、すべての XPS ドキュメントで署名する必要があるパーツと、必要に応じて署名されるパーツの一覧を示します。 リレーションシップの場合、XPS 署名ポリシーでは、必要なリレーションシップ (必要なパーツを対象とするリレーションシップ) が、OPC 定義のリレーションシップ変換を使用して常に署名されるように指定します。 パーツが署名されている場合は、そのパーツを対象とするリレーションシップも署名する必要があります。

パーツの種類 ポリシー
FixedDocumentSequence パーツ 署名する必要がある
FixedDocument パーツ 署名する必要がある
DocumentStructure パーツ 署名する必要がある
SignatureDefinitions パーツ 署名する必要がある
FixedPage パーツ 署名する必要がある
必要なリソース パーツ (フォント、イメージなど) 署名する必要がある
StoryFragments パーツ 署名する必要がある
サムネイル パーツ 署名する必要がある
CoreProperties パーツ 必要に応じて署名
デジタル署名の配信元パーツ 必要に応じて署名
デジタル署名証明書パーツ 必要に応じて署名
PrintTicket パーツ 必要に応じて署名
DiscardControl パーツ 必要に応じて署名

XPS 署名ポリシーの詳細については、「XML Paper Specification」の「XPS ドキュメント パッケージ機能: デジタル署名: 署名規則」セクションを参照してください。

マークアップ互換性署名ポリシー

XML Paper Specification では、XPS ドキュメントに代替コンテンツを含める方法について説明します。 代替コンテンツは、マークアップ互換性名前空間の要素内に配置されます。 ポリシーによって、マークアップ互換性要素と属性を持つ XPS ドキュメントは、署名アプリケーションがすべてのコンテンツ代替手段を同等と認識しない限り、有効に署名できません。 署名または検証できるのは、認識される要素と属性を含む XPS ドキュメントのみです。

副署名

XPS ドキュメントのコンテンツには、複数の署名を適用できます。 たとえば、法的契約を表すコンテンツでは、署名されたコンテンツと署名者の ID を示す署名の適用が複数のユーザーに要求される場合があります。

新しい署名を追加すると、常に、デジタル署名の配信元パーツにアタッチされているリレーションシップ パーツ内に新しいリレーションシップが作成されます。 既存の署名を無効にせずに XPS ドキュメントに新しい署名を追加するには、このリレーションシップ パーツは署名されていない状態を維持する必要があります (ただし、リレーションシップのサブセットは署名される可能性があります)。 リレーションシップ パーツが署名に含まれている場合、その署名は、その後適用されるすべての署名によって無効になります。

XPS 署名の検証

XPS 署名ポリシーでは、署名の作成を定義するだけでなく、署名を有効として検証する方法も指定します。 ポリシーは、次の表に示すように、非準拠、破損、疑わしい、有効な署名の有効性の状態を定義します。

署名の状態 必要なパーツとリレーションシップはすべて署名されますか? 署名には、認識されたコンテンツのみが含まれますか? 署名されたコンテンツのハッシュが検証されていますか? 署名付きマークアップ互換性コンテンツが認識されますか? 証明書は有効ですか?
非準拠 NO

YES

該当なし

NO

該当なし

該当なし

該当なし

該当なし

該当なし

該当なし

中断 YES YES NO 該当なし 該当なし
疑わしい YES

YES

YES

YES

YES

YES

NO

YES

該当なし

NO

有効 YES YES YES YES YES

XPS ビューアーには、疑わしい XPS 署名と壊れた XPS 署名と、有効な XPS 署名が表示されます。 準拠していないシグネチャは列挙されません。

XPS 署名のプログラミング サポート

XPS ドキュメントを使用する場合、アプリケーションは XpsDigitalSignature クラスの メソッドを使用できます。 このクラスは PackageDigitalSignature クラスに基づいており、XPS デジタル署名仕様で指定されているアルゴリズムと要件に従うメソッドが含まれています。 署名メソッドと検証メソッドは、XPS ドキュメントのすべての必須パーツとリレーションシップが署名されていることを確認します。

XPS ドキュメントへの署名

XPS ドキュメントに署名するには、 XpsDocument.SignDigitally() メソッドを使用します。 メソッドを呼び出す前に、アプリケーションには、オブジェクト System.Security.Cryptography.X509Certificates.X509Certificate2 を使用して取得できる X.509 証明書が必要です。

     // 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 パーツを署名から除外すると、アプリケーションは署名を無効にせずに一部のドキュメント プロパティを変更できます。

PrintTicket パーツと DiscardControl パーツは、SignDigitally() メソッドによって作成された署名から除外されますが、これらのパーツは必要に応じてアプリケーション固有の方法で署名できます。

XPS ドキュメント署名の確認

1 つまたは複数の署名を 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
          }
     }

リファレンス