XML デジタル署名 API

概要およびチュートリアル

目次

Java XML デジタル署名 API

XML セキュリティースタック

パッケージ階層

サービスプロバイダ

XML 署名について

XML 署名の例

XML デジタル署名 API の例

検証の例

XML 署名の検証

署名を含むドキュメントのインスタンス化

検証する署名要素の指定

検証コンテキストの作成

XML 署名の非整列化

XML 署名の検証

XML 署名の検証に失敗した場合

KeySelector の使用

genenveloped の例

XML 署名の生成

署名するドキュメントのインスタンス化

公開鍵のペアの作成

署名コンテキストの作成

XML 署名の構築

XML 署名の生成

生成されるドキュメントの印刷または表示


Java XML デジタル署名 API

Java XML デジタル署名 API は、XML 署名を生成および検証するための標準の Java API です。この API は、Java Community Process のもとで JSR 105 として定義されました (http://jcp.org/en/jsr/detail?id=105 を参照)。この JSR は最終的なものであり、このリリースの Java SE には、API の最終バージョンの FCS アクセス実装が含まれています。

XML 署名は、任意のタイプのデータ (XML またはバイナリ) に適用できます (http://www.w3.org/TR/xmldsig-core/ を参照)。結果の署名は、XML で表されます。XML 署名は、データを保護するために使用でき、データの整合性、メッセージ認証、および署名者認証を提供します。

このドキュメントでは、XML 署名と XML デジタル署名 API の概要を説明したあとで、API を使用して XML 署名を検証および生成する方法を示す 2 つの例について説明します。このドキュメントは、読者に暗号化およびデジタル署名の基本的な知識があることを前提としています。

API は、「XML-Signature Syntax and Processing」での W3C 勧告の必須機能または推奨機能をすべてサポートするように設計されています。API は拡張可能およびプラグイン可能であり、Java 暗号化サービスプロバイダアーキテクチャーに基づいてます。API は、次の 2 種類の開発者向けに設計されています。

  • XML デジタル署名 API を使用して XML 署名を生成および検証する開発者
  • XML デジタル署名 API の固定実装を作成し、JCA プロバイダの暗号化サービスとして登録する開発者

パッケージ階層

次に示す 6 個のパッケージが、XML デジタル署名 API を構成します。

  • javax.xml.crypto
  • javax.xml.crypto.dsig
  • javax.xml.crypto.dsig.keyinfo
  • javax.xml.crypto.dsig.spec
  • javax.xml.crypto.dom
  • javax.xml.crypto.dsig.dom

javax.xml.crypto パッケージには、XML 署名の生成や XML データの暗号化など、XML 暗号化操作を行う場合に使用する共通クラスが含まれています。このパッケージで注意すべき 2 つのクラスのうちの 1 つは KeySelector クラスで、開発者は、KeyInfo オブジェクトに含まれる情報を使用して鍵を見つけてオプションで検証する実装を提供できます。もう 1 つのクラスは URIDereferencer クラスで、開発者は、実装を間接参照する独自の URI を作成および指定できます。

javax.xml.crypto.dsig パッケージには、W3C XML デジタル署名仕様で定義されているコア要素を表すインタフェースが含まれています。もっとも重要なのは XMLSignature クラスです。このクラスを使用すると、XML デジタル署名の署名および検証を行うことができます。XML 署名構造または要素のほとんどは、対応するインタフェースによって表されます (KeyInfo 構造を除く。これは独自のパッケージに含まれており、次の段落で説明)。これらのインタフェースには、SignedInfoCanonicalizationMethodSignatureMethodReferenceTransformDigestMethodXMLObjectManifestSignatureProperty、および SignatureProperties があります。XMLSignatureFactory クラスは、これらのインタフェースを実装するオブジェクトを作成する場合に使用する抽象ファクトリです。

javax.xml.crypto.dsig.keyinfo パッケージには、W3C XML デジタル署名勧告で定義されているほとんどの KeyInfo 構造を表すインタフェースが含まれています。この構造には、KeyInfoKeyNameKeyValueX509DataX509IssuerSerialRetrievalMethod、および PGPData があります。KeyInfoFactory クラスは、これらのインタフェースを実装するオブジェクトを作成する場合に使用する抽象ファクトリです。

javax.xml.crypto.dsig.spec パッケージには、ダイジェスト、署名、変換、または XML 署名の処理で使用される正規化アルゴリズム用の入力パラメータを表すインタフェースおよびクラスが含まれています。

最後に、javax.xml.crypto.dom および javax.xml.crypto.dsig.dom パッケージには、javax.xml.crypto および javax.xml.crypto.dsig パッケージ用の DOM 固有のクラスが含まれています。DOM ベースの XMLSignatureFactory または KeyInfoFactory 実装を作成または使用する開発者およびユーザーのみが、これらのパッケージを直接使用する必要があります。

サービスプロバイダ

JSR 105 暗号化サービスは、XMLSignatureFactory および KeyInfoFactory 抽象クラスの固定実装であり、XML 署名や KeyInfo 構造を解析、生成、および検証するオブジェクトやアルゴリズムを作成します。XMLSignatureFactory の固定実装は、XML 署名について W3C 勧告で指定されているように、必須アルゴリズムそれぞれをサポートする必要があります。オプションで、W3C 勧告またはその他の仕様で定義されているように、その他のアルゴリズムをサポートできます。

JSR 105 は、JCA プロバイダモデルを使用して XMLSignatureFactory および KeyInfoFactory 実装の登録とロードを行います。

固定実装 XMLSignatureFactory または KeyInfoFactory はそれぞれ、XML 署名や KeyInfo 構造を解析および生成するときに実装によって内部で使用される XML 処理メカニズムを識別する特定の「XML メカニズムタイプ」をサポートしています。この JSR は、1 つの標準形式である DOM をサポートします。Java SE にバンドルされている XML デジタル署名プロバイダ実装は、DOM メカニズムをサポートします。JDOM などの新しい標準形式のサポートが、将来的に追加される可能性があります。

XML デジタル署名 API 実装は、java.security.Signaturejava.security.MessageDigest など、基盤となる JCA エンジンクラスを使用して暗号化操作を実行するようにしてください。

XMLSignatureFactory および KeyInfoFactory クラス以外に、JSR 105 は、変換および正規化アルゴリズム用のサービスプロバイダインタフェースもサポートしています。TransformService クラスを使用すると、特定の XML メカニズムタイプ用の固有の変換または正規化アルゴリズムの実装を開発およびプラグインすることができます。TransformService クラスは、実装を登録およびロードするときに標準 JCA プロバイダモデルを使用します。各 JSR 105 実装は、TransformService クラスを使用して、生成または検証する XML 署名内の変換および正規化アルゴリズムをサポートするプロバイダを見つけるようにしてください。

XML 署名について

XML 署名を使用すると、XML かバイナリかにかかわらず、任意のデータに署名できます。データは 1 つ以上の Reference 要素内の URI によって識別されます。XML 署名は分離、内包、または包含の 3 つの形式のうち、1 つ以上の形式で記述されます。分離署名は外部、つまり署名要素自体の外にあるデータに対するものです。内包署名は署名要素の内側にあるデータに対する署名です。包含署名は署名対象のデータ内に含まれる署名です。

XML 署名の例

XML 署名の内容を説明するもっとも簡単な方法は、実際のサンプルを示し、各コンポーネントについて詳細に説明することです。次に、XML ドキュメントの内容に対して生成される包含 XML 署名の例を示します。署名される前のドキュメントの内容は、次のとおりです。

<Envelope xmlns="urn:envelope">
</Envelope> 

結果の包含 XML 署名は次のとおりです。読みやすくするために、インデントおよび形式設定されています。

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="urn:envelope">
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod 
        Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue>uooqbWYa5VCqcJCbuymBKqm17vY=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>
      KedJuTob5gtvYx9qM3k3gm7kbLBwVbEQRl26S2tmXjqNND7MRGtoew==
    </SignatureValue>
    <KeyInfo>
      <KeyValue>
        <DSAKeyValue>
          <P>
            /KaCzo4Syrom78z3EQ5SbbB4sF7ey80etKII864WF64B81uRpH5t9jQTxe
            Eu0ImbzRMqzVDZkVG9xD7nN1kuFw==
          </P>
          <Q>li7dzDacuo67Jg7mtqEm2TRuOMU=</Q>
          <G>
            Z4Rxsnqc9E7pGknFFH2xqaryRPBaQ01khpMdLRQnG541Awtx/
            XPaF5Bpsy4pNWMOHCBiNU0NogpsQW5QvnlMpA==
          </G>
          <Y>
            qV38IqrWJG0V/mZQvRVi1OHw9Zj84nDC4jO8P0axi1gb6d+475yhMjSc/
            BrIVC58W3ydbkK+Ri4OKbaRZlYeRA==
          </Y>
        </DSAKeyValue>
      </KeyValue>
    </KeyInfo>
  </Signature>
</Envelope> 

Signature 要素は署名対象の内容に挿入されており、それによって包含署名になっています。必須の SignedInfo 要素には、実際に署名される次の情報が含まれています。

<SignedInfo>
  <CanonicalizationMethod 
    Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
  <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
  <Reference URI="">
    <Transforms>
      <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
    </Transforms>
    <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
    <DigestValue>uooqbWYa5VCqcJCbuymBKqm17vY=</DigestValue>
  </Reference>
</SignedInfo> 

必須の CanonicalizationMethod 要素は、署名または検証の前に SignedInfo 要素を正規化するために使用されるアルゴリズムを定義します。正規化とは、そのデータに対する署名を無効化する可能性がある変更を考慮するために、XML の内容を正規形に変換する処理のことを意味します。正規化は、XML の性質および異なるプロセッサと中間的存在による解析のために必要です。正規化により、署名が無効になっても署名されたデータが論理的に同等であるようにデータを変更できます。

必須の SignatureMethod 要素は、署名の生成に使用されるデジタル署名アルゴリズムを定義します。この場合は、SHA-1 を使用する DSA です。

1 つ以上の Reference 要素が、ダイジェストされるデータを識別します。各 Reference 要素は、URI によってデータを識別します。この例では、URI の値は空の文字列 ("") で、これはドキュメントのルートを示します。オプションの Transforms 要素には、1 つ以上の Transform 要素のリストが含まれており、それぞれがダイジェスト前のデータの変換に使用される変換アルゴリズムを記述します。この例では、包含変換アルゴリズムの Transform 要素が 1 つあります。包含変換は、署名値を計算する前に署名要素自体が削除されるようにするために、包含署名に必要です。必須の DigestMethod 要素は、データのダイジェストに使用されるアルゴリズムを定義します。この場合は、SHA1 です。最後に、必須の DigestValue 要素には、実際の Base64 でエンコードされたダイジェスト値が含まれています。

必須の SignatureValue 要素には、SignedInfo 要素に対する署名の Base64 でエンコードされた署名値が含まれています。

オプションの KeyInfo 要素には、署名の検証に必要な鍵に関する情報が含まれています。

<KeyInfo>
  <KeyValue>
    <DSAKeyValue>
      <P>
        /KaCzo4Syrom78z3EQ5SbbB4sF7ey80etKII864WF64B81uRpH5t9jQTxe
        Eu0ImbzRMqzVDZkVG9xD7nN1kuFw==
      </P>
      <Q>li7dzDacuo67Jg7mtqEm2TRuOMU=</Q>
      <G>
        Z4Rxsnqc9E7pGknFFH2xqaryRPBaQ01khpMdLRQnG541Awtx/
        XPaF5Bpsy4pNWMOHCBiNU0NogpsQW5QvnlMpA==
      </G>
      <Y>
        qV38IqrWJG0V/mZQvRVi1OHw9Zj84nDC4jO8P0axi1gb6d+475yhMjSc/
        BrIVC58W3ydbkK+Ri4OKbaRZlYeRA==
      </Y>
    </DSAKeyValue>
  </KeyValue>
</KeyInfo> 

この KeyInfo 要素には KeyValue 要素が含まれています。この要素には、署名の検証に必要な公開鍵で構成される DSAKeyValue 要素が含まれています。KeyInfo には、X.509 証明書および PGP 鍵識別子など、さまざまな内容を含めることができます。さまざまなKeyInfo タイプの詳細については、XML 署名勧告の KeyInfo セクションを参照してください。

XML デジタル署名 API の例

次のセクションでは、XML デジタル署名 API を使用する方法を示す 2 つの例について説明します。

  • 検証の例
  • 署名の例

検証の例

このセクションで示すコードは、docs/technotes/guides/security/xmldsig ディレクトリの Validate.java ファイルにあります。処理のもとになるファイル envelopedSignature.xml は、同じディレクトリ内にあります。

この例をコンパイルして実行するには、docs/technotes/guides/security/xmldsig ディレクトリから次のコマンドを実行します。

$ javac Validate.java
$ java Validate signature.xml

サンプルプログラムは現在の作業ディレクトリ内のファイル signature.xml の署名を検証します。

XML 署名の検証

この例では、JSR 105 API を使用して XML 署名を検証する方法を示します。この例は DOM (Document Object Model) を使用して、署名要素を含む XMLドキュメントおよび JSR 105 DOM 実装を解析し、署名を検証します。

署名を含むドキュメントのインスタンス化

最初に、JAXP DocumentBuilderFactory を使用して、署名を含む XML ドキュメントを解析します。アプリケーションは、次のコード行を呼び出すことによって、DocumentBuilderFactory のデフォルト実装を取得します。

DocumentBuilderFactory dbf = 
  DocumentBuilderFactory.newInstance(); 

ファクトリ名前空間認識も作成します。

dbf.setNamespaceAware(true); 

次に、このファクトリを使用して DocumentBuilder のインスタンスを取得します。これはドキュメントの解析で使用されます。

DocumentBuilder builder = dbf.newDocumentBuilder();  
Document doc = builder.parse(new FileInputStream(argv[0])); 

検証する署名要素の指定

ドキュメントに複数含まれている場合もあるため、検証する Signature 要素を指定する必要があります。DOM メソッド Document.getElementsByTagNameNS を使用して、次に示すように、Signature 要素の XML 署名名前空間 URI およびタグ名をメソッドに渡します。

NodeList nl = doc.getElementsByTagNameNS
  (XMLSignature.XMLNS, "Signature");
if (nl.getLength() == 0) {
  throw new Exception("Cannot find Signature element");
} 

これは、ドキュメント内にあるすべての Signature 要素のリストを返します。この例では Signature 要素は 1 つのみです。

検証コンテキストの作成

署名を検証するための入力パラメータを含む XMLValidateContext インスタンスを作成します。DOM を使用しているため、DOMValidateContext インスタンス (XMLValidateContext のサブクラス) をインスタンス化し、2 つのパラメータを渡します。2 つのパラメータとは、KeyValueKeySelector オブジェクトと、先に生成した NodeList の最初のエントリである、検証する Signature 要素の参照です。

DOMValidateContext valContext = new DOMValidateContext
  (new KeyValueKeySelector(), nl.item(0)); 

KeyValueKeySelector については、「KeySelector の使用」で詳細に説明します。

XML 署名の非整列化

Signature 要素の内容を XMLSignature オブジェクトに抽出します。この処理は非整列化と呼ばれます。Signature 要素は XMLSignatureFactory オブジェクトを使用して非整列化されます。アプリケーションは次のコード行を呼び出すことによって、XMLSignatureFactory の DOM 実装を取得できます。

XMLSignatureFactory factory = 
  XMLSignatureFactory.getInstance("DOM"); 

次に、ファクトリの unmarshalXMLSignature メソッドを呼び出して XMLSignature オブジェクトを非整列化し、先に作成した検証コンテキストを渡します。


XMLSignature signature = 
  factory.unmarshalXMLSignature(valContext); 

XML 署名の検証

これで、署名を検証する準備が整いました。XMLSignatureオブジェクトで validate メソッドを呼び出して、次に示すように検証コンテキストを渡します。

boolean coreValidity = signature.validate(valContext); 

W3C XML 署名勧告コア検証規則に従って署名が正常に検証されると、validate メソッドは「true」を返します。それ以外の場合は false を返します。

XML 署名の検証に失敗した場合

XMLSignature.validate メソッドが false を返した場合、失敗の原因の絞り込みを試行できます。コア XML 署名検証には、次の 2 つのフェーズがあります。

  • Signature validation (署名の暗号検証)
  • Reference validation (署名内の各参照のダイジェストの検証)

署名が有効になるには、それぞれのフェーズが成功する必要があります。署名の暗号化の検証が失敗したかどうかをチェックするために、次に示すようにステータスをチェックできます。

boolean sv = 
  signature.getSignatureValue().validate(valContext);
System.out.println("signature validation status: " + sv); 

次に示すように、参照に対して繰り返し実行して、各参照の検証ステータスをチェックすることもできます。

Iterator i =
  signature.getSignedInfo().getReferences().iterator();
for (int j=0; i.hasNext(); j++) {
  boolean refValid = ((Reference) 
    i.next()).validate(valContext);
  System.out.println("ref["+j+"] validity status: " + 
    refValid);
} 

KeySelector の使用

KeySelectors は、XMLSignature の検証に必要な鍵を見つけて選択するために使用されます。以前は、DOMValidateContext オブジェクトを作成したときは、KeySelector オブジェクトを最初の引数として渡しました。

DOMValidateContext valContext = new DOMValidateContext
  (new KeyValueKeySelector(), nl.item(0)); 

また、署名の検証に必要な鍵がすでにわかっている場合は、PublicKey を最初の引数として渡すこともできました。ただし、多くの場合はわかりません。

KeyValueKeySelector は、抽象 KeySelector クラスの固定実装です。KeyValueKeySelector 実装は、XMLSignatureKeyInfo 要素の KeyValue 要素に含まれるデータを使用して、適切な検証鍵を見つけようとします。鍵が信頼できるかどうかは判断しません。これは、単純な KeySelector 実装であり、実際の使用というよりは説明のために設計されています。KeySelector のより実用的な例は、KeyInfo に含まれる X509Data 情報 (X509SubjectName 要素、X509IssuerSerial 要素、X509SKI 要素、X509Certificate 要素など) に一致する信頼できる鍵で KeyStore を検索する例です。

KeyValueKeySelector の実装は、次のとおりです。

private static class KeyValueKeySelector extends KeySelector {

  public KeySelectorResult select(KeyInfo keyInfo,
      KeySelector.Purpose purpose,
      AlgorithmMethod method,
      XMLCryptoContext context)
    throws KeySelectorException {

    if (keyInfo == null) {
      throw new KeySelectorException("Null KeyInfo object!");
    }
    SignatureMethod sm = (SignatureMethod) method;
    List list = keyInfo.getContent();

    for (int i = 0; i < list.size(); i++) {
      XMLStructure xmlStructure = (XMLStructure) list.get(i);
      if (xmlStructure instanceof KeyValue) {
        PublicKey pk = null;
        try {
          pk = ((KeyValue)xmlStructure).getPublicKey();
        } catch (KeyException ke) {
          throw new KeySelectorException(ke);
        }
        // make sure algorithm is compatible with method
        if (algEquals(sm.getAlgorithm(), 
            pk.getAlgorithm())) {
          return new SimpleKeySelectorResult(pk);
        }
      }
    }
    throw new KeySelectorException("No KeyValue element 
found!");
  }

  static boolean algEquals(String algURI, String algName) {
    if (algName.equalsIgnoreCase("DSA") &&
        algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) {
      return true;
    } else if (algName.equalsIgnoreCase("RSA") &&
        algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)) {
      return true;
    } else {
      return false;
    }
  }
} 

genenveloped の例

このセクションで説明するコードは、docs/technotes/guides/security/xmldsig ディレクトリの GenEnveloped.java ファイルにあります。処理のもとになるファイル envelope.xml は、同じディレクトリ内にあります。このファイルは、ファイル envelopedSignature.xml を生成します。

このサンプルをコンパイルして実行するには、docs/technotes/guides/security/xmldsig ディレクトリから次のコマンドを実行します。

$ javac GenEnveloped.java
$ java GenEnveloped envelope.xml envelopedSignature.xml

サンプルプログラムはファイル envelope.xml 内のドキュメントの包含署名を生成し、現在の作業ディレクトリ内のファイル envelopedSignature.xml に保存します。

XML 署名の生成

この例では、XML デジタル署名 API を使用して XML 署名を生成する方法を示します。より具体的には、この例は XML ドキュメントの包含 XML 署名を生成します。包含署名とは、署名対象の内容に含まれる署名です。この例は DOM (Document Object Model) を使用して、署名対象の XMLドキュメントおよび JSR 105 DOM 実装を解析し、結果の署名を生成します。

XML 署名およびそのさまざまなコンポーネントの基本的な知識が、このセクションの理解に役立ちます。詳細は、http://www.w3.org/TR/xmldsig-core/ を参照してください。

署名するドキュメントのインスタンス化

最初に、JAXP DocumentBuilderFactory を使用して、署名する XML ドキュメントを解析します。アプリケーションは、次のコード行を呼び出すことによって、DocumentBuilderFactory のデフォルト実装を取得します。

DocumentBuilderFactory dbf =
  DocumentBuilderFactory.newInstance(); 

ファクトリ名前空間認識も作成します。

dbf.setNamespaceAware(true); 

次に、このファクトリを使用して DocumentBuilder のインスタンスを取得します。これはドキュメントの解析で使用されます。

DocumentBuilder builder = dbf.newDocumentBuilder();  
Document doc = builder.parse(new FileInputStream(argv[0])); 

公開鍵のペアの作成

公開鍵のペアを生成します。あとの例では、非公開鍵を使用して署名を生成します。KeyPairGenerator を使用して、鍵のペアを作成します。この例では、512 バイトの長さの DSA KeyPair を作成します。

KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(512);
KeyPair kp = kpg.generateKeyPair(); 

実際には、非公開鍵は通常は以前に生成されて、関連する公開鍵証明書とともに KeyStore ファイルに保存されています。

署名コンテキストの作成

署名を生成するための入力パラメータを含む、XML デジタル署名 XMLSignContext を作成します。DOM を使用しているので、DOMSignContext (XMLSignContext のサブクラス) をインスタンス化し、2 つのパラメータを渡します。パラメータは、ドキュメントの署名に使用される非公開鍵と署名対象のドキュメントのルートです。

DOMSignContext dsc = new DOMSignContext
  (kp.getPrivate(), doc.getDocumentElement()); 

XML 署名の構築

Signature 要素のさまざまな部分を組み合わせて、XMLSignature オブジェクトにします。これらのオブジェクトはすべて、XMLSignatureFactory オブジェクトを使用して、作成され組み合わせられます。アプリケーションは次のコード行を呼び出すことによって、XMLSignatureFactory の DOM 実装を取得します。

XMLSignatureFactory fac = 
  XMLSignatureFactory.getInstance("DOM"); 

次に示すように、さまざまなファクトリメソッドを呼び出して XMLSignature オブジェクトのさまざまな部分を作成します。Reference オブジェクトを作成して、そのオブジェクトに次のものを渡します。

  • 署名対象のオブジェクトの URI (ここでは、ドキュメントのルートを示す URI "" を指定)
  • DigestMethod (ここでは、SHA1 を使用)
  • 1 つの Transform、包含 Transform (署名値の計算の前に署名自体が削除されるように、包含署名で必要)
Reference ref = fac.newReference
  ("", fac.newDigestMethod(DigestMethod.SHA1, null),
    Collections.singletonList
      (fac.newTransform(Transform.ENVELOPED,
        (TransformParameterSpec) null)), null, null); 

次に、SignedInfo オブジェクトを作成します。これは、次に示すように、実際に署名されるオブジェクトです。SignedInfo を作成するときは、次のものをパラメータとして渡します。

  • CanonicalizationMethod (ここでは、INCLUSIVE を使用してコメントを保持)
  • SignatureMethod (ここでは、DSA を使用)
  • References のリスト (この場合は 1 つのみ)
SignedInfo si = fac.newSignedInfo
  (fac.newCanonicalizationMethod
    (CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
      (C14NMethodParameterSpec) null),
    fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null),
    Collections.singletonList(ref)); 

次に、オプションの KeyInfo オブジェクトを作成します。このオブジェクトには、受け側が署名の検証に必要な鍵を見つけられるようにする情報が含まれています。この例では、公開鍵を含む KeyValue オブジェクトを追加します。KeyInfo およびそのさまざまなサブタイプを作成するには、KeyInfoFactory オブジェクトを使用します。このオブジェクトは次に示すように、XMLSignatureFactorygetKeyInfoFactory メソッドを呼び出すことによって取得できます。

KeyInfoFactory kif = fac.getKeyInfoFactory(); 

次に、KeyInfoFactory を使用して KeyValue オブジェクトを作成し、KeyInfo オブジェクトに追加します。

KeyValue kv = kif.newKeyValue(kp.getPublic());
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv)); 

最後に、XMLSignature オブジェクトを作成し、先に作成した SignedInfo および KeyInfo オブジェクトをパラメータとして渡します。

XMLSignature signature = fac.newXMLSignature(si, ki); 

まだ実際には署名を生成していません。次のステップで生成します。

XML 署名の生成

これで、署名を生成する準備が整いました。XMLSignature オブジェクトで sign メソッドを呼び出して、次に示すように署名コンテキストを渡します。

signature.sign(dsc); 

これで、結果のドキュメントには署名が含まれています。署名は、ルート要素の最後の子要素として挿入されました。

生成されるドキュメントの印刷または表示

次のコードを使用して、結果の署名済みドキュメントをファイルまたは標準出力に印刷できます。

OutputStream os;
if (args.length > 1) {
  os = new FileOutputStream(args[1]);
} else {
  os = System.out;
} 
TransformerFactory tf = TransformerFactory.newInstance();
Transformer trans = tf.newTransformer();
trans.transform(new DOMSource(doc), new StreamResult(os)); 


Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.