/// <summary> /// 验签 /// </summary> /// <param name="data">签名前的数据</param> /// <param name="publickey">公钥</param> /// <param name="sign">签名</param> /// <param name="encoding"></param> /// <returns></returns> public static bool rsaCheck(string data, string publickey, string sign, string encoding = "UTF-8") { byte[] bt = Encoding.GetEncoding(encoding).GetBytes(data); byte[] bt2 = Convert.FromBase64String(sign); RSA_PEM pem = RSA_PEM.FromPEM(publickey); using (RSACryptoServiceProvider provider = pem.GetRSA()) { return(provider.VerifyData(bt, CryptoConfig.MapNameToOID("SHA256"), bt2)); } }
/// <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> /// 签名 /// </summary> /// <param name="str">需签名的数据</param> /// <param name="privateKey">私钥</param> /// <param name="encoding">编码格式 默认utf-8</param> /// <returns></returns> public static string Signature(string str, string privateKey, string encoding = "UTF-8") { byte[] bt = Encoding.GetEncoding(encoding).GetBytes(str); RSA_PEM pem = RSA_PEM.FromPEM(privateKey); using (RSACryptoServiceProvider provider = pem.GetRSA()) { byte[] inArray = provider.SignData(bt, CryptoConfig.MapNameToOID("SHA256")); string sign = Convert.ToBase64String(inArray); return(sign); } }
/// <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); //看看有没有oid 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(); param.Key_D = readBlock(); param.Val_P = readBlock(); param.Val_Q = readBlock(); param.Val_DP = readBlock(); param.Val_DQ = readBlock(); param.Val_InverseQ = readBlock(); } else { throw new Exception("pem需要BEGIN END标头"); } return(param); }