【问题标题】:c# equivalent of "java.security.spec.RSAPublicKeySpec" and "java.security.PublicKey"c# 等效于“java.security.spec.RSAPublicKeySpec”和“java.security.PublicKey”
【发布时间】:2018-10-04 10:35:52
【问题描述】:

我正在用 C# 开发现有 java 应用程序的新版本。

现有应用程序使用带有 java.security.spec.* 和 boncycastle api 的 RSA 加密。

我正在为下面的 java 代码寻找 c# 中的等效代码:

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;
}

我“谷歌”了很多,但没有找到解决方案。

提前感谢您的帮助。

【问题讨论】:

    标签: c# java encryption rsa


    【解决方案1】:

    尽管您可能已经意识到这一点,但有一个 .NET 版本的 Bouncy Castle,因此您可以在您的 C# 项目中使用它。

    关于您的问题,here 是在纯 Bouncy Castle 中实现签名的示例,它处理 MakeKey 方法中的密钥生成,因此您可能想看看它。

    顺便说一句,如果此密钥在证书中,您可能需要查看 .NET X509Certificate2 类。

    编辑

    我试图将您的方法转换为等效的 c# 方法,结果越接近:

    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;
    }
    

    请注意,密钥被导出到一个字节数组中,这取决于您以后想要对您的密钥做什么,可能对您有帮助也可能没有帮助,此外,RSACryptoServiceProvider 对象允许您加密、解密、签名和验证,因此,如果您要为任何这些目的获取密钥,那么您可能希望返回 keyFactory 对象而不是导出的公钥。

    如果您想了解更多关于 RSACryptoServiceProvider 的信息,您可以在此处阅读:http://msdn.microsoft.com/en-us/library/s575f7e2.aspx

    【讨论】:

    • 你好拉斐尔,谢谢你的回答。我也在使用 Boncycastle。我的问题是:在 C# api(或 bouncycastle)中是否有类的等价性:java.security.KeyFactory 和 java.security.spec.RSAPublicKeySpec? PS:新的 C# 版本必须支持用旧的 java 版本生成的密钥。提前谢谢你。
    • 或者只是如何从 C# 中给定的模数和指数创建 RSA 公钥?可能吗 ?感谢您的帮助!
    【解决方案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;
    }
    

    【讨论】:

    • 欢迎来到 SO!此处不鼓励仅使用代码的答案,因为它们无法深入了解问题是如何解决的。请更新您的答案以解释您的代码如何解决 OP 的问题 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    相关资源
    最近更新 更多