-1

我正在尝试加密 C# 应用程序中的字符串,以便在 PHP 端使用 openssl_private_decrypt() 对其进行解密。我试图解密的初始公钥是从 PHP 的 openssl_pkey_get_details($privateKey) 中获得的;提前说,我可以使用 chilkat 来做到这一点,但它在 iOS 下的 monotouch 中不起作用,所以它对我来说没用(而且成本也很高)。有代码示例我是如何做到的:

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));
}

输出是:

success
decryption failed
decryption failed

我错过了什么?

4

1 回答 1

3

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.

于 2013-12-21T06:38:39.977 回答