言いたいこと
Enveloped署名は署名対象の文書の中に署名情報を埋め込む。
署名情報を埋め込むのは署名処理をした後。署名情報が埋め込まれた後に署名処理をするわけではない。
署名を検証する時、Enveloped署名の場合は署名対象の文書の中から署名情報を取り除いてから検証処理を行う。
文書がEnveloped署名されたものかどうかは、Enveloped署名を示すタグの存在で判断することができる。
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
文書に対して署名情報の追加や除外という例えばXMLタグの間に改行やスペースなどの異物が混入する恐れがある行為を行っても、署名がおかしくなることはない。
なぜならば署名処理の前にXML正規化という、XML文書に対して改行やスペースなどを統一したルールで整形し直す処理を行うため。
逆に言うと文書に対し署名した後に、人が見やすいよう余計な改行やスペースが付け加えられたり削除されたりしている可能性がある。
XML署名の種類について
Enveloped署名
署名対象の文書の中に署名情報を埋め込む方法。
<TargetDocument ID="target">
<DocumentContent>
<Title>タイトル</Title>
<Author>著者</Author>
<Content>内容</Content>
</DocumentContent>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="#target">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>ハッシュ値(ダイジェスト値)</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>署名値</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>署名検証用の公開鍵を含む電子証明書</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</TargetDocument>
Enveloping署名
署名情報の中に署名対象の文書を埋め込む方法。
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="#target">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>ハッシュ値(ダイジェスト値)</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>署名値</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>署名検証用の公開鍵を含む電子証明書</X509Certificate>
</X509Data>
</KeyInfo>
<TargetDocument ID="target">
<DocumentContent>
<Title>タイトル</Title>
<Author>著者</Author>
<Content>内容</Content>
</DocumentContent>
</TargetDocument>
</Signature>
Detached署名
署名対象の文書とは別に署名情報の文書を作成する方法。
<TargetDocument ID="target">
<DocumentContent>
<Title>タイトル</Title>
<Author>著者</Author>
<Content>内容</Content>
</DocumentContent>
</TargetDocument>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="#target">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>ハッシュ値(ダイジェスト値)</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>署名値</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>署名検証用の公開鍵を含む電子証明書</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
署名方法に対する考察
なぜ3種類の署名方法があるのか、どれを選択するべきかの情報が見つからなかったため自分の考えを記載します。
Enveloped署名
署名対象の文書の中に署名情報を埋め込む方法であるため、署名時にどこに署名値を埋め込むか判断したり、署名検証時には署名情報を取り除いたりと、プログラム的には面倒な方法。
しかし文書を扱う人にとっては文書がメインであり分かりやすい方法であるため、人が直接XMLファイルを操作することがある場合に良い方法と考えられる。
Enveloping署名
署名情報の中に署名対象の文書を埋め込む方法であるため、Enveloped署名とは逆にプログラムで処理しやすい方法。
文書をデータベースなどで集中して管理し、人が直接XMLファイルを操作せずに済む場合に良い方法と考えられる。
Detached署名
署名対象の文書とは別に署名情報の文書を作成する方法であるため、以下の使い方ができる。
- 署名情報を文書とは別に保管できる。
- 複数の文書に対し署名をまとめてすることができる。
- XML文書以外のファイルに対する署名も行うことができる。
デメリットとしては以下の点が考えられる。
- 署名対象の文書と署名情報が分離されるため、ファイルの数が増える。
- 特に複数の文書やファイルに対し署名した場合に、署名情報がどこにあるか紐づけが難しい。
またDetached署名では、「署名対象の文書と署名情報が1つの"ファイル"に存在する」ことも可能である。
つまり、"署名対象文書.xml"と"署名情報.xml"に分割されず、"署名対象文書.xml"に署名対象の文書と署名情報を存在させることが可能である。
どういうことかは、例として記述したXML文書のTargetDocumentタグとSignatureタグの位置関係を注視して欲しい。
さらに、一つの"署名対象文書.xml"に署名対象の文書に複数の署名対象の文書をまとめて署名した署名情報を存在させることもできる。
別ファイルに対するDetached署名の場合は、ReferenceタグのURI属性の値が#付きのタグ名でなくファイル名となる。
ただしDetached署名の場合でも「署名対象の文書と署名情報が1つの"ファイル"に存在する」時はURI属性の値が#付きのタグ名である。