數字簽名:ios
將報文按雙方約定的HASH算法計算獲得一個固定位數的報文摘要。在數學上保證:只要改動報文中任何一位,從新計算出的報文摘要值就會與原先的值不相符。這樣就保證了報文的不可更改性。git
將該報文摘要值用發送者的私人密鑰加密,而後連同原報文一塊兒發送給接收者,而產生的報文即稱數字簽名github
數字證書:算法
數字證書就是互聯網通信中標誌通信各方身份信息的一系列數據,提供了一種在Internet上驗證您身份的方式,其做用相似於司機的駕駛執照或平常生活中的身份證。它是由一個由權威機構—–CA機構,又稱爲證書受權,(Certificate Authority)中心發行的,人們能夠在網上用它來識別對方的身份。數字證書是一個經證書受權中心數字簽名的包含公開密鑰擁有者信息以及公開密鑰的文件。最簡單的證書包含一個公開密鑰、名稱以及證書受權中心的數字簽名。數組
(1) 鮑勃有兩把鑰匙,一把是公鑰,另外一把是私鑰。
安全
(2) 鮑勃把公鑰送給他的朋友們—-帕蒂、道格、蘇珊—-每人一把。
(3) 蘇珊要給鮑勃寫一封保密的信。她寫完後用鮑勃的公鑰加密,就能夠達到保密的效果
(4) 鮑勃收信後,用私鑰解密,就看到了信件內容。這裏要強調的是,只要鮑勃的私鑰不泄露,這封信就是安全的,即便落在別人手裏,也沒法解密。
(5) 鮑勃給蘇珊回信,決定採用 「數字簽名」。他寫完後先用Hash函數,生成信件的摘要(digest)。
(6) 而後,鮑勃使用私鑰,對這個摘要加密,生成」數字簽名」(signature)。
(7) 鮑勃將這個簽名,附在信件下面,一塊兒發給蘇珊。
(8) 蘇珊收信後,取下數字簽名,用鮑勃的公鑰解密,獲得信件的摘要。由此證實,這封信確實是鮑勃發出的。
(9) 蘇珊再對信件自己使用Hash函數,將獲得的結果,與上一步獲得的摘要進行對比。若是二者一致,就證實這封信未被修改過。
(10) 複雜的狀況出現了。道格想欺騙蘇珊,他偷偷使用了蘇珊的電腦,用本身的公鑰換走了鮑勃的公鑰。此時,蘇珊實際擁有的是道格的公鑰,可是還覺得這是鮑勃的公鑰。所以,道格就能夠冒充鮑勃,用本身的私鑰作成「數字簽名」,寫信給蘇珊,讓蘇珊用假的鮑勃公鑰進行解密。
(11) 後來,蘇珊感受不對勁,發現本身沒法肯定公鑰是否真的屬於鮑勃。她想到了一個辦法,要求鮑勃去找」證書中心」(certificate authority,簡稱CA),爲公鑰作認證。證書中心用本身的私鑰,對鮑勃的公鑰和一些相關信息一塊兒加密,生成「數字證書」(Digital Certificate)。
(12) 鮑勃拿到數字證書之後,就能夠放心了。之後再給蘇珊寫信,只要在簽名的同時,再附上數字證書就好了。
(13) 蘇珊收信後,用CA的公鑰解開數字證書,就能夠拿到鮑勃真實的公鑰了,而後就能證實」數字簽名」是否真的是鮑勃籤的。
網絡
X.509 是密碼學裏公鑰證書的格式標準。app
X.509 標準規定了證書能夠包含什麼信息,並說明了記錄信息的方法(數據格式)。框架
X.509 證書裏含有公鑰、身份信息(好比網絡主機名,組織的名稱或個體名稱等)和簽名信息(能夠是證書籤發機構CA的簽名,也能夠是自簽名)。函數
對於一份經由可信的證書籤發機構簽名或者能夠經過其它方式驗證的證書,證書的擁有者就能夠用證書及相應的私鑰來建立安全的通訊,對文檔進行數字簽名。
另外除了證書自己功能,X.509還附帶了證書吊銷列表和用於從最終對證書進行簽名的證書籤發機構直到最終可信點爲止的證書合法性驗證算法。
X.509是ITU-T標準化部門基於他們以前的ASN.1定義的一套證書標準。
1.1. 版本號(Version)
——標識證書的版本(版本一、版本2或是版本3)。
1.2. 序列號(Serial Number)
——標識證書的惟一整數,由證書頒發者分配的本證書的惟一標識符。
1.3. 簽名(Signature)
——用於簽證書的算法標識,由對象標識符加上相關的參數組成,用於說明本證書所用的數字簽名算法。例如,SHA-1和RSA的對象標識符就用來講明該數字簽名是利用RSA對SHA-1雜湊加密。
1.4. 頒發者(Issuer:)
——證書頒發者的可識別名(DN)。
1.5. 有效期(Validity)
——證書有效期的時間段。本字段由」Not Before」和」Not After」兩項組成,它們分別由UTC時間或通常的時間表示(在RFC2459中有詳細的時間表示規則)。
1.6. 主體(Subject)
——證書擁有者的可識別名,這個字段必須是非空的,除非你在證書擴展中有別名。
1.7. 主體公鑰信息(Subject Public Key Info)
——主體的公鑰(以及算法標識符)。
1.8. 頒發者惟一標識符(Issuer Unique Identifier)
——標識符—證書頒發者的惟一標識符,僅在版本2和版本3中有要求,屬於可選項。
1.9. 主體惟一標識符(Subject Unique Identifier)
——證書擁有者的惟一標識符,僅在版本2和版本3中有要求,屬於可選項。
可選的標準和專用的擴展(僅在版本2和版本3中使用),擴展部分的元素都有這樣的結構:
Extension ::= SEQUENCE { extnID OBJECT IDENTIFIER, critical BOOLEAN DEFAULT FALSE, extnValue OCTET STRING }
extnID:表示一個擴展元素的OID
critical:表示這個擴展元素是否極重要
extnValue:表示這個擴展元素的值,字符串類型。
擴展部分包括:
2.1. 發行者密鑰標識符(Autority Key Identifier)
——證書所含密鑰的惟一標識符,用來區分同一證書擁有者的多對密鑰。
2.2. 密鑰使用(Key Usage)
——一個比特串,指明(限定)證書的公鑰能夠完成的功能或服務,如:證書籤名、數據加密等。
若是某一證書將 KeyUsage 擴展標記爲「極重要」,並且設置爲「keyCertSign」,則在 SSL 通訊期間該證書出現時將被拒絕,由於該證書擴展表示相關私鑰應只用於簽寫證書,而不該該用於 SSL。
2.3. CRL分佈點(CRL Distribution Points)
——指明CRL的分佈地點。
2.4. 私鑰的使用期
——指明證書中與公鑰相聯繫的私鑰的使用期限,它也有Not Before和Not After組成。若此項不存在時,公私鑰的使用期是同樣的。
2.5. 證書策略(Certificate Policies)
——由對象標識符和限定符組成,這些對象標識符說明證書的頒發和使用策略有關。
2.6. 策略映射
——代表兩個CA域之間的一個或多個策略對象標識符的等價關係,僅在CA證書裏存在。
2.7. 主體別名
——指出證書擁有者的別名,如電子郵件地址、IP地址等,別名是和DN綁定在一塊兒的。
2.8. 頒發者別名
——指出證書頒發者的別名,如電子郵件地址、IP地址等,但頒發者的DN必須出如今證書的頒發者字段。
2.9. 主體目錄屬性
——指出證書擁有者的一系列屬性。可使用這一項來傳遞訪問控制信息。
https://www.github.com 的證書信息以下:
調用Openssl庫的API對githubcom.pem證書文件解析結果以下:
#include <fstream> #include <openssl/pem.h> #include <openssl/x509.h> #include <openssl/x509v3.h> #include <iostream> #include <sstream> using namespace std; //----------------------------------------------------------------------*/ void parseCert(X509* x509) { cout <<"--------------------" << endl; BIO *bio_out = BIO_new_fp(stdout, BIO_NOCLOSE); //PEM_write_bio_X509(bio_out, x509);//STD OUT the PEM X509_print(bio_out, x509);//STD OUT the details //X509_print_ex(bio_out, x509, XN_FLAG_COMPAT, X509_FLAG_COMPAT);//STD OUT the details BIO_free(bio_out); } //----------------------------------------------------------------------*/ int main(int argc, char **argv) { OpenSSL_add_all_algorithms(); std::ifstream t; int length; t.open("./githubcom.pem"); // open input file t.seekg(0, std::ios::end); // go to the end length = t.tellg(); // report location (this is the length) t.seekg(0, std::ios::beg); // go back to the beginning char* buffer = new char[length]; // allocate memory for a buffer of appropriate dimension t.read(buffer, length); // read the whole file into the buffer t.close(); // close file handle BIO *bio_mem = BIO_new(BIO_s_mem()); BIO_puts(bio_mem, buffer); X509 * x509 = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL); parseCert(x509); BIO_free(bio_mem); X509_free(x509); } //----------------------------------------------------------------------