1

There are examples on the web on how to use bouncy castle library in Java to encrypt with RSA/ECB/OAEPWithSHA256AndMGF1Padding (Example is shown at breaking down RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING). However the bouncy castle library in C# seem to have deviated from Java library in that it is more explicit (hence requires more steps) and I am not able to figure out how to make it work for the above algorithm.

Would appreciate if some body can put a code sample together to encrypt a sample text using RSA/ECB/OAEPWithSHA256AndMGF1Padding.

Robert
  • 39,162
  • 17
  • 99
  • 152
Raghu
  • 2,859
  • 4
  • 33
  • 65

1 Answers1

1

Unfortunately, even the Java construct is ambiguous as it's open to different and incompatible interpretations, as is shown here. The Java Bouncycastle provider will do one thing with "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" and the Oracle provider will do a different thing.

You can and should specify exactly which behavior you want in both the Java and C# code.

C#:

using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.OpenSsl;

namespace ScratchPad
{
    class MainClass
    {
        public static void OaepEncryptExample()
        {
            var plain = Encoding.UTF8.GetBytes("The sun also rises.");
            // Read in public key from file
            var pemReader = new PemReader(File.OpenText(@"/Users/horton/tmp/key-examples/myserver_pub.pem"));
            var rsaPub = (Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters)pemReader.ReadObject();
            // create encrypter
            var encrypter = new OaepEncoding(new RsaEngine(), new Sha256Digest(), new Sha256Digest(), null);
            encrypter.Init(true, rsaPub);
            var cipher = encrypter.ProcessBlock(plain, 0, plain.Length);
            Console.WriteLine(Convert.ToBase64String(cipher));
        }
    }
}

Java:

import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.PEMParser;

import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.io.FileReader;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

public class OaepExample {
    public static void oeapDecrypt() throws Exception {
        final PEMParser pemParser = new PEMParser(new FileReader("/Users/horton/tmp/key-examples/myserver.p8"));
        final PrivateKeyInfo privKey = (PrivateKeyInfo) pemParser.readObject();
        KeyFactory kf = KeyFactory.getInstance("RSA");
        RSAPrivateKey rsaPriv = (RSAPrivateKey) kf.generatePrivate(new PKCS8EncodedKeySpec(privKey.getEncoded()));
        String cipher64 = "k8AYnTV6RgzQXmD7qn8QwucDXGjbYct+qMVvDmMELTnUcCOeTp82oJ0BryZyEEGXVSZ2BFg95e72Jt9ZAKWNcot2rZ0+POcda8pzY/MfdwIpnSJKITovk8xHL3B/jZDJyQrLMmNPjVV/uBFY2vgKhhLhJzzAJATcGpNdw+gF+XI=";
        Cipher decrypter = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        OAEPParameterSpec parameterSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256,
                PSource.PSpecified.DEFAULT);
        decrypter.init(Cipher.DECRYPT_MODE, rsaPriv, parameterSpec);
        final byte[] plain = decrypter.doFinal(Base64.getDecoder().decode(cipher64));
        System.out.println(new String(plain, StandardCharsets.UTF_8));

    }
}
President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
  • James: Unfortunately there is no ReadObject method on the PemReader class any more. That is where I was stuck. – Raghu Jun 07 '19 at 16:15
  • James: Why would you pass "new Sha256Digest()" for IDigest mgf1Hash argument in OaepEncoding constructor? If some one uses the same arguments to OaepEncoding (as you have shown) and produces encrypted bytes, would I be able to decrypt those bytes by using same arguments (assuming I substitute public key for private key)? Or I do need to do anything else? – Raghu Jun 07 '19 at 22:33
  • It's an example, you can pass whatever you think is appropriate. SHA-256 is good choice. – President James K. Polk Jun 07 '19 at 22:56