Search code examples
rsaphpseclibandroid-biometric

Private/Public RSA 2048 key pair - How to verify RSA PKCS#1v1.5 SHA 256 with phpseclib


I need to verify a signature in an api endpoint, but whatever I tried I can't validate it. Data comes from mobile device.

Key pair is created on android through this library and in particular, with these functions.

  1. Key pair ReactNativeBiometrics.createKeys --> in deep source code
  2. Signature ReactNativeBiometrics. createSignature --> In deep source code

composer.json

{
    "require": {
        "phpseclib/phpseclib": "^3.0",
        "kint-php/kint": "^4.2"
    }
}

index.php

<?php

require "vendor/autoload.php";

use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Crypt\RSA\PublicKey;
use phpseclib3\Crypt\RSA;

$message = "CIAO";
$signature = "nu92wNMUDDUgZJbrKOIJt09FOfvMvQ6fWlNCfvkxqhUuGIT7hCnikQCM4KfXJN/X7D3+ISQvu1+BbVYug2uvxDwtDt7mHRr7lo7SRN6/yFq237LJ9iHZNZWXz1Ict1ez92Aa1oeDZtMpO84VOrVE372UNOETFvz+AaeTJ3lO/3WV+xu+uQ36FiOhLtAi7CXFhCki3+P6oO0Va1PtB2rmdiMcbHSkn3y5IZG5UTxLtRYr0dkTbbq+ySNMdYY01Yd1aOHl7phgoR+sRHQwOaq2/IHAahBOTZShrjLy5b/DmDaYwjjAs76FSQFiWtPjtm0WdiroGbzdwsHjWgBXKyHzHA==";

$hash = hash('sha256', $message, true);

$publicKey = "
-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu4sNG1i5Tiqc2nz5nFU8
Q7UaKbOqV2jTCB0Alg2hwT6GQX/GhPTHiPicoLPX1yubPbDxn9e/4ZPCwdfW20JG
4oaGNUnT6VSfH9Tx5ckBGIYzsHbRU7llKgMFK91RVrTCb/3v1sSEHBthby2C4c2V
N1zDCZxaTGfY3zgsEhUIYHhagam1c/WHR9mVCu+9a9QwsMgJ9ppKwikzLyetNkla
MvIKzTxsFHrtZrmBhlbmRHFXGKqqwvnwxkER14YpldiXBFUJ1/p4JHE09byfxmC/
9kRjFxqOxU3hwvO2YlRbk9/T8+6mtyyUxHLLK37vBYOuvKEaPIKM/ASm8UiZLwqq
swIDAQAB
-----END RSA PUBLIC KEY-----
";

$key = PublicKeyLoader::loadPublicKey($publicKey, $password = false);

\Kint::dump(
    $publicKey,
    $key::getSupportedKeyFormats(),
    $key->getLoadedFormat(),
    $key->getPadding(),
    (string) $key->getHash(),
    $key,
    $key instanceof \phpseclib3\Crypt\Common\PublicKey,
    $key->verify(base64_decode($message, true), base64_decode($signature, true)),
    $key->verify(base64_decode($message, true), $signature),
    $key->verify($message, base64_decode($signature, true)),
    $key->verify($message, $signature),
    $key->verify($hash, base64_decode($signature, true))
);

Result:

enter image description here

I verified signature with success with this tool online here

Obviously there is something that I miss, but I can't figured out


Solution

  • Validates fine for me with this code:

    $message = "CIAO";
    $signature = "nu92wNMUDDUgZJbrKOIJt09FOfvMvQ6fWlNCfvkxqhUuGIT7hCnikQCM4KfXJN/X7D3+ISQvu1+BbVYug2uvxDwtDt7mHRr7lo7SRN6/yFq237LJ9iHZNZWXz1Ict1ez92Aa1oeDZtMpO84VOrVE372UNOETFvz+AaeTJ3lO/3WV+xu+uQ36FiOhLtAi7CXFhCki3+P6oO0Va1PtB2rmdiMcbHSkn3y5IZG5UTxLtRYr0dkTbbq+ySNMdYY01Yd1aOHl7phgoR+sRHQwOaq2/IHAahBOTZShrjLy5b/DmDaYwjjAs76FSQFiWtPjtm0WdiroGbzdwsHjWgBXKyHzHA==";
    $publicKey = "-----BEGIN RSA PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu4sNG1i5Tiqc2nz5nFU8
    Q7UaKbOqV2jTCB0Alg2hwT6GQX/GhPTHiPicoLPX1yubPbDxn9e/4ZPCwdfW20JG
    4oaGNUnT6VSfH9Tx5ckBGIYzsHbRU7llKgMFK91RVrTCb/3v1sSEHBthby2C4c2V
    N1zDCZxaTGfY3zgsEhUIYHhagam1c/WHR9mVCu+9a9QwsMgJ9ppKwikzLyetNkla
    MvIKzTxsFHrtZrmBhlbmRHFXGKqqwvnwxkER14YpldiXBFUJ1/p4JHE09byfxmC/
    9kRjFxqOxU3hwvO2YlRbk9/T8+6mtyyUxHLLK37vBYOuvKEaPIKM/ASm8UiZLwqq
    swIDAQAB
    -----END RSA PUBLIC KEY-----";
    
    $signature = base64_decode($signature);
    $key = PublicKeyLoader::load($publicKey)->withPadding(RSA::SIGNATURE_PKCS1);
    echo $key->verify($message, $signature) ? 'good' : 'bad';
    

    The key thing I'm doing that you're not is ->withPadding(RSA::SIGNATURE_PKCS1). sha256 is the default hash for phpseclib v3 so you don't need to do anything with that. Also, my code cleans up some redundancies in your code.