【问题标题】:Generating XML signature生成 XML 签名
【发布时间】:2018-11-30 23:01:14
【问题描述】:

两天来,我一直在尝试生成一种有效的方式来签署我的 xml。

签名部分应该是这样的:

<Signature>
    <SignedInfo>
        <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
        <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
        <Reference URI="">
            <Transforms>
                <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <DigestValue>cTKLzl3+JJitmqnEmdv4x/h3HZU=</DigestValue>
        </Reference>
    </SignedInfo>
    <SignatureValue>GBDvnBoVHlJJ+96+aVqS34Ei7jHRDXm7n21SeFxD42Cqah1FXK0lCz6z/lp3ptDPYMLljCcoYYSX miRdD3/in4inMmn6nb/ZGVPHo26K+gphPg3ChhZGz5YA1cLTaBNMhC0yqSNuuqNnyxPuLix2U7a3 g5jTCmm4F8ehqhP2JZ8pSVTziyT0UgwjB9OUrHEa8qMxRgIG4t4nxTz0+1norLZf3frhHwnu0XE4 UaHCfP1eWV81Npqgdj3TrGUeOjfkEqgxKUEP/E3TLjDNxUm7gjMSszaG1I58qKPEAqfoDWuOhyZi TsuGyu682q9qouo12A6RzH4MatA8i/nUagQ02Q==</SignatureValue>
    <KeyInfo>
        <KeyValue>
            <RSAKeyValue>
                <Modulus>i+rh6NJ7Z6Q8XiMSVK/Z8DYXIyk5j7N9GUX8AOSKONabse4us7/ogR0x7OOf0FsrdxAhQls59Wn1vDxujSVOu3v1JhML/v/WK8glcxM433oEEpb0C56XRHlt27Qkbsn6v3njC1z0NGyDFdAtg5PaMx7YmjyWR6ezMKj9wR5cK4CRZ7idm2PwzQaLUDFm7wUFXudZNkQ6pb60OvDw4ey1t68EVCPtq4nGdHG+3jlSDTTJc/03qk50pa6Nb/t5+EWsE3jFt/uhHim1rC2pMf5UrT26FL6/DjA0PxQFecc76zeuv3xbGSP7B7ubpG8fyatGb4oLB4eU0ceCJvqljGMP0w==</Modulus>
                <Exponent>AQAB</Exponent>
            </RSAKeyValue>
        </KeyValue>
    </KeyInfo>
</Signature>

我通过这样做正确地得到了 DigestValue

$ns = $xml->documentElement->namespaceURI;
$body = $xml
    ->getElementsByTagNameNS($ns, 'paymentRequest')
    ->item(0);

$xml = $body->C14N(false, true);
$digest = base64_encode(hash('SHA1', $xml, true));

通过从证书 .pem 文档中获取 Modulus 部分,我也可以。 我似乎无法生成的唯一部分是 SignatureValue。

我尝试这样做:

$signature = "";

$fp = fopen(__API__ . 'elvartai/keys/payment/testKey.pem', "r");
$priv_key = fread($fp, filesize(__API__ . 'elvartai/keys/payment/testKey.pem'));
fclose($fp);

$pkeyid = openssl_get_privatekey($priv_key);
openssl_sign($digest, $signature, $pkeyid, "sha1");

$base64_signature = base64_encode($signature);

$digest 是我在cTKLzl3+JJitmqnEmdv4x/h3HZU= 之前生成的digestValue,它确实符合示例。我做错了什么?

这是我得到的 SignatureValue

H8/jxi2Z0fA1qTtBG8bwKc2XSN0fJpHTPyypyYBMV/6uQCS4F0UdEefftFeuCEdOyablK67RhN+6wtLMuQDgVLfYjPD+rB9A/FRgQljDVHaMhjIxODpG2z8w3A/MJc86D2Fj0ylRKXykSNbA2n8b7MP4ESemoBJ7sm3xGAMb7z8QPJFfIVj4XXFbnXHMnw9nuwt4HD9e0VuZtOQWKPgVpdsLqQtsD5zQksWTb1HzhGO+jfm6l9dsC1k9BbpyO5GgOL25UVyaRHeOIF+Lxp9TAXmUXs7Y1teYXMfaHzIlRTXVjIdWPiJGM6U8gzSu6fpFQK8yEOngNH4137kEZ6f1RQ==

【问题讨论】:

标签: php xml openssl ssl-certificate digital-signature


【解决方案1】:

出于签名的目的,您不负责计算摘要。 openssl_sign() 函数的第一个参数应该是您要签名的数据(在您的示例中为 $xml),而不是您自己计算的摘要(在您的示例中为 hash() 调用的结果)或 @该摘要的 987654325@d 值(就像您对 $digest 所做的那样)。

作为openssl_sign() 生成签名的一部分,将计算摘要。这就是为什么你传入 "sha1" 值,告诉它使用哪种摘要算法。

关于后者的小评论:查看openssl_sign documentation,它提供了一种更好的方法来指定摘要算法,使用OPENSSL_ALGO_SHA1 而不是您的文字字符串。

【讨论】:

    猜你喜欢
    • 2013-09-22
    • 2020-05-25
    • 2014-04-06
    • 2017-03-17
    • 1970-01-01
    • 1970-01-01
    • 2021-05-16
    • 1970-01-01
    • 2012-09-08
    相关资源
    最近更新 更多