(轉)創建X509證書,并獲取證書密鑰的一點研究

創建X509證書,并獲取證書密鑰的一點研究

作者:肖波

個人博客:http://blog.csdn.net/eaglet ; http://www.cnblogs.com/eaglet

2007/7 南京

?

背景

服務器SSL數字證書和客戶端單位數字證書的格式遵循 X.509 標準。 X.509 是由國際電信聯盟(ITU-T)制定的數字證書標準。為了提供公用網絡用戶目錄信息服務, ITU 于 1988 年制定了 X.500 系列標準。其中 X.500 和 X.509 是安全認證系統的核心, X.500 定義了一種區別命名規則,以命名樹來確保用戶名稱的唯一性; X.509 則為 X.500 用戶名稱提供了通信實體鑒別機制,并規定了實體鑒別過程中廣泛適用的證書語法和數據接口, X.509 稱之為證書。

?? X.509 給出的鑒別框架是一種基于公開密鑰體制的鑒別業務密鑰管理。一個用戶有兩把密鑰:一把是用戶的專用密鑰(簡稱為:私鑰),另一把是其他用戶都可得到和利用的公共密鑰(簡稱為:公鑰)。用戶可用常規加密算法(如 DES)為信息加密,然后再用接收者的公共密鑰對 DES 進行加密并將之附于信息之上,這樣接收者可用對應的專用密鑰打開 DES 密鎖,并對信息解密。該鑒別框架允許用戶將其公開密鑰存放在CA的目錄項中。一個用戶如果想與另一個用戶交換秘密信息,就可以直接從對方的目錄項中獲得相應的公開密鑰,用于各種安全服務。

?? 最初的 X.509 版本公布于 1988 年,版本 3 的建議稿 1994 年公布,在 1995 年獲得批準。本質上, X.509 證書由用戶公共密鑰與用戶標識符組成,此外還包括版本號、證書序列號、CA 標識符、簽名算法標識、簽發者名稱、證書有效期等。用戶可通過安全可靠的方式向 CA 提供其公共密鑰以獲得證書,這樣用戶就可公開其證書,而任何需要此用戶的公共密鑰者都能得到此證書,并通過 CA 檢驗密鑰是否正確。這一標準的最新版本 -- X.509 版本 3 是針對包含擴展信息的數字證書,提供一個擴展字段,以提供更多的靈活性及特殊環境下所需的信息傳送。

?? 為了進行身份認證, X.509 標準及公共密鑰加密系統提供了一個稱作數字簽名的方案。用戶可生成一段信息及其摘要(亦稱作信息“指紋”)。用戶用專用密鑰對摘要加密以形成簽名,接收者用發送者的公共密鑰對簽名解密,并將之與收到的信息“指紋”進行比較,以確定其真實性。

?? 目前, X.509 標準已在編排公共密鑰格式方面被廣泛接受,已用于許多網絡安全應用程序,其中包括 IP 安全( Ipsec )、安全套接層( SSL )、安全電子交易( SET )、安全多媒體 INTERNET 郵件擴展( S/MIME )等。

?

創建X509 證書

創建X509證書方法較多,在Windows 環境下大致總結了幾中辦法,

1)????? 通過CA獲取證書,

2)????? 通過微軟提供的makecert 工具得到測試證書

3)????? 編程的方法創建,.Net提供了 X509Certificate2 類,該類可以用于創建證書,但只能從RawData中創建,創建后無法修改除FriendlyName以外的任何屬性。

?

我在互聯網上找了很久,始終沒有找到完全通過程序創建自定義的證書的方法。后來想了一個折中辦法,就是用程序調用 makecert.exe 先生成一個證書,證書的一些參數如Subject,有效期,序列號等可以通過參數傳入,然后把生成的證書文件讀到Rawdata中,得到X509Certificate2 類型的證書對象。當然這種方法確實比較笨,必須要依賴外部進程。等后面有時間的話,我還是想按照X509 V3 標準,自己創建RawData,然后生成證書,這樣應該是比較靈活的做法。不知道網友們有沒有什么更好的方法來創建一個自定義的證書。

