如何从id_rsa.pub文件导入公钥以使用RSACryptoServiceProvider加密
错误原因
ImportSubjectPublicKeyInfo方法仅支持X.509标准的SubjectPublicKeyInfo格式公钥,而ssh-keygen生成的id_rsa.pub属于OpenSSH自定义公钥格式,二者结构不兼容,因此会抛出ASN1 corrupted data错误。
解决方案
方案1:公钥格式转换(操作最简单)
不需要修改代码,只需要把OpenSSH格式的公钥转成X.509格式即可:
- 打开Git Bash或者WSL终端,进入id_rsa.pub所在目录
- 执行转换命令:
ssh-keygen -f id_rsa.pub -e -m pkcs8 > pub.pem - 打开生成的pub.pem文件,删除首尾的
-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----标记,剩余的Base64内容即可直接用于公钥导入
导入示例代码:
// 替换为pub.pem中提取的Base64公钥内容 var rsaPublicKey = @"转换后的Base64公钥内容"; using var rsa = new RSACryptoServiceProvider(); rsa.ImportSubjectPublicKeyInfo(Convert.FromBase64String(rsaPublicKey), out _); // 加密示例 var rawData = System.Text.Encoding.UTF8.GetBytes("待加密的消息"); var encryptedData = rsa.Encrypt(rawData, System.Security.Cryptography.RSAEncryptionPadding.OaepSHA256);
方案2:代码直接解析OpenSSH公钥(无需额外转换)
如果不想手动转换格式,可以直接在代码中解析OpenSSH公钥的Base64内容,提取RSA参数后导入:
// 填写id_rsa.pub中去掉ssh-rsa前缀和结尾用户名注释的Base64部分 var sshRsaBase64 = @"AAAAB3NzaC1yc2EAAAADAQABAAABgQC17+CDVUZ4dGFmHsuCcPiH8mmKg6ysyKj54sgtNaLjkQXeC94HEfCfLiULDqqY462ImfnALWbGf3/zwSxC7/xH9Ak/oZnsOxZ07iDVFEuuGmujNvcOPjNKW1MQC0Qka/FjxhVxTCqOYUjY8iOYZ5aAxdKkRYMCwDxa4BPCsEVDyEfksxmRT28yaACucbaHk6IrAWRAMozXB6JuonyJ68wbUUZ5hjjuZLmvB1EOOD6ue5A96bo1a/zGOAtVPU8HmZIPAxxQp7fAwNPcY3RMS/ytwqw+39ve7oLCaKvkmbnNrn55IhWBV8MwpE8Sl2UV33T/anzoBAFh6XCi3WrGPtTbIA9vmW6WuCtTGKbQPSdYvy6b06hiqBiQQ3V1xQOtG6WqsaOWv5DgPoO8Z/1ajHWbJqy9tKJsVBDAwdG+3H3pZ4j8N2Qo1ZDE3vMRvvSsidxUpfrfxmH5XKl2Xx4jARBculflfShCsqo9xnWN0/YJfZeFPCIdy1R6Rn36jAl1FpE="; var pubBytes = Convert.FromBase64String(sshRsaBase64); using var ms = new MemoryStream(pubBytes); using var reader = new BinaryReader(ms); // 读取公钥类型校验 var typeLen = ReadBigEndianInt32(reader); var pubType = System.Text.Encoding.ASCII.GetString(reader.ReadBytes(typeLen)); if (pubType != "ssh-rsa") throw new InvalidOperationException("非RSA类型SSH公钥"); // 读取公钥指数 var expLen = ReadBigEndianInt32(reader); var exponent = reader.ReadBytes(expLen); // 读取模数 var modLen = ReadBigEndianInt32(reader); var modulus = reader.ReadBytes(modLen); // 导入RSA参数 using var rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(new RSAParameters { Modulus = modulus.Skip(1).ToArray(), // 跳过前导填充0 Exponent = exponent }); // 后续直接调用加密方法即可 // 辅助方法:读取大端序32位整数 static int ReadBigEndianInt32(BinaryReader reader) { var bytes = reader.ReadBytes(4); if (BitConverter.IsLittleEndian) Array.Reverse(bytes); return BitConverter.ToInt32(bytes, 0); }
注意事项
- 加密时建议使用
RSAEncryptionPadding.OaepSHA256等高安全性填充方式,不推荐使用过时的Pkcs1填充 - 跨端解密时需保证两端填充算法完全一致
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

