openssl command in php - php

I want to generate example.com.crt and example.com.pem using php. The Linux command to get the files is given:
openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes
-out example.com.crt -keyout example.com.pem
I want to get the two file contents in two string in php. What is the php equivalent code for this?
UPDATE: Please don't ask to execute the Linux command.

here another command:
<?php
// generate 2048-bit RSA key
$pkGenerate = openssl_pkey_new(array(
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA
));
// get the private key
openssl_pkey_export($pkGenerate,$pkGeneratePrivate); // NOTE: second argument is passed by reference
// get the public key
$pkGenerateDetails = openssl_pkey_get_details($pkGenerate);
$pkGeneratePublic = $pkGenerateDetails['key'];
// free resources
openssl_pkey_free($pkGenerate);
// fetch/import public key from PEM formatted string
// remember $pkGeneratePrivate now is PEM formatted...
// this is an alternative method from the public retrieval in previous
$pkImport = openssl_pkey_get_private($pkGeneratePrivate); // import
$pkImportDetails = openssl_pkey_get_details($pkImport); // same as getting the public key in previous
$pkImportPublic = $pkImportDetails['key'];
openssl_pkey_free($pkImport); // clean up
// let's see 'em
echo "\n".$pkGeneratePrivate
."\n".$pkGeneratePublic
."\n".$pkImportPublic
."\n".'Public keys are '.(strcmp($pkGeneratePublic,$pkImportPublic)?'different':'identical').'.';
?>

You could use phpseclib, a pure PHP X.509 implementation:
http://phpseclib.sourceforge.net/x509/examples.html#selfsigned
<?php
include('File/X509.php');
include('Crypt/RSA.php');
// create private key / x.509 cert for stunnel / website
$privKey = new Crypt_RSA();
extract($privKey->createKey());
$privKey->loadKey($privatekey);
$pubKey = new Crypt_RSA();
$pubKey->loadKey($publickey);
$pubKey->setPublicKey();
$subject = new File_X509();
$subject->setDNProp('id-at-organizationName', 'phpseclib demo cert');
//$subject->removeDNProp('id-at-organizationName');
$subject->setPublicKey($pubKey);
$issuer = new File_X509();
$issuer->setPrivateKey($privKey);
$issuer->setDN($subject->getDN());
$x509 = new File_X509();
//$x509->setStartDate('-1 month'); // default: now
//$x509->setEndDate('+1 year'); // default: +1 year
$result = $x509->sign($issuer, $subject);
echo "the stunnel.pem contents are as follows:\r\n\r\n";
echo $privKey->getPrivateKey();
echo "\r\n";
echo $x509->saveX509($result);
echo "\r\n";
?>
That'll create a private key and a self-signed X.509 cert (as your CLI example does) with the private keys corresponding public key.

Execute the command with the exec() or system() function, then read the output files with file_get_contents().

There is OpenSSL extension to PHP, you should check if it is not enough for you as it would be better to use it insteaf of exec():
http://php.net/manual/en/book.openssl.php

Perhaps it's not the finest solution, but you can use exec() and file_get_contents(), something like:
exec("openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out example.com.crt -keyout example.com.pem");
$crtFile = file_get_contents("example.com.crt");
$pemFile = file_get_contents("example.com.pem");
Be aware file permissions and obviously file paths. Better if you add some error handling around these commands.
Read more: http://php.net/manual/en/function.exec.php
And: http://php.net/manual/en/function.file-get-contents.php

Related

How to digitally Sign data using p8 form private key in PHP and Verify it using Public key

