Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

XML ドキュメントの署名

この章では、XML ドキュメントにデジタル・シグニチャを追加する方法を説明します。以下のトピックについて説明します。

Tip:

このネームスペースで SOAP ロギングを有効にしておくと、あらゆるエラーの詳細を受け取ることができるので便利です。"Caché での Web サービスおよび Web クライアントの作成" の “Caché SOAP の問題のトラブルシューティング” にある “Caché SOAP ログ” を参照してください。

別のダイジェスト、シグニチャ、正規化メソッドの詳細は、"Caché Web サービスの保護" の “デジタル・シグニチャの追加” を参照してください。

デジタル署名が行われたドキュメントについて

デジタル署名が行われた XML ドキュメントには 1 つ以上の <Signature> 要素が含まれ、その要素それぞれがデジタル・シグニチャです。それぞれの <Signature> 要素によって、以下のように、ドキュメント内の特定の要素に対して署名が行われます。

  • 署名されたそれぞれの要素には Id 属性があり、この属性は何らかの一意の値となります。以下はその例です。

    <Person xmlns="http://mynamespace" Id="123456789">
    
  • <Signature> 要素には、以下のように、その Id を指す <Reference> 要素が含まれています。

    <Reference URI="#123456789">
    

    <Signature> 要素は、秘密鍵によって署名されます。この要素には、認証機関によって署名された X.509 証明書が含まれています。この署名されたドキュメントの受信者は、この認証機関を信頼していれば、その証明書を検証し、含まれている公開鍵を使用してシグニチャを検証できます。

Note:

Caché では、署名された要素が Id ではなく、ID という名前の属性を保持するというバリエーションもサポートしています。詳細は、この章の最後のセクションを参照してください。

以下の例では、見やすくするために空白を追加してあります。

<?xml version="1.0" encoding="UTF-8"?>
<Person xmlns="http://mynamespace" Id="123456789">
  <Name>Persephone MacMillan</Name>
  <DOB>1976-02-20</DOB>
  <s01:Signature xmlns="http://www.w3.org/2000/09/xmldsig#" 
                 xmlns:s01="http://mynamespace" 
                 s02:Id="Id-BC0B1674-758D-40B9-84BF-F7BAA3AA19F4" 
xmlns:s02="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
      </CanonicalizationMethod>
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1">
      </SignatureMethod>
      <Reference URI="#123456789">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature">
          </Transform>
          <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml1317c14n-20010315">
          </Transform>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
        <DigestValue>FHwW2U58bztLI4cIE/mp+nsBNZg=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>MTha3zLoj8Tg content omitted</SignatureValue>
    <KeyInfo>
      <X509Data>
        <X509Certificate>MIICnDCCAYQCAWUwDQYJ content omitted</X509Certificate>
      </X509Data>
    </KeyInfo>
  </s01:Signature>
</Person>

デジタル・シグニチャを作成するには、クラス %XML.Security.SignatureOpens in a new tab を使用します。これは、XML 対応のクラスのうち、適切なネームスペースにおいてこのプロジェクションが有効な <Signature> 要素になっているものです。

デジタル署名が行われた XML ドキュメントの作成

デジタル署名が行われた XML ドキュメントを作成するには、%XML.WriterOpens in a new tab を使用して、適切に定義された 1 つ以上の XML 対応オブジェクトの出力を生成します。

オブジェクトの出力を生成する前に、必要とされるシグニチャを作成してオブジェクトに記述することによって、出力先に情報を書き込めるようにしておく必要があります。

署名の前提条件

ドキュメントに署名するには、まず少なくとも 1 つの Caché 資格情報セットを作成する必要があります。Caché 資格情報セットとは以下の情報セットの別名であり、システム管理者のデータベースに格納されています。

  • 公開鍵を含む証明書。この証明書は、ドキュメントの受信者に信頼される認証機関によって署名されている必要があります。

  • 関連付けられている秘密鍵。この秘密鍵は、必要なときに Caché が使用しますが、送信することはありません。

    秘密鍵は署名用に必要です。

  • (オプション) 秘密鍵のパスワード。この秘密鍵は、必要なときに Caché が使用しますが、送信することはありません。秘密鍵をロードすることも、実行時にこれを指定するとこもできます。

詳細は、"Caché Web サービスの保護" の “設定およびその他の一般的なアクティビティ” を参照してください。

XML 対応クラスの要件

XML 対応クラスには、以下のものが含まれている必要があります。

  • Id 属性として投影されているプロパティ。

  • タイプが %XML.Security.SignatureOpens in a new tab で、<Signature> 要素として投影されている、少なくとも 1 つのプロパティ (1 つの XML ドキュメントには、複数の <Signature> 要素が含まれる場合もあります)。

以下のクラスを考えてみます。

