/// <summary> /// 通过公钥或私钥创建RSA,出错抛异常 /// </summary> public RSA(string key) { if (!key.StartsWith("<")) { RSAObject = RsaPem.FromPEM(key).GetRSA(); } else { var rsaParams = new CspParameters { Flags = CspProviderFlags.UseMachineKeyStore }; RSAObject = new RSACryptoServiceProvider(rsaParams); RSAObject.FromXmlString(key); } }
/// <summary> /// 通过一个pem对象创建RSA,pem为公钥或私钥,出错抛异常 /// </summary> public RSA(RsaPem pem) { RSAObject = pem.GetRSA(); }
/// <summary> /// 将XML格式密钥转成PEM,支持公钥xml、私钥xml /// 出错将会抛出异常 /// </summary> public static RsaPem FromXML(string xml) { var rtv = new RsaPem(); var xmlM = XmlExp.Match(xml); if (!xmlM.Success) { throw new Exception("XML内容不符合要求"); } var 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.KeyModulus = val; break; case "Exponent": rtv.KeyExponent = val; break; case "D": rtv.KeyD = val; break; case "P": rtv.ValP = val; break; case "Q": rtv.ValQ = val; break; case "DP": rtv.ValDp = val; break; case "DQ": rtv.ValDq = val; break; case "InverseQ": rtv.ValInverseQ = val; break; } tagM = tagM.NextMatch(); } if (rtv.KeyModulus == null || rtv.KeyExponent == null) { throw new Exception("XML公钥丢失"); } if (rtv.KeyD != null) { if (rtv.ValP == null || rtv.ValQ == null || rtv.ValDp == null || rtv.ValDq == null || rtv.ValInverseQ == null) { return(new RsaPem(rtv.KeyModulus, rtv.KeyExponent, rtv.KeyD)); } } return(rtv); }
/// <summary> /// 用PEM格式密钥对创建RSA,支持PKCS#1、PKCS#8格式的PEM /// 出错将会抛出异常 /// </summary> public static RsaPem FromPEM(string pem) { RsaPem param = new RsaPem(); 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++]); } if (data[idx] == 0x82) { idx++; return(((data[idx++]) << 8) + data[idx++]); } 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.KeyModulus = readBlock(); //Exponent param.KeyExponent = 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.KeyModulus = readBlock(); param.KeyExponent = readBlock(); param.KeyD = readBlock(); param.ValP = readBlock(); param.ValQ = readBlock(); param.ValDp = readBlock(); param.ValDq = readBlock(); param.ValInverseQ = readBlock(); } else { throw new Exception("pem需要BEGIN END标头"); } return(param); }