Openssl 从SignedInfo计算SignatureValue

Openssl 从SignedInfo计算SignatureValue,openssl,digest,xml-signature,Openssl,Digest,Xml Signature,我目前正在尝试继续“签名XML文档”。到目前为止,我已经能够运行c14n算法并计算出相应的DigestValue 但是,我似乎无法获得SignatureValue字段的正确值。我目前正在正确计算SignedInfo标记的摘要值,因为它与作者的计算相匹配,但我似乎无法解决的问题是,对哈希进行签名会产生与预期不同的字符串 我当前的脚本如下所示: <?php $c14n = '<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">

我目前正在尝试继续“签名XML文档”。到目前为止,我已经能够运行c14n算法并计算出相应的
DigestValue

但是,我似乎无法获得
SignatureValue
字段的正确值。我目前正在正确计算
SignedInfo
标记的摘要值,因为它与作者的计算相匹配,但我似乎无法解决的问题是,对哈希进行签名会产生与预期不同的字符串

我当前的脚本如下所示:

<?php
$c14n = '<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod>
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod>
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
        <DigestValue>UWuYTYug10J1k5hKfonxthgrAR8=</DigestValue>
      </Reference>
    </SignedInfo>';

echo sha1($c14n).PHP_EOL.PHP_EOL; // a25a06d339d68b625cd7383a932357889956a54e OK !!

$data = sha1($c14n); // sha1($c14n,true) wont work either

$pkeyid = openssl_pkey_get_private("file://key.txt",'password'); // PK

// compute signature
openssl_sign($data, $signature, $pkeyid);

// free the key from memory
openssl_free_key($pkeyid);

// Result should be: TSQUoVrQ0kg1eiltNwIhKPr ...
echo base64_encode($signature); // Wont match!
?>
如果从终端运行,我已经能够检查openssl生成的摘要是否与预期的不同(a25a06d339d68b625cd7383a932357889956a54e)。我进行了双重检查,三次检查,并确保文件内容与
$c14n
变量完全相同

我到底做错了什么

注意事项:
我确实检查了作者提供的XML,看起来还可以。与“操作方法”上的相同。

我使用以下方法:

1) 获取.pem文件openssl pkcs12-in certificate.pfx-nocerts-out privatekey.pem-nodes 然后在PHP中 (二)

$certificateNode=$doc3
->getElementsByTagName('X509Certificate')
->项目(0);

$content=$certificateNode->C14N(假、真);// 我知道这是一个很老的帖子,但我只是被它绊倒了,因为我有一个类似的问题

我阅读了相同的教程,据我所知,您不能为规范化字符串计算sha1,而是直接将其插入到openssl_sign命令中。根据您的第一个示例(php),它应该说:

$c14n = '<SignedInfo... </SignedInfo>';
// Do not use sha1 here
//$data = sha1($c14n); // sha1($c14n,true) wont work either

$pkeyid = openssl_pkey_get_private("file://key.txt",'password'); // PK

// compute signature
// openssl_sign($data, $signature, $pkeyid);   // your initial command
openssl_sign($c14n, $signature, $pkeyid, 'OPENSSL_ALGO_SHA1');   // modified version

// free the key from memory
openssl_free_key($pkeyid);

// Result should be: TSQUoVrQ0kg1eiltNwIhKPr ...
echo base64_encode($signature); // Should match now  ;-)

$c14n='Juan,谢谢你的回答。它似乎仍然不起作用。返回的值是D8U622BVNIEXBTFCD90。。。哪个不是正确的。我正在正确计算SignedInfo标记的摘要值,但无法使签名步骤正常工作。将字符串转换为Base64应该是最后一步$实际最大值不应采用Base64编码!
$certificateNode = $doc3
        ->getElementsByTagName('X509Certificate')
        ->item(0);

$content = $certificateNode->C14N(FALSE, TRUE); // <-- no exclusive, with comments

$actualDigest = base64_encode(hash('SHA1', $content, true)); 
$fp = fopen('privatekey.pem', "r");
$priv_key = fread($fp, 8192);
fclose($fp);
$passphrase = 'the pasphrase';
$res = openssl_get_privatekey($priv_key,$passphrase);
openssl_private_encrypt($actualDigest, $crypttext, $res);
$signatureValueBase64 = base64_encode($crypttext);
$c14n = '<SignedInfo... </SignedInfo>';
// Do not use sha1 here
//$data = sha1($c14n); // sha1($c14n,true) wont work either

$pkeyid = openssl_pkey_get_private("file://key.txt",'password'); // PK

// compute signature
// openssl_sign($data, $signature, $pkeyid);   // your initial command
openssl_sign($c14n, $signature, $pkeyid, 'OPENSSL_ALGO_SHA1');   // modified version

// free the key from memory
openssl_free_key($pkeyid);

// Result should be: TSQUoVrQ0kg1eiltNwIhKPr ...
echo base64_encode($signature); // Should match now  ;-)