一个完整的类用来读取OpenSSL生成的pem格式的x509证书(C#)
internal static class CcbRsaHelper
{
private const string Begin = "-----BEGIN ";
private const string End = "-----END ";
private const string Private = "PRIVATE KEY"; /// <summary>Imports PEM formatted key or certificate into crypto provider</summary>
/// <param name="data">Content of PEM-formatted object.</param>
/// <returns>Crypto provider, defined by given argument.</returns>
internal static RSACryptoServiceProvider FromPem(string data)
{
return FromPem(data, null);
} /// <summary>Imports PEM formatted key or certificate into crypto provider</summary>
/// <param name="data">Content of PEM-formatted object.</param>
/// <param name="passKey">Passkey for PEM-formatted object.</param>
/// <returns>Crypto provider, defined by given argument.</returns>
internal static RSACryptoServiceProvider FromPem(string data, string passKey)
{
using (var reader = new StringReader(data))
{
var line = reader.ReadLine();
if (line.IsEmpty() || !line.StartsWith(Begin))
{
throw new ArgumentException("This is not valid PEM format", "data", new FormatException("PEM start identifier is invalid or not found."));
}
line = line.Substring(Begin.Length);
var idx = line.IndexOf('-');
if (idx <= )
{
throw new ArgumentException("This is not valid PEM format", "data", new FormatException("PEM start identifier is invalid or not found."));
}
var type = line.Before(idx);
return LoadPem(reader, type, passKey);
}
} internal static RSAParameters FromPemPublicKey(string pemFileConent)
{
if (string.IsNullOrEmpty(pemFileConent))
{
throw new ArgumentNullException("pemFileConent", "This arg cann't be empty.");
} pemFileConent = pemFileConent.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", "").Replace("\r", "");
var keyData = Convert.FromBase64String(pemFileConent);
var keySize1024 = (keyData.Length == );
var keySize2048 = (keyData.Length == );
if (!(keySize1024 || keySize2048))
{
throw new ArgumentException("pem file content is incorrect, Only support the key size is 1024 or 2048");
} var pemModulus = (keySize1024 ? new byte[] : new byte[]);
var pemPublicExponent = new byte[];
Array.Copy(keyData, (keySize1024 ? : ), pemModulus, , (keySize1024 ? : ));
Array.Copy(keyData, (keySize1024 ? : ), pemPublicExponent, , );
var para = new RSAParameters {Modulus = pemModulus, Exponent = pemPublicExponent};
return para;
} private static RSACryptoServiceProvider LoadPem(TextReader reader, string type, string passkey)
{
var end = End + type;
var headers = new PemHeaders();
string line;
var body = new StringBuilder();
while ((line = reader.ReadLine()) != null && line.IndexOf(end, StringComparison.Ordinal) == -)
{
var d = line.IndexOf(':');
if (d >= )
{
// header
var n = line.Substring(, d).Trim();
if (n.StartsWith("X-")) n = n.Substring();
var v = line.After(d).Trim();
if (!headers.ContainsKey(n))
{
headers.Add(n, v);
}
else
{
throw new FormatException("Duplicate header {0} in PEM data.".Substitute(n));
}
}
else
{
// body
body.Append(line);
}
}
if (body.Length% != )
{
throw new FormatException("PEM data is invalid or truncated.");
} return CreatePem(type, headers, Convert.FromBase64String(body.ToString()), passkey);
} private static RSACryptoServiceProvider CreatePem(string type, PemHeaders headers, byte[] body, string passkey)
{
if (type.EndsWith(Private))
{
return FromPrivateKey(type, headers, body, passkey);
}
throw new NotSupportedException("Import of {0} is not supported. Only RSA private key import is supported.".Substitute(type));
} private static RSACryptoServiceProvider FromPrivateKey(string type, PemHeaders headers, byte[] body, string passkey)
{
if (type == null) throw new ArgumentNullException("type");
var pType = headers.TryGet("Proc-Type");
if (pType != "4,ENCRYPTED") return null;
if (passkey.IsEmpty())
{
throw new ArgumentException("Passkey is mandatory for encrypted PEM object");
} var dek = headers.TryGet("DEK-Info");
var tkz = dek.Split(',');
if (tkz.Length > )
{
var alg = new Alg(tkz[]);
var saltLen = tkz[].Length;
var salt = new byte[saltLen/];
for (var i = ; i < saltLen/; i++)
{
var pair = tkz[].Substring(*i, );
salt[i] = Byte.Parse(pair, NumberStyles.AllowHexSpecifier);
} body = DecodePem(body, passkey, alg, salt);
if (body != null)
{
return DecodeRsaPrivateKey(body);
}
}
else
{
throw new FormatException("DEK information is invalid or truncated.");
} return null;
} private static RSACryptoServiceProvider DecodeRsaPrivateKey(byte[] body)
{
using (var ms = new MemoryStream(body))
{
using (var reader = new BinaryReader(ms))
{
try
{
var tb = reader.ReadUInt16(); // LE: x30 x81
switch (tb)
{
case 0x8130:
reader.ReadByte(); // fw 1
break;
case 0x8230:
reader.ReadInt16(); // fw 2
break;
default:
return null;
} tb = reader.ReadUInt16(); // version
if (tb != 0x0102)
{
return null;
}
if (reader.ReadByte() != 0x00)
{
return null;
} var modulus = ReadInt(reader);
var e = ReadInt(reader);
var d = ReadInt(reader);
var p = ReadInt(reader);
var q = ReadInt(reader);
var dp = ReadInt(reader);
var dq = ReadInt(reader);
var iq = ReadInt(reader); var result = new RSACryptoServiceProvider();
var param = new RSAParameters
{
Modulus = modulus,
Exponent = e,
D = d,
P = p,
Q = q,
DP = dp,
DQ = dq,
InverseQ = iq
};
result.ImportParameters(param);
return result;
}
finally
{
reader.Close();
}
}
}
} private static readonly Func<BinaryReader, byte[]> ReadInt = r =>
{
var s = GetIntSize(r);
return r.ReadBytes(s);
}; private static readonly Func<BinaryReader, int> GetIntSize = r =>
{
int c;
var b = r.ReadByte();
if (b != 0x02)
{
//int
return ;
}
b = r.ReadByte(); switch (b)
{
case 0x81:
c = r.ReadByte(); //size
break;
case 0x82:
var hb = r.ReadByte();
var lb = r.ReadByte();
byte[] m = {lb, hb, 0x00, 0x00};
c = BitConverter.ToInt32(m, );
break;
default:
c = b; //got size
break;
} while (r.ReadByte() == 0x00)
{
//remove high zero
c -= ;
}
r.BaseStream.Seek(-, SeekOrigin.Current); // last byte is not zero, go back;
return c;
}; private static byte[] DecodePem(byte[] body, string passkey, Alg alg, byte[] salt)
{
if (alg == null) throw new ArgumentNullException("alg");
if (alg.AlgBase != Alg.BaseAlg.DES_EDE3 && alg.AlgMode != Alg.Mode.CBC)
{
throw new NotSupportedException("Only 3DES-CBC keys are supported.");
}
var des = Get3DesKey(salt, passkey);
if (des == null)
{
throw new ApplicationException("Unable to calculate 3DES key for decryption.");
}
var rsa = DecryptRsaKey(body, des, salt);
if (rsa == null)
{
throw new ApplicationException("Unable to decrypt RSA private key.");
}
return rsa;
} private static byte[] DecryptRsaKey(byte[] body, byte[] desKey, byte[] iv)
{
byte[] result;
using (var stream = new MemoryStream())
{
var alg = TripleDES.Create();
alg.Key = desKey;
alg.IV = iv;
using (var cs = new CryptoStream(stream, alg.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(body, , body.Length);
cs.Close();
}
result = stream.ToArray();
}
return result;
} private static byte[] Get3DesKey(byte[] salt, string passkey)
{
const int hashlength = ;
const int m = ; // 2 iterations for at least 24 bytes
const int c = ; // 1 hash for Open SSL
var k = new byte[hashlength*m]; var pk = Encoding.ASCII.GetBytes(passkey);
var data = new byte[salt.Length + pk.Length];
Array.Copy(pk, data, pk.Length);
Array.Copy(salt, , data, pk.Length, salt.Length);
var md5 = new MD5CryptoServiceProvider();
byte[] result = null;
var hash = new byte[hashlength + data.Length]; for (var i = ; i < m; i++)
{
if (i == )
{
result = data;
}
else
{
Array.Copy(result, hash, result.Length);
Array.Copy(data, , hash, result.Length, data.Length);
result = hash;
} for (var j = ; j < c; j++)
{
result = md5.ComputeHash(result);
}
Array.Copy(result, , k, i*hashlength, result.Length);
}
var dk = new byte[]; //final key
Array.Copy(k, dk, dk.Length);
return dk;
} private class PemHeaders : Dictionary<string, string>
{
} private sealed class Alg
{
public Alg(string alg)
{
AlgMode = Mode.ECB;
switch (alg.Trim())
{
//TK: DES-EDE based algorithms come only with ECB mode.
case "DES-EDE":
AlgBase = BaseAlg.DES_EDE;
return;
case "DES-EDE3":
AlgBase = BaseAlg.DES_EDE3;
return;
default:
var p = alg.LastIndexOf('-');
if (p >= )
{
AlgBase = (BaseAlg) _parseVal(typeof (BaseAlg), alg.Before(p));
AlgMode = (Mode) _parseVal(typeof (Mode), alg.After(p));
return;
}
break;
}
throw new ArgumentException("Unknown DEK algorithm '{0}'", alg);
} public BaseAlg AlgBase { get; private set; } public Mode AlgMode { get; private set; } private readonly Func<Type, string, Enum> _parseVal = (t, s) =>
{
s = s.Replace('-', '_');
return (Enum) Enum.Parse(t, s);
}; public enum BaseAlg
{
DES_EDE,
DES_EDE3
}; public enum Mode
{
CBC,
ECB
};
}
} internal static class Helper
{
public static bool IsEmpty(this string value)
{
return String.IsNullOrWhiteSpace(value);
} public static string Before(this string value, int end)
{
return (end == ? String.Empty : value.Between(, end - ));
} public static string After(this string value, int start)
{
return value.Between(start + , Int32.MaxValue);
} public static string Between(this string value, int start, int end)
{
var len = (String.IsNullOrEmpty(value) ? : value.Length);
if (start < ) start += len;
if (end < ) end += len;
if (len == || start > len - || end < start)
{
return String.Empty;
}
if (start < ) start = ;
if (end >= len) end = len - ;
return value.Substring(start, end - start + );
} public static string Substitute(this string format, params object[] args)
{
var value = String.Empty;
if (String.IsNullOrEmpty(format)) return value;
if (args.Length == ) return format;
try
{
return String.Format(format, args);
}
catch (FormatException)
{
return format;
}
catch
{
return "***";
}
} public static TV TryGet<TK, TV>(this Dictionary<TK, TV> dictionary, TK key)
{
return dictionary.TryGet(key, default(TV));
} public static TV TryGet<TK, TV>(this Dictionary<TK, TV> dictionary, TK key, TV defaultValue)
{
if (dictionary != null && dictionary.ContainsKey(key))
{
return dictionary[key];
}
return defaultValue;
}
}
一个完整的类用来读取OpenSSL生成的pem格式的x509证书(C#)的更多相关文章
- 一个完整的类用来读取OpenSSL生成的pem格式的x509证书
internal static class CcbRsaHelper { private const string Begin = "-----BEGIN "; private c ...
- 使用openssl 生成RSA pem格式的公钥私钥
1.生存私钥 openssl genrsa -des3 -out private_key.pem 1024 2.生成公钥 openssl rsa -in private_key.pem -pubout ...
- .NET使用OpenSSL生成的pem密钥文件
NET要使用OpenSSL生成的pem密钥文件,网上资料很少(http://www.faqs.org/rfcs/rfc1421.html,RFC1421文件又老长老长),仅有的资料还是有错误的,所以今 ...
- OpenSSL 使用拾遗(二)---- X509 证书的 SKID/AKID 字段
SKID(证书使用者密钥标识符,subject key identifier 的简称)和 AKID(证书颁发机构密钥标识符,authority key identifier 的简称)是 X509 证书 ...
- openssl rsa加密,解密以及X509证书的使用
Openssl的相关使用 生成证书 生成证书见:使用 openssl 生成证书 代码实现 Cert.h #ifndef _CERT_H #define _CERT_H ///header files ...
- linux下使用openssl生成https的crt和key证书
x509证书一般会用到三类文,key,csr,crt Key 是私用密钥openssl格,通常是rsa算法. Csr 是证书请求文件,用于申请证书.在制作csr文件的时,必须使用自己的私钥来签署申,还 ...
- 一个完整的类用来生成RSACryptoServiceProvider单例类(.NET)
internal class CcbRsaCryptProvider { private static RSACryptoServiceProvider _providerForSign; priva ...
- 用openssl生成SSL使用的私钥和证书,并自己做CA签名(转)
本 文记叙的是一次基于SSL的socket通讯程序开发中,有关证书,签名,身份验证相关的步骤. 我们的场景下,socket服务端是java语言编写的,客户端是c语言.使用了一个叫做matrixssl的 ...
- .NET使用OpenSSL生成的pem密钥文件[1024位]
using System; using System.Text; using System.Security.Cryptography; using System.Web; using System. ...
随机推荐
- UVA572 (并查集解法)
紫书第六章的题,用并查集重写一遍,果然还是书上给的dfs方法更简单...... 一开始用fa[i*m+j] != i*m+j 来判断是否访问过,虽然没想出来为什么WA,但是确实不如用vis稳 #inc ...
- 白话解说TCP/IP协议三次握手和四次挥手
白话解说TCP/IP协议三次握手和四次挥手 1.背景 和女朋友异地恋一年多,为了保持感情我提议每天晚上视频聊天一次. 从好上开始,到现在,一年多也算坚持下来了. 1.1.问题 有时候聊天的过程中,我的 ...
- Java 使用Builder解决构造函数参数过多的问题
原文:https://blog.csdn.net/michael_f2008/article/details/77715075 //Builder Pattern public class Nutri ...
- Codes: MODERN ROBOTICS Ch.3_Expo. Coods.基础代码实现
%%1 Transform omega to so3 matrix % W for skew-symmetirc matirx % w for omega, angular velocity func ...
- pyspark读取hdfs 二进制文件
程序如下: from pyspark import SparkConf, SparkContext conf = SparkConf().setAppName("My test App&qu ...
- 访问stackoverflow非常慢
其实GFW并没有限制访问stackoverflow,但是打开stackoverflow会非常慢. 解决方法是 打开host文件加入下面这句 127.0.0.1 ajax.googleapis.com ...
- js计算两个时间差
时间格式 time:'2018-04-26 15:49:00'需要转换为time:'2018/04/26 15:49:00' 使用time.replace(/\-/g, "/") ...
- vue路由机制导致的坑,坑,坑
实现一个手机定位的功能: 跳转到指定页面的时候,安卓手机地图定位正常,苹果手机第一次进入页面,地图定位不准, 要刷新后,才可以准确定位,后来无意间不用路由跳转,使用JS跳转,完美解决, 特此记录,方便 ...
- 错误信息: Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
这个错误主要原因是:数据库的配置出问题,比如写错库名什么的,仔细检查下.
- netty: 以默认的ByteBuf作为传输数据
client部分代码: //线程 EventLoopGroup worker = new NioEventLoopGroup(); //辅助类 Bootstrap b = new Bootstrap( ...