title: RSA signing and verification with C#,BouncyCastle and imported RSA key - Working Python example and non-working C# code sample inside
body: <p>I have been tearing what is left of my hair out trying to get a trivial example of RSA data signing and verification with C# and BouncyCastle working.  </p>
  
  <p>RSACryptoServiceProvider.VerifyHash() always returns false on an example that works for me with Python and M2Crypto.</p>
  
  <p>I have verified that the hash signatures are identical between the working example and the C# example and it is there I am stuck.  I feel I am missing some vital detail.</p>
  
  <p>The working Python code and non working C# code follow.</p>
  
  <p>The key was generated with</p>
  
  <pre><code>openssl genrsa -out testkey.pem 1024
  openssl rsa -in testkey.pem -pubout &gt; testkey.pub
  </code></pre>
  
  <p>Python code (working):</p>
  
  <pre><code>    private = """-----BEGIN RSA PRIVATE KEY-----
  MIICXQIBAAKBgQCxSHbp1ID/XHEdzVzgqYR1F/79PeMbqzuKNZChvt1gFObBhKyB
  pgaHDHw3UZrO8s/hBEE/Mpe2Lh90ZAFdPIXq+HyVoznXMoJYBv0uLDApvSQbJNOd
  f7T5VwmpBbkfj1NAlm39Eun9uBSokEOnB24g+bczPQPGOASrQ2Ly9afOZQIDAQAB
  AoGBAIEzQIZ1OnXgVwfTLMcGg+QaUtkYizUU+9Vj6D4YrZliYjHSkS4DY2p0rOpb
  7Ki5yMpCoZJ/OpWo03+tilj6zNUU6X3aHrPPSv8jcsE0sDi9zYJr/Ztk3EG23sad
  bM28Bb4fV/Z0/E6FZJrmuvI2dZP/57oQSHGOhtkHFO21cW5BAkEA3l/i5Rc34YXc
  WHYEsOYe0kAxS4dCmhbLWaWvsghW/TomjdxzePsO70GZZqRMdzkfA1iS1OrK+pP4
  4suL2rSLrQJBAMwXFnBp4Jmek0CTSxoYf6q91eFm/IRkGLnzE1fEZ76vQOBTas8T
  /mpjNQHSEywo/QB62h9A8hy7XNrfZJAMJJkCQA5TYwybKFBxDTbts3Op/4ZP+F0D
  Q7klisglsmHnw6Lgoic1coLyuY2UTkucfgiYN3VBuYPZ9GWcLsZ9km7ufqkCQQCz
  NVa70Qyqd+cfXfcla/u2pskHCtKTQf3AUmRavhjHBMa39CemvAy7yG9EMP4q2bcH
  U9jydqnidtdbTavVHQSJAkA0zJtLzHGPtQqQaI7K6kBDXYPqloGnQxHxad0HPx2e
  Vj2qv1tEsqeG6HC7aL/afXOtxcfjq4oMHbGUjDv+dGfP
  -----END RSA PRIVATE KEY-----"""
  
  public = """-----BEGIN PUBLIC KEY-----
  MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxSHbp1ID/XHEdzVzgqYR1F/79
  PeMbqzuKNZChvt1gFObBhKyBpgaHDHw3UZrO8s/hBEE/Mpe2Lh90ZAFdPIXq+HyV
  oznXMoJYBv0uLDApvSQbJNOdf7T5VwmpBbkfj1NAlm39Eun9uBSokEOnB24g+bcz
  PQPGOASrQ2Ly9afOZQIDAQAB
  -----END PUBLIC KEY-----"""
  
  message = "test input string"
  
  import base64
  
  # Use EVP api to sign message
  from M2Crypto import EVP
  key = EVP.load_key_string(private)
  key.reset_context(md='sha1')
  key.sign_init()
  key.sign_update(message)
  signature = key.sign_final()
  
  encoded = base64.b64encode(signature)
  print encoded
  
  with open("python_sig2.txt","w") as f:
      f.write(encoded)
  
  # Use EVP api to verify signature
  from M2Crypto import BIO, RSA, EVP
  bio = BIO.MemoryBuffer(public)
  rsa = RSA.load_pub_key_bio(bio)
  pubkey = EVP.PKey()
  pubkey.assign_rsa(rsa)
  pubkey.reset_context(md="sha1")
  pubkey.verify_init()
  pubkey.verify_update(message)
  decoded = base64.b64decode(encoded)
  print pubkey.verify_final(decoded) == 1
  </code></pre>
  
  <p>C# code (verifyhash() returns false):</p>
  
  <pre><code>using System;
  using System.IO;
  using System.Security.Cryptography;
  using System.Text;
  using Org.BouncyCastle.Crypto;
  using Org.BouncyCastle.Crypto.Parameters;
  using Org.BouncyCastle.OpenSsl;
  using Org.BouncyCastle.Security;
  
  
  namespace RsaSignTest
  {
      class Program
      {
          private const string privateKey =
              @"-----BEGIN RSA PRIVATE KEY-----
  MIICXQIBAAKBgQCxSHbp1ID/XHEdzVzgqYR1F/79PeMbqzuKNZChvt1gFObBhKyB
  pgaHDHw3UZrO8s/hBEE/Mpe2Lh90ZAFdPIXq+HyVoznXMoJYBv0uLDApvSQbJNOd
  f7T5VwmpBbkfj1NAlm39Eun9uBSokEOnB24g+bczPQPGOASrQ2Ly9afOZQIDAQAB
  AoGBAIEzQIZ1OnXgVwfTLMcGg+QaUtkYizUU+9Vj6D4YrZliYjHSkS4DY2p0rOpb
  7Ki5yMpCoZJ/OpWo03+tilj6zNUU6X3aHrPPSv8jcsE0sDi9zYJr/Ztk3EG23sad
  bM28Bb4fV/Z0/E6FZJrmuvI2dZP/57oQSHGOhtkHFO21cW5BAkEA3l/i5Rc34YXc
  WHYEsOYe0kAxS4dCmhbLWaWvsghW/TomjdxzePsO70GZZqRMdzkfA1iS1OrK+pP4
  4suL2rSLrQJBAMwXFnBp4Jmek0CTSxoYf6q91eFm/IRkGLnzE1fEZ76vQOBTas8T
  /mpjNQHSEywo/QB62h9A8hy7XNrfZJAMJJkCQA5TYwybKFBxDTbts3Op/4ZP+F0D
  Q7klisglsmHnw6Lgoic1coLyuY2UTkucfgiYN3VBuYPZ9GWcLsZ9km7ufqkCQQCz
  NVa70Qyqd+cfXfcla/u2pskHCtKTQf3AUmRavhjHBMa39CemvAy7yG9EMP4q2bcH
  U9jydqnidtdbTavVHQSJAkA0zJtLzHGPtQqQaI7K6kBDXYPqloGnQxHxad0HPx2e
  Vj2qv1tEsqeG6HC7aL/afXOtxcfjq4oMHbGUjDv+dGfP
  -----END RSA PRIVATE KEY-----";
  
          private const string publicKey =
              @"-----BEGIN PUBLIC KEY-----
  MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxSHbp1ID/XHEdzVzgqYR1F/79
  PeMbqzuKNZChvt1gFObBhKyBpgaHDHw3UZrO8s/hBEE/Mpe2Lh90ZAFdPIXq+HyV
  oznXMoJYBv0uLDApvSQbJNOdf7T5VwmpBbkfj1NAlm39Eun9uBSokEOnB24g+bcz
  PQPGOASrQ2Ly9afOZQIDAQAB
  -----END PUBLIC KEY-----";
  
          static void Main(string[] args)
          {
              var data = "test input string";
              var sig = SignWithPrivateKey(data);
              var valid = VerifyWithPublicKey(data,sig);
          }
  
          private static byte[] SignWithPrivateKey(string data)
          {
              RSACryptoServiceProvider rsa;
  
              using (var keyreader = new StringReader(privateKey))
              {
                  var pemreader = new PemReader(keyreader);
                  var y = (AsymmetricCipherKeyPair) pemreader.ReadObject();
                  var rsaPrivKey = (RsaPrivateCrtKeyParameters)y.Private;
                  rsa = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create();
                  var rsaParameters = DotNetUtilities.ToRSAParameters(rsaPrivKey);
                  rsa.ImportParameters(rsaParameters);
  
              }
  
              // compute sha1 hash of the data
              var sha = new SHA1CryptoServiceProvider();
              byte[] hash = sha.ComputeHash(Encoding.ASCII.GetBytes(data));
  
              // actually compute the signature of the SHA1 hash of the data
              var sig = rsa.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
  
              // base64 encode the signature and write to compare to the python version
              String b64signature = Convert.ToBase64String(sig);
              using (var sigwriter = new StreamWriter(@"C:\scratch\csharp_sig2.txt"))
              {
                  sigwriter.Write(b64signature);
              }
  
              return sig;
          }
  
          private static bool VerifyWithPublicKey(string data,byte[] sig)
          {
              RSACryptoServiceProvider rsa;
  
              using (var keyreader = new StringReader(publicKey))
              {
                  var pemReader = new PemReader(keyreader);
                  var y = (RsaKeyParameters) pemReader.ReadObject();
                  rsa = (RSACryptoServiceProvider) RSACryptoServiceProvider.Create();
                  var rsaParameters = new RSAParameters();
                  rsaParameters.Modulus = y.Modulus.ToByteArray();
                  rsaParameters.Exponent = y.Exponent.ToByteArray();
                  rsa.ImportParameters(rsaParameters);
              }
  
              // compute sha1 hash of the data
              var sha = new SHA1CryptoServiceProvider();
              byte[] hash = sha.ComputeHash(Encoding.ASCII.GetBytes(data));
  
              // This always returns false
              return rsa.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"),sig);
          }
      }
  }
  </code></pre>
  
  <p>At this point I don't know how to proceed and any help would be greatly appreciated.</p>