Class XMLSignature.Simple Extends (%RegisteredObject, %XML.Adaptor)
{

Parameter NAMESPACE = "http://mynamespace";

Parameter XMLNAME = "Person";

Property Name As %String;

Property DOB As %String;

Property PersonId As %String(XMLNAME = "Id", XMLPROJECTION = "ATTRIBUTE");

Property MySig As %XML.Security.Signature(XMLNAME = "Signature");

//methods
}

シグニチャの生成と追加

デジタル署名を生成して追加するには、以下の手順を実行します。

  1. 必要に応じて、%soap.inc インクルード・ファイルを組み込みます。このファイルには、使用する可能性のあるマクロが定義されています。

  2. 適切な Caché 資格情報セットにアクセスする %SYS.X509CredentialsOpens in a new tab のインスタンスを作成します。これには、%SYS.X509CredentialsOpens in a new tabGetByAlias() クラス・メソッドを呼び出します。

    classmethod GetByAlias(alias As %String, pwd As %String) as %SYS.X509Credentials
    
    • alias は、証明書のエイリアスです。

    • pwd は、秘密鍵のパスワードです。秘密鍵のパスワードは、関連付けられている秘密鍵が暗号化されていて、その秘密鍵のファイルをロードしたときにパスワードがロードされなかった場合にのみ必要です。

    このメソッドを実行するには、当該の資格情報セットの OwnerList に記載されたユーザとしてログインするか、OwnerList が NULL である必要があります。"Caché Web サービスの保護" の “プログラムによる資格情報セットの取得” も参照してください。

  3. 指定された資格情報セットを使用する %XML.Security.SignatureOpens in a new tab のインスタンスを作成します。これには、そのクラスの CreateX509() クラス・メソッドを呼び出します。

    classmethod CreateX509(credentials As %SYS.X509Credentials,              signatureOption As %Integer,              referenceOption As %Integer) as %XML.Security.Signature
    
    • credentials は、先ほど作成した %SYS.X509CredentialsOpens in a new tab のインスタンスです。

    • signatureOption$$$SOAPWSIncludeNone です (他のオプションもありますが、このシナリオには該当しません)。

    • referenceOption は、署名された要素に対する参照の特性です。許可される値については、"Caché Web サービスの保護" の “X.509 証明書の参照オプション” を参照してください。

    ここで使用されるマクロは、%soap.inc インクルード・ファイルで定義します。

  4. このシグニチャが指す Id については、Id 属性の値を取得します。

    この詳細は、XML 対応オブジェクトの定義によって異なります。

  5. その Id を指す %XML.Security.ReferenceOpens in a new tab のインスタンスを作成します。これには、そのクラスの Create() クラス・メソッドを呼び出します。

    ClassMethod Create(id As %String,                    algorithm As %String,                    prefixList As %String)
    

    id は、この参照が指す ID です。

    algorithm は、以下のいずれかにする必要があります。

    • $$$SOAPWSEnvelopedSignature_","_$$$SOAPWSexcc14n — 排他的な正規化には、このバージョンを使用します。

    • $$$SOAPWSEnvelopedSignature — これは、上記のオプションと同等です。

    • $$$SOAPWSEnvelopedSignature_","_$$$SOAPWSexcc14n — 包含的な正規化には、このバージョンを使用します。

  6. シグニチャ・オブジェクトの場合は、AddReference() メソッドを呼び出して、この参照をシグニチャに追加します。

    Method AddReference(reference As %XML.Security.Reference)
    
  7. XML 対応クラスの該当するプロパティを更新して、シグニチャを含むようにします。

    この詳細は、XML 対応クラスによって異なります。以下はその例です。

    set object.MySig=signature 
    
  8. XML としてシリアル化された XML 対応オブジェクトを含む %XML.DocumentOpens in a new tab のインスタンスを作成します。

    署名されたドキュメントについての情報がシグニチャに記載されている必要があるため、これは必要です。

    このドキュメントで前述の “例 2 : オブジェクトの DOM への変換” を参照してください。

    Note:

    このドキュメントには、空白は含まれていません。

  9. シグニチャ・オブジェクトの SignDocument() メソッドを呼び出します。

    Method SignDocument(document As %XML.Document) As %Status
    

    このメソッドの引数は、先ほど作成した %XML.DocumentOpens in a new tab のインスタンスです。SignDocument() メソッドでは、そのインスタンスに入っている情報を使用してシグニチャ・オブジェクトを更新します。

  10. %XML.WriterOpens in a new tab を使用して、オブジェクトの出力を生成します。“Caché オブジェクトからの XML 出力の記述” の章を参照してください。

    Note:

    生成する出力では、空白 (または空白の欠落) が、このシグニチャで使用されているドキュメントに含まれているものと同じである必要があります。シグニチャにはドキュメントのダイジェストが含まれており、ライターで Indent プロパティを 1 に設定している場合には、ダイジェストとドキュメントは一致しません。

