C#从pem格式解码公钥
我写这段代码是为了解码我的公钥,但这段代码无法解码。我转换的base64公钥是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.
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
有时也具有有效的表示形式
有三种处理方法:
就我个人而言,我会结合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(); }
}