C# Net 使用 RSA 加密解密 OpenSSL 生成的密码
C# Net 使用 RSA 加密解密 OpenSSL 生成的密码
有时候回得到如下的公钥
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNwWw9Ae1b+hZmDbheF5Zel25i
D6tlta9.......
-----END PUBLIC KEY-----
或者私钥
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDNwWw9Ae1b+hZmDbheF5Zel25iD6tlta9nYDal2ex/Blsy9Utb
EKYoUrZjR.....
-----END RSA PRIVATE KEY-----
C#的RSA:
https://www.cnblogs.com/duanjt/p/11061380.html
RSA 的 OpenSSL 介绍:
https://www.codeproject.com/Articles/25487/Cryptographic-Interoperability-Keys
此博文参考文章:
https://www.cnblogs.com/lidj/p/5220816.html
在线测试RSA:
http://www.metools.info/code/c81.html
正式代码,我们使用下面的方式转换
using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace Ping.CryptologyHelp { /// <summary> /// RSA 密码(OpenSSL方式) /// </summary> public class RSAOpenSSLCryptology { /// <summary> /// 加密 /// </summary> /// <param name="text"></param> /// <returns></returns> public static string Encrypt(string text, string publicKey = null) { var _publicKeyRsaProvider = CreateRsaProviderFromPublicKey(publicKey); return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text), false)); } /// <summary> /// 解密 /// </summary> /// <param name="text"></param> /// <returns></returns> public static string Decrypt(string text, string privateKey = null) { var _privateKeyRsaProvider = CreateRsaProviderFromPrivateKey(privateKey); return Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(System.Convert.FromBase64String(text), false)); } private static RSACryptoServiceProvider CreateRsaProviderFromPublicKey(string publicKeyString) { // 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[] x509key; byte[] seq = new byte[15]; int x509size; x509key = Convert.FromBase64String(publicKeyString); x509size = x509key.Length; // --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------ using (MemoryStream mem = new MemoryStream(x509key)) { using (BinaryReader binr = new BinaryReader(mem)) //wrap Memory Stream with BinaryReader for easy reading { byte bt = 0; ushort twobytes = 0; 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); int firstbyte = binr.PeekChar(); 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); // ------- 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; } } } private static RSACryptoServiceProvider CreateRsaProviderFromPrivateKey(string privateKey) { var privateKeyBits = System.Convert.FromBase64String(privateKey); var RSA = new RSACryptoServiceProvider(); var RSAparams = new RSAParameters(); using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits))) { byte bt = 0; ushort twobytes = 0; twobytes = binr.ReadUInt16(); if (twobytes == 0x8130) binr.ReadByte(); else if (twobytes == 0x8230) binr.ReadInt16(); else throw new Exception("执行 binr.ReadUInt16() 失败"); twobytes = binr.ReadUInt16(); if (twobytes != 0x0102) throw new Exception("错误的版本"); bt = binr.ReadByte(); if (bt != 0x00) throw new Exception("执行 binr.ReadByte() 失败"); RSAparams.Modulus = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.Exponent = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.D = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.P = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.Q = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.DP = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.DQ = binr.ReadBytes(GetIntegerSize(binr)); RSAparams.InverseQ = binr.ReadBytes(GetIntegerSize(binr)); } RSA.ImportParameters(RSAparams); return RSA; } private static int GetIntegerSize(BinaryReader binr) { byte bt = 0; byte lowbyte = 0x00; byte highbyte = 0x00; int count = 0; bt = binr.ReadByte(); if (bt != 0x02) return 0; bt = binr.ReadByte(); if (bt == 0x81) count = binr.ReadByte(); else if (bt == 0x82) { highbyte = binr.ReadByte(); lowbyte = binr.ReadByte(); byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; count = BitConverter.ToInt32(modint, 0); } else { count = bt; } while (binr.ReadByte() == 0x00) { count -= 1; } binr.BaseStream.Seek(-1, SeekOrigin.Current); return count; } private static bool CompareBytearrays(byte[] a, byte[] b) { if (a.Length != b.Length) return false; int i = 0; foreach (byte c in a) { if (c != b[i]) return false; i++; } return true; } } }
调用方式如下:(需要去掉 -----BEGIN xxx KEY----- )
var aaa = RSAOpenSSLCryptology.Encrypt("", @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNwWw9Ae1b+hZmDbheF5Zel25i
D6tlta9.......");
如有问题请联系QQ:
var d=["1","2","3","4","5","6","7","8","9"];
var pass=d[8]+d[6]+d[0]+d[8]+d[2]+d[0]+d[4]+d[3]+d[2];
源代码(github)包(NuGet)关注:ping9719