?

通過 makecert.exe 創建X509證書的代碼如下,供大家參考

?

static object semObj = new object();

?

/// <summary>

/// 自定義的證書信息

/// </summary>

public class T_CertInfo

{

??? public String FriendlyName;

??? public String Subject;

??? public DateTime BeginDate;

??? public DateTime EndDate;

??? public int SerialNumber;

}

?

/// <summary>

/// 生成X509證書

/// </summary>

/// <param name="makecrtPath">makecert進程的目錄</param>

/// <param name="crtPath">證書文件臨時目錄</param>

/// <param name="certInfo">證書信息</param>

/// <returns></returns>

public static X509Certificate2 CreateCertificate(String makecrtPath, String crtPath,

??? T_CertInfo certInfo)

{

??? Debug.Assert(certInfo != null);

??? Debug.Assert(certInfo.Subject != null);

?

??? string MakeCert = makecrtPath + "makecert.exe";

??? string fileName = crtPath + "cer";

?

??? string userName = Guid.NewGuid().ToString();

?

??? StringBuilder arguments = new StringBuilder();

?

??? arguments.AppendFormat("-r -n \"{0}\" -ss my -sr currentuser -sky exchange ",

??????? certInfo.Subject);

?

??? if (certInfo.SerialNumber > 0)

??? {

??????? arguments.AppendFormat("-# {0} ", certInfo.SerialNumber);

??? }

?

??? arguments.AppendFormat("-b {0} ", certInfo.BeginDate.ToString(@"MM\/dd\/yyyy"));

??? arguments.AppendFormat("-e {0} ", certInfo.EndDate.ToString(@"MM\/dd\/yyyy"));

??? arguments.AppendFormat("\"{0}\"", fileName);

?

??? lock (semObj)

??? {

??????? Process p = Process.Start(MakeCert, arguments.ToString());

??????? p.WaitForExit();

?

??????? byte[] certBytes = ReadFile(fileName);

??????? X509Certificate2 cert = new X509Certificate2(certBytes);

??????? cert = new X509Certificate2(certBytes);

?

??????? if (certInfo.FriendlyName != null)

??????? {

??????????? cert.FriendlyName = certInfo.FriendlyName;

??????? }

?

??????? return cert;

??? }

}

?

?

internal static byte[] ReadFile(string fileName)

{

??? using (FileStream f = new FileStream(fileName, FileMode.Open, FileAccess.Read))

??? {

??????? int size = (int)f.Length;

??????? byte[] data = new byte[size];

??????? size = f.Read(data, 0, size);

??????? return data;

??? }

}

?

獲取證書私鑰

通過上述方法得到的X509證書,只能獲取其公鑰信息,由于公鑰私鑰是成對出現的,如果我們要在程序中使用該證書來加解密,就必須要獲取公鑰對應的那個私鑰。一樣是在互聯網上沒有找到很好的解決辦法,只能自己研究。目前總結出兩種方法,給大家分享:

第一種方法:

從密鑰容器中獲取私鑰。具體方法如下:

首先在 makecert 的參數中要加入一條 -sk keyname ?指定主題的密鑰容器位置,該位置包含私鑰。如果密鑰容器不存在,系統將創建一個。

然后 在執行完 p.WaitForExit(); 這一句后執行下面語句獲取私鑰和私鑰參數

RSAParameters privateKey;

RSACryptoServiceProvider rsa = GetKeyFromContainer("keyname");

privateKey = rsa.ExportParameters(true);

?

public static RSACryptoServiceProvider GetKeyFromContainer(string ContainerName)

{

??? // Create the CspParameters object and set the key container

??? // name used to store the RSA key pair.

??? CspParameters cp = new CspParameters();

??? cp.KeyContainerName = ContainerName;

?

??? // Create a new instance of RSACryptoServiceProvider that accesses

??? // the key container MyKeyContainerName.

??? return new RSACryptoServiceProvider(cp);

}

