Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C中X509EncodedKeySpec的等价物是什么#_C#_.net_Encryption_Jwt_X509certificate2 - Fatal编程技术网

C# C中X509EncodedKeySpec的等价物是什么#

C# C中X509EncodedKeySpec的等价物是什么#,c#,.net,encryption,jwt,x509certificate2,C#,.net,Encryption,Jwt,X509certificate2,我正在尝试将一段Java代码移植到.NET中,该代码采用Base64编码的字符串,将其转换为字节数组,然后使用它生成一个X.509证书,以获取RSA加密的模数和指数。 这是我试图转换的Java代码: byte[] externalPublicKey = Base64.decode("base 64 encoded string"); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); EncodedKeySpec publicKeySpe

我正在尝试将一段Java代码移植到.NET中,该代码采用Base64编码的字符串,将其转换为字节数组,然后使用它生成一个X.509证书,以获取RSA加密的模数和指数。 这是我试图转换的Java代码:

byte[] externalPublicKey = Base64.decode("base 64 encoded string");
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(externalPublicKey);
Key publicKey = keyFactory.generatePublic(publicKeySpec);
RSAPublicKey pbrtk = (java.security.interfaces.RSAPublicKey) publicKey;
BigInteger modulus = pbrtk.getModulus();
BigInteger pubExp = pbrtk.getPublicExponent();
我一直在试图找出将其转换为.NET的最佳方法。到目前为止,我已经想到了这个:

byte[] bytes = Convert.FromBase64String("base 64 encoded string");
X509Certificate2 x509 = new X509Certificate2(bytes);
RSA rsa = (RSA)x509.PrivateKey;
RSAParameters rsaParams = rsa.ExportParameters(false);
byte[] modulus = rsaParams.Modulus;
byte[] exponent = rsaParams.Exponent;
在我看来,它应该可以工作,但当我使用Java代码中的base 64编码字符串生成X509证书时,它抛出了一个加密异常。我收到的确切信息是:

找不到请求的对象


是Java的X.509实现与.NET不兼容,还是我在从Java到.NET的转换过程中出错了?

在.NET Core 3.0及以上版本中,有一种直接导入这些密钥的方法

代码如下:

var bytes = Convert.FromBase64String("encoded key");
var rsa = RSA.Create();
rsa.ImportSubjectPublicKeyInfo(bytes, out _);
var rsaParams = rsa.ExportParameters(false);
例如

            var subjectPublicKeyInfo = new SubjectPublicKeyInfo(your bytes);
            var publicKey = subjectPublicKeyInfo.GetPublicKey();

            using (var rsa = new RSACryptoServiceProvider())
            {
                RSAParameters parameters = new RSAParameters()
                {
                    Modulus = publicKey.Item1,
                    Exponent = publicKey.Item2
                };
                rsa.ImportParameters(parameters);
                /*
                do something
                */
            }
