I have a small string of some data (less than 1kb) that I would like to have user agents pass to other sites when they are sent from my site. In order for the other sites to verify that I was the one that created the string I though of two options.
The server pings me back to confirm (like paypal, openid, etc..)
I use public/private keys to prove I sent the message (like PGP, DKIM, etc..)
I don't want to setup HMAC because that would mean I have to use custom keys for each site which would be a pain.
Out of those two choices it seems that #2 would save on bandwidth which makes it seem like a better choice.
So how can you setup public/private key cryptography using PHP and are there any downsides?
Creating a private and public key pair using the PHP Openssl functions:
// Configuration settings for the key
$config = array(
"digest_alg" => "sha512",
"private_key_bits" => 4096,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
);
// Create the private and public key
$res = openssl_pkey_new($config);
// Extract the private key into $private_key
openssl_pkey_export($res, $private_key);
// Extract the public key into $public_key
$public_key = openssl_pkey_get_details($res);
$public_key = $public_key["key"];
You can then encrypt and decrypt using the private and public keys like this:
// Something to encrypt
$text = 'This is the text to encrypt';
echo "This is the original text: $text\n\n";
// Encrypt using the public key
openssl_public_encrypt($text, $encrypted, $public_key);
$encrypted_hex = bin2hex($encrypted);
echo "This is the encrypted text: $encrypted_hex\n\n";
// Decrypt the data using the private key
openssl_private_decrypt($encrypted, $decrypted, $private_key);
echo "This is the decrypted text: $decrypted\n\n";
I would create S/MIME public/private keypairs using OpenSSL and then use the OpenSSL command to do the encryption & decryption. I believe that this is superior to using PGP because openssl is included with most linux operating systems and PGP isn't. OpenSSL is also standards-based and generally easier to work with, once you have the commands down.
I recommended against a "pure-PHP" solution (by pure-PHP I mean doing the crypto in PHP, rather than using PHP to call an existing library or a separate executable). You don't want to do bulk crypto in PHP. Too slow. And you want to use OpenSSL, because it's high performance and the security is well understood.
Here's the magic.
To make an X.509 key:
$subj="/C=US/ST=California/L=Remote/O=Country Govt./OU=My Dept/CN=Mr. Agent/emailAddress=agent#investiations.com"
openssl req -x509 -newkey rsa:1024 -keyout mycert.key -out mycert.pem -nodes -subj $subj
That puts the private key in mycert.key and the public key in mycert.pem. The private key is not password protected.
Now, to sign a message with S/MIME:
openssl smime -sign -signer mycert.pem -inkey mycert.key <input >output
To encrypt a message with S/MIME:
openssl smime -encrypt -recip yourcert.pem <input >output
To decrypt a message with S/MIME:
openssl smime -decrypt -inkey mycert.key -certfile mycert.pem <input >output
I also have some demos on using OpenSSL from the C language bindings, but not from PHP.
Rule 1: Don't implement it yourself, use a library.
Which library? Here are my recommended PHP public-key cryptography libraries:
Halite, depends on libsodium (but emphasizes simplicity and ease-of-use in addition to security).
libsodium, from PECL
EasyRSA, which implements secure public-key encryption and public-key signatures using RSA in the most secure modes (NOT PKCS1v1.5, ever!)
phpseclib, which EasyRSA piggybacks off of.
In general, you'll want libsodium if security is your goal. Whether or not you use Halite is a matter of taste.
PGP is a good option - it is implemented properly and completely (i.e. you have little room for security mistakes with PGP). I think this SO question will help you with interfacing with GnuPG. The question is whether and how the other sites will verify your signature. You need to either conform to their verification mechanism requirements or provide your own module that those sites will use for verification.
Also it's possible that you can use OAuth or OpenID to identify users on those other sites, but I am not an expert in these technologies.
Related
I am encrypting data in the browser with JS, and then attempting to decrypt it on the backend with PHP.
In JS, I am using npm-rsa which was built using browserify.
In PHP, I am using phpseclib
My JS:
key = new rsa({
environment: 'browser',
encryptionScheme: 'pkcs1_oaep',
signingScheme: 'pkcs1-sha256',
b: 2048
});
cleartext = 'this is a test';
console.log(key.encrypt(cleartext, 'base64'));
console.log(this.key.exportKey('pkcs8-private-pem'));
I then take my public key and cyphertext to PHP:
$rsa = new RSA();
$rsa->load($privkey, 'pkcs8');
$cleartext = $rsa->decrypt(base64_decode($cyphertext));
When I run this, $cleartext is null. Using Xdebug, I can see that $rsa->load($pubkey, 'pkcs8'); does appear to be populating the modulus, exponents, primes, coefficients, etc fields of $rsa.
I have even tried $rsa->setHash('sha256'); before calling decrypt(), but it's my understanding that the hash method is only used for encryption and not even used in decryption.
Also, I understand that this is not secure because i'm sharing the private key. I'm just trying to verify compatibility between the two libraries.
I have tested that i can encrypt and decrypt with both libraries independently, but taking a key from the JS lib to the PHP lib I can't get to work.
EDIT:
Exported private key:
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDX7/224Phogd/B
4DGOf81GeNAkE0bAWieN9Tmq6S1Xe0iMY56J9hJ86HveCcJcJCMNAJtGVPjOObNf
HZ58CUrqyMoj6VJ8wXGVPZuwkvBQrVFg4k/h+8+b3p5Z0cb8J9m8WWpnL/hifoyt
9O7aEiSnkvHBWBgEK6qxEYVLJKUPI94HlZe4B+ScCaflUMw1/uMfp1pVGxVUAfER
f8URfCjCUY8cL+yFNQ5/CVNMQ8CTlb6HItpfS/QVBqTUD3wNf97oFZDPzbFfFCD7
M50NbCal6CfRTaMBPoWrhsUGVab/Nj81qcY7dpoYEFyLLnJ80jHR6+o1fKDSinuQ
KIYkQ9PxAgMBAAECggEBANKs7tgx/anYrDo3RaJFxjzvOgM4W1rnmpfBnRXGkdo8
CbgOqWrojXkYSWGEHABRsXDKGrQvyt9JJFu0Rh+14UXXyH/o7/WPtgVpKjDH63aK
4k6n/k/4ocDtHYl8RatWJfTBODKcdrWByjceNLrF4MUtdHiyPhwzjkFbWrTJd9Cf
3wEh0aD83JT/wg1VkRYEOdJTPeq2kCpgoukBFXYAnGj9DYL2+Kityhnx/GB0RG/8
GGpMyG8R72P6zYkXr0YfLhGLlW7+XbLT+WiPThjT9+e00uPAKMj7d0qaerKR6Asf
NGSAg83eWG9ZKT1GXtn8mOP6p+15DcVLBbFXvPAA/cECgYEA7IYRWGNhEJ9l+XJH
DYQVndS9KN8+zMx5OM/wy47v9FiiwGdAnwwHFAX3GyZe6eJ2sAX73tPm56QadRPK
HGZFNnYx3BBdcl7WKT13DrmgpsH9CO6ish+2TwHfYDqOKs5EvT3yHJIG4T/Z50JM
bUKSdrndV6LtOT2gplLxjUwastUCgYEA6bf23y5p8t9Unn55bIYKdFWj/5kLJdI1
d/MBP3eZ405veVzZqvhs04JscElx1M0U1mTx7g96IWnBTuqsgkU9TLlXg8N5nLM0
AWVlFlu657NwJaAc9zfmaamI4UKwNHCXDoxx+u2zJuzNOJwttPV3d7NTBWZOh+P+
DEgAzNYOEq0CgYEA42Oo/U7dnHuCMCTbhnT7yzchfE/UMlRKHoJbP3f13PXx0gPy
LnYDwA5UGLf0++oKrQOzt/AEx6IPBYu2/UKdO9S57pWVIUVno1JCSdfQSUGqoJG7
vH+cZ6ynMf5Ze3G+yCjrwOfq0VbviNNGYqxj3tylnYE3i5ZiAkUvkOYfrNkCgYBa
rZBvyN88Zt+62pEbxOm7dxq46VUE6IjsL/EVAb9IDL99U8Pz7Iy0h06xRh2PFb52
7BVdas3UtuZUSwKBTIHbCbHlomrFnFWaEQ/mW9KpYNorDvMOC7cu2aMM2sXooqJI
976lP6IZgRiiVR36rp4aaA3W83mWiaOgejMtRgORxQKBgQDTMG0Wl3FbPZ57uqmi
rE2Gwr1TiZ7LcYSEt4Z7KQV/u0Q7b9hyNXctaK2DzcEz+wA1eiAzioC9ZULOVVvW
xZzVvj2D741A6EXMITa3E/Wv1XkbotNg8RXG8lvNY/IJ+35TZGBNzJ4gD+n0lOCK
IrdIMYPrt9dcGIqqRE4wwaeLmA==
-----END PRIVATE KEY-----
cyphertext:
mbPLBF3YNmyb5AD1vk6D8K0C9AiRU3C2a2aCKXpzDXb1uUCy7KYUFB3bOoU4ZhU7RXcWr9VHZq3APxtdyqKyEqr48NqVEPeBuYsDjcgDfPBFdPXf36f1FveeCJ7cFtHIvGy9/2EHIyNyXKy/6VaoakGRwBB3V14shXdqCDIW2FfEdUcfka5X8sAroq9pKrTGbN21hwtbiAjP2MmTHDYWu1zhDmrKxdcBbP6wdBgnZodCwGhBw11uXoEAnL1/yYFFqGZeKAhzxfjdPY2irvAuQOPN3U7UDBF0zhyMNF07JbCccCsNIguX4esferShw8w1mVzAxgwHzbjDpudko1/VSg==
I saved these into two files, privatekey.pem and cypher.text. Then I base64 decoded the cyphertext:
cat cypher.text | base64 --decode > -in cypher.bin
And use openssl to decrypt this:
openssl rsautl -decrypt -inkey privatekey.pem -in cypher.bin -oaep
This gives me the cleartext! So it appears that phpseclib has an issue in decoding.
It turns out that the hash has to be set in the decryption method with BOTH:
$rsa->setMGFHash('sha1');
$rsa->setHash('sha1');
Although i had tried it with setHash(), it was not enough without also setMGFHash()
I am studying the digital certificates in PKI ( Public Key Infrastructure ). Almost all manuals / pages regarding this give following similar steps.
Get subject identity + subject public key, (AND/OR Encrypted Message hash with subject's private key) and build a certificate.
Sign certificate with CA's private key
At destination, verify certificate with CA's public key
Now I am able to find way in php (using openssl lib) to for 1st and 2nd step which can generate a certificate and sign it ( optionally generate a signature hash and sign it too ) through openssl APIs.
But Issue with third step, Their are no guide line or function call which show how to verify certificate with CA's public key.
If I am missing something ?
Example code I checking is like below
$data = 'my data';
//create new private and public key
$req_key = openssl_pkey_new(array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
));
$dn = array(
"countryName" => "IN",
"stateOrProvinceName" => "Delhi",
"organizationName" => "example.net",
"organizationalUnitName" => "Security",
"commonName" => "example.net"
);
$req_csr = openssl_csr_new ($dn, $req_key);
$req_cert = openssl_csr_sign($req_csr, null, $req_key, 365);
openssl_x509_export ($req_cert, $out_cert);
echo $out_cert;
BACKGROUND : I need to implement PKI based data sharing/validating for some application. It would be involve some data entity (data entity would have its on public and private key) encrypted at source side and then send to destination. Then destination decrypt and get clear data. But that whole must involve PKI that means digital signature + digital certificate implementation along with.
This task isn't pretty straightforward in PHP. In fact, PHP isn't good tool for implementing CA stuff. It supports basic PKI operations but that's all. I see three options:
X.509 is just DER encoded ASN.1 structure. You can inspect it with guiDumpASN-ng for example. There are also some ASN.1 libraries in PHP world. Basicaly, the CA signature is inside certificate. If you'll able to extract it, you can then verify digital signature on your own.
http://php.net/manual/en/function.openssl-verify.php#98282
Try to use function like openssl-x509-checkpurpose that should be able to check certificate chain.
Try to use phpseclib - look at Validate X.509 certificates -> validateSignature().
I hope it will help you a little bit.
Do not mess up with implementing certificates validation by yourself but look for an implementation of the CPV (Certification Path Validation) algorithm, which includes all the validations required to be performed in a certification chain, where certificate signature validation is only one of them.
Now, I've been looking for a PHP API to perform CPV but I found none so I resorted to execute the following external OpenSSL command from PHP:
exec("openssl verify -CAfile trusted_root_cas.pem -untrusted intermediate_cas.pem endentity_cert.pem", $output, $return_var);
if ($return_var == 0) {
echo "Certification path validation completed successfully";
} else {
echo "Certification path validation completed with errors";
}
Where all trusted_root_cas.pem, intermediate_cas.pem and endentity_cert.pem could be temporal files created just for the execution of the previous command.
Now, if you want to know what openssl verify does, execute man verify:
The verify command verifies certificate chains.
I want to use PGP encryption to encrypt a CSV files, I am generating through a PHP script and then send that file to client via email. Client will give me the encryption key, which I need to use for encryption files.
I Googled about PGP and found it is Pretty Good Privacy, also I found OpenPGP http://www.openpgp.org/ and GnuPG http://www.gnupg.org/ What are these two types of PGP? and which one should I use?
Also how to encrypt a files using PGP in PHP with the key that my client will provide?
I have heard this term first time, can anyone please help in understanding this and implementing this in PHP.
Question 1: About PGP
PGP (Pretty Good Privacy) is a product and trademark of Symantec Corporation (they bought it some years ago).
OpenPGP is the standard used by PGP.
GnuPG (Gnu Privacy Guard) is a free and open source implementation of PGP.
So what you want to do is encrypt to an OpenPGP key. Which implementation of OpenPGP your client uses to decrypt the data is not important for you. With PHP, commonly GnuPG is used and there are interfaces built-in.
Question 2: Using GnuPG in PHP
Use the GnuPG interface, which is an extension that can be installed for PHP.
At first, import the key, where $keydata is the ASCII armored public key:
<?php
$gpg = new gnupg();
$info = $gpg -> import($keydata);
print_r($info);
?>
Then use this key to encrypt the data, this time using the client's key's fingerprint:
<?php
$gpg = new gnupg();
$gpg -> addencryptkey("8660281B6051D071D94B5B230549F9DC851566DC");
$enc = $gpg -> encrypt("just a test");
echo $enc;
?>
If you want to encrypt files, read and pass them to encrypt(). Be sure to use at least long key IDs (eg. DEADBEEFDEADBEEF), better fingerprints (as in the example) when referencing keys; and never use short key IDs (DEADBEEF), as those are vulnerable to collision attacks.
The is a more comprehensive example for doing both added by a user in the PHP manual.
Going to leave an answer here as many examples across the net for PHP GnuPG are very bare bones and hopefully this saves someone some frustration.
Basically, it mirrors how the GnuPG command line tool works. You need to import a key if it's not already in gpg's key ring then you need to select the recipient's key to use for encryption/decryption.
gpg --import recipients-public-key.asc
gpg -r recipient --encrypt test.txt
If you did what I did and passed in the key as the recipient it doesn't work!
It's not clear what this field is in either the GPG manual or PHP documentation which refers to this field as "fingerprint". Check gpg's key ring for your freshly imported key with:
gpg --list-keys
This will output something like this:
pub rsa2048 2019-04-14 [SC] [expires: 2021-04-14]
0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA
uid [ultimate] Dean Or
sub rsa2048 2019-04-14 [E] [expires: 2021-04-14]
This will give you the UID and on the second line the fingerprint associated with every key. As far as I can tell you can use the UID and fingerprint as the recipient.
So your PHP code to encrypt might look like this:
// Encrypt
$gpg = new gnupg();
$gpg->seterrormode(gnupg::ERROR_EXCEPTION);
// Check key ring for recipient public key, otherwise import it
$keyInfo = $gpg->keyinfo('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA');
if (empty($keyInfo)) {
$gpg->import('recipients-public-key.asc');
}
$gpg->addencryptkey('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA');
echo $gpg->encrypt('This is a test!');
Then the recipient's code will look like this:
// Decrypt
$gpg = new gnupg();
$gpg->seterrormode(gnupg::ERROR_EXCEPTION);
// Check key ring for recipient private key, otherwise import it
$keyInfo = $gpg->keyinfo('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA');
if (empty($keyInfo)) {
$gpg->import('recipients-private-key.asc');
}
$gpg->adddecryptkey('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA', '');
echo $gpg->decrypt($encyptedMessage);
Note the fingerprints are the same for both the recipient's public and private key.
There is also a known issue with adddecryptkey not taking a passphrase! You either need to remove the passphrase or change your version of GnuPG.
I want to use PGP encryption to encrypt a CSV files, I am generating through a PHP script and then send that file to client via email. Client will give me the encryption key, which I need to use for encryption files.
I Googled about PGP and found it is Pretty Good Privacy, also I found OpenPGP http://www.openpgp.org/ and GnuPG http://www.gnupg.org/ What are these two types of PGP? and which one should I use?
Also how to encrypt a files using PGP in PHP with the key that my client will provide?
I have heard this term first time, can anyone please help in understanding this and implementing this in PHP.
Question 1: About PGP
PGP (Pretty Good Privacy) is a product and trademark of Symantec Corporation (they bought it some years ago).
OpenPGP is the standard used by PGP.
GnuPG (Gnu Privacy Guard) is a free and open source implementation of PGP.
So what you want to do is encrypt to an OpenPGP key. Which implementation of OpenPGP your client uses to decrypt the data is not important for you. With PHP, commonly GnuPG is used and there are interfaces built-in.
Question 2: Using GnuPG in PHP
Use the GnuPG interface, which is an extension that can be installed for PHP.
At first, import the key, where $keydata is the ASCII armored public key:
<?php
$gpg = new gnupg();
$info = $gpg -> import($keydata);
print_r($info);
?>
Then use this key to encrypt the data, this time using the client's key's fingerprint:
<?php
$gpg = new gnupg();
$gpg -> addencryptkey("8660281B6051D071D94B5B230549F9DC851566DC");
$enc = $gpg -> encrypt("just a test");
echo $enc;
?>
If you want to encrypt files, read and pass them to encrypt(). Be sure to use at least long key IDs (eg. DEADBEEFDEADBEEF), better fingerprints (as in the example) when referencing keys; and never use short key IDs (DEADBEEF), as those are vulnerable to collision attacks.
The is a more comprehensive example for doing both added by a user in the PHP manual.
Going to leave an answer here as many examples across the net for PHP GnuPG are very bare bones and hopefully this saves someone some frustration.
Basically, it mirrors how the GnuPG command line tool works. You need to import a key if it's not already in gpg's key ring then you need to select the recipient's key to use for encryption/decryption.
gpg --import recipients-public-key.asc
gpg -r recipient --encrypt test.txt
If you did what I did and passed in the key as the recipient it doesn't work!
It's not clear what this field is in either the GPG manual or PHP documentation which refers to this field as "fingerprint". Check gpg's key ring for your freshly imported key with:
gpg --list-keys
This will output something like this:
pub rsa2048 2019-04-14 [SC] [expires: 2021-04-14]
0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA
uid [ultimate] Dean Or
sub rsa2048 2019-04-14 [E] [expires: 2021-04-14]
This will give you the UID and on the second line the fingerprint associated with every key. As far as I can tell you can use the UID and fingerprint as the recipient.
So your PHP code to encrypt might look like this:
// Encrypt
$gpg = new gnupg();
$gpg->seterrormode(gnupg::ERROR_EXCEPTION);
// Check key ring for recipient public key, otherwise import it
$keyInfo = $gpg->keyinfo('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA');
if (empty($keyInfo)) {
$gpg->import('recipients-public-key.asc');
}
$gpg->addencryptkey('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA');
echo $gpg->encrypt('This is a test!');
Then the recipient's code will look like this:
// Decrypt
$gpg = new gnupg();
$gpg->seterrormode(gnupg::ERROR_EXCEPTION);
// Check key ring for recipient private key, otherwise import it
$keyInfo = $gpg->keyinfo('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA');
if (empty($keyInfo)) {
$gpg->import('recipients-private-key.asc');
}
$gpg->adddecryptkey('0DAA2C747B1974BE9EB9E6DCF7EE249AD00A46AA', '');
echo $gpg->decrypt($encyptedMessage);
Note the fingerprints are the same for both the recipient's public and private key.
There is also a known issue with adddecryptkey not taking a passphrase! You either need to remove the passphrase or change your version of GnuPG.
I have a task: generate private/public key pairs for banks.
User data like State, City, Company, Name, Email, and some other data should be included. How I can generate those keys with PHP or Shell?
UPDATE 1
I need a private key and cert for a Bank.
PHP offers interface to OpenSSL functions. You need to generate a certificate (the keypair can't include user data), and this is a bit more complicated than generating a keypair. You can generate self-signed certificates (in such certificates Issuer and Subject fields are identical), which is probably what you need.
If you need a CA-signed certificate, than you need to generate a certificate signing request (CSR) and a private key, then send a CSR to the certificate authority that will sign it and send you back the certificate (remember that private key remains on your side, so you need to save it).
Also, google search revealed a good tutorial for you.
Private&public key pairs do not contain identifying information like name and address. Certificates do (and also certificate requests, since those are meant to be turned into certificates).
The openssl command can generate both key pairs and certificate requests, and it can sign certificate requests to produce certificates as well. First, figure out exactly which kinds of objects you need, whether you need to use a central CA to sign certificates, etc... Then you should be able to easily find information on what arguments you need to pass to generate each type of object.
Here is a shell script that I use for generating certificates using openssl.
This is just a test script I wrote, so you might want to set some additional security. Having passwords written somewhere is not a good idea. You might want to run it thoroughly in your test environment or tweak as you like.
Here is what it requires:
A proper CA certificate, its own private key etc, I assume you already have it.
(I generated a self signed one and I would have it in the demoCA folder. Or you can generate using /usr/share/ssl/misc/CA.sh -newca)
Openssl
Text file (cert.input) having Required data {Country, State, City, Company, Org, Common name etc everything in a newline}
Text file (caconfirm.input) for confirmation input (for saying 'yes')
Text file for passwords. (pass.input) I will use MyPassword for all my cert related passwords.
There is only 1 only requirement, the ca private key file should not be password protected. If it is, you can run:
openssl rsa -in demoCA/private/cakey.pem -out
demoCA/private/cakey_nopass.pem
Lets say I stored filename in CERT_FILE_NAME.
In the end you will get a folder with the name you provided (filename) containing:
cert in pem format (filename.pem), cert in crt format (filename.crt), cert in der (binary format, (filename.der)), cert in password protected .p12 format (filename.p12), cert private key password protected (filename_Password.key) and cert private key non password protected. (filename_NoPassword.key)
#!/bin/sh
CERT_FILE_NAME=$1
#Lets generate a typical private key
openssl genrsa -passout pass:MyPassword -des3 -out ${CERT_FILE_NAME}_Password.key 1024
#Now, generate a cert signing request, and recieve the data from cert.input
openssl req -passin pass:MyPassword -new -key ${CERT_FILE_NAME}_Password.key -out ${CERT_FILE_NAME}.csr < cert.input
#Sign the csr with the private key of our CA, and recieve the confirmation from caconfirm.input
openssl ca -in ${CERT_FILE_NAME}.csr -cert demoCA/cacert.pem -keyfile demoCA/private/cakey_nopass.pem -out ${CERT_FILE_NAME}.crt -days 3825 < caconfirm.input
#Export my new cert to a password protected p12 file
openssl pkcs12 -passin pass:MyPassword -passout pass:MyPassword -export -in ${CERT_FILE_NAME}.crt -inkey ${CERT_FILE_NAME}_Password.key -out ${CERT_FILE_NAME}.p12
#(Optional) Export my private key to a plain text private key
openssl rsa -passin file:pass.input -in ${CERT_FILE_NAME}_Password.key -out ${CERT_FILE_NAME}_NOPassword.key
# Output the crt into strict pem format having BEGIN/END lines
grep -A 1000 BEGIN ${CERT_FILE_NAME}.crt > ${CERT_FILE_NAME}.pem
# Convert the pem into der (binary) format
openssl x509 -outform der -in ${CERT_FILE_NAME}.pem -out ${CERT_FILE_NAME}.der
# Create a directory
mkdir ${CERT_FILE_NAME}
# Move all my cert files in the folder
mv ${CERT_FILE_NAME}*.* ${CERT_FILE_NAME}
Now the contents of the text files that we used (every item in newline):
cert.input:
Country
State
CityName
CompanyName
OrgName
CommonName
pass.input:
MyPassword
caconfirm.input:
y
y
Here are PHP codes to generate PRIVATE and PUBLIC KEYS:
===method A) ====
<?php
// generate 2048-bit RSA key
$pk_Generate = openssl_pkey_new(array(
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA
));
// getting private-key
openssl_pkey_export($pk_Generate, $pk_Generate_Private); // we pass 2nd argument as reference
// getting public-key
$pk_Generate_Details = openssl_pkey_get_details($pk_Generate);
$pk_Generate_Public = $pk_Generate_Details['key'];
// free resources
openssl_pkey_free($pk_Generate);
// getting/importing public-key using PEM format
// $pk_Generate_Private now gets into PEM format...
// this is an alternative method compared to above used "public retrieval"
$pk_Import = openssl_pkey_get_private($pk_Generate_Private); // importing
$pk_Import_Details = openssl_pkey_get_details($pk_Import); // same method to get public key, like in previous
$pk_Import_Public = $pk_Import_Details['key'];
openssl_pkey_free($pk_Import); // cleanup
// see output
echo "\r\n\r\n".$pk_Generate_Private."\r\n\r\n".$pk_Generate_Public."\r\n\r\n".$pk_Import_Public ."\r\n\r\n".'Public keys are '.(strcmp($pk_Generate_Public,$pk_Import_Public)?'different':'identical').'.';
?>
====method b) =======
include this [phpsec open-source library][1](with [examples][2]), and then execute:
<?php
include('File/X509.php');
include('Crypt/RSA.php');
// creating private key / x.509 cert for stunnel / website
$priv_Key = new Crypt_RSA();
extract($priv_Key->createKey());
$priv_Key->loadKey($privatekey);
$pub_Key = new Crypt_RSA();
$pub_Key->loadKey($publickey);
$pub_Key->setPublicKey();
$object = new File_X509();
$object->setDNProp('id-at-organizationName', 'phpseclib demo cert');
//$object->removeDNProp('id-at-organizationName');
$object->setPublicKey($pub_Key);
$cert_Issuer = new File_X509();
$cert_Issuer->setPrivateKey($priv_Key);
$cert_Issuer->setDN($object->getDN());
$x_509 = new File_X509();
//$x_509->setStartDate('-1 month'); // default: now
//$x_509->setEndDate('+1 year'); // default: +1 year from now
$result = $x_509->sign($cert_Issuer, $object);
echo "the stunnel.pem contents are as follows:\r\n\r\n".$priv_Key->getPrivateKey()."\r\n\r\n".$x_509->saveX509($result);
?>
What type of private/public are you need? Someone who said you to do this must provide algorythm or type of keys. There is a huge variety of private/public key types, not only RSA.