はじめまして。XMLの電子署名のプログラムをPHPで開発しています。
XMLの正規化についてご教授いただけないかと思い、質問させていただきます。
開発に使用しているPHPのバージョンは5.2.6です。
またDOMのDOM/XML API Versionは2.6.32、OpenSSLのバージョンは0.9.8gとなります。
上記はXAMPP for Windowsの1.6.8のものです。
今回ご教授いただきたいのは、以下サンプルの署名値の算出についてです。
ハッシュ値の計算や署名に使用された証明書のBase64エンコード値の算出にはOpenSSLを使用しています。
*************************************************************
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="20090101010101">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#%E6%A7%8B%E6%88%90%E6%83%85%E5%A0%B1">
<Transforms>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>[申請書に対する構成情報.xmlのハッシュ値]</DigestValue>
</Reference>
<Reference URI="999999999999999999_01.xml">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>[999999999999999999_01.xmlのハッシュ値]</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>[署名値]</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>[署名に使用された証明書のBase64エンコード]</X509Certificate>
<X509Certificate>[ルート証明書のBase64エンコード]</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
*************************************************************
署名値の算出を行うにあたり、仕様書には以下のような記載があります。
「Signature 要素は署名対象の内容に挿入されており、それによって包含署名になっています。
必須の SignedInfo 要素には、実際に署名される次の情報が含まれています。
必須の CanonicalizationMethod 要素は、署名または検証の前に SignedInfo 要素を正規化するために使用されるアルゴリズムを定義します。
正規化とは、そのデータに対する署名を無効化する可能性がある変更を考慮するために、XML の内容を正規形に変換する処理のことを意味します。
正規化は、XMLの性質および異なるプロセッサと中間的存在による解析のために必要です。
正規化により、署名が無効になっても署名されたデータが論理的に同等であるようにデータを変更できます。
必須の SignatureMethod 要素は、署名の生成に使用されるデジタル署名アルゴリズムを定義します。この場合は、SHA-1 を使用する DSA です。
必須の SignatureValue 要素には、SignedInfo 要素に対する署名の Base64- 符号化された署名値が含まれています。
XMLの正規化はW3Cに定義され公開されています。(http://www.w3.org/TR/xml-c14n)」
この仕様から以下のようなソースを作成し署名値を算出しようとしています。
該当ソース部分のみ抜粋しています。不足部分があれば追記させていただきます。
注)署名値を算出するために使用しているOpenssl関数のopenssl_signの第三引数の $certs[0][2] は署名付与の際に使用する電子証明書(.p12ファイル)から取得したRSA PRIVATE KEY(秘密鍵)の値となります。
**************************************************************************
//署名値計算のため<SignedInfo>エレメント部分を変数に格納
$strSigInfo = <<<XML
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#%E6%A7%8B%E6%88%90%E6%83%85%E5%A0%B1">
<Transforms>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>[申請書に対する構成情報.xmlのハッシュ値]</DigestValue>
</Reference>
<Reference URI="999999999999999999_01.xml">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>[999999999999999999_01.xmlのハッシュ値]</DigestValue>
</Reference>
</SignedInfo>
XML;
//Windows のCRLF改行(\r\n)をLF改行(\n)に変更
$strSigInfo = str_replace("\r\n","\n",$strSigInfo);
$dom = new domDocument;
$dom->loadXML($strSigInfo);
//SignedInfo 要素の正規化
$dom->normalize();
$signature = "" ;
//署名値計算
//第一引数:署名値の生成対象、第二引数:算出した署名値、第三引数:暗号化キー(秘密鍵)、第四引数:署名アルゴリズム
openssl_sign($dom->savexml(), $signature, $certs[0][2], OPENSSL_ALGO_SHA1);
//署名値をBase64エンコード
$strSigVale = base64_encode($signature) ;
**************************************************************************
上記ソースで算出した署名値がテスト環境でエラーとなり、正しい値を算出できないため、以下の点を教えていただければと思っております。
1.上記に記載した仕様の署名値を算出するためにopenssl_signを使用することは間違いないものなのかどうか。
2.openssl_signを使用して間違いない場合、SignedInfo 要素を正規化するためにDOMNode::normalizeを使用していますが、
うまく正規化できません。DOMNode::normalizeは正しく機能するものなのでしょうか。
正しく機能するというのはW3Cに定義されている形の正規化できるものかどうかということです。
私の上記ソース上ではW3Cに定義されている形の正規化の結果にはなっていないようです。むしろ逆の結果になっている感じがします。
3.DOMNode::normalizeが機能する場合は上記ソースではどのように使用することが正しいのでしょうか。
正しい署名値が算出できていないため、使用方法が間違っていると思っています。
4.DOMNode::normalizeが機能しない場合、PHPを使ってDOMNode::normalize以外の他の関数あるいはメソッドでSignedInfo 要素をW3Cに定義されている形で正規化する方法はあるのでしょうか。
色々と検索を行っていますが、DOMNode::normalize以外に見当たらず、DOMNode::normalize自体の情報もあまりありません。
XMLの電子署名に関しては情報がほとんどなく困っております。
よろしくお願いいたします。
追記:XML及びソース部分について、うまくインデント出来ませんでした。大変見づらくて申し訳ありません。
« 最終編集者 oka_hoccs 日時 2010 年 7 月 13 日(火) 16:40. »