1

I'm developing a new version in c# of an existing java application.

The existing application uses RSA encryption with java.security.spec.* and boncycastle api.

I'm looking for equivalent code in c# for the java below code:

public static java.security.PublicKey getKey
(
org.bouncycastle.asn1.x509.RSAPublicKeyStructure  rsaPublicKey
)
{

java.security.KeyFactory keyFactory = KeyFactory.getInstance("RSA");

 java.security.spec.RSAPublicKeySpec keySpec = new RSAPublicKeySpec(
rsaPublicKey.getModulus(), 
rsaPublicKey.getPublicExponent());

java.security.PublicKey pkey = keyFactory.generatePublic(keySpec);

return pkey;
}

I "googled" a lot but don't found solution.

Thanks in advance for your help.

2 Answers2

2

Although you may be already aware of this, there is a .NET version of Bouncy Castle, so you can use it in your C# project.

Regarding your question, here is an example of implementing signing in pure Bouncy Castle, an it deals with key generation in the MakeKey method, so you may want to take a look at it.

By the way, if this key is in a certificate, you may want to look at the .NET X509Certificate2 class.

Edit

I tried to convert your method into a c# equivalent, and this it the closer I got:

public static byte[] getKey(Org.BouncyCastle.Asn1.x509.RSAPublicKeyStructure  rsaPublicKey)
{
    Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters bcKeySpec = new RsaKeyParameters();
    bcKeySpec.RsaKeyParameters(false, rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent());
    RSAParameters keySpec = Org.BouncyCastle.Security.DotNetUtilities.ToRSAParameters(bcKeySpec);
    RSACryptoServiceProvider keyFactory = new RSACryptoServiceProvider();
    keyFactory.ImportParameters(keySpec);
    byte[] pKey = keyFactory.ExportCspBlob(false);
    return pKey;
}

Note that the key is exported into a byte array, which depending of what you want to do with your key later, may or may not be helpful to you, also, the RSACryptoServiceProvider object let you encrypt, decrypt, sign and verify, so if you are going to get the key for any of these purposes, then you may want to return the keyFactory object instead of the exported public key.

If you want more information about RSACryptoServiceProvider you can read here: http://msdn.microsoft.com/en-us/library/s575f7e2.aspx

Community
  • 1
  • 1
Rafael
  • 2,827
  • 1
  • 16
  • 17
  • Hello Rafael, thank you for your answer. I'm using Boncycastle too. My question means : are there in C# api (or bouncycastle) equivalence for classes : java.security.KeyFactory and java.security.spec.RSAPublicKeySpec ? PS: The new C# version must support keys generated with old java version. thank u in advance. – Ibrahima Mouctar Diallo Apr 16 '13 at 09:10
  • Or Simply how to create a RSA public Key from given Modulus and Exponent in C# ? Is it possible ? Thanks for your help! – Ibrahima Mouctar Diallo Apr 16 '13 at 14:27
0
 public static string EncryptRsa(string stringPublicKey, string stringDataToEncrypt)
{
    byte[] publicKey = Convert.FromBase64String(stringPublicKey);
    using (RSACryptoServiceProvider rsa = DecodeX509PublicKey(publicKey))
    {
        byte[] dataToEncrypt = Encoding.UTF8.GetBytes(stringDataToEncrypt);
        byte[] encryptedData = rsa.Encrypt(dataToEncrypt, false);
        return Convert.ToBase64String(encryptedData);
    }
}

public static RSACryptoServiceProvider DecodeX509PublicKey(byte[] x509key)
{
    byte[] SeqOID = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };

    MemoryStream ms = new MemoryStream(x509key);
    BinaryReader reader = new BinaryReader(ms);

    if (reader.ReadByte() == 0x30)
        ReadASNLength(reader); //skip the size 
    else
        return null;

    int identifierSize = 0; //total length of Object Identifier section 
    if (reader.ReadByte() == 0x30)
        identifierSize = ReadASNLength(reader);
    else
        return null;

    if (reader.ReadByte() == 0x06) //is the next element an object identifier? 
    {
        int oidLength = ReadASNLength(reader);
        byte[] oidBytes = new byte[oidLength];
        reader.Read(oidBytes, 0, oidBytes.Length);
        if (oidBytes.SequenceEqual(SeqOID) == false) //is the object identifier rsaEncryption PKCS#1? 
            return null;

        int remainingBytes = identifierSize - 2 - oidBytes.Length;
        reader.ReadBytes(remainingBytes);
    }

    if (reader.ReadByte() == 0x03) //is the next element a bit string? 
    {
        ReadASNLength(reader); //skip the size 
        reader.ReadByte(); //skip unused bits indicator 
        if (reader.ReadByte() == 0x30)
        {
            ReadASNLength(reader); //skip the size 
            if (reader.ReadByte() == 0x02) //is it an integer? 
            {
                int modulusSize = ReadASNLength(reader);
                byte[] modulus = new byte[modulusSize];
                reader.Read(modulus, 0, modulus.Length);
                if (modulus[0] == 0x00) //strip off the first byte if it's 0 
                {
                    byte[] tempModulus = new byte[modulus.Length - 1];
                    Array.Copy(modulus, 1, tempModulus, 0, modulus.Length - 1);
                    modulus = tempModulus;
                }

                if (reader.ReadByte() == 0x02) //is it an integer? 
                {
                    int exponentSize = ReadASNLength(reader);
                    byte[] exponent = new byte[exponentSize];
                    reader.Read(exponent, 0, exponent.Length);

                    RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024);
                    RSAParameters RSAKeyInfo = new RSAParameters();
                    RSAKeyInfo.Modulus = modulus;
                    RSAKeyInfo.Exponent = exponent;
                    RSA.ImportParameters(RSAKeyInfo);
                    return RSA;
                }
            }
        }
    }
    return null;
}

public static int ReadASNLength(BinaryReader reader)
{
    //Note: this method only reads lengths up to 4 bytes long as 
    //this is satisfactory for the majority of situations. 
    int length = reader.ReadByte();
    if ((length & 0x00000080) == 0x00000080) //is the length greater than 1 byte 
    {
        int count = length & 0x0000000f;
        byte[] lengthBytes = new byte[4];
        reader.Read(lengthBytes, 4 - count, count);
        Array.Reverse(lengthBytes); // 
        length = BitConverter.ToInt32(lengthBytes, 0);
    }
    return length;
}
Jony Di
  • 1
  • 1
  • Welcome to SO! Code-only answers are discouraged here, as they provide no insight into how the problem was solved. Please update your answer to explain how your code solves the OP's problem :) – Joel Oct 04 '18 at 03:06