问题
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.
回答1:
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
回答2:
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;
}
来源:https://stackoverflow.com/questions/16022062/c-sharp-equivalent-of-java-security-spec-rsapublickeyspec-and-java-security-p