RSA读取PublicKey [英] RSA read PublicKey

查看:223
本文介绍了RSA读取PublicKey的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用带有算法 RSA 的java生成公钥,并且能够使用以下代码重建:

I have public key generated using java with algorithm RSA and able to reconstruct using following code:

X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(arrBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
publicKey = keyFactory.generatePublic(pubKeySpec);

问题
如何使用csharp在dotnet端构建PublicKey ?

QUESTION How to construct PublicKey on dotnet side using csharp?

示例公钥将是:,在上面的代码中,我传递元素中包含的数据编码

sample public key would be:, In above code i pass data contained in element encoded

    <sun.security.rsa.RSAPublicKeyImpl resolves-to="java.security.KeyRep">
    <type>PUBLIC</type>
    <algorithm>RSA</algorithm>
    <format>X.509</format>
    <encoded>MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMf54mcK3EYJn9tT9BhRoTX+8AkqojIyeSfog9ncYEye
0VXyBULGg2lAQsDRt8lZsvPioORZW7eB6IKawshoWUsCAwEAAQ==</encoded>
    </sun.security.rsa.RSAPublicKeyImpl>


推荐答案

不幸的是,C#没有提供任何简单的方法做这个。但这将正确解码x509公钥(确保首先解码x509key参数):

Unfortunately, C# doesn't provide any simple way to do this. But this will correctly decode an x509 public key (make sure to Base64 decode the x509key parameter first):

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

以上代码基于这个问题(仅适用于某些密钥大小)。上面的代码几乎适用于任何RSA密钥大小,并且已经使用您提供的密钥以及2048位和4096位密钥进行了测试。

The above code is based off of this question (which only worked for certain key sizes). The above code will work for pretty much any RSA key size though, and has been tested with the key you provided as well as 2048-bit and 4096-bit keys.

另一种解决方案是使用工具生成证书( XCA 是一个很好的),导出将证书发送到p12(PKCS12)文件,然后在Java和C#中加载证书以获取密钥。

An alternative solution would be to generate a certificate using a tool (XCA is a good one), export the cert to a p12 (PKCS12) file and then load the cert in both Java and C# to get at the keys.

在C#中,您可以使用<加载PKCS12文件code> X509Certificate2 class。

In C# you can load a PKCS12 file using the X509Certificate2 class.

X509Certificate2 cert = new X509Certificate2(certificateFile, certificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
RSACryptoServiceProvider provider1 = (RSACryptoServiceProvider)cert.PublicKey.Key;
RSACryptoServiceProvider provider2 = (RSACryptoServiceProvider)cert.PrivateKey;

在Java中,您可以使用 KeyStore class。

In Java you can load a PKCS12 file using the KeyStore class.

KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(new FileInputStream(certificateFile), certificatePassword.toCharArray());
Key key = keystore.getKey(certName, certificatePassword.toCharArray());
Certificate cert = keystore.getCertificate(certName);
PublicKey publicKey = cert.getPublicKey();
KeyPair keys = new KeyPair(publicKey, (PrivateKey) key);

这篇关于RSA读取PublicKey的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