RSA C# encryption with public key to use with PHP

2019-04-17 15:29发布

i'm trying to encrypt the string in C# application for it to be decrypted on PHP side with openssl_private_decrypt(). the initial public key that i'm trying to decrypt with is obtained from within PHP's openssl_pkey_get_details($privateKey); talking ahead, i am able to do it using chilkat, but it doesn't work in monotouch under iOS so it is useless for me (and it costs pretty much too). there is code sample how i'm doing it:

void TestEncryption(string publicKey, string data)
{
        var bytes = Encoding.UTF8.GetBytes(data);

        //by using chilkat
        var key = new Chilkat.PublicKey();
        var result = key.LoadOpenSslPem(publicKey);
        var ck = new Chilkat.Rsa();
        ck.UnlockComponent("blablabla");
        var keyXml = key.GetXml();
        ck.ImportPublicKey(keyXml);
        var ckBytes = ck.EncryptBytes(bytes, false);

        //by using BouncyCastle
        Object obj;
        using (TextReader sr = new StringReader(publicKey))
        {
            PemReader pem = new PemReader(sr);
            obj = pem.ReadObject();               
        }
        var par = obj as Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters;
        RsaEngine e = new RsaEngine();
        e.Init(true, par);           
        var bcBytes = e.ProcessBlock(bytes, 0, bytes.Length);

        //RSACryptoServiceProvider. don't know exectly how to initialize it, one way that must work i think is from chilkat's xml, just to test
        RSACryptoServiceProvider csp = new RSACryptoServiceProvider(1024);
        csp.FromXmlString(keyXml);

        //also tryed to initialize like this:
        //var pp = csp.ExportParameters(false);
        //pp.Modulus = byteKey; //this one is publicKey, stripped from --begin-- and --end-- sections and encoded from base64 to byte array (162 bytes)
        //csp.ImportParameters(pp);
        //
        //or if i do
        //var pp = new RSAParameters();
        //pp.Exponent = Convert.FromBase64String("AQAB");
        //pp.Exponent array is the same: {1, 0, 1};

        var cspBytes = csp.Encrypt(bytes, false); //or (bytes, true), doesn't matter           

        //this function sends request to php and returns result of decryption attempt         
        Debug.WriteLine(ExecRequest(ckBytes));
        Debug.WriteLine(ExecRequest(bcBytes));
        Debug.WriteLine(ExecRequest(cspBytes));
}

the output is:

success
decryption failed
decryption failed

what am i missing?

1条回答
祖国的老花朵
2楼-- · 2019-04-17 16:01

ok, after doing some shamanic dances with tambourine i've come to somewhat-satisfying solution. please hold in mind, that it is all done in context of working with PHP's openssl_private_decrypt() function.

so i got next:

  1. encryption of BouncyCastle just doing it not right

  2. i don't know how to get modulus out of private key to use it with RSACryptoServiceProvider

  3. why not try to use BouncyCastle's key data and initialize RSACryptoServiceProvider

    Object obj;
    using (TextReader sr = new StringReader(publicKey))
    {
        PemReader pem = new PemReader(sr);
        obj = pem.ReadObject();               
    }
    var par = obj as Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters;
    
    RSACryptoServiceProvider csp = new RSACryptoServiceProvider(1024);        
    //var pp = csp.ExportParameters(false); //works on native .NET, doesn't work on monotouch
    var pp = new RSAParameters();
    pp.Modulus = par.Modulus.ToByteArrayUnsigned(); //doesn't work with ToByteArray()
    pp.Exponent = par.Exponent.ToByteArrayUnsigned();                          
    csp.ImportParameters(pp);
    var cspBytes = csp.Encrypt(bytes, false); 
    

actually, it is strange that i've came up with solution at all, cuz of these niceties. i hope it would be helpful for someone someday.

查看更多
登录 后发表回答