?

這種方法有一個缺點就是程序的調用者必須要具備讀取密鑰容器的權限才行,如果是Web應用,由于IIS來賓帳戶沒有這個權限,將無法讀取密鑰容器中的密鑰。嘗試采用模擬超級用戶登錄的方法(NetworkSecurity.ImpersonateUser),也無法解決這個問題,而且這樣做我個人覺得對網站的安全性方面也不是很好。后來想出了第二種方法,就是干脆重置密鑰對,用自己生成的密鑰對替換證書中的密鑰對,試了一下,還是行之有效的。

第二種方法:

重置密鑰對,方法如下:

首先要生成一個加密算法和加密位數與makecert生成的證書密鑰相同的密鑰。通過實測發現makecert采用交換密鑰時,默認產生一個1024位RSA密鑰,Exponent 為1,0,1,這和

RSACryptoServiceProvider 默認的密鑰是相同的。所以只要用 RSACryptoServiceProvider RSA = new RSACryptoServiceProvider() 生成一個密鑰就可以了。

?

第二步就是替換,也就是將密鑰文件中公鑰參數替換為要置換的公鑰參數。

?

RSAParameters publicKey;

RSAParameters privateKey;

?

RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)cert.PublicKey.Key;

publicKey = RSA.ExportParameters(false);

?

//查找公鑰參數在RawData中的位置

if (publicKey.Modulus.Length != 128 || publicKey.Exponent.Length != 3)

{

??? throw new Exception("public key module lenght != 128!");

}

?

if (publicKey.Exponent[0] != 1 ||

??? publicKey.Exponent[1] != 0 ||

??? publicKey.Exponent[2] != 1)

{

??? throw new Exception("public key Exponent != 101!");

}

?

byte[] module = publicKey.Modulus;

?

int i = 0;

int matchCnt = 0;

int modulePos = 0;

int j = 0;

?

while (i < certBytes.Length)

{

?

??? if (certBytes[i] == module[j]) //cerBytes 為 RawData,什么可以參加創建證書的代碼

??? {

??????? i++;

??????? j++;

?????? ?matchCnt++;

?

??????? if (matchCnt == 128)

??????? {

??????????? modulePos = i - 128;

??????????? break;

??????? }

??? }

??? else

??? {

??????? if (matchCnt == 128)

??????? {

??????????? modulePos = i - 128;

??????????? break;

??????? }

??????? else

????? ??{

??????????? matchCnt = 0;

??????????? j = 0;

??????????? i++;

??????? }

??? }

}

?

//創建密鑰對

RSA = new RSACryptoServiceProvider();

publicKey = RSA.ExportParameters(false);

privateKey = RSA.ExportParameters(true);

?

//將要重置的密鑰對中的公鑰參數覆蓋原參數

?

j = 0;

for (i = modulePos; i < modulePos + 128; i++)

{

??? certBytes[i] = publicKey.Modulus[j];

??? j++;

}

?

//用新參數重新創建證書

cert = new X509Certificate2(certBytes);

?

這樣一來privateKey就成了新證書的私鑰了。

?

這種方法的問題:

這種方法的問題是查找證書中公鑰信息,是通過匹配的方式來做的,這是一個偷懶的方法,正確的做法應該是按照標準的定義來查找,由于暫時沒有太多時間去仔細研究標準,所以就偷了一個懶,但感覺這種方法目前來說還是行之有效的,待以后改進吧。

?

?

參考資料

http://www.ietf.org/rfc/rfc2459.txt?IETF X509 V3 版本標準全文

http://blog.csdn.net/chinaipcnet/archive/2007/05/23/1621989.aspx?makecert.exe使用說明

?from :http://www.cnblogs.com/eaglet/archive/2007/07/11/814600.html

轉載于:https://www.cnblogs.com/gxh973121/archive/2007/07/12/815117.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/277028.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/277028.shtml
英文地址,請注明出處:http://en.pswp.cn/news/277028.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