类主题PublicKeyInfo和类顺序


        /// <summary>
        /// DER解析
        /// </summary>
        public class DER : IDisposable
        {
            private bool disposedValue;
            private BinaryReader reader;

            public DER(byte[] bytes)
            {
                MemoryStream stream = new MemoryStream(bytes);
                reader = new BinaryReader(stream);
            }

            public bool CanRead => reader.BaseStream.Position < reader.BaseStream.Length;

            private ValueType ReadType()
            {
                return (ValueType)reader.ReadByte();
            }

            private int ReadLength()
            {
                int length = reader.ReadByte();

                //检查第7位是否是1,如果是,则指示该内容长度大于127字节,则此字节6-0为实际的内容占用的字节
                if ((length & 0b10000000) == 0b10000000)
                {
                    //获取长度字节的长度
                    int count = length & 0b01111111;
                    byte[] bytes = new byte[count];

                    //指向内容的长度
                    reader.Read(bytes, 0, bytes.Length);

                    //翻转顺序
                    Array.Reverse(bytes);
                    length = LengthBytesToInt(bytes);
                }

                return length;
            }

            /// <summary>
            /// 根据文档显示,长度不应该超过 256^126 ,即两个字节
            /// </summary>
            /// <param name="lengthBytes"></param>
            /// <returns></returns>
            private int LengthBytesToInt(byte[] lengthBytes)
            {
                if (lengthBytes.Length > 2)
                    throw new ArgumentOutOfRangeException($"length {lengthBytes.Length} too big.");
                int value = 0;
                for (int i = 0; i < lengthBytes.Length; i++)
                {
                    value = (value << 8) | lengthBytes[i];
                }
                return value;
            }

            public ValueTuple<ValueType, byte[]> ReadValue()
            {
                ValueType type = ReadType();
                byte[] value = new byte[ReadLength()];
                reader.Read(value, 0, value.Length);
                ValueTuple<ValueType, byte[]> wrapper = new ValueTuple<ValueType, byte[]>(type, value);
                return wrapper;
            }

            public enum ValueType
            {
                BOOLEAN = 0x01,
                INTEGER = 0x02,
                BIT_STRING = 0x03,
                OCTET_STRING = 0x04,
                NULL = 0x05,
                OBJECT_IDENTIFIER = 0x06,
                UTF8String = 0x0c,
                PrintableString = 0x13,
                TeletexString = 0x14,
                IA5String = 0x16,
                BMPString = 0x1e,
                SEQUENCE = 0x30,
                SET = 0x31
            }

            protected virtual void Dispose(bool disposing)
            {
                if (!disposedValue)
                {
                    if (disposing)
                    {
                        reader.Dispose();
                    }
                    disposedValue = true;
                }
            }

            public void Dispose()
            {
                Dispose(disposing: true);
                GC.SuppressFinalize(this);
            }
        }

        /// <summary>
        /// 兼容 Java X.509 SubjectPublicKeyInfo DER
        /// </summary>
        public class SubjectPublicKeyInfo
        {
            private DER der;
            private readonly byte[] RSA_OID = new byte[] { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };

            public SubjectPublicKeyInfo(byte[] derBytes)
            {
                der = new DER(derBytes);
            } 

            /// <summary>
            /// 获取公钥
            /// </summary>
            /// <returns>modulus and exponent 返回模数和指数</returns>
            public ValueTuple<byte[], byte[]> GetPublicKey()
            {
                //获取主序列
                var wrapper1 = der.ReadValue();
                if (wrapper1.Item1 != DER.ValueType.SEQUENCE)
                {
                    throw new InvalidDataException();
                }
                var sequence1 = new DER(wrapper1.Item2);
                var wrapper2 = sequence1.ReadValue();

                //检查第一个结构体是否存在
                if (wrapper2.Item1 != DER.ValueType.SEQUENCE)
                {
                    throw new InvalidDataException();
                }

                var sequence2 = new DER(wrapper2.Item2);
                var wrapper3 = sequence2.ReadValue();
                if (wrapper3.Item1 != DER.ValueType.OBJECT_IDENTIFIER)
                {
                    throw new InvalidDataException();
                }

                if (Enumerable.SequenceEqual(wrapper3.Item2, RSA_OID) == false)
                {
                    throw new InvalidDataException();
                }

                var wrapper4 = sequence1.ReadValue();
                if (wrapper4.Item2.First() != 0x00)
                {
                    throw new InvalidDataException();
                }

                //这里有个不明意义的0x00
                var sequence3 = new DER(wrapper4.Item2.Skip(1).ToArray());
                var wrapper5 = sequence3.ReadValue();
                if (wrapper5.Item1 != DER.ValueType.SEQUENCE)
                {
                    throw new InvalidDataException();
                }

                var sequence4 = new DER(wrapper5.Item2);
                var wrapper6 = sequence4.ReadValue();
                if (wrapper6.Item1 != DER.ValueType.INTEGER)
                {
                    throw new InvalidDataException();
                }
                var integer1 = wrapper6.Item2.First() == 0x00 ? wrapper6.Item2.Skip(1).ToArray() : wrapper6.Item2;

                var wrapper7 = sequence4.ReadValue();
                if (wrapper7.Item1 != DER.ValueType.INTEGER)
                {
                    throw new InvalidDataException();
                }

                var integer2 = wrapper7.Item2;

                return new ValueTuple<byte[], byte[]>(integer1, integer2);
            }
        }

/// 
///德解析
/// 
公共类:IDisposable
{
私人财产处置价值;
私有二进制读取器;
公共顺序(字节[]字节)
{
MemoryStream stream=新的MemoryStream(字节);
读卡器=新的二进制读卡器(流);
}
public bool CanRead=>reader.BaseStream.Position2)
抛出新ArgumentOutOfRangeException($“长度{lengthBytes.length}太大。”);
int值=0;
for(int i=0;i值=(您是否尝试过X509Certificate2.ImportData?检查您是否有SubjectPublicKeyInfo,而不是整个证书。.NET没有收件箱API来直接读取这些内容。Java和.NET支持不同的标准。Java的X509EncodedKeySpec实际上是X.509标准中的SubjectPublicKeyInfo对象。.NET支持用于交换p的XML标准公钥和私钥。在我看来,编写Java代码以导出此XML格式的公钥要比编写C#/.NET代码以导入SubjectPublicKeyInfo容易得多。请参阅导出此格式私钥的示例答案。您可以通过删除所有私钥组件来修改公钥。