static void RSATest() { var rsa = new RSA(512); Console.WriteLine("【" + rsa.KeySize + "私钥(XML)】:"); Console.WriteLine(rsa.ToXML()); Console.WriteLine(); Console.WriteLine("【" + rsa.KeySize + "私钥(PEM)】:"); Console.WriteLine(rsa.ToPEM_PKCS1()); Console.WriteLine(); Console.WriteLine("【" + rsa.KeySize + "公钥(PEM)】:"); Console.WriteLine(rsa.ToPEM_PKCS1(true)); Console.WriteLine(); var str = "abc内容123"; var en = rsa.Encode(str); Console.WriteLine("【加密】:"); Console.WriteLine(en); Console.WriteLine("【解密】:"); Console.WriteLine(rsa.DecodeOrNull(en)); Console.WriteLine("【签名SHA1】:"); Console.WriteLine(rsa.Sign("SHA1", str)); Console.WriteLine(); var rsa2 = new RSA(rsa.ToPEM_PKCS8(), true); Console.WriteLine("【用PEM新创建的RSA是否和上面的一致】:"); Console.WriteLine("XML:" + (rsa2.ToXML() == rsa.ToXML())); Console.WriteLine("PKCS1:" + (rsa2.ToPEM_PKCS1() == rsa.ToPEM_PKCS1())); Console.WriteLine("PKCS8:" + (rsa2.ToPEM_PKCS8() == rsa.ToPEM_PKCS8())); var rsa3 = new RSA(rsa.ToXML()); Console.WriteLine("【用XML新创建的RSA是否和上面的一致】:"); Console.WriteLine("XML:" + (rsa3.ToXML() == rsa.ToXML())); Console.WriteLine("PKCS1:" + (rsa3.ToPEM_PKCS1() == rsa.ToPEM_PKCS1())); Console.WriteLine("PKCS8:" + (rsa3.ToPEM_PKCS8() == rsa.ToPEM_PKCS8())); //--------RSA_PEM验证--------- RSA_PEM pem = rsa.ToPEM(); Console.WriteLine("【RSA_PEM是否和原始RSA一致】:"); Console.WriteLine(pem.KeySize + "位"); Console.WriteLine("XML:" + (pem.ToXML(false) == rsa.ToXML())); Console.WriteLine("PKCS1:" + (pem.ToPEM(false, false) == rsa.ToPEM_PKCS1())); Console.WriteLine("PKCS8:" + (pem.ToPEM(false, true) == rsa.ToPEM_PKCS8())); Console.WriteLine("仅公钥:"); Console.WriteLine("XML:" + (pem.ToXML(true) == rsa.ToXML(true))); Console.WriteLine("PKCS1:" + (pem.ToPEM(true, false) == rsa.ToPEM_PKCS1(true))); Console.WriteLine("PKCS8:" + (pem.ToPEM(true, true) == rsa.ToPEM_PKCS8(true))); var rsa4 = new RSA(new RSA_PEM(pem.Key_Modulus, pem.Key_Exponent, pem.Key_D)); Console.WriteLine("【用n、e、d构造解密】"); Console.WriteLine(rsa4.DecodeOrNull(en)); }
/// <summary> /// 将XML格式密钥转成PEM,支持公钥xml、私钥xml /// 出错将会抛出异常 /// </summary> static public RSA_PEM FromXML(string xml) { RSA_PEM rtv = new RSA_PEM(); Match xmlM = xmlExp.Match(xml); if (!xmlM.Success) { throw new Exception("XML内容不符合要求"); } Match tagM = xmlTagExp.Match(xmlM.Groups[1].Value); while (tagM.Success) { string tag = tagM.Groups[1].Value; string b64 = tagM.Groups[2].Value; byte[] val = Convert.FromBase64String(b64); switch (tag) { case "Modulus": rtv.Key_Modulus = val; break; case "Exponent": rtv.Key_Exponent = val; break; case "D": rtv.Key_D = val; break; case "P": rtv.Val_P = val; break; case "Q": rtv.Val_Q = val; break; case "DP": rtv.Val_DP = val; break; case "DQ": rtv.Val_DQ = val; break; case "InverseQ": rtv.Val_InverseQ = val; break; } tagM = tagM.NextMatch(); } if (rtv.Key_Modulus == null || rtv.Key_Exponent == null) { throw new Exception("XML公钥丢失"); } if (rtv.Key_D != null) { if (rtv.Val_P == null || rtv.Val_Q == null || rtv.Val_DP == null || rtv.Val_DQ == null || rtv.Val_InverseQ == null) { return(new RSA_PEM(rtv.Key_Modulus, rtv.Key_Exponent, rtv.Key_D)); } } return(rtv); }
/// <summary> /// 通过一个pem对象创建RSA,pem为公钥或私钥,出错抛异常 /// </summary> public RSA(RSA_PEM pem) { rsa = pem.GetRSA(); }
/// <summary> /// 通过一个pem文件创建RSA,pem为公钥或私钥,出错抛异常 /// </summary> public RSA(string pem, bool noop) { rsa = RSA_PEM.FromPEM(pem).GetRSA(); }
/// <summary> /// 用PEM格式密钥对创建RSA,支持PKCS#1、PKCS#8格式的PEM /// 出错将会抛出异常 /// </summary> static public RSA_PEM FromPEM(string pem) { RSA_PEM param = new RSA_PEM(); var base64 = _PEMCode.Replace(pem, ""); byte[] data = null; try { data = Convert.FromBase64String(base64); } catch { } if (data == null) { throw new Exception("PEM内容无效"); } var idx = 0; //读取长度 Func <byte, int> readLen = (first) => { if (data[idx] == first) { idx++; if (data[idx] == 0x81) { idx++; return(data[idx++]); } else if (data[idx] == 0x82) { idx++; return((((int)data[idx++]) << 8) + data[idx++]); } else if (data[idx] < 0x80) { return(data[idx++]); } } throw new Exception("PEM未能提取到数据"); }; //读取块数据 Func <byte[]> readBlock = () => { var len = readLen(0x02); if (data[idx] == 0x00) { idx++; len--; } var val = new byte[len]; for (var i = 0; i < len; i++) { val[i] = data[idx + i]; } idx += len; return(val); }; //比较data从idx位置开始是否是byts内容 Func <byte[], bool> eq = (byts) => { for (var i = 0; i < byts.Length; i++, idx++) { if (idx >= data.Length) { return(false); } if (byts[i] != data[idx]) { return(false); } } return(true); }; if (pem.Contains("PUBLIC KEY")) { /****使用公钥****/ //读取数据总长度 readLen(0x30); //检测PKCS8 var idx2 = idx; if (eq(_SeqOID)) { //读取1长度 readLen(0x03); idx++; //跳过0x00 //读取2长度 readLen(0x30); } else { idx = idx2; } //Modulus param.Key_Modulus = readBlock(); //Exponent param.Key_Exponent = readBlock(); } else if (pem.Contains("PRIVATE KEY")) { /****使用私钥****/ //读取数据总长度 readLen(0x30); //读取版本号 if (!eq(_Ver)) { throw new Exception("PEM未知版本"); } //检测PKCS8 var idx2 = idx; if (eq(_SeqOID)) { //读取1长度 readLen(0x04); //读取2长度 readLen(0x30); //读取版本号 if (!eq(_Ver)) { throw new Exception("PEM版本无效"); } } else { idx = idx2; } //读取数据 param.Key_Modulus = readBlock(); param.Key_Exponent = readBlock(); int keyLen = param.Key_Modulus.Length; param.Key_D = BigL(readBlock(), keyLen); keyLen = keyLen / 2; param.Val_P = BigL(readBlock(), keyLen); param.Val_Q = BigL(readBlock(), keyLen); param.Val_DP = BigL(readBlock(), keyLen); param.Val_DQ = BigL(readBlock(), keyLen); param.Val_InverseQ = BigL(readBlock(), keyLen); } else { throw new Exception("pem需要BEGIN END标头"); } return(param); }