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证书的更多相关文章

  1. 一个完整的类用来读取OpenSSL生成的pem格式的x509证书(C#)

    internal static class CcbRsaHelper { private const string Begin = "-----BEGIN "; private c ...

  2. 使用openssl 生成RSA pem格式的公钥私钥

    1.生存私钥 openssl genrsa -des3 -out private_key.pem 1024 2.生成公钥 openssl rsa -in private_key.pem -pubout ...

  3. .NET使用OpenSSL生成的pem密钥文件

    NET要使用OpenSSL生成的pem密钥文件,网上资料很少(http://www.faqs.org/rfcs/rfc1421.html,RFC1421文件又老长老长),仅有的资料还是有错误的,所以今 ...

  4. OpenSSL 使用拾遗(二)---- X509 证书的 SKID/AKID 字段

    SKID(证书使用者密钥标识符,subject key identifier 的简称)和 AKID(证书颁发机构密钥标识符,authority key identifier 的简称)是 X509 证书 ...

  5. openssl rsa加密,解密以及X509证书的使用

    Openssl的相关使用 生成证书 生成证书见:使用 openssl 生成证书 代码实现 Cert.h #ifndef _CERT_H #define _CERT_H ///header files ...

  6. linux下使用openssl生成https的crt和key证书

    x509证书一般会用到三类文,key,csr,crt Key 是私用密钥openssl格,通常是rsa算法. Csr 是证书请求文件,用于申请证书.在制作csr文件的时,必须使用自己的私钥来签署申,还 ...

  7. 一个完整的类用来生成RSACryptoServiceProvider单例类(.NET)

    internal class CcbRsaCryptProvider { private static RSACryptoServiceProvider _providerForSign; priva ...

  8. 用openssl生成SSL使用的私钥和证书,并自己做CA签名(转)

    本 文记叙的是一次基于SSL的socket通讯程序开发中,有关证书,签名,身份验证相关的步骤. 我们的场景下,socket服务端是java语言编写的,客户端是c语言.使用了一个叫做matrixssl的 ...

  9. .NET使用OpenSSL生成的pem密钥文件[1024位]

    using System; using System.Text; using System.Security.Cryptography; using System.Web; using System. ...

随机推荐

  1. 23.实现一个名为Person的类和它的子类Employee,Employee有两个子类Faculty 和Staff。 具体要求如下: (1)Person类中的属性有:姓名name(String类型),地址address(String类型), 电话号码telphone(String类型)和电子邮件地址email(String类型); (2)Employee类中的属性有:办公室office(Stri

    package banking; public class Person { private String name; public String address; public String tel ...

  2. Netty学习三:线程模型

    1 Proactor和Reactor Proactor和Reactor是两种经典的多路复用I/O模型,主要用于在高并发.高吞吐量的环境中进行I/O处理. I/O多路复用机制都依赖于一个事件分发器,事件 ...

  3. 【QQ技术】群文件报毒怎样下载?~ 变相绕过QQ复杂检验过程

    刚才又人问我,要是群文件被鉴定为病毒那怎么下载? 我简单说一下吧: 其实qq客户端过滤比较严的,而web段却还是老一套,很多人说出现这个情况其实是腾讯已经把他库里面的文件删了,其实不然 如果源删了,那 ...

  4. CSS学习目录

    前面的话 CSS是前端工程师的基本功,但好多执迷于学习javascript的人的基本功并不扎实.可能一些人从w3school网站匆匆过了一遍,只是对CSS常用概念有一些表面上的理解,就一头扎进java ...

  5. Android线程机制——AsyncTask

    对于Android为什么要使用多线程,因为从Android4.0之后,谷歌规定了网络操作不允许放在主线程中执行,由此就有了多线程的机制,有个JAVA学习经验的朋友一定知道多线程指的是什么,简单来讲就是 ...

  6. 如何用Python实现目录遍历

    1. 基本实现 [root@localhost ~]# cat dirfile.py import os path='/tmp' for dirpath,dirnames,filenames in o ...

  7. Java多线程系列--“基础篇”10之 线程优先级和守护线程

    概要 本章,会对守护线程和线程优先级进行介绍.涉及到的内容包括:1. 线程优先级的介绍2. 线程优先级的示例3. 守护线程的示例 转载请注明出处:http://www.cnblogs.com/skyw ...

  8. PHP学习总结(一)

    对最近学习PHP做个简单的总结吧 书籍:<PHP和MySQL Web开发> 环境/工具:wamp/Editplus&Chrome 时间:8月2日-8月7日 内容: 以前把前3章学了 ...

  9. Windows Azure Web Site (11) 使用源代码管理器管理Azure Web Site

    <Windows Azure Platform 系列文章目录> 熟悉Azure Web Site平台的读者都知道,我们可以通过FTP等方式,把本地的Web Application部署到微软 ...

  10. CentOS上安装SQL Server vNext CTP1

    今天微软正式发布上SQL Server 2016 SP1,根据以往的SP1定律,可以在生产环境上使用了.打了SP1的标准版将具有企业版几乎所有的的功能.只有RAM 超过128GB或者超过24核心或者超 ...