XML ドキュメントの署名
このトピックでは、XML ドキュメントにデジタル・シグニチャを追加する方法を説明します。
このネームスペースで SOAP ロギングを有効にしておくと、エラーの詳細を受信するので便利です。"Web サービスおよび Web クライアントの作成" の "InterSystems IRIS での SOAP の問題のトラブルシューティング" にある "InterSystems IRIS SOAP ログ" を参照してください。
別のダイジェスト、シグニチャ、正規化メソッドの詳細は、"Web サービスの保護" の "デジタル・シグニチャの追加" を参照してください。
デジタル署名が行われたドキュメントについて
デジタル署名が行われた XML ドキュメントには 1 つ以上の <Signature> 要素が含まれ、その要素それぞれがデジタル・シグニチャです。それぞれの <Signature> 要素によって、以下のように、ドキュメント内の特定の要素に対して署名が行われます。
-
署名されたそれぞれの要素には Id 属性があり、この属性は何らかの一意の値となります。以下はその例です。
<Person xmlns="http://mynamespace" Id="123456789">
-
<Signature> 要素には、以下のように、その Id を指す <Reference> 要素が含まれています。
<Reference URI="#123456789">
<Signature> 要素は、秘密鍵によって署名されます。この要素には、認証機関によって署名された X.509 証明書が含まれています。この署名されたドキュメントの受信者は、この認証機関を信頼していれば、その証明書を検証し、含まれている公開鍵を使用してシグニチャを検証できます。
InterSystems IRIS では、署名された要素が 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 つの InterSystems IRIS 資格情報セットを作成する必要があります。InterSystems IRIS 資格情報セットとは以下の情報セットの別名であり、システム管理者のデータベースに格納されています。
-
公開鍵を含む証明書。この証明書は、ドキュメントの受信者に信頼される認証機関によって署名されている必要があります。
-
関連付けられている秘密鍵。この秘密鍵は、必要なときに InterSystems IRIS が使用しますが、送信することはありません。
秘密鍵は署名用に必要です。
-
(オプション) 秘密鍵のパスワード。この秘密鍵は、必要なときに InterSystems IRIS が使用しますが、送信することはありません。秘密鍵をロードすることも、実行時にこれを指定するとこもできます。
詳細は、"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
}
シグニチャの生成と追加
デジタル署名を生成して追加するには、以下の手順を実行します。
-
必要に応じて、%soap.inc インクルード・ファイルを組み込みます。このファイルには、使用する可能性のあるマクロが定義されています。
-
適切な InterSystems IRIS 資格情報セットにアクセスする %SYS.X509CredentialsOpens in a new tab のインスタンスを作成します。これには、%SYS.X509CredentialsOpens in a new tab の GetByAlias() クラス・メソッドを呼び出します。
classmethod GetByAlias(alias As %String, pwd As %String) as %SYS.X509Credentials
-
alias は、証明書のエイリアスです。
-
pwd は、秘密鍵のパスワードです。秘密鍵のパスワードは、関連付けられている秘密鍵が暗号化されていて、その秘密鍵のファイルをロードしたときにパスワードがロードされなかった場合にのみ必要です。
このメソッドを実行するには、当該の資格情報セットの OwnerList に記載されたユーザとしてログインするか、OwnerList が NULL である必要があります。"Web サービスの保護" の "プログラムによる資格情報セットの取得" も参照してください。
指定された資格情報セットを使用する %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 は、署名された要素に対する参照の特性です。許可される値については、"Web サービスの保護" の "X.509 証明書の参照オプション" を参照してください。
ここで使用されるマクロは、%soap.inc インクルード・ファイルで定義します。
このシグニチャが指す Id については、Id 属性の値を取得します。
この詳細は、XML 対応オブジェクトの定義によって異なります。
その 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 — 包含的な正規化には、このバージョンを使用します。
シグニチャ・オブジェクトの場合は、AddReference() メソッドを呼び出して、この参照をシグニチャに追加します。
Method AddReference(reference As %XML.Security.Reference)
XML 対応クラスの該当するプロパティを更新して、シグニチャを含むようにします。
この詳細は、XML 対応クラスによって異なります。以下はその例です。
set object.MySig=signature
XML としてシリアル化された XML 対応オブジェクトを含む %XML.DocumentOpens in a new tab のインスタンスを作成します。
署名されたドキュメントについての情報がシグニチャに記載されている必要があるため、これは必要です。
"例 2 : オブジェクトの DOM への変換" を参照してください。
Note:このドキュメントには、空白は含まれていません。
シグニチャ・オブジェクトの SignDocument() メソッドを呼び出します。
FeedbackOpens in a new tabMethod SignDocument(document As %XML.Document) As %Status
このメソッドの引数は、先ほど作成した %XML.DocumentOpens in a new tab のインスタンスです。SignDocument() メソッドでは、そのインスタンスに入っている情報を使用してシグニチャ・オブジェクトを更新します。
%XML.WriterOpens in a new tab を使用して、オブジェクトの出力を生成します。"オブジェクトからの 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="" を保持できます。この方法でデジタル・シグニチャを作成するには、以下を実行します。
-
必要に応じて、%soap.inc インクルード・ファイルを組み込みます。このファイルには、使用する可能性のあるマクロが定義されています。
-
適切な InterSystems IRIS 資格情報セットにアクセスする %SYS.X509CredentialsOpens in a new tab のインスタンスを作成します。そのためには、前述の手順の説明に従って、%SYS.X509CredentialsOpens in a new tab の GetByAlias() クラス・メソッドを呼び出します。
-
指定された資格情報セットを使用する %XML.Security.SignatureOpens in a new tab のインスタンスを作成します。そのためには、前述の手順の説明に従って、そのクラスの CreateX509() クラス・メソッドを呼び出します。
-
以下のように、%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> 要素を作成します。
-
以下のように、<X509Data> 要素をシグニチャの <KeyInfo> 要素に加えます。
do signature.KeyInfo.KeyInfoClauseList.Insert(x509data)
signature は %XML.Security.SignatureOpens in a new tab のインスタンスであり、x509data は %XML.Security.X509DataOpens in a new tab のインスタンスです。
-
以下のように、%XML.Security.ReferenceOpens in a new tab のインスタンスを作成します。
set algorithm=$$$SOAPWSEnvelopedSignature set reference=##class(%XML.Security.Reference).Create("",algorithm)
-
手順 6 (AddReference() の呼び出し) で前述の手順を続けます。
デジタル・シグニチャの検証
デジタル署名が行われたドキュメントを受信した場合は、シグニチャを検証できます。ドキュメントの内容と一致した XML 対応クラスは不要です。
シグニチャの検証の前提条件
デジタル・シグニチャを検証するには、まず、署名者の信頼された証明書を InterSystems IRIS に提供する必要があります。InterSystems IRIS が署名を検証できるのは、中間証明書 (もしあれば) を含め、署名者独自の証明書から、InterSystems IRIS が信頼する認証機関 (CA) の自己署名証明書までの署名者の証明書チェーンを検証できる場合です。
詳細は、"Web サービスの保護" の "設定およびその他の一般的なアクティビティ" を参照してください。
シグニチャの検証
デジタル署名が行われた XML ドキュメントのシグニチャを検証するには、以下の手順を実行します。
-
%XML.ReaderOpens in a new tab のインスタンスを作成し、それを使用してドキュメントを開きます。
このクラスの詳細は、"オブジェクトへの XML のインポート" を参照してください。
-
リーダの Document プロパティを取得します。これは、XML ドキュメントを DOM として含む %XML.DocumentOpens in a new tab のインスタンスです。
-
リーダの Correlate() メソッドを使用して、1 つまたは複数の <Signature> 要素をクラス %XML.Security.SignatureOpens in a new tab に関連付けます。以下はその例です。
do reader.Correlate("Signature","%XML.Security.Signature")
-
ドキュメントで 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 のインスタンスです。
-
インポートされたシグニチャの 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> 要素が含まれます。InterSystems IRIS では、<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() を呼び出す直前に以下の手順を含めます。
-
%XML.DocumentOpens in a new tab インスタンスの AddIDs() メソッドを呼び出します。
-
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")
-
-