GNUPG decryption failed in php - php

I am using GnuPG library to encrypt decrypt messages. I have successfully confirgured the GPG extension on my server and generated a key pair. Also I am successfull in importing another public key and enrypting data using that public key.
I also encrypted data using my public key and decrypted it using my private key.
But when somebody else encrypts data using my public key I am unable to decrypt it. the error is
Warning: gnupg_decrypt(): decrypt failed in pgpdecrypt.php on line 22
my code is
$Message = $_REQUEST["Message"];
// Specify custom location of GnuPG binary.
$res = gnupg_init();
gnupg_seterrormode($res, GNUPG_ERROR_WARNING);
$rtv = gnupg_adddecryptkey($res, "rizwan#google.com", "0000");
echo gnupg_geterror($res) . "<br>"; // Print if any errors
$enc = gnupg_decrypt($res, $Message); // ERROR IS AT THIS LINE
echo gnupg_geterror($res) . "<br>"; // Print if any errors
echo $enc;
this same code is decrypting data encrypted by me at my machine.
I am unable to extract error details.

Cipher Algorithm 6 reffers to DES. DES is not supported in GnuPG, it uses 3DES/Triple-DES instead. I encrypted the data using 3DES and it successfuly decrypted at my site.
Hope this helps to other people encountering same problem. :)

Related

PHP GnuPG - Signing message fails

Update
Apparently, even though I thought I was generating keys that did not have a password, gnupg still expected a password for them (which the gnupg extension no longer supports). I regenerated a new keypair using Kleopatra on Windows and bypassed all the "no passphrase" warnings and I was able to successfully sign/encrypt with those keys.
So, the bottom line is be very sure that your key does not have a passphrase.
I am attempting to sign a message using PHP's gnupg extension. I have the environment setup correctly, and I can successfully import the key, and adding it using gnupg_addsignkey is successful (returns true).
When I attempt to sign the message using gnupg_sign($res, "my message"), I get the following error and gnupg_sign returns false:
gnupg_sign(): data signing failed
I can't seem to find any way to get more verbose information to figure out why it's failing.
I've tried the procedural methods, as well as the OO methods, and get the same result. The permission are all correct on the server.
Here's the OO code I've used:
# /tmp/.gnupg is there (but empty if that helps figure out the problem)
putenv("GNUPGHOME=/tmp/.gnupg");
$gpg = new gnupg();
$gpg->seterrormode(GNUPG_ERROR_WARNING);
$ascii = file_get_contents('/etc/my.key'); // Yes, this reads successfully
$start = strpos($ascii, '-----BEGIN PGP PRIVATE KEY BLOCK-----');
$end = strpos($ascii, '-----END PGP PRIVATE KEY BLOCK-----')+34;
$key = substr($ascii, $start, ($end-$start));
$info = $gpg->import($key); // Fingerprint is there and everything seems OK
$gpg->addsignkey($info['fingerprint']);
$signed = $gpg->sign("test!"); // fails with any string I try
$signed is false, and I get the PHP warning gnupg::sign(): data signing failed
Is your private key password protected?
According to pecl/gnupg documentation you cannot pass a plaintext password for gnupg ≥ version 2.
So all you can do is use a private key that has no password set, I guess.
IMO pecl/gnupg errors are quite misleading.

CI REST Server API keys

I am a newbie to API development, but have successfully managed to implement CI REST Server by Phil Sturgeon and Chris Kacerguis by reading all articles I could find, but there is one answer that eludes me, from the following question: CodeIgniter REST API Library Ajax PUT throwing 403 Forbidden and How can I generate an API Key in My own Controller in Codeigniter.
I have added the "boguskey" to the database as suggested in the first question's accepted answer, but I am confused about security here. If I need to have a hard-coded API key to generate new keys, and someone can view the header to see this bogus API key, how do I secure my API then from someone who then use this API key to generate tons of API keys for us within my API? If I do not add the boguskey, then I get "Invalid API key" regardless of which function I call.
My apologies if this is a stupid question, but if someone has an example of how I can generate keys securely (or at least inform me if I am misinterpreting the situation) I will greatly appreciate it.
To ensure the max security you should encrypt all the sent data, then if the API could decrypt it correctly you should be fine, you can use RSA encryption, so if any one intercept the request he cant decrypt or clone it, But RSA is not designed to be used on long blocks of plain text, so you can use hybrid encryption. Namely, this involves using RSA to asymmetrically encrypt a symmetric key.
Randomly generate a symmetric encryption (say AES) key and encrypt the plain text message with it. Then, encrypt the symmetric key with RSA. Transmit both the symmetrically encrypted text as well as the asymmetrically encrypted symmetric key.
The API can then decrypt the RSA block, which will yield the symmetric key, allowing the symmetrically encrypted text to be decrypted.
To implement RSA on CodeIgniter you can use this class, call the file on your controller require_once("RSA.php");.
On the API consumer controller make an array which will contain the data and the the asymmetrically encrypted symmetric key
$request_data = array();
$request_data["username"] = "taghouti";
$request_data["project"] = "Secured_API";
$serialized_request_data = serialize($request_data);
$enc = new RSAEnc($serialized_request_data,'public_key');
$encrypted = $enc->result();
$request_data = array(
"data" => base64_encode($encrypted->result),
"key" => base64_encode($encrypted->key)
);
And on the API controller you should try to decrypt the symmetric key using your private key, if the decryption done successfully you should be fine
if ($_POST["key"]) {
$key = base64_decode($_POST["key"]);
$_POST["key"] = null;
if (isset($_POST["data"])) {
$data = base64_decode($_POST["data"]);
$dec = new RSADec($data, 'private_key', $key);
$decrypted = $dec->result();
if($decrypted->success !== true) die("Decryption failed");
$decrypted = #unserialize($decrypted->result);
$_POST = is_array($decrypted) ? $decrypted : array();
$this->_post_args = $_POST;
}
}
if($this->input->post('project') && $this->input->post('username')) {
//Enjoy
} else {
die('data parsing error');
}

