I have an email which is digitally signed.
email :
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
The below email has been digitally signed for test purposes. We will
now go on and save this signed email in our dms system.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (MingW32)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iQEcBAEBAgAGBQJTnwd9AAoJEEWjhuB1kNr9dQcH/2YeZlHEfK/KOPg8XhpOY+4l
3camfFVya8JIzLHsOzhhdSqIItDr7VlGDrjrMgPPiD1abyy9zhcqZ18Kh8sUuFJV
/TA434rrnMJC0xmSzXl4uo+UagyNyCjzwR4TFCGP4Ob6SzPl/jxfrcfO5yXEdF1I
X6wgQUmnb3ZLczdPVXsKpwpVIGqX7diwe1CAZKxCmjZo9rr/MmDLLl7AjYq/WQDT
uOYqXs2IasOIiTGpYrqexBpDn1qRUNiKVgFSRUTfTjYGXYij9P635WTfeE1bQrn1
HpT9hKhipYPkFcELAor7asqAcnE0lc4Oy9NV2bUryss8ic/pkhiXvlohA3MpCDA=
=+IbK
-----END PGP SIGNATURE-----
Public Key:
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.22 (MingW32)
mQENBFOfBmkBCAC6gH9rR185hiCADttaQeUp9Jc+4Zzx60E+ogWd33Tb1dNvK/IK
wqpnRpYI1CHVpqX0xWy8Ylcw3rLpPJ6BUzO3hWFLRMXAIXiemV/+VKrKysgm1Xdg
1PSAVfqmgkXLEEGGSj2OHNA0VVnl1G8AI8/SMpLqhS3PMz3X1nmBv4hLohugLla9
AVdYp6Me5OAWfjHswkUxCvc/fSh2ufFSnFxgjUibIyn+GP5qG8Wc+GjrBzTLzjA7
LvP198fWIHQ5w342F3WE8/9ec+1ir/a4japcFodRibXBEqltF+BXgk9pVcEXTd8O
FCxygrnSkWioj9Qf5uyjuKfV1F7Wq/Nu5uPZABEBAAG0JkFiaGluYXYgQWdnYXJ3
YWwgPGFiaGluYXZAdHJ1dGVjaC5vcmc+iQE/BBMBAgApBQJTnwZpAhsjBQkJZgGA
BwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQRaOG4HWQ2v2F9Af/RAKCz0uo
xqrVe1MXqCe9ZCPSwlHGH4X4NtQbo7FTYy7K2fo9ucoKI4c2lHZA+Ef1K6BhZG34
IlXPSwy8nhTWJl7pi/xo7gEDlnHJMJCGvQcdtm4lkp39V2cy/Y0lS9V/EYmiesIX
tmPwwyYxo85jNsdmbjQKDTv5mcir9AebllCk2NlrxpyTO8oAnp1peHaHHq+U92e3
ZipHEiuAvE0U6WU/fA7tHoWoUor9AUm1hE5mSsyi+do4o/YJqGEgAss62v0npcBx
oyHoHum5XUgZ1kjvq40Mzkxo9N6vU7P7ULyt9FZylM+pk9XEqiz8IGTPW6JGiJS2
WmhJli2Szl1xgLkBDQRTnwZpAQgA27UvNu/m61pZwTBSQAVjLNJnJTlU4yh/DxKU
B3opw7JvvgXYB3VS9AyqSYaIJTcziCBZRewMH+WVpZwRk9SFMyeyNhuk9SGeGU9s
vyE5dGPa/U5zpvhaqn//CMdRr+wf6XeBKjzc9eKgWMrPLhzlHZ6kzLsbRsalOd4x
0M3aeO4SV00HFFfXVfJplNB8/zsHNNqtF5ACz9DX69p1GWJD6AAlu/s04xkkUScr
M2B5lHm6iU6NmfP1GeTD+rOyigcOrSlAL4QGIzGDfoDJOy9UYtk+YOv8UBa3IpG0
7sARkd+MZGUOgPWIDYQLiSi+9opFHtn4EzrvuUP3Zj1kN4ZUTwARAQABiQElBBgB
AgAPBQJTnwZpAhsMBQkJZgGAAAoJEEWjhuB1kNr9kHoIAKnjEAiH53ZrWYuummPR
PRztZL1K7LkxEAxQ00V+PMrg4wNlp1WW5Vl3X0jB5FqUTUmI/65MhoWa+Ucqg31c
pUOpw5OHK/cyrsscj+gL3nknhswWcvqBNQuiB8UO7Kt89yFYysA754sADKE+nDBM
D+kmlH4u3vvKep0hZ+gzvH3AOZDhijKJYN9zMMf/gtwZhlEm/N+yBpkP1sxcFsJ+
V5hduu4sqJnAcCWg3V/JXonAOZGPS/GE+wXt4Om1D/6RcBBtrBGwh/ezBFS/gSio
vGRcFzZYRhM1rMEu82raZ3ji3X/5fOjxvhSXdrajG3LX8s2gCk+a0nGDi3MYs5l0
p14=
=cn4r
-----END PGP PUBLIC KEY BLOCK-----
I want to write a program in php which will verify the digital signature. I have public key of the sender. I tried downloading GnuPG library from this site, but it is not getting downloaded.
Is there any other way? How should I do it? Any help will be appreciated.
PHP already brings a module for interfacing GnuPG, which is fairly easy to use.
GnuPG must already be installed, on Linux servers it usually is, on Windows machines I heard of getting PHP running together with GnuPG rather difficult.
For verifying signatures, use gnupg_verify(...), example from the linked PHP documentation:
<?php
$plaintext = "";
$gpg = new gnupg();
// clearsigned
$info = $gpg -> verify($signed_text,false,$plaintext);
print_r($info);
// detached signature
$info = $gpg -> verify($signed_text,$signature);
print_r($info);
?>
You will have to import the signer's public key before verifying, if not done already.
Related
How do I export certificate in a format that will be acceptable by PHP SSL context option cafile?
My code below uses openssl_x509_export to export a certificate chain of stackoverflow.com to a file. The code is based on How to get SSL certificate info with CURL in PHP?
$context = stream_context_create(["ssl" => ["capture_peer_cert_chain" => true]]);
$h = stream_socket_client(
"ssl://stackoverflow.com:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT,
$context);
$params = stream_context_get_params($h);
$ca = null;
foreach ($params["options"]["ssl"]["peer_certificate_chain"] as $cert)
{
openssl_x509_export($cert, $output);
$ca .= $output;
}
file_put_contents("cafile", $ca);
(I'm aware that it's not necessary to export whole chain.)
Then, I try with the following code snippet to connect to the same host using the exported file for verifying the certificate. But the code fails with:
PHP Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in /path/test.php on line 22
$context = stream_context_create(["ssl" => ["cafile" => "cafile"]]);
file_get_contents("https://stackoverflow.com/", false, $context);
What is wrong with the format of the file?
Interestingly wget is happy with the exported certificate, the following succeeds:
wget --ca-certificate=cafile https://sourceforge.net/
The export is:
-----BEGIN CERTIFICATE-----
MIIHJDCCBgygAwIBAgISA76ZNTywMU3d6zogRjuFkuFnMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0yMDA2MDgxNjI0MDBaFw0y
MDA5MDYxNjI0MDBaMB4xHDAaBgNVBAMMEyouc3RhY2tleGNoYW5nZS5jb20wggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCp1azQ2CMWUtXrIZDFim7tu2xF
NFYSLt+lIjyZJ1MeCJkljjaiNB02guKeFRSuPsMk2J3Xz8OmOoEfbvVQejMcaw6i
BVP1V+QhF+JhgyOORQkZQV8JJ58IcOJ1PwokyMCAMOWvdxHzaj73jXsxC+n/+MU7
yuq+Y2LuZE1hQYtftYia/e0QtnPDUlpnjUSd7YEDvAzNnKY3+r1smFOHChDjAxMs
W+lJfKLscNKspncihsx16JhZcGZbXiPPOd90B/zA5xNFOCUolldtMAdxFHKoKYpN
mgWrQwVvDB7VCGAQ3CiNGRvdcMa/TpB4SVsZc07C6TvD35dr0wLoZN4WqKfrAgMB
AAGjggQuMIIEKjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFM73q8X//0OoBswZWBlG
kTPmW5HPMB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUF
BwEBBGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNy
eXB0Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNy
eXB0Lm9yZy8wggHkBgNVHREEggHbMIIB14IPKi5hc2t1YnVudHUuY29tghIqLmJs
b2dvdmVyZmxvdy5jb22CEioubWF0aG92ZXJmbG93Lm5ldIIYKi5tZXRhLnN0YWNr
ZXhjaGFuZ2UuY29tghgqLm1ldGEuc3RhY2tvdmVyZmxvdy5jb22CESouc2VydmVy
ZmF1bHQuY29tgg0qLnNzdGF0aWMubmV0ghMqLnN0YWNrZXhjaGFuZ2UuY29tghMq
LnN0YWNrb3ZlcmZsb3cuY29tghUqLnN0YWNrb3ZlcmZsb3cuZW1haWyCDyouc3Vw
ZXJ1c2VyLmNvbYINYXNrdWJ1bnR1LmNvbYIQYmxvZ292ZXJmbG93LmNvbYIQbWF0
aG92ZXJmbG93Lm5ldIIUb3BlbmlkLnN0YWNrYXV0aC5jb22CD3NlcnZlcmZhdWx0
LmNvbYILc3N0YXRpYy5uZXSCDXN0YWNrYXBwcy5jb22CDXN0YWNrYXV0aC5jb22C
EXN0YWNrZXhjaGFuZ2UuY29tghJzdGFja292ZXJmbG93LmJsb2eCEXN0YWNrb3Zl
cmZsb3cuY29tghNzdGFja292ZXJmbG93LmVtYWlsghFzdGFja3NuaXBwZXRzLm5l
dIINc3VwZXJ1c2VyLmNvbTBMBgNVHSAERTBDMAgGBmeBDAECATA3BgsrBgEEAYLf
EwEBATAoMCYGCCsGAQUFBwIBFhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCC
AQIGCisGAQQB1nkCBAIEgfMEgfAA7gB1AF6nc/nfVsDntTZIfdBJ4DJ6kZoMhKES
EoQYdZaBcUVYAAABcpT136gAAAQDAEYwRAIhAP68FqsHN7WAMY3gio0PiAX1o0ID
d9G35wA7pgn/OetjAh9f9JkgTdN4U58fsIVcZAPstOIoKOblbzAof32fixlAAHUA
B7dcG+V9aP/xsMYdIxXHuuZXfFeUt2ruvGE6GmnTohwAAAFylPXfyQAABAMARjBE
AiArXFv1bOQ2wDYjJvVjSm13AnPCQmbkRRgw6YEaSDhP7gIgJQPAbeBEhu44aJQe
Ih4j33U59OY4Ux2f02dWw3oqhNIwDQYJKoZIhvcNAQELBQADggEBAHyW5+Ss+0vt
jKPFOL9atcI3WZYlwp7Djg3dXByWFBgVEzhrRGGJKEZyK9N178cG9zGXXXbxrxGY
L81pxfZNGiPBYueQ191bTKRS0/9NyCfQhSjFG9SUy7BHDC8OTX5OxEZfnG4wglCf
vPcBkdZ49b0TsTiDrRfCltQvqkeY+/6CfJnayFV/RuZcfRV2bcnu2lLE3da57mA0
TEc9hSW/AefP5ad4noqhSsPISPPbo8S1U4JAFnn1M0KnoEKr5/awHenQeqKgPSKr
DmtDcoy8Tf0RpqSMUwIKqBZEERthO6FC506E64wcuYww3EqA7Um7MM1MkQ8hosFN
WK9ZLI8ylk4=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
Some background: I'm using certificate bundle from https://curl.se/docs/caextract.html.
For some reason PHP is not able to validate certificates issued by "USERTrust RSA Certification Authority", although the root certificate seems to be present in the bundle. For example a certificate sectigo.com itself. This is a part of my attempt to find the root cause or a workaround.
stackoverflow only provides the server cert, and the intermediate ca cert. not the root ca cert.
openssl cafile only works if the full chain (to a self signed root ca) can by verified,
so you either have to trust the ROOT CA your self by downloading it, or use some kind of pki so you have all the global trusted root CAs.
on Debian GNU / Linux based machines you can install the ca-certificates package,
sudo apt-get install ca-certificates
or you can use the cacert from mozilla https://curl.haxx.se/docs/caextract.html
Download CA certificate from here https://curl.haxx.se/ca/cacert.pem
Execute the following code:
<?php
$context = stream_context_create([
"ssl" => [
"cafile" => "cacert.pem"
]
]);
file_get_contents("https://stackoverflow.com/", false, $context);
you will see no errors
Explanations:
regarding documentation cafile accept Certificate Authority file but you tried to put chain certificates
There might be a misunderstanding. stream_context_create() is to create a TCP server. It can handle handshakes, but to do so must have a whole keyring, formatted like below:
This is a .crt and a private .key file generated by openssl, concatenated in one file.
-----BEGIN CERTIFICATE-----
MIIDaDCCAlCgAwIB(...)
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAK(...)
-----END RSA PRIVATE KEY-----
With a key ring like this, I am able to implement ssl/https and secure wss:// websockets servers.
Not sure what you are looking to do, why file_get_contents() doesn't works without a context. Usually you don't have to import any CAcert, and if so, it belong to the browser.
This can be useful in an enterprise context, or to avoid errors with self_signed keyrings.
Thus, what's wrong with just:
echo file_get_contents("https://stackoverflow.com/");
Or
wget https://sourceforge.net/
It just works without hassle.
Please explain precisely what you are trying to achieve, got many notes from experiments around ssl and php.
To extract the public key of a given server, you have to query on the port 443:
<?php
$opt = [
"capture_peer_cert" => true,
"capture_peer_cert_chain" => true
];
$a = stream_context_create(["ssl"=>$opt]);
$b = stream_socket_client("tls://stackoverflow.com:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $a);
$cont = stream_context_get_params($b);
$key = openssl_pkey_get_public($cont["options"]["ssl"]["peer_certificate"]);
$c = openssl_pkey_get_details($key);
var_dump($c["key"]);
Output
string(451) "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqdWs0NgjFlLV6yGQxYpu
7btsRTRWEi7fpSI8mSdTHgiZJY42ojQdNoLinhUUrj7DJNid18/DpjqBH271UHoz
HGsOogVT9VfkIRfiYYMjjkUJGUFfCSefCHDidT8KJMjAgDDlr3cR82o+9417MQvp
//jFO8rqvmNi7mRNYUGLX7WImv3tELZzw1JaZ41Ene2BA7wMzZymN/q9bJhThwoQ
4wMTLFvpSXyi7HDSrKZ3IobMdeiYWXBmW14jzznfdAf8wOcTRTglKJZXbTAHcRRy
qCmKTZoFq0MFbwwe1QhgENwojRkb3XDGv06QeElbGXNOwuk7w9+Xa9MC6GTeFqin
6wIDAQAB
-----END PUBLIC KEY-----
"
Maybe this answer can help
I don't have any problem with Encryption but I'm unable to Decrypt the text.
The response which I receive is simply false. The code looks like this
putenv("GNUPGHOME=/tmp");
$gpg = new \gnupg();
$key = $gpg->import($user->pgp_key);
$gpg->addencryptkey($key['fingerprint']);
$encrypted_text = "
-----BEGIN PGP MESSAGE-----
hQEMA8b5QPvIxFcnAQgAl55QDu/QPn5A16Ag0+GAGwWzFVJcj4zGQMTVMHRNoZJw
h29gWkIjXXtgyBxsQCv+tiLxuyBmtUR1r45RDyZgtunrATtJAMBHOEORDZ8bRQps
87mY5Tw3VklLokAahjnJiqzY/HrodjQLXMdk8FXXoNk+SvZq+gdr5XVqAEtKgn/8
24NMzWD+k+zZL+8GLi3Fb2C6C2/go4oJBW+pTzNZF1yIkaIqpJp/T2nvp879bi1s
t8sUbGEUyVcJ8/qdQs1D4tq3g327RypHV9KV0nJ8fCCjN186uKrn4EUNaOB9p3RQ
IbeP94V5jGDNJdfdUOcfuiHS74cRLgNsSGf2S80ipNKSATApW498uYae7EtSHK/N
tEli+Mg3ZgJZ6iSoBEPsCSSSQmBprmha8W9SoXRT1LhvMXZZLdGGOCMOSgbS5cx1
Sl23jUK7xANGKwwyw4tSNh0G6yjULJ/bU00jMyhX/JyOQ64ZeKQdyW+z7pFs5n7u
SC7Y3V/kNjjyHzJshV4P9nru56sfyghA90GZoA3+R6LOvWE=
=gKpy
-----END PGP MESSAGE-----";
$plain = $gpg->decrypt($encrypted_text);
var_dump($plain); return bool(false)
I'm using gnupg version and PHP version
GPGme Version 1.7.1
Extension Version 1.4.0
PHP 7.0.18
Any idea why decryption fail?
I have generated a SSH key with PHP OpenSSL:
$rsaKey = openssl_pkey_new(array(
'private_key_bits' => 4096,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
));
$privKey = openssl_pkey_get_private($rsaKey);
openssl_pkey_export($privKey, $pem);
This results in $pem looking like this:
-----BEGIN PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQC8ggt6rVHYnqNP
...
e95+EXbPc6THyWt9pgwOsJltpylIYG4=
-----END PRIVATE KEY-----
But I cannot authenticate using this key. Before I can use it, I have to convert it using this command:
openssl rsa -in xxx.key -outform pem > xxx.key2
The result of the conversion is this:
-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEAvIILeq1R2J6jT+xjlK5NrOqFZTOJ4PByvgPQNbb2Kp7c3W15
...
o1t2KBkaSoR+JyOPOZakq5BLv8lgD3vefhF2z3Okx8lrfaYMDrCZbacpSGBu
-----END RSA PRIVATE KEY-----
Both are PEM format, but the second is a RSA private key. With the second, PHP can login. So I need a key that starts with RSA PRIVATE KEY, not just PRIVATE KEY. How can I create this with PHP and OpenSSL PHP implementation?
So, these are two different key types. You're looking for PKCS #1, but getting PKCS #8.
This appears to be related to the version of OpenSSL that PHP uses. Versions since 1.0 create a PKCS #8 file, and there's nothing the PHP developers want to do about it. The same issue arises when doing it from the command line with this command:
openssl req -new -keyout mykey.key -out mycertreq.csr -nodes -sha1 -newkey rsa:2048
You can try using an external library called phpseclib, though I haven't tried it myself:
<?php
include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_OPENSSH);
$result = $rsa->createKey();
echo $result["privatekey"];
?>
When I'm creating private key strings with the following PHP code (and same config-parameter), they are enclosed between different strings:
$configs = array('config' => 'OpenSSL.cnf',
'digest_alg' => 'sha1',
'x509_extensions' => 'v3_ca',
'req_extensions' => 'v3_req',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
'encrypt_key' => false,
'encrypt_key_cipher' => OPENSSL_CIPHER_3DES);
$privateKeyResourceId = openssl_pkey_new($this->configs);
openssl_pkey_export($privateKeyResourceId, $privateKeyString);
On Linux the $privateKeyString looks like this:
-----BEGIN PRIVATE KEY-----NBgkqhkiG9w0BAQE....ASDFasjkfa-----END PRIVATE KEY-----
On Windows the $privateKeyString looks like this:
-----BEGIN RSA PRIVATE KEY-----NBgkqhkiG9E....ASDFasjkfa-----END RSA PRIVATE KEY-----
When I copy the Windows private key string to Linux it works until I remove the 'RSA' from the start/end (same behavior vice versa). Why is this?
This is a differece between openssl versions not PHP. The following openssl command creates different key headers/footers between openssl versions 0.9.x and 1.0.0x:
openssl req -new -keyout mykey.key -out mycertreq.csr -nodes -sha1 -newkey rsa:2048
For version 0.9.x, the key header/footer is:
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
For version 1.0.0x, the key header/footer is:
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
For the later version of openssl, I have to run the key file through the following command to make it compatible with the older default:
openssl rsa -in mykey.key -text > mykey.pem
The "mykey.pem" file then has the header/footers (and format) that is compatible with AWS and like services.
According to a user note php.net this is a known issue:
Please take note that older versions of PHP/OpenSSL exports the RSA private key with '-----BEGIN RSA PRIVATE KEY-----' PEM tag, which includes just the privateKey field, thus omitting the version and privateKeyAlgorithm fields.
The effect of that would be that if you're converting it to DER, and
then back to PEM, but using '-----BEGIN PRIVATE KEY-----' PEM tag,
that the openssl_pkey_get_privatekey() function will fail!Senthryl's
code can be used to prefix the PEM encoded data with the version and
privateKeyAlgorithm fields again.
The newer PHP/OpenSSL versions exports the RSA private key with
'-----BEGIN PRIVATE KEY-----' PEM tag, which includes the version and
privateKeyAlgorithm fields.
I noticed these differences between my two servers:
PHP Version 5.3.3 (OpenSSL 1.0.0a-fips 1 Jun 2010) on Fedora Core 12 x64
PHP Version 5.2.9 (OpenSSL 0.9.8g 19 Oct 2007) on Fedora Core 10 x64
I'm looking for days how to translate this command to OpenSLL php function:
$ openssl pkcs8 -inform DER -in aaa010101aaa_CSD_01.key -out AAA010101AAA.key.pem
Enter Password: a0123456789
This work perfect, but I can't (I don't know) use the correct function of PHP OpenSSL
http://www.php.net/manual/es/ref.openssl.php
I have made this for .cer working perfect:
command : openssl x509 -inform DER -outform PEM -in aaa010101aaa_CSD_01.cer -out AAA010101AAA.cer.pem
PHP equivalent:
function der2pem($der_data) {
$pem = chunk_split(base64_encode($der_data), 64, "\n");
$pem = "-----BEGIN CERTIFICATE-----\n".$pem."-----END CERTIFICATE-----\n";
return $pem;
}
$fp = fopen("llaves/aaa010101aaa_CSD_01.cer", "r");
$priv_key = fread($fp, 8192);
fclose($fp);
echo der2pem($priv_key);
It's perfect, giving it to me the PEM. But doesn't work for the .key, just for the .cer, I obtain on OpenSSL this for .key using the funcion on PHP:
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDpmiW1q9gyzCFtMcbaFDJexk2IpLoTdNXg4ToGRZ/f+hIjmj3N
6ODWX1ARNFGYocEHf113GpW5Oe/mj6UqhBpiH4JRTNR4Udb8myJTArIlODynVHuI
UuyhKo7gbMbDdXjilTAYY2XWQuQ7aDtWwntUmNg4vAC/F3OtRz3+y9wM5QIDAQAB
AoGAfNkHomqvZ6a1jrh1wIPez8xID+mKEW/2BvQYoNWBNqFeJG0A7xWxZKEYF7nQ
ijSZB7rIZylsL8yJLL5E1c44koc+2+S6OF6gcWujcLR5UFRIZscxo0e1ro30wSTy
MBcdBeWASbaEy7+7MF46W0hAhBE7b49JUmduz1fBjtNNeoECQQD3VbNAsbf/90Vw
ZVexUXWNquwPsAZjmdpL1Te1RdC5txj2EbUdDPaaYC1cCXXjblf9rsyyViUowsNt
cnh92wSRAkEA8clIHObESiZZEndtmYuRlgLsX2Gr/qo30uAUurH7p8Q07SWOZCJk
OPJUhh2qanYZsnsOYHW+9Br5U6gDknxdFQJBALoua9nWLdDjnQTHdKSI0jmLIVmJ
wrV1GgsdfGrbHAzAlGye1bwBhxycK2jtwi0qYdgXngTcreop+hxIIAV1OdECQQC7
v7rZhnBhy8lax5Y5puEUBY0au7Nc+zyB6TLvjgmGSpt2krUxGGuOtM3hnuOX68Ek
kN2nFYeD8fYtecfcVenJAkEAxM+QzoVdJpw1/ijh+IfZ5eNhvMK2bj4De+/2Sx5K
ZZ9SiI7bRaOjBfvaI7AkeH0LpihURW12Zt7hZv8kC058Jg==
-----END RSA PRIVATE KEY-----
The same function on php give me:
-----BEGIN-----
MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIgkLCyAP9+nQCAggA MBQGCCqGSIb3DQMHBAgTJc/0zgL+tASCAoBHumtbuHsY5IevnUwr1Ha5P+S3RpVS 6iYvoOvKs5L6bPE+fjCkLxset0e68NcyXDw3WO/qzfGkFVGBnC90gekWUiS7/2pf ltPeKjo8Fw7T4CgVWhtnVdPZmJWihY52FuIQ2HuyQYzH8K/SnjYP4GBkJKpdPCjy JNzjspfJPoOlfdOkj7URwvKH5RjsLGYkopjtdaqxS2pFfz6PPCSiFMn+Jo9Vkjwv 3d1b3X2SoYuYhV2g3XgHWHBQNqoas8Blhcw8OYNlntxcaNnx3Eb9YcCWSmNj7l+c pibvosXzEqVoat6PsJyUVzJQZBao15PnI438qomkprsCy6EvFSSXuIunMH7nVIGH gcS0TRxYpXPHY3cdQOdsJtxb4Ny1aCJqLQkHs2jbiLZ5mu+rmQUil3tLxfRd4Bje AYA3T1e5VVVha97BmNQVTbNfxj9wWvkmrearxJXTvvnML4f0ma830S/1AGmCGLb/ A2KlqHq9RxqJn1SdOuYQbcQTeGe/JRVOaJVGUKxJ2vbwjB/35cmGNLKYj4faZZgy jYpC3BqVeDcPGlPuMnoNkgrBfLDgDX+JV6tqqT2uMo76Wp6xYKmM41jkO1IAWpHR /R7d3aG2psL0wKkFSEXWxhX3SRLdurVcFLv6E6bEPHqHJR4QrvF2OUwpDhOZz9F/ Lz935gz5MQNRuVRtAVBAa2ZmjRbdCboL/qiL2MKibZLNRmKy3dqRdPOmnlKKBR8d cYQc4YwRm5dWuObO2tY68R4H43g7shw+POKSzvSPhAkzRRGExONVDJ6Zg/0iAUNe 0xYlsqKJyCJ1fg/b1AuFyyAnOhCO9ywUGiK7t92pZRgmwxEfVBDRNcbA
-----END -----
Any ideas?
There's a library that allows just that. It is called Chilkat2. I used it to do the same in Python without console.
Right now I'm trying to remove this dependency in my library because it's closed source and it can't be installed through package managers, it must be installed manually with the website instructions.
It works pretty well, however, so here's how you would do it, assuming you have the .key file, the password, and Chilkat2 PHP Extension installed:
include("chilkat_9_5_0.php"); //whatever version you download
privateKey = new CkPrivateKey();
privateKey.LoadPkcs8EncryptedFile('path/to/private.key',password)
pemString = privateKey.getPkcs8Pem()
Note: I created this code with the documentation, but I have never used Chilkat2 with PHP.