0

I am signing data from the client in c# and then transmitting the data to a php web server which is supposed to return Verified if the data has not been tampered with but it always returns Unverified. I use http://phpseclib.sourceforge.net/rsa/intro.html to verify the RSA data. This is the c# function that signs the data:

public string SignRSA(string privateKey, string rawData)
{
    ASCIIEncoding ByteConverter = new ASCIIEncoding();
    byte[] originalData = ByteConverter.GetBytes(rawData);
    RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider();
    RSAalg.FromXmlString(privateKey);
    return Convert.ToBase64String(RSAalg.SignData(originalData, new SHA256Managed()));
}

Here is the php code that verifies the data:

$key = str_replace("%3c", "<", $_POST['PublicKey']);
$key = str_replace("%3e", ">", $key);
$key = str_replace("%3d", "=", $key);
$key = str_replace("%2f", "/", $key);
$key = str_replace("%2b", "+", $key);
$sig = str_replace("%2f", "/", $_POST['Signature']);
$sig = str_replace("%2b", "+", $sig);
$rsa = new Crypt_RSA();
$rsa->loadKey($key);
$rsa->setPublicKey();
$rsa->setHash(sha256);
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
//$publickey = $rsa->getPublicKey();
echo $rsa->verify(unpack("C*", $_POST["Text"]), base64_decode($sig)) ? 'verified' : 'unverified';

All of the str_replace functions are used because the /'s are replaced by %2f, ='s are replaced by %3d, etc.

neubert
  • 15,947
  • 24
  • 120
  • 212
Di Saber
  • 57
  • 7
  • So the string is base64encoded, then URL encoded? If so shouldn't it be `base64_decode(urldecode($_POST["Signature"]))`. Also `$sig` is never being used. – user3783243 Jan 06 '20 at 00:39
  • The verification code looks like it expects the data to be html encoded. So the equivalent in c# is System.Net.WebUtility.HtmlEncode(string) and System.Net.WebUtility.HtmlDecode(string) – jdweng Jan 06 '20 at 00:56
  • `%2f` is a URL encoding, not HTML. `urldecode` is the equivalent inverse of that. – user3783243 Jan 06 '20 at 01:05
  • I modified the code so the decoded signature was being used. I tried using urldecode but some of the characters were missing. The str_replace functions are getting the signature to be exactly the same as It was sent but the code still returns unverified. – Di Saber Jan 06 '20 at 13:41
  • `unpack("C*", $_POST["Text"])` don't do that. phpseclib expects _strings_ to be passed to `$rsa->verify()` - not an array of integers, between 0 and 255 each, which is what `unpack("C*", $_POST["Text"])` gives. Also, for good measure, I'd see if (1) the key loaded by doing `echo $rsa;` after `$rsa->setPublicKey();`. And did `base64_decode($sig)` work? I'd do echo bin2hex(base64_decode($sig))` just to double check. And altho it's nitpicky I guess... `$rsa->setHash(sha256);` - put that in single or double quotes. As is it'll produce an E_NOTICE error, depending on your level of error reporting. – neubert Jan 08 '20 at 02:20
  • Also, I'd say post your (public) key, plaintext and signature. Since it's your public key it shouldn't be a huge issue and having it will greatly assist in diagnosis. – neubert Jan 08 '20 at 02:23

0 Answers0