Encrypt in C# && Decrypt in PHP using PEM file

1.1k views Asked by At

I was searching for a solution but i can't find a functional solution. I need to transmit a string(AESkey) from C# app to PHP server. The client(in C#) download a key.public.pem file(public key) and encrypt the pass, and later send it to the server. The server takes key.pem file(private key).

Server in PHP:

function RSADecryption($text) {
    //re() reads a document an return it as string
    openssl_private_decrypt(base64_decode($text), $decrypted,re("key.pem"));
    return $decrypted;
}

Client in C#:

using System;
using System.Text;
using System.Security.Cryptography;


namespace myApp
{
    class MyRSA
    {
        public static MyRSA getMyRSA()
        {
            if (_Instance == null)
            {
                _Instance = new MyRSA();
            }
            return _Instance;
        }
        public Boolean setPubKey(string url)
        {
            System.Net.WebClient wc = new System.Net.WebClient();
            try
            {
                publicKey = wc.DownloadString(url);
            }
            catch(Exception e)
            {
                return false;
            }
            return true;

        }
        public string crypt(string text)
        {
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            RSAParameters rsaParam = rsa.ExportParameters(false);
            rsaParam.Modulus = Convert.FromBase64String(publicKey.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", ""));
            rsa.ImportParameters(rsaParam);
            byte[] encValue = rsa.Encrypt(Encoding.UTF8.GetBytes(text), false);

            return Convert.ToBase64String(encValue);
        }


        private static MyRSA _Instance;
        private static string publicKey;

        private MyRSA() {}
    }
}

And later i do something like that from main:

MyRSA rsa = MyRSA.getMyRSA();
rsa.setPubKey(site+"key.public.pem");
sendData(rsa.crypt(user));

I think the problem is in the decrypter(PHP function) because doesn't return anything. I don't know but, maybe the problem is that you can't encrypt using RSACryptoServiceProvider and decrypt with openssl? Because they use diferents paramethers or other similars things?

For example, i generated this AES key:

cA?uW=kImEYGsgu

I use this public key

-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApxjhdfvCuafPZmE//cOM OVxBZvMXjwlcyaCfnTuVdbewQ5ITu6hlJ3vX/oTMbik7DprsWoc2tGk3Rx7RdAPd n3VnPm62QjaKtETWJ8/5Nzf+MxlVD0t5tzqzhniZ5BKZTtvCI6STbrFYnKcJwTyI eaEDNtre5EaqEBbrYhlGTRxNmz2SdRi9Im9iCSw9pjDVDDJdzmhENhASmFQMeo7N IS8AY3zJSjOQPKFymZrSa8hxWp88K1/igxs12IhhpqNjMiUi29gH2T+QLPTDzwEq EHTY1K6B0zlNuyp8HR5pNOqYymdnoSpCV3z0deTobAF7KiFYp2pXvoNo8Pc19Yl0 mQIDAQAB -----END PUBLIC KEY-----

And the encrypted password was:

CgG33ytbS3CuK+rOpJRamQ6e8xCj7Q35m6YxWXc44r/D03VubXZO1f5/zF7Zsc42UOOwqbYahApXBXL6o3J5MVu0cDkjstVoUnFJiPRHWmwq9AA0uvLC55gou+VzvmvRzFO38LMZ2BpsQLOjfv16LGWx7MLfKSVFGC8YVHgv6QlEbDFdd/HJDbqAKOoyQWlKXfVeMKmd8ORnq3+B3Tmk57O3BHDVOlmezSgf+YN828u4ChZ08JzjgBo7MP2xCl6pLEeZxiFGjRwrTgRfLXQ7aMB/RyeMMHwInJiTS3/M2Mez8C3/+Za/DIfrLDA9LVdRYdy2n4AxbtyrLTun4mjDO+pYS3HqZlGn2MW5Orc9VH+1CPn2omLVj/qqa6tIoFuJOdpxn/y9

Thanks for your atencion. Regards.

1

There are 1 answers

0
bartonjs On

If your .PEM file says "BEGIN PUBLIC KEY", then it's probably an X.509 SubjectPublicKeyInfo structure. That means it looks like

30 xx  // SEQUENCE (SubjectPublicKeyInfo)
  30 0D  // SEQUENCE (AlgorithmIdentifier)
     06 09 2A 86 48 86 F7 0D 01 01 01  // OID (algorithm = rsaEncryption)
     05 00 // NULL (parameters)
  03 xx  // BIT STRING (subjectPublicKey)
     30 xx  // SEQUENCE (RSAPublicKey)
        02 xx [modulus value here]  // INTEGER (Modulus)
        02 xx [exponent value here]  // INTEGER (Exponent)

Which is a DER encoded blob. Each of the xx values represents a length, which could be more than one byte.

So when you're loading this key you're taking all of the overhead/structural content, as well as the modulus bytes AND the exponent bytes, and calling all of that Modulus. So the net effect is you are encrypting with a different public key than you are decrypting with.

.NET doesn't make reading PEM key contents easy. Your best bet is to turn this key into a certificate. If you don't already have a certificate you can do openssl req -x509 -new -key theprivatekey.pem -out selfsignedcert.cer (and answer whatever you like for the subject prompts).

Otherwise, you're now reduced to How to load the RSA public key from file in C# (and other related questions).