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. 1.安装Redis

    首要条件:安装VMware,在虚拟机中安装CentOS. 安装步骤: 1.打开终端(Terminal) 2.在终端输入:wget http://download.redis.io/releases/r ...

  2. 使用模板技术处理ASP.NET中GridView额外序号列的问题

    问题描述: 现在要在一张GridView表中添加一列来显示行号,要求是显示下一页的时候能够递增而不是从新编号.数据库中的没有相关序号列 如何在软件端实现呢? 通过测试,添加以下代码即可解决需求. &l ...

  3. web前端攻击详解

    前端攻击成因 在web网页的脚本中,有些部分的显示内容会依据外界输入值而发生变化,而如果这些声称html的程序中存在问题,就会滋生名为跨站脚本的安全隐患 XSS跨站脚本攻击: 英文全称cross-si ...

  4. 网站CSS写在html里面的好处

    这是应付超大流量的一种优化方案.为提高速度,他们的外部连接文件一般都存储在单独的服务器上,例如img.****.com,如果这个服务器挂掉 ,整个首页就挂掉了.放在页面内,比较安全.用户访问页面时,不 ...

  5. OpenCascade Application Framework Introduction

    OpenCascade Application Framework Introduction eryar@163.com 本教程介绍了Open CASCADE程序框架(Application Fram ...

  6. Zookeeper-Zookeeper启动过程

    在上一篇,我们了解了zookeeper最基本的配置,也从中了解一些配置的作用,那么这篇文章中,我们将介绍Zookeeper的启动过程,我们在了解启动过程的时候还要回过头看看上一篇中各个配置参数在启动时 ...

  7. Oracle如何实现从特定组合中随机读取值

    在这里,我们会用到DBMS_RANDOM包和CASE WHEN语句,思路如下: 一.利用DBMS_RANDOM.RANDOM函数随机生成数值,然后对数值进行取模,如果我们要在10个元素中随机读取的话, ...

  8. Prim算法(二)之 C++详解

    本章是普里姆算法的C++实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里姆算法的代码说明 4. 普里姆算法的源码 转载请注明出处:http://www.cnblogs.com/sk ...

  9. 深入了解ibatis源码----简单ibatis示例代码

    搭建源码环境: 1.创建sql数据库. CREATE TABLE USER_ACCOUNT ( USERID INT(3) NOT NULL AUTO_INCREMENT, USERNAME VARC ...

  10. jQuery.noConflict()

    转载:http://blog.163.com/mjuxiaom@126/blog/static/13397047120117324320858/ 运行这个函数将变量$的控制权让渡给第一个实现它的那个库 ...