Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/318.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#从pem格式解码公钥_C#_Python_Cryptography_Rsa_Pem - Fatal编程技术网

C#从pem格式解码公钥

C#从pem格式解码公钥,c#,python,cryptography,rsa,pem,C#,Python,Cryptography,Rsa,Pem,我写这段代码是为了解码我的公钥,但这段代码无法解码。我转换的base64公钥是Convert.fromBase64字符串(“MCgCIQCWeC4U3lLF7JCJePjZpK9rd1TOsqbT+/8TT++WL1KUFWIDAKAB)”这是DecodeX509PublicKey函数的输入。密钥由python rsa模块生成 python代码: pub, prv = rsa.newkeys(256) pub_pem = pub.save_pkcs1(format='PEM') pub_pem.

我写这段代码是为了解码我的公钥,但这段代码无法解码。我转换的base64公钥是
Convert.fromBase64字符串(“MCgCIQCWeC4U3lLF7JCJePjZpK9rd1TOsqbT+/8TT++WL1KUFWIDAKAB)”
这是
DecodeX509PublicKey
函数的输入。密钥由python rsa模块生成

python代码:

pub, prv = rsa.newkeys(256)
pub_pem = pub.save_pkcs1(format='PEM')
pub_pem.replace('-----BEGIN RSA PUBLIC KEY-----\n', '').replace('-----END RSA PUBLIC KEY-----\n', '')
C#代码:


为什么
DecodeX509PublicKey
函数无法解码公钥?

您已经创建了一个位大小为256位的测试公钥。那太小了,没用了。现在的问题是BER将长度编码为:

  • 如果值字段的大小小于128字节(仅为长度),则为1字节
  • 如果值字段的大小小于256字节(
    81 XX
    ,其中
    XX
    仅为无符号数字的长度,此处用十六进制表示)
  • 如果值字段的大小小于65536字节(
    82 XX-YY
    ,其中
    XX-YY
    是无符号、大端编码数字的长度,再次以十六进制表示)
当然,如果该值非常小,则长度的第一个字节不以
81
82
开头。请注意,例如,
84 00 00 XX YY
有时也具有有效的表示形式

有三种处理方法:

  • 实现模数的一字节长度(快速修复)
  • 仅测试1024位或更高的RSA密钥(始终是一个好主意)
  • 使用BER解码器,甚至是成熟的ASN.1库(也是一个好主意)

  • 就我个人而言,我会结合2。和3

    “不能解码公钥”是什么意思?会发生什么情况?函数在其第一个
    if else
    语句中返回null。建议通过库(如Bouncy Castle)进行PEM处理。我测试了第二种方法,但没有成功@Maarten-Bodewe可以是模和指数的符号或endian问题。通常我不会回答“未工作”错误描述。
    //------- Parses binary asn.1 X509 SubjectPublicKeyInfo; returns RSACryptoServiceProvider ---
        public static RSACryptoServiceProvider DecodeX509PublicKey(byte[] x509key)
        {
            // encoded OID sequence for  PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
            byte[] SeqOID = {0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00} ;
            byte[] seq = new byte[15];
            // ---------  Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob  ------
            MemoryStream  mem = new MemoryStream(x509key) ;
            BinaryReader binr = new BinaryReader(mem) ;    //wrap Memory Stream with BinaryReader for easy reading
            byte bt = 0;
            ushort twobytes = 0;
    
            try{
    
                twobytes = binr.ReadUInt16();
                if(twobytes == 0x8130)  //data read as little endian order (actual data order for Sequence is 30 81)
                    binr.ReadByte();    //advance 1 byte
                else if(twobytes == 0x8230)
                    binr.ReadInt16();   //advance 2 bytes
                else
                    return null;
                seq = binr.ReadBytes(15);       //read the Sequence OID
                if(!CompareBytearrays(seq, SeqOID)) //make sure Sequence for OID is correct
                    return null;
    
                twobytes = binr.ReadUInt16();
                if(twobytes == 0x8103)  //data read as little endian order (actual data order for Bit String is 03 81)
                    binr.ReadByte();    //advance 1 byte
                else if(twobytes == 0x8203)
                    binr.ReadInt16();   //advance 2 bytes
                else
                    return null;
    
                bt = binr.ReadByte();
                if(bt != 0x00)      //expect null byte next
                    return null;
    
                twobytes = binr.ReadUInt16();
                if(twobytes == 0x8130)  //data read as little endian order (actual data order for Sequence is 30 81)
                    binr.ReadByte();    //advance 1 byte
                else if(twobytes == 0x8230)
                    binr.ReadInt16();   //advance 2 bytes
                else
                    return null;
    
                twobytes = binr.ReadUInt16();
                byte lowbyte = 0x00;
                byte highbyte = 0x00;
    
                if(twobytes == 0x8102)  //data read as little endian order (actual data order for Integer is 02 81)
                    lowbyte = binr.ReadByte();  // read next bytes which is bytes in modulus
                else if(twobytes == 0x8202) {
                    highbyte = binr.ReadByte(); //advance 2 bytes
                    lowbyte = binr.ReadByte();
                }
                else
                    return null;
                byte[] modint = {lowbyte, highbyte, 0x00, 0x00} ;   //reverse byte order since asn.1 key uses big endian order
                int modsize = BitConverter.ToInt32(modint, 0) ;
    
                byte firstbyte = binr.ReadByte();
                binr.BaseStream.Seek(-1, SeekOrigin.Current);
    
                if(firstbyte == 0x00)   {   //if first byte (highest order) of modulus is zero, don't include it
                    binr.ReadByte();    //skip this null byte
                    modsize -=1  ;  //reduce modulus buffer size by 1
                }
    
                byte[] modulus = binr.ReadBytes(modsize);   //read the modulus bytes
    
                if(binr.ReadByte() != 0x02)         //expect an Integer for the exponent data
                    return null;
                int expbytes = (int) binr.ReadByte() ;      // should only need one byte for actual exponent data (for all useful values)
                byte[] exponent = binr.ReadBytes(expbytes);
    
    
                //Console.WriteLine("\nExponent", exponent);
                //Console.WriteLine("\nModulus", modulus) ;    
    
                // ------- create RSACryptoServiceProvider instance and initialize with public key -----
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                RSAParameters RSAKeyInfo = new RSAParameters();
                RSAKeyInfo.Modulus = modulus;
                RSAKeyInfo.Exponent = exponent;
                RSA.ImportParameters(RSAKeyInfo);
                return RSA;
            }
            catch(Exception){
                return null; 
            }
    
            finally { binr.Close(); }
    
        }