I need a little help.
I have a txt file with ecdsa public keys:
KEY_ID: 1
STATUS: VALID
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+Y5mYZL/EEY9zGji+hrgGkeoyccK
D0/oBoSDALHc9+LXHKsxXiEV7/h6d6+fKRDb6Wtx5cMzXT9HyY+TjPeuTg==
-----END PUBLIC KEY-----
KEY_ID: 2
STATUS: VALID
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaq6djyzkpHdX7kt8DsSt6IuSoXjp
WVlLfnZPoLaGKc/2BSfYQuFIO2hfgueQINJN3ZdujYXfUJ7Who+XkcJqHQ==
-----END PUBLIC KEY-----
KEY_ID: 3
STATUS: VALID
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkvgJ6sc2MM0AAFUJbVOD/i34YJJ8
ineqTN+DMjpI5q7fQNPEv9y2z/ecPl8qPus8flS4iLOOxdwGoF1mU9lwfA==
-----END PUBLIC KEY-----
Now I need use key by ID in openssl_verify function.
My code:
$ecdsa_url_string = 'ECDSA_URL_STRING';
$stringToVerify = 'MY_STRING';
$ecdsa_keys = openssl_pkey_get_public(file_get_contents(PATH . '/ecdsa_keys.txt'));
$verified = openssl_verify($stringToVerify,pack("H*",$ecdsa_url_string ),$ecdsa_keys,"sha256");
if($verified === 1){
.....
}
Now my question/problem:
I also have the KEY_ID parameter in the return URL. When ID is 1, everything is OK because openssl_pkey_get_public function always returns only the ID 1 key.
Q1: I can not retrieve the other keys.
Q2: How do I specify which ID I want use for openssl_pkey_get_public?
I am ashamed of my ignorance and my stupidity.
Can anyone please help me with this?
thx
#Lawrence Cherone answer work for me.
Parse public keys from .txt file by php
my code:
$ecdsa_keys = file_get_contents(PATH . '/ecdsa_keys.txt');
$ecdsa_key_id = 'KEY_FROM_URL';
function getKeyById($id, $ecdsa_keys){
if(preg_match("~KEY_ID: $id\s+STATUS: VALID\s+(-{5}BEGIN PUBLIC KEY-{5}.+?-{5}END PUBLIC KEY-{5})~s", $ecdsa_keys, $match)){
$result = $match[1];
return $result;
}
return null;
}
if(($ecdsa_key = getKeyById($ecdsa_key_id, $ecdsa_keys)) !== null){
echo "<pre>".$ecdsa_key."</pre>";
} else {
echo "not found";
}
thx for help
Related
Create public key OpenSSL in c
RSA *rsaKeyPair;
rsaKeyPair = RSA_new();
BIGNUM* exp = NULL;
exp = BN_new();
BN_set_word(exp, 65537);
RSA_generate_key_ex(rsaKeyPair, 2048, exp, NULL);
/* To get the C-string PEM form: */
PEM_write_bio_RSAPublicKey(bio, rsaKeyPair);
keylen = BIO_pending(bio);
pem_key = calloc(keylen+1, 1); /* Null-terminate */
BIO_read(bio, pem_key, keylen);
printf("%s", pem_key); // public key
Then copy-paste in php code.
$key2 = <<<EOT
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAn9VPzLkhDIzPZCA3rYEOttipOjokVQjN7XUjN++n+aYM8PNYp9QY
zlllawj16WE7KchiHjAng5Z+/wgNuz6uxRT4rYcQdjQ+l6JgayVv17vmc4gjuvqN
HeI1vJzs6Ob/kRLRf+QqX84zbSaIWjV1mtVBAyYfG0ln2JW3QvOueGLSV79s0lpE
08YRdXDZ7ohkEWa266RZ5w4970ALVHod8Mq8yPWvQFDpVT7UCMt1Apkz8VfF0zzz
1pxe2NWBJSnuhOkJ3Za+MG1SbiqmHpk6a+wvH9oJYyuR0PV6Tj0baVWenYDY+a6X
m4lmZM18IeLE7RZIqUlfY42hgkviJ45zpQIDAQAB
-----END RSA PUBLIC KEY-----
EOT;
openssl_public_encrypt($c,$d,$key2);
Error is
Warning: openssl_public_encrypt(): key parameter is not a valid public key
Have tried with base64encode in c and decode in php, send over url. Didn't help. Key in 2 ways looks the same.
Here is working locally created public key in php
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyIZzbuW0B7LNQR5JKqCD 6gRKp3DvRkZISaAQDQACSaOpIq7zRUVkgdrYXniECXBmzwGc3Fu5ECkvP0SWbaCI MBh0/YkPKbiQuAnhRwtcVQ8gFKaJ2vdUwp44PkP5pVvfraJPGmfWPAfiL9PyZmRN 1uZfgPznsNVrxqwZvYhApJy57vn4YL4J7kHpK3Peb/K4yTCMyAV/CE8YIe9q0p+L rzFQyIQm2dZ/OI7IU0izQwkbV0ZoMuUGJLhiPMrJ/dkOP3cDLdepJBewald2Hdnp 1aROlXhw0zp4Pj2ERgKkvJ+FnLJ0Se9XxGBBt4e+6gioQfdxvNwKk1oWmsIiyaRE UwIDAQAB -----END PUBLIC KEY-----
In the supplementary comments for PHP's OpenSSL functions there's this snippet
function pem2der($pem_data) {
$begin = "CERTIFICATE-----";
$end = "-----END";
$pem_data = substr($pem_data, strpos($pem_data, $begin)+strlen($begin));
$pem_data = substr($pem_data, 0, strpos($pem_data, $end));
$der = base64_decode($pem_data);
return $der;
}
function der2pem($der_data) {
$pem = chunk_split(base64_encode($der_data), 64, "\n");
$pem = "-----BEGIN CERTIFICATE-----\n".$pem."-----END CERTIFICATE-----\n";
return $pem;
}
These functions aren't inverses. My test code:
$priv_key = ...;
print $priv; // dev data, of course
print der2pem (pem2der ($priv));
Prints
-----BEGIN PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAAS... (etc)
then
-----BEGIN CERTIFICATE-----
TEKEYMIIJQwIBADANBgkqhkiG9w0BAQEFA... (etc)
Note the second one has a TEKEY prefix. In hex that's 4c4284 which doesn't look significant.
Where did this come from?
These functions are only designed to handle certificates, not private keys. The reason the result is wrong is because the pem2der function is looking for the start of a certificate (CERTIFICATE----- from -----BEGIN CERTIFICATE-----). You're trying to decode a key starting with -----BEGIN PRIVATE KEY-----. The "TE KEY" part of the result comes from here: "-----BEGIN PRIVATE KEY-----" and is a result of the functions not handling that header so the substr calls return the wrong result.
In theory, the functions should be very easy to modify to process private key files though.
I encrypt password with RSA method, I set the padding mode "OPENSSL_NO_PADDING", it returns false. But if I remove the padding mode parameter, keep it default, encrypt successfully.
$pass = 'gmwtwjfws';
$encrypetd_pass = '';
$pub_key = '-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs+JvfyTOMHqvjxHJyDZG
HZpz3atV7qcOT8mijXGGG3S+8Bb2p2kREGJwrzC2IIErCQUcZ3Wa3wTugKQDxqXE
SPt76HN2353ufegbvTI9kYgK0MLFpY8OZAMsaTytVrvUEVHjqGXZO4z7oVTqByuB
wcZAvK+sN39+MqisS6ZejACbbQLkWZgcSgt5wBAaDaEa2lvRYcVbNyO/mqTU6SSf
d+w78uM07BpmxhimOMwf+l/qs+Z04LUm4Ay7b+AHHAwbaHeehC1wInzNDfipgR0H
0FCa/LOnEblj2HVpptB/NY4XNG+CDHTBKkxzEw92D/Nj1JIlr1oP0l+/VdAnxxiW
uQIDAQAB
-----END PUBLIC KEY-----';
$result = openssl_public_encrypt($pass, $encrypetd_pass, $pub_key);
var_dump($result); //return false
exit;
What's more, I am confused about the public key's format. If I keep the default padding mode, and the format of public key is like above, it return true. But when I modify the key format as follow(remove one new line), it return false. Would anyone explain the reason? Thanks very mush.
$pub_key = '-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs+JvfyTOMHqvjxHJyDZGHZpz3atV7qcOT8mijXGGG3S+8Bb2p2kREGJwrzC2IIErCQUcZ3Wa3wTugKQDxqXE
SPt76HN2353ufegbvTI9kYgK0MLFpY8OZAMsaTytVrvUEVHjqGXZO4z7oVTqByuB
wcZAvK+sN39+MqisS6ZejACbbQLkWZgcSgt5wBAaDaEa2lvRYcVbNyO/mqTU6SSf
d+w78uM07BpmxhimOMwf+l/qs+Z04LUm4Ay7b+AHHAwbaHeehC1wInzNDfipgR0H
0FCa/LOnEblj2HVpptB/NY4XNG+CDHTBKkxzEw92D/Nj1JIlr1oP0l+/VdAnxxiW
uQIDAQAB
-----END PUBLIC KEY-----';
I hit the same problem and found a bug report at https://bugs.php.net/bug.php?id=61203
The answer to the bug report was that when using OPENSSL_NO_PADDING you have to provide data of the correct size, i.e. by appending \0's.
Now all I need to do is figure out the correct size :)
I have saved Private Key in DB in this format e.g.
-----BEGIN PRIVATE KEY-----
MIICdgIBADA................CHGIdCtZEmTD7sbLUcFCYDbohnqaWf2d+2I
EyC/Hg/tS4d+BQ==
-----END PRIVATE KEY-----
I need extract Public Key from it. openssl_pkey_get_details need resource, but how can I create resource from string?
I tried this
$public_key = openssl_pkey_get_details(openssl_pkey_get_public($private));
Error is openssl_pkey_get_details() expects parameter 1 to be resource, boolean given
EDIT 1:
I'm trying solution from #kbarborak bellow, but $pk_get is false:
$pk_string = "-----BEGIN PRIVATE KEY-----\n".chunk_split($data[4], 64, "\n")."-----END PRIVATE KEY-----\n";
$pk_get = openssl_pkey_get_private($pk_string);
die(var_dump($pk_string));
Output of var_dump is:
string(944) "-----BEGIN PRIVATE KEY-----
MIICjAIBAAINBgkqhkiG9w0BAQEFAAIJKoZIhvcNAQEBAgACggJhMIICXQIBAAKB
gQCvUSrEHS1T5g5z/Yv5ETeXA6CLsdo15Dqk0LevSAXGgbFarSRLfTYtN1/zwqgs
+YWnU/0lZKmzJpmDFRmH/wDeu8o7ptEOrNLgbs6TM85cS4ZmRhJnrOG3G6oBMq5m
UCPw+r06HIuxwyS54/2vY/GGjXpxV59yNUhKh9H9V216YwIDAQABAoGARZAbO/2n
wqaCDZwJMiaWvCEATu2e+8s3SbZXbAFT6VQEn0ocIKfqGz7hn8MZH99SHPbCd1fd
zev+9XglzURtf0sHneq8zT8qT4KYYriRj6dwlyJ6xpf1lLrBqi+eifvZR3+i60Ql
YuBNEXhq/OuSAwV+qTCLYrchUE0jTtX3HWECQQDerLyy1hs2SxlXgLbf80BdIuxB
gqj7QGirYBY/tnPvyLBJWF8RLGjEdPUEaN2hUgkhq2+IQ6lRADKJBQX+1u33AkEA
yY4Hz0rFgjDXx1PLOlX3z6vAFNhtWagcsz+DNp0fwaD1jLVvWnAcAgjJWQ9GBRrC
OGctw6hN92tX19vuKIbr9QJBAIFR1oESIVmlwcD0ysBDOFUezBC7vkG0xVUKB8HW
x3wxlFf0T7ncjbfSqN13vYdL6mu4cZy0lueo8rBqz3GSBz8CQQCTibEzzzL20xQQ
p8jbAfTtgnaPi8G34HRpzbMZ9jg5v74e6u0BEZGe95mT5LdHo0fKi9SXJYs08tGR
hD84UVNFAkAgR+Z0ox6HbNMj5bBIvqEC25mAMnayFyezPZ+/B/IyHDYmQSO9FGsG
/YVA8prMnAZ/YEiCC/2kYA2Ds7GjdJipAgACAAIAAgA=
-----END PRIVATE KEY-----
"
Extracting public key
// Private key as string
$pem_private_key = file_get_contents('mykey.pem');
$private_key = openssl_pkey_get_private($pem_private_key);
// Public key as PEM string
$pem_public_key = openssl_pkey_get_details($private_key)['key'];
// As PHP resource
$public_key = openssl_pkey_get_public($pem_public_key);
echo $pem_public_key;
echo $public_key;
Preparing private key string
$pk_string = "-----BEGIN RSA PRIVATE KEY-----\n".chunk_split($data[4], 64, "\n")."-----END RSA PRIVATE KEY-----\n";
$pk_get = openssl_pkey_get_private($pk_string);
die(var_dump($pk_string));
Use BEGIN RSA PRIVATE KEY instead just BEGIN PRIVATE KEY (same for END).
Hope that's help.
openssl_pkey_get_public() returns false if there's an error. So this is was most likely happens and is passing false to openssl_pkey_get_details(). Debug you $private variable.
How can I export only the public key to a file(.pem) with PHP?
Of course it is possible to export the whole certificate and a private key but I can't find a solution to export a public key.
The file should look like
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArDjwWcPjZRQpiMRsG1fG
kudSYEHnSR57dKUoK+qIc++YZSCWG/q460LrNtQ/EBx6ZdJJnhBk4EwY0snb7TEr
pH5efU2BuCygO3f78DozMxNvvHFFfZ1uw4hobBMSKLKtVcJKmh7r7dvgXtKWdqJf
sUmr2V3LDXTF3r6G5NEorGC4crcSByAvyPatUKRR5t6kAuU8pnWrHnDo+GoSjHy2
vvaUuds6FxHMieFXKrnN8dk6VPpV2PEwzSAk9Ofbq3oZxkIhVGTHjgFPF9tIx3Vu
yo+S4KCP6sxmEt1/p4B5VsCsRU4STbA5jC8qK9vJ1YhMD6tK5FWreaDiWL3wBjf5
xwIDAQAB
-----END PUBLIC KEY-----
That's the solution. Thanks to https://www.virendrachandak.com/techtalk/encryption-using-php-openssl/
// Generate the public key for the private key
$key = openssl_pkey_get_details($privateKey); // $privateKey is created with openssl_pkey_new()
// Save the public key in public.pem file
file_put_contents('public.pem', $key['key']);