title: C# BouncyCastle - RSA Encryption with Public/Private keys
body: <p>I need to encrypt data in C# in order to pass it to Java. The Java code belongs to a 3rd party but I have been given the relevant source, so I decided that as the Java uses the Bouncy Castle libs, I will use the C# port.</p>
  
  <p>Decryption works fine. However, decryption works only when I use the encrypt using the private key, and not with the public key. When using the public key, decryption fails with <code>unknown block type</code>.</p>
  
  <p>Obviously the encryption inside the <code>RsaEncryptWithPrivate</code> uses the public key when encrypting, so I do not get why the two encryption methods are not functionally identical:</p>
  
  <pre><code>using Org.BouncyCastle.Crypto;
  using Org.BouncyCastle.Crypto.Encodings;
  using Org.BouncyCastle.Crypto.Engines;
  using Org.BouncyCastle.OpenSsl;
  
  public class EncryptionClass
  {       
      public string RsaEncryptWithPublic(string clearText
          , string publicKey)
      {
          var bytesToEncrypt = Encoding.UTF8.GetBytes(clearText);
  
          var encryptEngine = new Pkcs1Encoding(new RsaEngine());
  
          using (var txtreader = new StringReader(publicKey))
          {
              var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();
  
              encryptEngine.Init(true, keyParameter);
          }
  
          var encrypted = Convert.ToBase64String(encryptEngine.ProcessBlock(bytesToEncrypt, 0, bytesToEncrypt.Length));
          return encrypted;
  
      }
  
      public string RsaEncryptWithPrivate(string clearText
          , string privateKey)
      {
          var bytesToEncrypt = Encoding.UTF8.GetBytes(clearText);
  
          var encryptEngine = new Pkcs1Encoding(new RsaEngine());
  
          using (var txtreader = new StringReader(privateKey))
          {
              var keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject();
  
              encryptEngine.Init(true, keyPair.Public);
          }
  
          var encrypted= Convert.ToBase64String(encryptEngine.ProcessBlock(bytesToEncrypt, 0, bytesToEncrypt.Length));
          return encrypted;
      }
  
  
      // Decryption:
  
      public string RsaDecrypt(string base64Input
          , string privateKey)
      {
          var bytesToDecrypt = Convert.FromBase64String(base64Input);
  
          //get a stream from the string
          AsymmetricCipherKeyPair keyPair;
          var decryptEngine = new Pkcs1Encoding(new RsaEngine());
  
          using ( var txtreader = new StringReader(privateKey) )
          {
              keyPair = (AsymmetricCipherKeyPair) new PemReader(txtreader).ReadObject();
  
              decryptEngine.Init(false, keyPair.Private);
          }
  
          var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));
          return decrypted;
      }
  }
  
  // In my test project   
  
      [Test()]
      public void EncryptTest()
      {
          // Set up 
          var input = "Perceived determine departure explained no forfeited";
          var enc = new EncryptionClass();
          var publicKey = "-----BEGIN PUBLIC KEY----- // SNIPPED // -----END PUBLIC KEY-----";
          var privateKey = "-----BEGIN PRIVATE KEY----- // SNIPPED // -----END PRIVATE KEY-----";
  
          // Encrypt it
          var encryptedWithPublic = enc.RsaEncryptWithPublic(input, publicKey); 
  
          var encryptedWithPrivate = enc.RsaEncryptWithPrivate(input, privateKey);
  
          // Decrypt
          var outputWithPublic = payUEnc.RsaDecrypt(encryptedWithPrivate, privateKey); 
          // Throws error: "unknown block type"
  
          var outputWithPrivate = payUEnc.RsaDecrypt(encryptedWithPrivate, _privateKey); 
          // returns the correct decrypted text, "Perceived determine departure explained no forfeited"
  
          // Assertion
          Assert.AreEqual(outputWithPrivate, input); // This is true
      }
  </code></pre>
  
  <p>Incidentally the Java decryption exhibits the same issue - when encrypted with the public key only, it fails.</p>
  
  <p>I'm very new to cryptography, so I'm sure I'm doing something very simple wrong in the <code>RsaEncryptWithPublic</code> method.</p>
  
  <p>EDIT: </p>
  
  <p>I've also added a unit test which proves that the public key is equal to the public key that is extracted from the private key:</p>
  
  <pre><code>    [Test()]
      public void EncryptCompareTest()
      {
          AsymmetricKeyParameter keyParameterFromPub;
          AsymmetricKeyParameter keyParameterFromPriv;
          AsymmetricCipherKeyPair keyPair;
  
          using (var txtreader = new StringReader(_publicKey))
          {
              keyParameterFromPub = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject();
          }
  
          using (var txtreader = new StringReader(_privateKey))
          {
              keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject();
              keyParameterFromPriv = keyPair.Public;
          }
  
          Assert.AreEqual(keyParameterFromPub, keyParameterFromPriv); // returns true;
  
      } 
  </code></pre>