Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verify SHA1withRSA signature generated in Java (Android) with phpseclib

This is what I want to do:

  • Generate a 512 bit RSA keypair in Java/Android
  • Generate a SHA1withRSA signature for some message in Java
  • Send message, signature and public key to PHP (for testing this will be done at the same time)
  • Verify the message in PHP using phpseclib

What I got so far:

On the Java side:

String msg = "Test message";

// generate keypair
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(512);
KeyPair keyPair = keyGen.generateKeyPair();

// generate signature
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(keyPair.getPrivate(), SecureRandom.getInstance("SHA1PRNG"));
signature.update(msg.getBytes());
byte[] sigBytes = signature.sign();

// send message, signature and public key to php script
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(uploadNum + 1);
nameValuePairs.add(new BasicNameValuePair("msg", msg));
nameValuePairs.add(new BasicNameValuePair("signature", Base64.encodeToString(sigBytes,
        Base64.DEFAULT)));
nameValuePairs.add(new BasicNameValuePair("pubkey", Base64.encodeToString(keyPair
        .getPublic().getEncoded(), Base64.DEFAULT)));

HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(UPLOAD_SCRIPT);
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpClient.execute(httpPost);

On the PHP side:

EDIT: As neubert mentioned, the solution is to add $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);. In addition I added the trim function around $_POST['pubkey'] as I noticed that the base64-encoded key ends with a linebreak.

include('Crypt/RSA.php');
$rsa = new Crypt_RSA();
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$rsa->loadKey("-----BEGIN PUBLIC KEY-----\n" . trim($_POST['pubkey']) . "\n-----END PUBLIC KEY-----");
echo $rsa->verify($_POST['msg'], base64_decode($_POST['signature'])) ? 'verified' : 'unverified';

What happens is:

phpseclib gives me a php notice "Invalid signature" and the result is "unverified".

I already tested this with different variations on the PHP side, e.g. base64-decoding the public key before handing it to loadKey(...), not base64-decoding the signature, leaving away the "-----BEGIN PUBLIC KEY-----\n" things, but nothing helped so far.

So what do I have to do to make this work?

EDIT: Now it works!

like image 236
x-ray Avatar asked Oct 23 '22 13:10

x-ray


1 Answers

Seems like $_POST['msg'] might need to be base64_decode()'d as well? Also, try doing $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1). By default phpseclib does OAEP padding which, although more secure, is not as widely supported nor is it the default for most stuff.

like image 146
neubert Avatar answered Nov 08 '22 10:11

neubert