Шифрование RSA C# с открытым ключом для использования с PHP openssl_private_decrypt(): Chilkat, BouncyCastle, RSACryptoServiceProvider

я пытаюсь зашифровать строку в приложении С#, чтобы она была расшифрована на стороне PHP с помощью openssl_private_decrypt(). исходный открытый ключ, который я пытаюсь расшифровать, получен из PHP openssl_pkey_get_details($privateKey); забегая вперед, я могу сделать это с помощью чилката, но он не работает в монотаче под iOS, поэтому для меня он бесполезен (и стоит тоже довольно дорого). есть пример кода, как я это делаю:

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

что мне не хватает?


person jungle_mole    schedule 20.12.2013    source источник
comment
-1 и поставить на удержание? ржу не могу. то, что я спрашиваю, очевидно: как зашифровать данные с помощью RSA в приложении C#, чтобы эти данные были расшифрованы с помощью PHP openssl_private_decrypt(). и не использовать для этого чилкат. неясно, почему шифрование BouncyCastle не будет работать и как получить модуль открытого ключа для использования с RSACryptoServiceProvider.   -  person jungle_mole    schedule 21.12.2013
comment
Есть два типа людей, которые обычно хотят вам помочь. Есть те, которые сделали в точности то же, что и вы, и поэтому могут легко определить, чего не хватает. И есть те, кто хотел бы помочь вам, если бы они могли взять какой-нибудь код, демонстрирующий проблему, и работать с ним. Поскольку первая категория обычно очень невелика, вы хотите стремиться ко второй категории, и поэтому вы всегда должны стремиться предоставить 1) достаточно информации о проблеме, чтобы даже те, кто не являются экспертами в этой области домен может это понять, и 2) полный пример со всеми необходимыми данными.   -  person Lasse V. Karlsen    schedule 21.12.2013
comment
извините, если каких-то данных не хватает, но я постарался сделать пример кода максимально доступным. Я даже переписал свой тестовый образец, чтобы он был минимальным по размеру, но все же полным. Пожалуйста, просто скажите мне, какой информации могут не хватать люди из второй категории. какие необходимые данные? этот код можно протестировать с открытыми и закрытыми ключами, сгенерированными в PHP, любой среде IDE C# и библиотеке надувных замков. visualstudio.com/en-US/products/visual-studio- экспресс-против bouncycastle.org/csharp   -  person jungle_mole    schedule 21.12.2013
comment
я видел много вопросов, которые являются более общими или неполными, но никто не придирается. может быть дело в том, что на эти вопросы проще ответить. я не знаю. во всяком случае, я нашел специальное решение. мне это не очень нравится, но это работает. в любом случае, я просто хочу знать, как решить задачу, используя только надувной замок или просто стандартный .NET RSACryptoServiceProvider (и все, что ему может понадобиться)   -  person jungle_mole    schedule 21.12.2013
comment
но дело в том, что по моим наблюдениям, несмотря на то, что первая категория невелика, как вы говорите, на подавляющее большинство узких вопросов отвечает именно она. Итак, основная задача задающего — сделать вопрос понятным для первой категории, людей, которые уже что-то знают по предмету. очевидно, очень небольшое количество людей будет портить себе время решением задачи, они даже никогда не застревали вплотную, и это не теоретический или фундаментальный, а скорее специальный в ней прием. поправьте меня если я ошибаюсь   -  person jungle_mole    schedule 22.12.2013


Ответы (1)


хорошо, после шаманских танцев с бубном я пришел к несколько удовлетворительному решению. имейте в виду, что все это делается в контексте работы с функцией PHP openssl_private_decrypt().

так что я получил следующее:

  1. шифрование BouncyCastle просто делает это неправильно

  2. я не знаю, как получить модуль из закрытого ключа, чтобы использовать его с RSACryptoServiceProvider

  3. почему бы не попробовать использовать ключевые данные BouncyCastle и инициализировать 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); 
    

на самом деле странно, что я вообще придумал решение из-за этих тонкостей. я надеюсь, что это будет полезно для кого-то когда-нибудь.

person jungle_mole    schedule 21.12.2013