1

I have a encryption C# code, that i'm trying to implement in PHP and phpseclib and get exactly same results. It's RSA. But I cannot get it done. It gives me empty string in PHP as encoded.

Public key is in this format:

<?xml version="1.0" encoding="utf-16"?>

<RSAParameters xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Exponent>AQAB</Exponent>
      <Modulus>sMFsHSyxAP5N85yvx/XDs9acJa30qwBjoOdDKvNOHJUYBpspwatkdtErCqM2W6tXH9rbvhIn8/nqW4OqAdLinlgkEJoQ/qnzKjYJhHl4YzKFL6Wp+iFRH6ar6ZWOE87LeNQ0nHwlXKoWkJQKV8NB38XRw6aLvNTj8Po2yaFDbQFztsJ+ILkumRh7Leu77IV+124Swc6JqLRt5z2FnDX869dRi2fqcnFa1EHEBsPEndVd2HSeJUncTQiWJ9SNRU+WLltVVewYiGheqr1ABab++3XM5qrB6fWn/RN9Fcg5nM8fachAFSX2YRrEsg7mcbNALRes6OEdpI0LBdX8Wdw6oQ==</Modulus>
    </RSAParameters>

The C# code is:

public static string Encrypt(string data, string public)
    {
        RSAParameters pubKey = public;
        var csp = new RSACryptoServiceProvider();
        csp.ImportParameters(pubKey);

        var bytesPlainTextData = System.Text.Encoding.Unicode.GetBytes(data);
        var bytesCypherText = csp.Encrypt(bytesPlainTextData, false);
        return Convert.ToBase64String(bytesCypherText);
    }

In PHP i'm doing this, but results an empty string:

$rsa = new Crypt_RSA();
$modulus = new Math_BigInteger(($modulus), 16);
$exponent = new Math_BigInteger(($exponent), 16);
$rsa->loadKey(array('n' => $modulus, 'e' => $exponent));
$rsa->setPublicKey(array('n' => $modulus, 'e' => $exponent));
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$encryptedPassword = $rsa->encrypt($password);

echo $encryptedPassword;
neubert
  • 15,947
  • 24
  • 120
  • 212
Simos Fasouliotis
  • 1,383
  • 2
  • 16
  • 35
  • i'm not familiar with the used biginteger class on the php side, but maybe it's worth noting that rsaparameters holds the numbers in big-endian representation ... at least with the c# BigInteger class you can run into some trouble because it expects little endian ... – DarkSquirrel42 Apr 18 '17 at 11:51
  • Aren't you simply forgetting to convert the result to base 64? Printing random binary bytes is not a good idea. – Maarten Bodewes Apr 18 '17 at 12:21
  • @MaartenBodewes $encryptedPassword is null so it doesnt made a change – Simos Fasouliotis Apr 18 '17 at 12:42
  • This is basic troubleshooting. Did you get any warnings at all from the system? PHP sometimes generates warnings on the log / console next to to error results (great error handling, that). How big is your key? How big is the "password" etc.? These are all things we cannot see. – Maarten Bodewes Apr 18 '17 at 16:31
  • There is no error and the result is NULL. The public key i'm trying is the one i've posted. the password is about 100 characters long. – Simos Fasouliotis Apr 18 '17 at 16:55

1 Answers1

0

phpseclib has had native support for keys of that format for years. Since v0.2.2 which, per https://github.com/phpseclib/phpseclib/releases/tag/0.2.2, was released a little less than five years ago.

Anyway, this worked for me:

<?php
include('Crypt/RSA.php');

$xml = '<RSAParameters xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <Exponent>AQAB</Exponent>
      <Modulus>sMFsHSyxAP5N85yvx/XDs9acJa30qwBjoOdDKvNOHJUYBpspwatkdtErCqM2W6tXH9rbvhIn8/nqW4OqAdLinlgkEJoQ/qnzKjYJhHl4YzKFL6Wp+iFRH6ar6ZWOE87LeNQ0nHwlXKoWkJQKV8NB38XRw6aLvNTj8Po2yaFDbQFztsJ+ILkumRh7Leu77IV+124Swc6JqLRt5z2FnDX869dRi2fqcnFa1EHEBsPEndVd2HSeJUncTQiWJ9SNRU+WLltVVewYiGheqr1ABab++3XM5qrB6fWn/RN9Fcg5nM8fachAFSX2YRrEsg7mcbNALRes6OEdpI0LBdX8Wdw6oQ==</Modulus>
    </RSAParameters>';

$rsa = new Crypt_RSA();
$rsa->loadKey($xml);

$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$encryptedPassword = $rsa->encrypt('password');

echo base64_encode($encryptedPassword);

I had to remove the <?xml version="1.0" encoding="utf-16"?> bit from the key but other than that it worked.

neubert
  • 15,947
  • 24
  • 120
  • 212
  • Dear neubert, @neubert your script works perfect as execution and provides an encrypted string. But for some reason this key cannot be decrypted correctly with the C# descryption, meaning that something in the encryption algorithm is different than the c# code. If it helps, I found in C# that uses encryption algorithm "RSA-PKCS1-KeyEx". Do we need to make any alterations to the code your provided based Rsa-pkcs1-keyex ? – Simos Fasouliotis Apr 23 '17 at 07:42
  • suppose that i use your code - even the result is not the same with c# encryption - what would the code be for decrypting the string ? I have salt, private, vector data if they needed for decryption. – Simos Fasouliotis Apr 23 '17 at 08:09
  • @Simos - the C# code you've posted is for encryption - not decryption. For PKCS1 padding I'd suggest you try `define('CRYPT_RSA_PKCS15_COMPAT', true);`. – neubert Apr 24 '17 at 03:15
  • hello, thanks for your reply. I've tried that, but still the encrypted string is not the same with C#, in other words it cannot be decrypted by c#. The code i've posted is encryption and there is another code that decrypts again in c#. I'm trying to simulate the c# encryption code to php, but still the c# decryption will remain. But all encoded strings i tried from your code (including define('CRYPT_RSA_PKCS15_COMPAT', true);) do not get properly decrypted later on from c#. any other idea what might be different? – Simos Fasouliotis Apr 24 '17 at 07:14
  • @SimosFasouliotis - maybe post your latest C# code then. As I previously observed the C# code in your OP appears to encrypt - not to decrypt. I'm not a C# expert but I tried to adapt the code to decrypt without success: https://pastebin.com/z8NTCUGw That's based off of the first four lines of the C# code you posted and trying to compile it gets me a `error CS0029: Cannot implicitly convert type 'string' to 'System.Security.Cryptography.RSAParameters'` error.. – neubert Apr 25 '17 at 12:39
  • @SimosFasouliotis - also, the encrypted strings shouldn't ever match. PKCS1 encryption adds random padding. If you encrypt the same string with multiple times with either Java or phpseclib and with the same key you should get a different ciphertext each time. They should always decrypt, however, if you're doing things correctly. If your ciphertext's in Java are always matching then I submit that not even PKCS1 padding is being used.. – neubert Apr 25 '17 at 12:43