im working with a web application for some client who needs sign some documents other company give him 2 files
- file1.key
- file2.cer
if im understand thus files are encrypted with a password so the user needs his password
the company give me some example in php and say i need get the private key with thus commands
-convert *.key a *.pem:
openssl pkcs8 -inform DER -in llave.key -out llave.key.pem -passin pass:contrasenia
-Conver *.cer to *.pem:
openssl pkcs8 -inform DER -in llave.key -out llave.key.pem -passin pass:contrasenia
but for the end user i can't request him "run this command" the end user need to indicate his password
the company give me some code in php
$private_file="c:/firma/llave_carlos.key.pem";
$public_file="c:/firma/cert_carlos.cer.pem";
$private_key = openssl_get_privatekey(file_get_contents($private_file));
exito = openssl_sign($cadena_original,$Firma,$private_key, OPENSSL_ALGO_SHA256);
openssl_free_key($private_key);
$public_key = openssl_pkey_get_public(file_get_contents($public_file));
$PubData = openssl_pkey_get_details($public_key);
$result = openssl_verify($cadena_original, $Firma, $public_key, "sha256WithRSAEncryption");
but im working with Nodejs searching in google i found the npm package
node-openssl-cert
but until now i can't found a similar method to php "openssl_get_privatekey"
im thinks the solution is with the crypto module from node
const crypto = require('crypto');
const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', {
namedCurve: 'sect239k1'
});
const sign = crypto.createSign('SHA256');
sign.write('some data to sign');
sign.end();
const signature = sign.sign(privateKey, 'hex');
const verify = crypto.createVerify('SHA256');
verify.write('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature));
but my problem its this line
const { privateKey, publicKey } = crypto.generateKeyPairSync('ec', {
namedCurve: 'sect239k1'
});
the "privatekey" and "publickey" should come from the files
thanks for the support and sorry for my english idont speak
Let me guess: you're building a CFDI 3.3 and trying to sign the original string to get the digital sign. I ran into the same problem, searched a lot, downloaded lots of Node libraries, and your progress really helped me, so I could integrate a solution using only crypto library, here it is:
Firstful, be sure that the original string is ok (that was my first issue, the original string was wrong), you can use this tool: https://solucionfactible.com/sfic/capitulos/timbrado/cadena_original.jsp#herramientaCO
Once you checked the original string you need to sign the original string with SHA256, here you can find a function I coded for that:
const privateKey = "./EKU9003173C9.key.pem" //Note that I converted the .key to .key.pem
const firmarCadena = cadena => {
let prvKey = fs.readFileSync( privateKey )
var signerObject = crypto.createSign("SHA256")
signerObject.update( cadena )
let signature = signerObject.sign( prvKey, "base64" )
return signature
}
You can also check this tool, so you can compare between the values you are getting and the ones which must be. It generates the original string and digital sign with a .xml, .key and private key password: https://solucionfactible.com/sfic/capitulos/timbrado/sello.jsp#herramientaSello
Finally, you can verify your digital sign here in section "Verificador de sello digital (verificador de firma)": https://solucionfactible.com/sfic/capitulos/timbrado/sello.jsp#herramientaSello
I need to say that I'm using Node 10.x. It already has a Crypto built-in library.
Related
I would like to achieve something I thought was pretty straighforward:
A) My VB.NET client (ideally targetting Framework 4.0) sends a text string to my Apache/PHP Server via an HTTPS POST request.
B) My Server responds with a Signature of that text string.
Private key used by the Server is always the same, and public key used by Client is already embeded within the source code.
After investigating and reading through a lot of documentation, I came up with the following strategy and have two questions:
Is my strategy efficient?
The code provided below does not work (.VerifyData returns FALSE). What am I missing?
Strategy
Server Side
Apache/PHP: Because that is the only server language I am familiar
with, but I could switch if recommended.
OpenSSL: Because I use PHP
PEM files: Because I use OpenSSL
RSA key size is 2048 bits: Recommended minimum in 2019
Algorythm is SHA256: Because everyone seems to use that one
Header text/plain, UTF8: Why not?
Client Side
VB.Net Framework 4.0 Client Profile: Because I want to maximise legacy (VSTO 2013)
System.Security.Cryptography.RSACryptoServiceProvider
PEM public key info loaded via XML string
HTTPS should be TLS1.0 or higher: Because I target .Net Framework 4.0 (TLS1.1 is recommended if possible)
Source Code
Server Side (generate .pem key files, only once)
<?
// Create new Keys Pair
$new_key_pair = openssl_pkey_new(array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
));
//Save Private Key
openssl_pkey_export($new_key_pair, $private_key_pem, "my passphrase to protect my private key; add random characters like $, ?, #, & or ! for improved security");
file_put_contents('private_key.pem', $private_key_pem);
//Save Public Key
$details = openssl_pkey_get_details($new_key_pair);
$public_key_pem = $details['key'];
file_put_contents('public_key.pem', $public_key_pem);
?>
Server Side (target of POST requests)
<?
header('Content-Type: text/plain; charset=utf-8');
// Verify connection is secure
if(empty($_SERVER['HTTPS']) || $_SERVER['HTTPS']=="off")
{
echo "Unauthorized Access";
exit;
}
// Data to Sign
$data = base64_decode(file_get_contents('php://input'));
//Load Private Key
$private_key_pem = openssl_pkey_get_private('file:///path/protected/by/dotHtaccess/private_key.pem', "my passphrase to protect my private key; add random characters like $, ?, #, & or ! for improved security");
//Create Signature
openssl_sign($data, $signature, $private_key_pem, OPENSSL_ALGO_SHA256);
echo base64_encode($signature);
?>
Client Side
imports System.Diagnostics
Sub mySignatureTest()
Dim oURI As Uri = New Uri("https://www.example.com/targetpage.php")
Dim sData As String = "myStringToSign"
Dim sResponse As String
'# Get POST request Response
Using oWeb As New System.Net.WebClient()
Try
System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol And Not System.Net.ServicePointManager.SecurityProtocol.Ssl3 'Override defautl Security Protocols: Prohibit SSL3
oWeb.Encoding = Encoding.UTF8
Debug.Print("SSL version is " & System.Net.ServicePointManager.SecurityProtocol.ToString)
Debug.Print("Sending " & sData)
Debug.Print("To " & oURI.ToString)
Debug.Print("Encoding is " & oWeb.Encoding.ToString)
sResponse = oWeb.UploadString(oURI, "POST", Convert.ToBase64String(Encoding.UTF8.GetBytes(sData)))
Debug.Print("Server reponse = " & sResponse)
Catch ex As Exception
MsgBox("Connection with server failed: " & ex.ToString, vbCritical + vbOKOnly, "Add-In")
End Try
End Using
'#Verify RSA SHA256 Signature
Dim sDataToSign As String = sData
Dim sSignatureToVerify As String = sResponse
Using myRSA As New System.Security.Cryptography.RSACryptoServiceProvider
'XML format obtain from PEM file by hand copy/paste here: https://superdry.apphb.com/tools/online-rsa-key-converter
myRSA.FromXmlString("<RSAKeyValue><Modulus>SomeLongBase64StringHere</Modulus><Exponent>SomeShortBase64StringHere</Exponent></RSAKeyValue>")
Debug.Print("Signature verification = " & myRSA.VerifyData(Encoding.UTF8.GetBytes(sDataToSign), _
System.Security.Cryptography.CryptoConfig.MapNameToOID("SHA256"), _
Convert.FromBase64String(sSignatureToVerify)).ToString)
End Using
End Sub
Once question 2) has been resolved, I hope we can let this code evolve so that it provides a good but yet simple example of how to implement .NET Client verification of OpenSSL Server signature. I was unable to locate a simple and clear example on the Internet.
This can typically be used for licensing purposes where a Server would provide a file containing an expiration date as well as a signature of that date, in order for the Client App to confirm this expiration date was not altered for example by the Owner of the Client computer.
Is there a coldfusion alternaitive to this php function: openssl_verify:
openssl_verify() verifies that the signature is correct for the
specified data using the public key associated with pub_key_id. This
must be the public key corresponding to the private key used for
signing.
I've looked all over but there doesn't seem to be any. Thanks in advance for any info?
There are no built in functions, AFAIK. However, java supports signature verification, which you could adapt with a bit of java code.
Convert the data you want to verify into binary. The exact steps depends on what you are verifying, but say it is a physical file:
dataBytes = fileReadBinary( "c:\path\someFile.zip" );
Decode the signature value into binary. Again, the "how" depends on the signature format. If it is a base64 encoded string:
signatureBytes = binaryDecode( base64SignatureString, "base64" );
Load the certificate from your keystore (or from a file) and extract the public key:
// Example: "C:\ColdFusion\jre\lib\security\cacerts"
fis = createObject("java", "java.io.FileInputStream").init( pathToKeyStore );
keyStore = createObject("java", "java.security.KeyStore").getInstance("JKS");
// Default keystore password is "changeit" (do not keep the default. change it)
keyStore.load(fis, keyStorePassword.toCharArray());
publicKey = keyStore.getCertificate( "yourCertAlias" ).getPublicKey();
Create a Signature object to perform the verification. Initialize it with the appropriate algorithm (ie SHA1withRSA, etcetera), public key and the data to verify:
sign = createObject("java", "java.security.Signature").getInstance("SHA1withRSA");
sign.initVerify( publicKey );
sign.update( dataBytes );
Finally, feed in the signature and verify its status:
isVerified = sign.verify(signatureBytes);
writeDump( isVerified );
For more details, see Lesson: Generating and Verifying Signatures and Weaknesses and Alternatives.
You could attempt using cfexecute along with the OpenSSL CLI. https://www.openssl.org/docs/manmaster/apps/verify.html
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 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.
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.