6

I am trying to use RSA encryption in JavaScript and then decrypt it in C#. In JavaScript I am using the library jsencrypt. In C# I using the API "bouncy castle". When I do the encryption/decryption within the same language everything works. I get back the correct text when I decrypt it. When I try to decrypt in C# what was encrypted in JavaScript I get nothing close. I am sure the keys are the same between the two. An example of the code is below. Any help on how to solve this would be greatly appreciated.

JavaScript

//using jsencrypt.min.js

var encrypt = new JSEncrypt();
encrypt.setPublicKey($('#pubkey').val());
var encrypted = encrypt.encrypt($('#input').val());

take the value I get from JavaScript "encrypted" and use it in C# for "encyp"

    AsymmetricCipherKeyPair KeyParameterPrivate;
        byte[] cipheredBytes = Convert.FromBase64String(encyp);


        string privateKeyFileName = @"C:\private.pem";
        using (var fileStream2 = File.OpenText(privateKeyFileName))
        {
            PemReader pemReader2 = new Org.BouncyCastle.OpenSsl.PemReader(fileStream2);
            KeyParameterPrivate = (Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair)pemReader2.ReadObject();
        }
        IAsymmetricBlockCipher cipher2 = new Org.BouncyCastle.Crypto.Engines.RsaEngine();
        RsaKeyParameters privateKey2 = (RsaKeyParameters)KeyParameterPrivate.Private;
        //cipher.Init(false, publicKey4);
        cipher2.Init(false, privateKey2);
        byte[] deciphered = cipher2.ProcessBlock(cipheredBytes, 0, cipheredBytes.Length);
        string decipheredText = utf8enc.GetString(deciphered);
1
  • 1
    What do you get in C# in the deciphered variable if you print out the bytes in hexadecimals? Commented Jan 2, 2015 at 14:39

4 Answers 4

2

My advice is to keep it as simple as possible and not use Bouncy Castle for this. You need to create a public key for encryption, private key for decryption and a certificate to fetch the private key from.

First, create private key and certificate PEM files using OpenSSL:

openssl req -newkey rsa:1024 -nodes -keyout private_key.pem -x509 -days 365 -out certificate.pem

Then create a public key PEM file from the certificate that you created:

openssl x509 -pubkey -noout -in certificate.pem > public_key.pem

Then export a PFX file using the private key and certificate PEM files that you created:

openssl pkcs12 -export -out certificate.pfx -inkey private_key.pem -in certificate.pem

When you do the export, you'll be asked to provide a certificate password.

Now here is how to do the RSA decryption in C#:

var cert = new X509Certificate2(@"C:\path\to\certificate.pfx", "password");
var rsaCng = (RSACng)cert.PrivateKey;
var decryptedText = Encoding.UTF8.GetString(rsaCng.Decrypt(Convert.FromBase64String(encryptedText), RSAEncryptionPadding.Pkcs1));
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot, Sirar! I would like to add that OpenSSL is available in Git folder on Windows: C:\Program Files\Git\usr\bin\openssl.exe. No need to install it
@hans did this sort your issue
0

Why would you want to torture yourself using BC for this?

The easiest approach to decryption here is :

 // store is a X509Store pointing to the correct store on the target machine
 // You have to ensure that the security principal for your app has access to the private key to decrypt
 X509Certificate2 cert = store.Certificates.Find(X509FindType.FindByThumbprint, "sha1hash", false)[0];

 var prov = (RSACryptoServiceProvider)cert.PrivateKey;
 var decipheredText = Encoding.UTF8.GetString(prov.Decrypt(Convert.FromBase64String(target), false));

Obviously you can get your X509Certificate2 from file or any other means, e.g. X509Certificate2 cert = new X509Certificate2(@"C:\someCert.pfx", "somePass");

If you followed jsencrypt tutorial, use this openssl command to get the pfx out of the pems you have:

openssl pkcs12 -export -out certificate.pfx -inkey privateKey.pem -in publicKey.pem

2 Comments

That openssl command doesn't work for me in Windows. I got "unable to load certificates" when I ran it.
Also the C# code doesn't work in .NET Core, it crashes at runtime when doing the RSA cast. Please see my answer below which has working code.
0

You'll have to use new PKCS1Encoding(cipher2). The RSAEngine only produces plain (also known as raw or textbook) RSA.

Comments

0

Tell me if it works for you.

public string Decrypt(RSACryptoServiceProvider provider, string toDecrypt)
{
    var input = Convert.FromBase64String(toDecrypt);
    IEnumerable<byte> output = new List<byte>();
    for (var i = 0; i < input.Length; i = i + input.Length)
    {
        var length = Math.Max(input.Length - i, 128);
        var block = new byte[length];
        Buffer.BlockCopy(input, i, block, 0, length);
        var chunk = provider.Decrypt(block, false);
        output = output.Concat(chunk);
    }
    return Encoding.UTF8.GetString(output.ToArray());
}

1 Comment

You need to use a private key to decrypt. You're not doing that in your code. Also I can confirm that your code doesn't work, it crashes at runtime when trying to decrypt. Please next time understand the question first, test your code and then suggest a working example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.