Openssl: bad magic number issue - php

I encrypted a file using file_input_contents function:
file_input_contents('myfile',openssl_encrypt("This string was AES-128 / ECB encrypted.", "AES-128-ECB", "password"));
But I can't decrypt it using openssl command. Always getting "bad magic number" error.
I tried with this command:
openssl enc -aes-128-ecb -d -in myfile -out outputfile

Related

.P12 Certificate in PHP cURL to an endpoint [duplicate]

i have to connect to a webservice, where a pkcs12 certificate is a must. the idea was to use curl in a bash script (under OS X, to be specific).
i have learnt that one of the few things curl cannot do in communication, is handling pkcs12 certificates (.p12). what are my options?
i have read that converting the certificate to PEM format would work (using openssl), however i have no idea how to tell curl that it gets a PEM and should communicate with a webservice requesting PKCS12 certificates.
converting pkcs12 to pem would be done like this (e.g.), it worked for me, however i haven't successfully used them with curl:
openssl pkcs12 -in mycert.p12 -out file.key.pem -nocerts -nodes
openssl pkcs12 -in mycert.p12 -out file.crt.pem -clcerts -nokeys
any hints? or, any alternatives to curl? the solution should be commandline based.
I think you have already resolved but I had the same problem. I answer to share my solution.
If you have a .p12 file your approach is right.
First of all, you have to get the cert and the key separated from the p12 file.
As an example, if you have a mycert.p12 file execute
openssl pkcs12 -in mycert.p12 -out file.key.pem -nocerts -nodes
openssl pkcs12 -in mycert.p12 -out file.crt.pem -clcerts -nokeys
Then you have to make the call to your url. For instance, assume that you want to get the WSDL of a specific web service
curl -E ./file.crt.pem --key ./file.key.pem https://myservice.com/service?wsdl
If the files file.crt.pem and file.key.pem are in your working folder "./" is mandatory.
Check if you have a newer curl. Newer versions can handle PKCS12 outright.
Tangentially, quote the password, or individually escape all shell metacharacters.
curl --cert-type P12 --cert cert.p12:'password' https://yoursite.com
bioffes answer is correct.
He was suggesting to do:
curl --cert-type P12 --cert cert.p12:password https://yoursite.com
For some reason that didn't work for me. I was getting:
curl could not open PKCS12 file
I just ended up exporting the p12 file without a password and ended up just using the following format.
curl --cert-type P12 --cert cert.p12 https://yoursite.com
You can easily check to see if your curl can handle p12. Very likely it does. Just do man curl and scroll down til you find the cert-type. Mine was like this:
--cert-type <type>
(TLS) Tells curl what type the provided client certificate is using. PEM, DER, ENG and P12 are recognized types. If not specified, PEM is assumed.
If this option is used several times, the last one will be used.
(I don't believe cmmd + F works to text not visible in the terminal. So you have to scroll down.

Decrypt using RSA OAEP with SHA256 on PHP

how to decrypt using RSA OAEP with SHA256 on PHP.?
maybe using some package or manual? I dont know how to use it with PHP.
example logic :
openssl base64 -A -d -in $encrypt > $temp.bin
openssl pkeyutl -decrypt -inkey $private -in $temp.bin -out $temp.txt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256

Encrypt file using certificate resulting in 'Expecting PUBLIC KEY' [duplicate]

I am using the below openssl command for storing my public key into a .pem file.
openssl> x509 -in E:/mycert.pem -pubkey -out E:/mypubkey.pem
But when i try to use this command, it is storing the whole certificate info in the mypubkey.pem file.
I have seen that i can save my public key using
openssl> x509 -pubkey -noout -in cert.pem > pubkey.pem
But it is throwing an error. I can't use ">" operator.
There are a couple ways to do this.
First, instead of going into openssl command prompt mode, just enter everything on one command line from the Windows prompt:
E:\> openssl x509 -pubkey -noout -in cert.pem > pubkey.pem
If for some reason, you have to use the openssl command prompt, just enter everything up to the ">". Then OpenSSL will print out the public key info to the screen. You can then copy this and paste it into a file called pubkey.pem.
openssl> x509 -pubkey -noout -in cert.pem
Output will look something like this:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAryQICCl6NZ5gDKrnSztO
3Hy8PEUcuyvg/ikC+VcIo2SFFSf18a3IMYldIugqqqZCs4/4uVW3sbdLs/6PfgdX
7O9D22ZiFWHPYA2k2N744MNiCD1UE+tJyllUhSblK48bn+v1oZHCM0nYQ2NqUkvS
j+hwUU3RiWl7x3D2s9wSdNt7XUtW05a/FXehsPSiJfKvHJJnGOX0BgTvkLnkAOTd
OrUZ/wK69Dzu4IvrN4vs9Nes8vbwPa/ddZEzGR0cQMt0JBkhk9kU/qwqUseP1QRJ
5I1jR4g8aYPL/ke9K35PxZWuDp3U0UPAZ3PjFAh+5T+fc7gzCs9dPzSHloruU+gl
FQIDAQAB
-----END PUBLIC KEY-----
if it is a RSA key
openssl rsa -pubout -in my_rsa_key.pem
if you need it in a format for openssh , please see Use RSA private key to generate public key?
Note that public key is generated from the private key and ssh uses the identity file (private key file) to generate and send public key to server and un-encrypt the encrypted token from the server via the private key in identity file.
I am not sure why the other answers have such high upvotes. They do not solve the two problems presented in the question. A key point to the problem is the openssl command interpreter is being used and not the shell prompt.
Problem #1 - the certificate is written with the public key.
I am using the below openssl command for storing my public key into a
.pem file.
openssl> x509 -in E:/mycert.pem -pubkey -out E:/mypubkey.pem But when
i try to use this command, it is storing the whole certificate info in
the mypubkey.pem file.
The solution is to add the command argument -noout.
Problem #2 - ">" operator is not supported:
openssl> x509 -pubkey -noout -in cert.pem > pubkey.pem
But it is throwing an error. I can't use ">" operator.
The solution is to add the -out <filename> command parameter.
Solution:
openssl> x509 -pubkey -in cert.pem -noout -out pubkey.pem

Use openssl_decrypt() with passphase (not key/iv)

I'm trying to decrypt some data that has been encrypted with a passphrase and aes-256-cbc method in a PHP script.
Here is how I encrypt the original data
printf "Hello" | openssl enc -e -base64 -A -aes-256-cbc -k "MYPASSWORD"
// output
U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=
When I try to decrypt it in command-line it works fine
printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -k "MYPASSWORD"
// output
Hello
BUT when I use openssl_decrypt() in my PHP script it doesn't work!!
$result = openssl_decrypt("U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=", 'AES-256-CBC', "MYPASSWORD");
var_dump($result);
//output
bool(false)
I append the following lines to get the error
while ($msg = openssl_error_string())
echo $msg . "<br />\n";
And it returns:
error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad
decrypt
I know that I should use a key/iv pair but I am not able to extract it from my passphrase with any salt. How can I get it to make the following command work?
printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -K ??????????????? -iv ????????????????
// expected output !!!
Hello
EDIT:
I tried to get key/iv with -p argument but it doesn't work
printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -k "MYPASSWORD" -p
salt=9D5AE06E8A2B627C
key=8ACC4E30E9128FBB0763DDDA8998A7141DFDC77B9DADF0A5FC65E67E2A8313FA
iv =4150125DCCD36F73A9F08F3020151A04
Hello
printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -K 8ACC4E30E9128FBB0763DDDA8998A7141DFDC77B9DADF05E67E2A8313FA -iv 4150125DCCD36F73A9F08F3020151A04
bad decrypt
140735954895816:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:529:
??G?"r!C???&C&??
There is a difference between the password (or passphrase) used as a parameter to openssl enc via the -k option (in your case "MYPASSWORD") and the key parameter that the PHP function openssl_decrypt() expects. The -k option to openssl enc is a passphrase of any length from which an actual 256 bits encryption key will be derived. That is also the key that the PHP openssl_decrypt() function needs. This encryption key is 256 bits because you have chosen aes-256.
You can get to know what that derived encryption key is by adding the -p option when invoking openssl enc. This also prints the iv, another parameter that you will need to use with the PHP openssl_decrypt() function. For example:
printf "Hello" | openssl enc -e -base64 -A -aes-256-cbc -k "MYPASSWORD" -nosalt -p
key=E0FAC2DD2C00FFE30F27A6D14568CB4F12EB84676A3A2BFB172A444C3BBB831F
iv =5A79774BB4B326EED949E6871FC27697
sp0z18QezUO8tSy7tgjOEw==
These printed key and iv values are the ones that you will need to feed into your PHP openssl_decrypt() function invocation, like this:
$ciphertext = 'sp0z18QezUO8tSy7tgjOEw==';
$key = hex2bin('E0FAC2DD2C00FFE30F27A6D14568CB4F12EB84676A3A2BFB172A444C3BBB831F');
$iv = hex2bin('5A79774BB4B326EED949E6871FC27697');
$result = openssl_decrypt($ciphertext, 'AES-256-CBC', $key, 0, $iv);
var_dump($result);
Running the PHP script now results in success:
$ php decrypt.php
string(5) "Hello"
You may have noticed the extra -nosalt option when running openssl enc. Salt is used to add some randomness/uniqueness to the key derivation process and -nosalt omits that step. As a result, the key, iv and ciphertext will be the same in every run (if the same passphrase and plaintext are used) and you should be able to exactly reproduce the output. If you do not use -nosalt, your experiment will still work but the key, iv and ciphertext values will be different for each run and you will also have to get rid of the salt that openssl adds as a header -- see further down this answer for the details.
Another option would be to let the PHP code derive the key and iv from the passphrase before invoking openssl_decrypt(). To do that, you will have to inspect the code of the enc tool for the openssl version that you are using. There you can see which key derivation function is used -- it depends on the version of openssl you are using as well as the options you are giving it -- and whether that is available in the PHP bindings of openssl.
Update, responding to your comment where you add the information that you only have the ciphertext and the passphrase available and that ciphertext was created with crypto-js.
Looking at the source code of crypto-js, it mentions in a comment in the source file evpkdf.js that "the key derivation function is meant to conform with EVP_BytesToKey", which is the same function that most openssl versions use. So you should be able to use the openssl enc tool to extract the key and the iv by using the -p option, like this:
$printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -k "MYPASSWORD" -p
salt=9D5AE06E8A2B627C
key=8ACC4E30E9128FBB0763DDDA8998A7141DFDC77B9DADF0A5FC65E67E2A8313FA
iv =4150125DCCD36F73A9F08F3020151A04
(which you have confirmed in another comment by now as well) and then use those when invoking the PHP function, as described above. Note that you will have to do this for every ciphertext separately, because the salt (and thus the key and iv) were chosen differently, randomly by crypto-js for each encryption action. To do this in PHP directly, see my previous remark: the required functionality does not seem to be available in its decrypt module.
You can verify that this works by feeding the key and iv into openssl enc when decrypting. However, there is a snag. When using a salt, the openssl way is to include that salt in the output, as you can see here:
$ printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl base64 -d -A | hexdump -C
00000000 53 61 6c 74 65 64 5f 5f 9d 5a e0 6e 8a 2b 62 7c |Salted__.Z.n.+b||
00000010 7e 33 bb 56 2f fe 5e fe 1d c7 c8 a9 1f f0 c5 27 |~3.V/.^........'|
00000020
The first 16 bytes of the output are the "magic" bytes Salted__ with the salt after that. This salt is normally read by the tool if you use a passphrase, but it is in the way if you decrypt with key and iv directly. So you will have to remove that header before feeding the bytes into openssl enc as ciphertext when decrypting, for example using tail like this:
printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl base64 -d -A | tail -c +17 | openssl enc -d -aes-256-cbc -K 8ACC4E30E9128FBB0763DDDA8998A7141DFDC77B9DADF0A5FC65E67E2A8313FA -iv 4150125DCCD36F73A9F08F3020151A04
Hello
This one-liner first does the base64 decoding, then removes the 16 first bytes and then feeds the result into openssl enc, no longer needing the -base64 options because that has already been taken care of.
In PHP:
$ciphertext = 'U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=';
$ciphertext_decoded = base64_decode($ciphertext);
$ciphertext_nosalt = base64_encode(substr($ciphertext_decoded, 16));
$key = hex2bin('8ACC4E30E9128FBB0763DDDA8998A7141DFDC77B9DADF0A5FC65E67E2A8313FA');
$iv = hex2bin('4150125DCCD36F73A9F08F3020151A04');
$result = openssl_decrypt($ciphertext_nosalt, 'AES-256-CBC', $key, 0, $iv);
var_dump($result);
All that said, you would probably be better off moving away from the key derivation that openssl enc and crypto-js use and that relies on the proprietary mechanism implemented by the OpenSSL EVP_ByesToKey function. Even openssl enc now warns about this being deprecated .
Instead, start using a standard algorithm like PBKDF2. This is supported by more recent versions of openssl enc and I have spotted it in the source code of the crypto-js and PHP crypto modules as well (but have never used those myself). If you have a database of encrypted data that you need to keep, you can re-encrypt its contents one time, using the old approach to decrypt and the PKDBF2 approach to encrypt. Make sure to store the salts separately and not as one blob together with the ciphertext.
The issue here is that you are not using EVP_BytesToKey. This is the OpenSSL KDF used to derive a key and IV from your password.
Note that it is insecure. You should prefer passing a hex key and IV directly to openssl enc.

PHP escapeshellarg messing up my password

$passphrase = "';__!!??()[]";
$passphrase = escapeshellarg($passphrase);
shell_exec("openssl\openssl.exe genrsa -des3 -passout pass:${passphrase} -out test.key 2048");
#Here the password works
echo system("openssl\openssl.exe rsa -in test.key -passin pass:${passphrase} -noout -text");
This code works fine to generate a key with openssl. I can also read the key without any problem. But when I want to read the key from the command line I'm unable to decrypt it. I use exactly the same command as in the code. The only difference is, that I copy the passphrase to the command line as it is written in the code. This always fails with a bad decrypt error.
How can I fix this issue?
Edit: To make this more clear. This does not work when run from terminal:
openssl\openssl.exe rsa -in test.key -passin pass:"';__!!??()[]" -noout -text
Why don't you use PHP's OpenSSL library instead of the shell?
http://php.net/manual/en/ref.openssl.php

Categories