Search code examples
c#rsasignaturepublic-key

C# Verifying data (signed with RSA private key) with public key


using BouncyCastle and with help from a stackoverflow question I got this:

        using System.Net.Sockets;
        using System.Security.Cryptography;
        using Org.BouncyCastle.Crypto.Parameters;
        using Org.BouncyCastle.OpenSsl;

...

        TcpClient client = new TcpClient("127.0.0.1", 1337);
        NetworkStream stream = client.GetStream();

        StreamWriter writer= new StreamWriter(stream);
        StreamReader reader = new StreamReader(stream);

        writer.WriteLine("hello");
        writer.AutoFlush = true;

        string response = Convert.FromBase64String(reader.ReadToEnd()).ToString();

        RSACryptoServiceProvider RCP;
        var x = new PemReader(File.OpenText(pubkey));
        var y = (RsaKeyParameters)x.ReadObject();

        RCP = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create();

        var pa = new RSAParameters();
        pa.Modulus = y.Modulus.ToByteArray();
        pa.Exponent = y.Exponent.ToByteArray();

        RCP.ImportParameters(pa);
        byte[] test = RCP.Decrypt(response, true);

Now, obviously Decrypt will fail, as since I'm trying to decrypt something which was signed (not "encrypted") and definately not by the same "key". I'm confused since I thought I should use a method like VerifyData(), but this returns a bool and takes arguments I'm not sure I have.

What I wish to accomplish is the C# equivalent of openssl rsautl -verify -inkey public.pem -pubin. That is, "decrypt" with the pubkey to verify the contents of said message.

Am I on the right track here?

  • Mik

Solution

  • Actually a decrypt of a signature should never fail unless you specified the wrong encoding parameters - a signature is simply the private-key encrypted hash of the data (typically SHA1); the only benefit of using the verify routine is that it decrypts the block and does the hash comparison work for you, if you wanted to be bloody minded you could instead do a decrypt operation with your public key and compare the hash bytes yourself.

    I'm not actually sure what response is in the context of your program; you should only be passing the RSA data to it, if you're also feeding it the data that was signed in the first place you are doing it wrong - similarly, do check if that function actually accepts a string, in my experience BouncyCastle generally expects a byte[]

    I'd recommend using SignerUtilities.GetSigner() - it takes a string arg to tell it what sort of signature you're using, I would imagine "SHA1WithRSA" to be right for you.