-->

How to Sign X.509 certificate with RS256 in PHP? N

2019-06-01 11:01发布

问题:

I have implemented JWT token generator library from Here, and i am able to get RS256 Token (Payload). But i am having issue with Header data: I need one header value "x5t", which is not generated from the given library. I need header data like:

{
    "typ": "JWT",
    "alg": "RS256",
    "x5t": "COm8ON2SD2MTc5jwcxZ0vE3-XJo"
}

I am getting first two parameter successfully, but not able to get valid third parameter.

My Sample code is :

$fingerprint = str_replace("SHA1 Fingerprint=", '', system('openssl x509 -noout -in my.pem -fingerprint'));
$fingerprint = sha1($fingerprint);
$fingerprint = base64_encode($fingerprint);
$fingerprint = rtrim(strtr($fingerprint, "+/", "-_"), '=');

To generate Valid "x5t" parameter there is already code available in .NET, need to convert in PHP.

Thanks for watching my question. Any suggestion welcomed.

回答1:

If you have PHP 5.6, you can use the following function openssl_x509_fingerprint:

$cert = openssl_x509_read($certificate);
$sha1_hash = openssl_x509_fingerprint($cert); // sha1 hash (x5t parameter)
$sha256_hash = openssl_x509_fingerprint($cert, 'sha256'); // sha256 hash (x5t#256 parameter)

If you do not have PHP 5.6, you can generate this fingerprint by yourself using the content of your certificate file (begins with BEGIN CERTIFICATE and ends with END CERTIFICATE):

function sha1_thumbprint($file_content)
{
   $file_content = preg_replace('#-.*-|\r|\n#', '', $file_content);
   $bin = base64_decode($file_content);
   return hash('sha1', $bin);
}

Do not forget to encode in Base64 Url Safe the result.

$encoded_fingerprint = rtrim(strtr(base64_encode($fingerprint), "+/", "-_"), '=');


回答2:

system outputs its result directly, unless you use the optional second parameter, which puts the result into the variable.

So use

system('openssl x509 -noout -in my.pem -fingerprint', $sha1);
$fingerprint = str_replace("SHA1 Fingerprint=", '', $sha1);

http://php.net/manual/en/function.system.php



回答3:

openssl_x509_fingerprint (which Florent Morselli mentioned) returns an sha1 hash of the DER encoding of the cert. eg.

<?php
$cert = '...';

echo openssl_x509_fingerprint($cert);
echo "\r\n<br />\r\n";
echo sha1(base64_decode(preg_replace('#-.*-|\r|\n#', '', $cert)));

They output the same thing. At least with this cert:

-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQT52W2WawmStUwpV8tBV9TTANBgkqhkiG9w0BAQUFADBM
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0xMTEwMjYwMDAwMDBaFw0x
MzA5MzAyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEA3rcmQ6aZhc04pxUJuc8PycNVjIjujI0oJyRLKl6g2Bb6YRhLz21ggNM1QDJy
wI8S2OVOj7my9tkVXlqGMaO6hqpryNlxjMzNJxMenUJdOPanrO/6YvMYgdQkRn8B
d3zGKokUmbuYOR2oGfs5AER9G5RqeC1prcB6LPrQ2iASmNMCAwEAAaOB5zCB5DAM
BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
AAOBgQAhrNWuyjSJWsKrUtKyNGadeqvu5nzVfsJcKLt0AMkQH0IT/GmKHiSgAgDp
ulvKGQSy068Bsn5fFNum21K5mvMSf3yinDtvmX3qUA12IxL/92ZzKbeVCq3Yi7Le
IOkKcGQRCMha8X2e7GmlpdWC1ycenlbN0nbVeSv3JUMcafC4+Q==
-----END CERTIFICATE-----

openssl_x509_fingerprint is only on PHP 5.6 so if you're PHP 5.5 or earlier you can use the alternative method instead.