css樣式優先級計算規則

css樣式的優先級分為引入優先級和聲明優先級。 引入優先級 引入樣式一般分為外部樣式&#xff0c;內部樣式&#xff0c;內聯樣式。 外部樣式&#xff1a;使用link引入的外部css文件。 內部樣式&#xff1a;使用style標簽書寫的css樣式。 內聯樣式&#xff1a;直接書寫在html標簽…

phpstudy-5.6.27-nts??安裝redis擴展

2019獨角獸企業重金招聘Python工程師標準>>> redis擴展安裝流程 第一步&#xff1a; 首先直接查看一下phpinfo()的信息 找到下面兩條信息 Architecturex86PHP Extension BuildAPI20131226,NTS,VC11Loaded Configuration FileD:\phpStudy\php\php-5.6.27-nts\php.ini…

用DDA Convolution和Perlin Noise來模擬水粉畫筆觸

在西方&#xff0c;水彩畫和水粉畫是可以統稱為Watercolor的,水粉畫通常也稱為不透明水彩畫或樹膠水彩畫&#xff08;Gouache&#xff09;&#xff0c;兩者既有相似之處&#xff0c;又有所區別。水粉畫是以水作為媒介&#xff0c;這一點&#xff0c;它與水彩畫是相同的。所以&a…

第三課 Makefile文件的制作(上)

1.序言&#xff1a; 前面的課程講解了從gcc編譯過程到其實踐&#xff0c;大家可以看到其實在這些步驟中有些是可以簡化編譯的&#xff0c;但由于參數多以及項目中文件數量多的原因難免會造成錯誤甚至是浪費大量的時間在這編譯上&#xff0c;為此linux系統中專門也有這個工具&am…

刺猬文│從啟動方式來看播客鏈的運行機制—設置驗證者

&#xff08;圖片出自網絡&#xff0c;版權歸原作者所有&#xff09;上一篇刺猬文我們介紹了播客鏈是如何實現Dpos的&#xff0c;其實質過程就是&#xff1a;節點A打包&#xff0c;將打包的區塊發送給其它的節點&#xff0c;其它節點根據當前時間&#xff0c;判斷是否應該由A節…

[記憶碎片的磁盤整理]老媽

卷標&#xff1a;老媽 掛載點&#xff1a;/family/mother 分區格式&#xff1a;親情 備注&#xff1a;老媽固然是我人生中的至親&#xff0c;但是搜遍我的大鬧&#xff0c;也沒能發現一點關于老媽的特殊記憶。老媽是一位再普通不過的女人、妻子、母親。也本該如此吧。碎片文件&…

探究Java如何實現原子操作(atomic operation)

1. 讓我們首先了解下java 中 Volatile 關鍵字 Volatile可實現java內存模型當中的可見性&#xff0c; java內存模型的可見性&#xff1a; 可見性&#xff0c;是指線程之間的可見性&#xff0c;一個線程修改的狀態對另一個線程是可見的。也就是一個線程修改的結果&#xff0c;另一…

JAVA-重寫equalse規范、技巧

JAVA-重寫equalse規范、技巧 1、自反性 任何非空引用x&#xff0c;x.equalse(x) 應該返回true2、對稱性 任何引用x和y&#xff0c;當x.equals(y)返回true&#xff0c;y.equals(x)也應返回true3、傳遞性 任何引用x、y和z&#xff0c;當x.equalse(y)和y.equalse(z)&#xff0c;那…

Password Creator(HTA)

<!--- 功能&#xff1a; 生成隨機密碼- 輸入&#xff1a; 用戶的設置- 輸出&#xff1a; 隨機密碼&#xff0c;同時拷貝到剪切板- 作者&#xff1a; maskx- 版本&#xff1a; v1.0- 歷史紀錄&#xff1a; 2007-7-11新建 - 創建時間&#xff1a; 200…

Julia 排坑指南