以下はその例です。

Method WriteSigned(filename As %String = "")
{
#Include %soap
    //create a signature object
    set cred=##class(%SYS.X509Credentials).GetByAlias("servercred")
    set parts=$$$SOAPWSIncludeNone
    set ref=$$$KeyInfoX509Certificate
    
    set signature=##class(%XML.Security.Signature).CreateX509(cred,parts,ref,.status)
    if $$$ISERR(status) {do $system.OBJ.DisplayError(status) quit}

    // get the Id attribute of the element we will sign;
    set refid=$this.PersonId ; this detail depends on structure of your classes
    
    // then create a reference to that Id within the signature object
    set algorithm=$$$SOAPWSEnvelopedSignature_","_$$$SOAPWSc14n
    set reference=##class(%XML.Security.Reference).Create(refid,algorithm)
    do signature.AddReference(reference)

    //set the MySig property so that $this has all the information needed
    //when we generate output for it
    set $this.MySig=signature ; this detail depends on structure of your classes
    
    //in addition to $this, we need an instance of %XML.Document
    //that contains the object serialized as XML
    set document=..GetXMLDoc($this)

    //use the serialized XML object to sign the document
    //this updates parts of the signature
    set status=signature.SignDocument(document)
    if $$$ISERR(status) {do $system.OBJ.DisplayError(status) quit}

    // write output for the object
    set writer=##class(%XML.Writer).%New()
    if (filename'="") {
        set status=writer.OutputToFile(filename)
        if $$$ISERR(status) {do $system.OBJ.DisplayError(status) quit}
    }
    do writer.RootObject($this)
}

前のインスタンス・メソッドでは以下の汎用クラス・メソッドを使用しており、このクラス・メソッドはどのような XML 対応オブジェクトでも使用できます。

ClassMethod GetXMLDoc(object) As %XML.Document
{
    //step 1 - write object as XML to a stream
    set writer=##class(%XML.Writer).%New()
    set stream=##class(%GlobalCharacterStream).%New()
    set status=writer.OutputToStream(stream)
    if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
    set status=writer.RootObject(object)
    if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}

    //step 2 - extract the %XML.Document from the stream
    set status=##class(%XML.Document).GetDocumentFromStream(stream,.document)
    if $$$ISERR(status) {do $System.Status.DisplayError(status) quit $$$NULLOREF}
    quit document
}

バリエーション : 参照に URI="" を用いたデジタル・シグニチャ

バリエーションとして、シグニチャ用の <Reference> 要素は、そのシグニチャを含む XML ドキュメントのルート・ノードを参照する URI="" を保持できます。この方法でデジタル・シグニチャを作成するには、以下を実行します。

  1. 必要に応じて、%soap.inc インクルード・ファイルを組み込みます。このファイルには、使用する可能性のあるマクロが定義されています。

  2. 適切な Caché 資格情報セットにアクセスする %SYS.X509CredentialsOpens in a new tab のインスタンスを作成します。そのためには、前述の手順の説明に従って、%SYS.X509CredentialsOpens in a new tabGetByAlias() クラス・メソッドを呼び出します。

  3. 指定された資格情報セットを使用する %XML.Security.SignatureOpens in a new tab のインスタンスを作成します。そのためには、前述の手順の説明に従って、そのクラスの CreateX509() クラス・メソッドを呼び出します。

  4. 以下のように、%XML.Security.X509DataOpens in a new tab のインスタンスを作成します。

    set valuetype=$$$KeyInfoX509SubjectName_","_$$$KeyInfoX509Certificate
    set x509data=##class(%XML.Security.X509Data).Create(valuetype,cred)
    

    cred は、先ほど作成した %SYS.X509CredentialsOpens in a new tab のインスタンスです。これらの手順により、<X509SubjectName> 要素および <X509Certificate> 要素を含む <X509Data> 要素を作成します。

  5. 以下のように、<X509Data> 要素をシグネチャの <KeyInfo> 要素に加えます。

    do signature.KeyInfo.KeyInfoClauseList.Insert(x509data)
    

    signature%XML.Security.SignatureOpens in a new tab のインスタンスであり、x509data%XML.Security.X509DataOpens in a new tab のインスタンスです。

  6. 以下のように、%XML.Security.ReferenceOpens in a new tab のインスタンスを作成します。

    set algorithm=$$$SOAPWSEnvelopedSignature
    set reference=##class(%XML.Security.Reference).Create("",algorithm) 
    
  7. 手順 6 (AddReference() の呼び出し) で前述の手順を続けます。

デジタル・シグニチャの検証

デジタル署名が行われたドキュメントを受信した場合は、シグニチャを検証できます。ドキュメントの内容と一致した XML 対応クラスは不要です。

シグニチャの検証の前提条件

