Method 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
}
デジタル・シグニチャの検証
デジタル署名が行われたドキュメントを受信した場合は、シグニチャを検証できます。ドキュメントの内容と一致した 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")