Julia 是一個高效的計算語言&#xff0c;據說性能和C有一拼。 Google也開始支持TPU的Julia&#xff0c; 個人覺得他的可視化比較厲害&#xff0c;下面是自己安裝過程的截圖&#xff0c;由于Julia的服務器在國外&#xff0c;所以下載的過程會出現一些不可描述的問題&#xff0c;…

Arts 第十九周(7/22 ~ 7/28)

ARTS是什么&#xff1f;Algorithm&#xff1a;每周至少做一個leetcode的算法題&#xff1b;Review&#xff1a;閱讀并點評至少一篇英文技術文章&#xff1b;Tip&#xff1a;學習至少一個技術技巧&#xff1b;Share&#xff1a;分享一篇有觀點和思考的技術文章。 Algorithm 深度…

難過的要命。。。。。。

請允許我這樣叫幾下&#xff0c;我知道自己是個老姑娘了&#xff0c;不能像小女孩那樣碰到點不開心的事就一哭二鬧三上吊。我不哭不鬧更不會傻得去上吊&#xff0c;我還有幾十年的大好日子要過呢&#xff0c;我兒子還沒生呢。現在我們還沒有正式的攤牌&#xff0c;應該說只差最…

基于.NET2.0的System.Net.Mail發送郵件Demo

第一種: //emailaddress郵件接收者地址 //mailcontent郵件主體內容 //mailtitle郵件標題 //mailsubject郵件主題 public bool SendMail(string emailaddress,string mailcontent,string mailtitle,string mailsubject) { …

美國美國,USA USA

外派美國微軟接的項目職位名稱&#xff1a;開發主管&#xff08;SDE LEADER&#xff09; 工作城市&#xff1a;Redmond 職位要求: Good English communicationGood SQL and C# .net framework experienceBackend developmentBI knowledge (he is expected to deal with millio…

Windows Server 2016之RDS配置證書

證書我們可以自己創建也可以到阿里云申請&#xff0c;一次申請可以用一年&#xff0c;&#xff08;自己創建的證書是不受信任的&#xff09;所以我們在阿里云上申請的&#xff0c;下面我們就把申請到的證書下載下來&#xff0c;放到一個文件夾里&#xff0c;并解壓接下來我們就…

升級tomcat7.0之后的問題

學習web也有幾天了&#xff0c;今天把tomcat改成7.0的之后老是出現嚴重警告&#xff1a; 嚴重: The web application [/struts2_0100] created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$10](value[com.opensymphony.xwork2.inject.Conta…

慎重對待青霉素皮試

青霉素類藥不同品種間存在交叉過敏關系。 所以&#xff0c;中國藥典規定&#xff0c;青霉素類藥物在注射前必先使用青霉素鈉&#xff08;鉀&#xff09;及氯化鈉注射液配制的溶液做皮內敏感試驗。皮試液濃度為每毫升500單位&#xff0c; 皮內注射0.1毫升&#xff0c;陽性反應者…

2018阿里云雙11拼團大促主會場全攻略

為什么80%的碼農都做不了架構師&#xff1f;>>> 摘要&#xff1a; 在雙十一這個一年唯一一次的大幅度降價促銷日&#xff0c;怎樣才能花最少的錢配置最特惠的云服務&#xff1f;云棲社區特為各位開發者奉獻出省錢大法如下&#xff01; 2018阿里云雙十一拼團大促活動…

匿名用戶訪問用發布站點模板創建網站的列表項時要求登錄的問題解決

因為發布站點中的一個Feature被打開了&#xff0c;造成將列表FormPage的查看給Lock了&#xff0c;所以需要登錄&#xff0c;將其關閉就OK了。哈哈。英文KB&#xff1a;Users are unexpectedly prompted to enter their credentials when they access a list in a Windows Share…

知識點1: 進度條隨數據變化,并添加漸變樣式

效果圖&#xff1a; dom&#xff1a; //  進度條             <div class"progress" :style"styleObj1"><div class"point"></div></div>//  數據容器<div class"precent"><counte…