I created a P8 format Private Key and signed data Using Java and tried to verify it using Public Key in PHP which Failed.
I created p8 file using openssl command
openssl pkcs8 -topk8 -inform PEM -outform DER -in myprivate.in.key -out myprivate.in.key.p8 -nocrypt
and Signed a Json data using
public byte[] sign(String data, String privateKeyFilePath) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException {
byte[] returnVal = null;
Signature signature = Signature.getInstance(RSA_SHA_256);
PrivateKey privateKey = getPrivateKey(privateKeyFilePath);
signature.initSign(privateKey);
signature.update(data.getBytes());
returnVal = signature.sign();
return returnVal;
}
But When I tried to verify it using Public cerificate in PHP using openssl command, it failed
$cert_path = file_get_contents(storage_path('certificates/my_in.cer'));
$pub_key = openssl_get_publickey($cert_path);
$keyData = openssl_pkey_get_details($pub_key);
$pub_key = $keyData['key'];
// $verify = openssl_x509_verify()
$verify = openssl_verify($dataSigned, $signatureDecoded, $pub_key, 'sha256WithRSAEncryption');
What am I doing wrong, Also is there a way I can Sign the data using p8 key in php!
By following this process everything is ok. Maybe it will be useful to you?
Use openssl to generate keys:
# Generate PK
openssl genpkey -algorithm RSA \
-pkeyopt rsa_keygen_bits:2048 \
-pkeyopt rsa_keygen_pubexp:65537 | \
openssl pkcs8 -topk8 -nocrypt -outform der > rsa-2048-private-key.p8
# Convert your PKCS#8 file to a plain private key
openssl pkcs8 -nocrypt -in rsa-2048-private-key.p8 -inform DER -out rsa-2048-private-key.pem
# Generate pub key
openssl rsa -in rsa-2048-private-key.pem -pubout -out rsa-2048-public-key.pem
Test pkey and sign data (index.php):
<?php
$privateKeyFile="file://".__DIR__.DIRECTORY_SEPARATOR."rsa-2048-private-key.pem";
$publicKeyFile="file://".__DIR__.DIRECTORY_SEPARATOR."rsa-2048-public-key.pem";
// Data to sign
$data = 'Hello world!';
// Test on get private key
$pkeyid = openssl_pkey_get_private($privateKeyFile);
if ($pkeyid === false) {
var_dump(openssl_error_string());
}else{
var_dump($pkeyid);
}
// Sign data
openssl_sign($data, $signature, $pkeyid);
// Free memory
openssl_free_key($pkeyid);
// Read pub key
$pubkeyid = openssl_pkey_get_public($publicKeyFile);
// Test if sign is ok
$ok = openssl_verify($data, $signature, $pubkeyid);
if ($ok == 1) {
echo "Sign OK";
} elseif ($ok == 0) {
echo "Sign NOK";
} else {
echo "Sign check error";
}
// Free memory
openssl_free_key($pubkeyid);
php -S localhost:8000, http://localhost:8000, returns:
resource(2) of type (OpenSSL key) Sign OK

OpenSSL req won't work on PHP Shell

I've been searching for the solution of my problem which is about OpenSSL. I'm using shell_exec() to run shell promts. For example:
shell_exec("openssl genrsa -out myprvkey.pem 1024"); works fine, and generates myprvkey.pem.
However,
shell_exec("openssl req -new -key myprvkey.pem -x509 -days 365 -out mypubcert.pem"); isn't working without giving any errors.
Am I doing something wrong? Thanks. PS: Please remind me if I'm missing something.
OpenSSL Version: 268439647
Looks like you're trying to create a CSR? If so you can do so using phpseclib, a pure PHP CSR implementation, pretty easily. Here's an example that creates a new RSA key and a new CSR:
<?php
include('File/X509.php');
include('Crypt/RSA.php');
$privKey = new Crypt_RSA();
extract($privKey->createKey());
$privKey->loadKey($privatekey);
$x509 = new File_X509();
$x509->setPrivateKey($privKey);
$x509->setDNProp('id-at-organizationName', 'phpseclib demo cert');
$csr = $x509->signCSR();
echo $x509->saveCSR($csr);
?>
Here's an example that creates a new CSR utilizing an existing RSA key:
<?php
include('File/X509.php');
include('Crypt/RSA.php');
$privKey = new Crypt_RSA();
$privKey->loadKey('...');
$x509 = new File_X509();
$x509->setPrivateKey($privKey);
$x509->setDNProp('id-at-organizationName', 'phpseclib demo cert');
$csr = $x509->signCSR();
echo $x509->saveCSR($csr);
?>
(the only diff is that loadKey is being passed a string [which could be populated via file_get_contents or just directly inputted] instead of the output of extract($rsa->createKey()))