デジタル・シグニチャを検証するには、まず Caché が使用するための信頼された証明書を用意する必要があります。Caché は、同様に独自の証明書が Caché によって信頼されているエンティティが署名した証明書を使用する場合に、シグニチャを検証できます。

詳細は、"Caché Web サービスの保護" の “設定およびその他の一般的なアクティビティ” を参照してください。

シグニチャの検証

デジタル署名が行われた XML ドキュメントのシグニチャを検証するには、以下の手順を実行します。

  1. %XML.ReaderOpens in a new tab のインスタンスを作成し、それを使用してドキュメントを開きます。

    このクラスについては、このドキュメント内で前述の “Caché オブジェクトへの XML のインポート” の章を参照してください。

  2. リーダの Document プロパティを取得します。これは、XML ドキュメントを DOM として含む %XML.DocumentOpens in a new tab のインスタンスです。

  3. リーダの Correlate() メソッドを使用して、1 つまたは複数の <Signature> 要素をクラス %XML.Security.SignatureOpens in a new tab に関連付けます。以下はその例です。

     do reader.Correlate("Signature","%XML.Security.Signature")
  4. ドキュメントで 1 つまたは複数の <Signature> 要素を繰り返し読み取ります。このためには、インポートされたオブジェクトがあれば参照によって返す、リーダの Next() メソッドを使用します。以下はその例です。

    if 'reader.Next(.isig,.status) {
        write !,"Unable to import signature",!
        do $system.OBJ.DisplayError(status)
        quit
        }
    

    インポートされたオブジェクトは %XML.Security.SignatureOpens in a new tab のインスタンスです。

  5. インポートされたシグニチャの ValidateDocument() メソッドを呼び出します。このメソッドに対する引数は、以前に取得した %XML.DocumentOpens in a new tab のインスタンスである必要があります。

     set status=isig.ValidateDocument(document)

    その他の検証オプションについては、クラス・リファレンスで、%XML.Security.SignatureOpens in a new tab のこのメソッドを参照してください。

例えば、以下のようになります。

ClassMethod ValidateDoc(filename As %String) 
{
    set reader=##class(%XML.Reader).%New()
    set status=reader.OpenFile(filename)
    if $$$ISERR(status) {do $System.Status.DisplayError(status) quit }
    
    set document=reader.Document
    //get <Signature> element
    //assumes there is only one signature
    do reader.Correlate("Signature","%XML.Security.Signature")
    if 'reader.Next(.isig,.status) {
        write !,"Unable to import signature",!
        do $system.OBJ.DisplayError(status)
        quit
    }
    set status=isig.ValidateDocument(document)
    if $$$ISERR(status) {do $System.Status.DisplayError(status) quit }
}

バリエーション :ID を参照するデジタル・シグニチャ

通常、<Signature> 要素には、ドキュメント内の別の場所にある一意の Id を指している <Reference> 要素が含まれます。Caché では、<Reference> 要素が Id ではなく、ID という名前の属性を指すというバリエーションもサポートしています。このバリエーションでは、ドキュメントの署名およびドキュメントの検証に余分な作業が必要になります。

ドキュメントをデジタル署名するには、“デジタル署名が行われた XML ドキュメントの作成” の手順に従いますが、以下の点を変更します。

  • XML 対応クラスの場合、Id 属性ではなく、ID 属性として投影されたプロパティを含めます。

  • シグニチャを生成して追加するときに、%XML.DocumentOpens in a new tab インスタンスの AddIDs() メソッドを呼び出します。これは、シリアル化した XML ドキュメントの取得後、シグニチャ・オブジェクトの SignDocument() メソッドを呼び出す前に行います。例えば、以下のようになります。

        //set the MySig property so that $this has all the information needed
        //when we generate output for it
        set $this.MySig=signature    ; this detail depends on structure of your classes
    
        //in addition to $this, we need an instance of %XML.Document 
        //that contains the object serialized as XML
        set document=..GetXMLDoc($this)
    
        //***** added step when signature references an ID attribute *****
        do document.AddIDs()
        
        //use the serialized XML object to sign the document
        //this updates parts of the signature 
        set status=signature.SignDocument(document)
        if $$$ISERR(status) {do $system.OBJ.DisplayError(status) quit}
    
  • ドキュメントを検証する場合は、Correlate() を呼び出す直前に以下の手順を含めます。

    1. %XML.DocumentOpens in a new tab インスタンスの AddIDs() メソッドを呼び出します。

    2. XML リーダの Rewind() メソッドを呼び出します。

    例えば、以下のようになります。

        set document=reader.Document
        
        //added steps when signature references an ID attribute
        do document.AddIDs()
        do reader.Rewind()
    
        //get <Signature> element
        do reader.Correlate("Signature","%XML.Security.Signature")
    
FeedbackOpens in a new tab