Decrypt data Xcode to PHP

I'm making an application with Xcode which encrypts information using the private key of a certificate, this information is sent to a server using a POST in PHP (Eg: username = "encrypted data") and I want to decrypt this information in the PHP with the private key and get the real information, I encrypted the information with SecKeyEncrypt in Xcode and then sent to PHP, but how I can decrypt it with the private key in php?
The function you are looking for is mcrypt_decrypt that comes with the mcrypt extension.

PHP ssh2_auth_pubkey_file(): Authentication failed using public key: Invalid key data, not base64 encoded

In PHP5.3.3 (on CentOS and apache2) I am attempting to connect to a SFTP via a php script. The code grabs the keys and server details from the constructor
function __construct(){
$this->host = 'servername.loc';
$this->port = SFTP_PORT;
$this->auth_user = 'username';
$this->auth_pub = '/data/home/username/.ssh/id_rsa.pub';
$this->auth_priv = '/data/home/username/.ssh/id_rsa';
$this->auth_pass = null;
$this->connection = null;
}
and uses those details to create the connection.
private function connect(){
if (!($this->connection = ssh2_connect($this->host, $this->port))) {
$this->response = array('code' => "20",
"message" => "Error connecting to SFTP server.");
return false;
}
if (!ssh2_auth_pubkey_file($this->connection, $this->auth_user, $this->auth_pub,
$this->auth_priv, $this->auth_pass)) {
$this->response = array('code' => "40",
"message" => "Error authenticating to SFTP server with key.");
$this->disconnect();
return false;
}
}
The result I get is an error on the call to ssh2_auth_pubkey_file().
The error is:
"ssh2_auth_pubkey_file(): Authentication failed for USERNAME using public key: Invalid key data, not base64 encoded"
There is no password on the key, and I can use these keys via CLI ssh to connect to the server manually.
I am stumped. Do I need to encode the keys somehow? Suggestions?
The prerequisite that you mention, namely the pubkey file not to have any comments and not even have a trailing newline is incorrect (and the newline thingy absurd when you think it through).
If your scriptfails, you have prob. sooner stumbled into the ssh2 bug that makes ssh2 fail when it is compiled wuth libgcrypt instead of openssl. The workaround is to create a PEM formatted copy of your private key file in PEM format with openssl:
~/.ssh> openssl rsa -in id_rsa -out id_rsa.pem
Then, in ssh2_auth_pubkey_file() in your PHP script, use id_rsa.pem as privkey file instead of id_rsa, and omit the passphrase.
That should make it work.
Well, it figures, I find the answer after asking the question openly. Found this on another site with dev comments.
d23d23 at gmail dot com said:
"The public key must be on one line starting with the key type, 1 space and followed by the keydata (no newlines) and not followed by comments. This is a limitation of libssh2, so remove any excess data from the file after creating it with your key generation tools."
So even though I used openssl to create the private key and public key, I had to edit it to put it all on one line with the key type as noted above. Thanks.

Android in-app purchase server signature verification using php OpenSSL

In an attempt to follow some of the security guidelines for in-app purchase here:
http://developer.android.com/guide/market/billing/billing_best_practices.html
I am trying to do signature validation on a server instead of in the app iteself. I would ideally like to use the php openssl libraries and it looks like code such as the following should work:
<?php
// $data and $signature are assumed to contain the data and the signature
// fetch public key from certificate and ready it
$fp = fopen("/src/openssl-0.9.6/demos/sign/cert.pem", "r");
$cert = fread($fp, 8192);
fclose($fp);
$pubkeyid = openssl_get_publickey($cert);
// state whether signature is okay or not
$ok = openssl_verify($data, $signature, $pubkeyid);
if ($ok == 1) {
echo "good";
} elseif ($ok == 0) {
echo "bad";
} else {
echo "ugly, error checking signature";
}
// free the key from memory
openssl_free_key($pubkeyid);
?>
I replace signature with the base64 decoded signature string in the app purchase bundle and the use the data from the same bundle. The public key needs to be in PEM format and I added the BEGIN and END tokens and some line breaks.
My problem is that I can not get this PHP code to successfully verify the data/signature and I do not know what needs to change to get it to work correctly.
If I use openssl, create a private and public key, create a signature for the same data using sha1 and run it through the above php code, it works fine and validate successfully.
Here is how I use OpenSSL:
openssl genrsa -out private.pem
openssl rsa -in private.pem -pubout -out public.pem
then I use the private.pem and some php code to generate a signature:
...
openssl_sign($data, $signature, $pkeyid);
...
Does anyone have any working sample php code with server side validation of in-app signatures?
I could just run the equivalent java code that is in the sample application, and that seems to work ok, but I would like to use php directly if possible.
I've written a library for verifying Android Market licensing responses and it's available on Google Code.
It just takes a few lines of PHP to verify a license, and the formatting of keys and OpenSSL stuff is taken care of for you.
Is it possible to use cURL in your PHP script, rather than the stuff built into PHP streams. I've used them before, and have found the problems more rare, and the error messages more verbose.

Categories