Using PHP/openssl to securly exchange business data

I want to exchange data with other businesses using PHP/OpenSSL. Each business creates public/private keys and publishes the public key. Then, I write code to manage all that. Here is a code in PHP (mostly from php.net):
<?php
$data = "secret message";
$key = file_get_contents("bus1.pub");
// get temp file w/ write access
$plaintextfile = tempnam(sys_get_temp_dir(), 'abc');
$ciphertextfile = tempnam(sys_get_temp_dir(), 'abc');
$fp = fopen($plaintextfile, "w");
fwrite($fp, $data);
fclose($fp);
// encrypt it
if (openssl_pkcs7_encrypt($plaintextfile, $ciphertextfile, $key,
array("To" => "nighthawk#example.com", // keyed syntax
"From: HQ <hq#example.com>", // indexed syntax
"Subject" => "Eyes only"))) {
echo "encryption ok<br>";
} else
echo "failure<br>";
?>
However, I get an error (failure). I suspect that I do not generate the keys correctly using OpenSSL. Please help in how to properly generate the keys so that they can be read by PHP functions above.
This is what I tried:
openssl genrsa -out bus1.pem 2048
openssl rsa -in bus1.pem -pubout > bus1.pub
Another suggestion from php docs https://www.php.net/manual/en/function.openssl-encrypt.php.
This Is The Most Secure Way To Encrypt And Decrypt Your Data,
It Is Almost Impossible To Crack Your Encryption.
--------------------------------------------------------
--- Create Two Random Keys And Save Them In Your Configuration File ---
<?php
// Create The First Key
echo base64_encode(openssl_random_pseudo_bytes(32));
// Create The Second Key
echo base64_encode(openssl_random_pseudo_bytes(64));
?>
--------------------------------------------------------
<?php
// Save The Keys In Your Configuration File
define('FIRSTKEY','Lk5Uz3slx3BrAghS1aaW5AYgWZRV0tIX5eI0yPchFz4=');
define('SECONDKEY','EZ44mFi3TlAey1b2w4Y7lVDuqO+SRxGXsa7nctnr/JmMrA2vN6EJhrvdVZbxaQs5jpSe34X3ejFK/o9+Y5c83w==');
?>
--------------------------------------------------------
<?php
function secured_encrypt($data)
{
$first_key = base64_decode(FIRSTKEY);
$second_key = base64_decode(SECONDKEY);
$method = "aes-256-cbc";
$iv_length = openssl_cipher_iv_length($method);
$iv = openssl_random_pseudo_bytes($iv_length);
$first_encrypted = openssl_encrypt($data,$method,$first_key, OPENSSL_RAW_DATA ,$iv);
$second_encrypted = hash_hmac('sha3-512', $first_encrypted, $second_key, TRUE);
$output = base64_encode($iv.$second_encrypted.$first_encrypted);
return $output;
}
?>
--------------------------------------------------------
<?php
function secured_decrypt($input)
{
$first_key = base64_decode(FIRSTKEY);
$second_key = base64_decode(SECONDKEY);
$mix = base64_decode($input);
$method = "aes-256-cbc";
$iv_length = openssl_cipher_iv_length($method);
$iv = substr($mix,0,$iv_length);
$second_encrypted = substr($mix,$iv_length,64);
$first_encrypted = substr($mix,$iv_length+64);
$data = openssl_decrypt($first_encrypted,$method,$first_key,OPENSSL_RAW_DATA,$iv);
$second_encrypted_new = hash_hmac('sha3-512', $first_encrypted, $second_key, TRUE);
if (hash_equals($second_encrypted,$second_encrypted_new))
return $data;
return false;
}
?>
OK. I figured out the mistake. Thanks to #towr for pointing out a debugging tool. For other readers, the solution is to generate the certificate as follows. Each business need to do this, keep the private key and publish the certificate:
openssl genrsa -out business1.pass.key 2048
openssl rsa -in business1.pass.key -out business1.key
openssl req -new -key business1.key -out business1.csr
openssl x509 -req -days 3650 -in business1.csr -signkey business1.key -out business1.crt

