Verify SHA1withRSA signature generated in Java (An

2019-02-17 23:56发布

问题:

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!

回答1:

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.