How i can create a self-signed certificate using phpseclib

How i can create a self-signed certificate using phpseclib from a existing .csr file, only i can use a .csr file.
I've read the manual and the method use a private key, but in my assignment i only can use a .csr file.
I hope you can help me.
Here's my code:
<?php
include('File/X509.php');
include('Crypt/RSA.php');
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
}
else
{
//This is the content of the file
$csr = file_get_contents($_FILES["file"]["name"]);
}
// create private key / x.509 cert for stunnel / website
$privKey = new Crypt_RSA();
extract($privKey->createKey());
$privKey->loadKey($privatekey);
$pubKey = new Crypt_RSA();
$pubKey->loadKey($publickey);
$pubKey->setPublicKey();
$subject = new File_X509();
$subject->loadCSR('...'); // see csr.pem
// calling setPublicKey() is unnecessary when loadCSR() is called
$issuer = new File_X509();
$issuer->setPrivateKey($privKey);
$issuer->setDN($subject->getDN());
$x509 = new File_X509();
//$x509->setStartDate('-1 month'); // default: now
//$x509->setEndDate('+1 year'); // default: +1 year
$result = $x509->sign($issuer, $subject);
echo "the stunnel.pem contents are as follows:\r\n\r\n";
echo $privKey->getPrivateKey();
echo "\r\n";
echo $x509->saveX509($result);
echo "\r\n";
?>
You need a private key, plain and simple. Otherwise, what are you going to sign it with? The signature field of an X.509 cert is mandatory.
I mean, if all you want is a public key, you don't need to bother with the X.509 overhead. You can just pony up a public key that looks like this:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4eCZ0
FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RKNUSesmQRMSGkVb1/
3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZwIDAQAB
-----END PUBLIC KEY-----
But X.509 is more than just a public key - it's a signed public key. Technically, a CSR is, too, but CSR's are always self-signed whereas X.509 certs can be signed by anyone.

openssl: how can i get public key from modulus

I generate a pair of keys using openssl:
shell> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/mike/.ssh/id_rsa): /path/to/test_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /path/to/test_rsa.
Your public key has been saved in /path/to/test_rsa.pub.
And then, I generate modulus from private key:
shell> openssl rsa -in /path/to/test_rsa -noout -modulus > /path/to/modulus.txt
Now, is there any way to get test_rsa.pub(public key) just from modulus?
You can get the public key in a more standardized format using phpseclib, a pure PHP RSA implementation. eg.
<?php
include('Crypt/RSA.php');
$modulus = 'yEQs2LxSHBZgZCH0rRQQy9kmry8g2tNhQL1B9f5azNz9Ce9pXPgSRjVUo1B9Ggb/FK3jy41wWd2IfS6rse3vBzRsabMj29CVODM/19yZPmwEmjJHCgYd+AA2qweKZanDp4FLsSw/kyV5WoPN16GHEMLmLGkJFNIWtzzH5jV+S80=';
$exponent = 'AQAB';
$rsa = new Crypt_RSA();
$modulus = new Math_BigInteger(base64_decode($modulus), 256);
$exponent = new Math_BigInteger(base64_decode($exponent), 256);
$rsa->loadKey(array('n' => $modulus, 'e' => $exponent));
$rsa->setPublicKey();
echo $rsa->getPublicKey();

Categories