1 基礎(chǔ)
1.1 對稱算法
- 描述:對稱加密是指加密過程和解密過程使用相同的密碼。主要分:分組加密、序列加密。
- 原理:XOR運(yùn)算,將二進(jìn)制數(shù)據(jù)進(jìn)行XOR運(yùn)算,兩次同樣的操作得到原文,所以大致過程就是加密->A xor B = C,解密->C xor B = A(B就是密鑰)。
- 優(yōu)點:加密速度快,適合于對大量數(shù)據(jù)加密。
- 缺點:發(fā)送方和接受方需要使用相同的密鑰,一旦密鑰泄露,在互聯(lián)網(wǎng)上傳輸?shù)募用軘?shù)據(jù)將會被中間人破解。而且由于加密數(shù)據(jù)量大
分類:
- DES(Data Encryption Standard),
- 分組算法
- 分組長度64bit(8字節(jié)),明文分為左右兩側(cè)輪回與密鑰XOR運(yùn)算,每輪使用不同的密鑰
- 密鑰空間2^56
- 三重DES(triple-DES),將DES重復(fù)3次
- 分組長度64bit(8字節(jié))
- AES(Advances Encryption Standard),高級加密標(biāo)準(zhǔn)
- 分組長度為128bit(16字節(jié))
- 密鑰長度只有128、192、256bit
- RC2,RC4,RC5
- RC2和RC5是分組算法,RC4是序列算法
- RC5分組可變、密鑰長度可變
- SSF33,SM1,SM4
- 分組算法
- 分組長度128bit(16字節(jié))
1.2 摘要算法
摘要算法使用密碼學(xué)hash函數(shù),用于驗證數(shù)據(jù)完整性(沒有修改、插入、刪除、或重放)。找到兩個不同數(shù)據(jù)具有相同hash值的難度高。
輸入數(shù)據(jù)的長度首先被填充為某固定長度分組的整數(shù)倍,填充的內(nèi)容包括原始數(shù)據(jù)的位長度信息。安全性要求如下兩種情況在計算上不可行(即沒有攻擊方法比窮舉攻擊更有效):
- 對預(yù)先指定的hash值找到對應(yīng)的數(shù)據(jù)塊(單向性)
- 找到兩個不同的數(shù)據(jù)塊對應(yīng)相同的hash值(抗碰撞性)
Hash算法一般是指Hash表的摘要算法,將不同的鍵值分散到不同的數(shù)組位置,允許少量的沖突碰撞。安全Hash算法(SHA)是使用最廣泛的Hash函數(shù)
- MD2、MD4、MD5
- 摘要長度128bit(16字節(jié))
- SHA1、SHA2、SHA3
- Secure Hash Algorithm
- SHA-1摘要長度160bit(20字節(jié))
- SHA-2摘要長度256bit(32byte)
- SHA-3摘要長度384bit(48byte)
- SM3
- 中國國家商用密碼算法
- 摘要長度256bit(32byte)
摘要函數(shù)——MD2/MD4/MD5數(shù)字簽名
附1:消息認(rèn)證碼(MAC)
又稱密碼校驗和,利用密鑰K和可變長度的數(shù)據(jù)M生成固定長度的短數(shù)據(jù)塊MAC,并將數(shù)據(jù)塊附加在數(shù)據(jù)M之后:
$$
MAC = C(K, M)
$$
若對于數(shù)據(jù)的保密性要求不高(例如廣播),可直接將消息M和MAC一起發(fā)給接受者,接收者收到后使用相同的密鑰K和MAC函數(shù)C對消息M計算得出MAC2,再對比兩者是否相等。(這里設(shè)定通信雙方共享相同的密鑰K)
若對于數(shù)據(jù)的保密性要求嚴(yán)格,可選擇將消息M和MAC加密再發(fā)送:
$$
ENC = E(K_2, M||C(K_1,M))
$$
接收者收到數(shù)據(jù)后首先解密。
附2:基于Hash函數(shù)的MAC:HMAC
HMAC將Hash函數(shù)視為黑盒,將現(xiàn)有Hash函數(shù)作為一個模塊,預(yù)先封裝,在需要時直接使用。
- H:嵌入的Hash函數(shù)
- IV:Hash函數(shù)輸入的初始化數(shù)組
- M:HMAC的消息輸入(包括由嵌入Hash函數(shù)定義的填充位)
- $Y_i$:M的第i個分組
- L:M中的分組個數(shù)
- b:每一分組所含位數(shù)(bits)
- n:嵌入的Hash函數(shù)所產(chǎn)生的Hash碼長
1.3 分組模式
- ECB (Electronic Code book,電子密碼本方式)明文分組與密文分組一一對應(yīng)
- 優(yōu)點:最簡單的一種模式,可并行運(yùn)算,誤差不會傳遞
- 缺點:若有相同明文分組,將被加密成相同密文分組,即明文的結(jié)構(gòu)容易被泄露
- CA產(chǎn)品的私鑰保護(hù)使用ECB算法
- CBC (Cipher-block chaining,密碼分組鏈接)明文分組首先與一個密文分組XOR運(yùn)算,然后再加密,這樣做的目的就是改變明文分組的結(jié)構(gòu),由于第一個明文分組前沒有密文分組,需增添IV初始化向量,與第一個明文分組XOR運(yùn)算
- 若密文分組損壞,但是長度沒有改變,即僅改變幾位的數(shù)據(jù),解密后最多只影響兩個明文分組(密文分組本身對應(yīng)的明文分組,密文分組為后一個分組提供XOR伙伴的后一個明文分組)
- 若密文缺失bit,則缺失bit之后的密文全部無法解密
- CFB (Cipher Feedback ,密碼反饋模式)明文分組與密鑰XOR運(yùn)算,CFB實現(xiàn)了一個被我成為偽偽隨機(jī)數(shù)發(fā)生器的密碼算法,它將前一個密文分組加密生成一個bit序列,稱為密鑰流(key stream),由于第一個明文分組前沒有密文分組,需添加IV初始化向量,執(zhí)行加密生成第一個密鑰流。
- OFB (Output Feedback ,輸出反饋模式)OFB與CFB相同的地方在于都是將明文分組與密鑰XOR運(yùn)算,區(qū)別就在于密鑰的生成。OFB的密鑰算法的輸入來自于上一個密鑰算法的輸出。第一個密鑰算法的輸入使用一個IV向量
OFB與CFB都采用將分組加密轉(zhuǎn)換成流加密的方式
1.4 填充模式
- PKCS#5Padding
如圖,用自己的話來描述就是缺多少bit,就在每個bit里填多少。該方式是8分組結(jié)構(gòu),只適合DES/3DES。
- PKCS7Padding
分組長度可以是小于255的任意長度 - ZeroPadding
使用0X0補(bǔ)齊:... | DD DD DD DD DD DD DD DD | DD DD DD DD 00 00 00 00 |
- ANSI X.923
該模式在最后一個字節(jié)填缺少的bit數(shù),其它補(bǔ)0X0(我覺得這個模式更符合一般人的想法):... | DD DD DD DD DD DD DD DD | DD DD DD DD 00 00 00 04 |
- ISO 10126
該模式個人覺得稍好一些,最后一個填充位填寫缺少的bit數(shù),其它位填充隨機(jī)數(shù):... | DD DD DD DD DD DD DD DD | DD DD DD DD 81 A6 23 04 |
- ISO/IEC 7816-4
填充實例如下:... | DD DD DD DD DD DD DD DD | DD DD DD DD 80 00 00 00 |
(未解)
1.5 密鑰運(yùn)算
密鑰運(yùn)算包含兩種操作(私鑰操作、公鑰操作),簽名驗簽正是基于這兩種操作:
$$
C=P^d mod n
$$
$$
P=C^d mod n
$$
1.5.1 簽名驗簽
使用簽名的前提是使用公鑰加密的密文只有私鑰才能解開,使用私鑰加密的密文只有公鑰才能解開,確保了身份認(rèn)證抗抵賴性。
過程:
- 對原文摘要
- A使用自己的私鑰AS對摘要私鑰加密運(yùn)算,得到簽名
- B使用A的公鑰AP對簽名公鑰解密運(yùn)算,得到摘要值2,這一步證明簽名來自A,若C偽造A的身份使用自己的私鑰CP,則B的公鑰解密失敗。
- B再使用和A相同的hash算法對原文摘要,得到摘要值3,這一步可用來驗證原文是否遭到篡改,
- B驗證摘要值2和3是否相等
至于填充模式,定義在PKCS#1:00||BT||PS||00||D
- 00保證大數(shù)是非負(fù)整數(shù)
- BT分為00,01,02。00,01是私鑰操作,02是公鑰操作
- 00:填充數(shù)據(jù)全為0X00,摘要必須以非0開頭,如果摘要以0開頭,將與填充數(shù)據(jù)無法區(qū)分
- 01:填充數(shù)據(jù)全為0XFF
- 02:填充數(shù)據(jù)必須為隨機(jī)數(shù)
1.5.2 RSA公鑰加密
使用RSA公鑰運(yùn)算,過程如下:
- 對原文數(shù)據(jù)填充、封裝->$P$
- 對P大數(shù)運(yùn)算:$C=P^e mod n$
用途:用于非對稱傳輸信息,比如Bob有一個信息想傳給Alice,需使用Alice的公鑰加密信息,傳給Alice,Alice得到加密信息后使用自己的私鑰即可解開讀取信息。他人即使截獲加密信息也無法解開,利用了大數(shù)分解難題。
1.5.3 RSA私鑰解密
使用RSA私鑰運(yùn)算,過程如下:
- 對密文數(shù)據(jù)大數(shù)運(yùn)算:$P=C^d mod n$
- 對P進(jìn)行去填充
以上可以看出,私鑰解密和簽名的運(yùn)算過程一致!
1.6 PKCS#1
定義RSA公私鑰數(shù)據(jù)表達(dá)形式,及加密,解密,簽名,驗簽,填充過程,定義了數(shù)字簽名如何計算,包括簽名數(shù)據(jù)和簽名本身的格式。
RSA公鑰結(jié)構(gòu):
RSAPublicKey :: = SEQUENCE{
modulus INTEGER, ------ n(RSA合數(shù)模)
publicExponent INTEGER ------ e (RSA公開冪,3~n-1范圍內(nèi)的正整數(shù))
}
RSA公鑰的ASN.1結(jié)構(gòu),可以表述為:名為RSAPublicKey的這個結(jié)構(gòu)呢,就可以用來表述一個RSA公鑰了。它有兩個INTEGER型變量:modulus和publicExponent。
RSA私鑰結(jié)構(gòu):
RSAPrivateKey :: = SEQUENCE{
version Version,(版本號,如果使用多素數(shù),版本號為1)
modulus INTEGER, ------ n(RSA合數(shù)模)
publicExponent INTEGER, ------ e(RSA的公開冪)
privateExponent INTEGER, ------ d(RSA的私有冪)
prime1 INTEGER, ------ p(n的素數(shù)因子p)
prime2 INTEGER, ------ q(n的素數(shù)因子q)
exponent1 INTEGER, ------ d mod (p -1)
exponent2 INTEGER, ------ d mod (q -1)
coefficient INTEGER, ------- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos ------ OPTIONAL(當(dāng)version為0時,不存在;當(dāng) version為1時,必須有)
}
加密和簽名方案的對象標(biāo)識
以下是對PKCS#1 OID的類型表示的定義
PKCS1Algorithms ALGORITHM-IDENTIFIER ::= {
{ OID rsaEncryption PARAMETERS NULL } |
{ OID md2WithRSAEncryption PARAMETERS NULL } |
{ OID md5WithRSAEncryption PARAMETERS NULL } |
{ OID sha1WithRSAEncryption PARAMETERS NULL } |
{ OID sha256WithRSAEncryption PARAMETERS NULL } |
{ OID sha384WithRSAEncryption PARAMETERS NULL } |
{ OID sha512WithRSAEncryption PARAMETERS NULL } |
{ OID id-RSAES-OAEP PARAMETERS RSAES-OAEP-params } |
PKCS1PSourceAlgorithms |
{ OID id-RSASSA-PSS PARAMETERS RSASSA-PSS-params } ,
... -- Allows for future expansion --
}
RSAES-OAEP加密
RSAES-OAEP-params ::= SEQUENCE {
hashAlgorithm [0] HashAlgorithm DEFAULT sha1,(標(biāo)識了散列函數(shù))
maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, (標(biāo)識掩膜生成函數(shù))
pSourceAlgorithm [2] PSourceAlgorithm DEFAULT pSpecifiedEmpty(標(biāo)識標(biāo)簽L的源)
}
hashAlgorithm
支持的散列函數(shù):
OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
{ OID id-sha1 PARAMETERS NULL }|
{ OID id-sha256 PARAMETERS NULL }|
{ OID id-sha384 PARAMETERS NULL }|
{ OID id-sha512 PARAMETERS NULL },
... -- Allows for future expansion --
}
1.7 PKCS#5
基于口令的加密規(guī)范Password-Based Cryptography Specification
目的:保護(hù)私鑰文件的安全性
通過將原始口令+salt派生出新口令進(jìn)行加密
PKSC5Padding(用于制定算法DES)對稱加密填充方式,填充塊固定為8個字節(jié),填充值為待填充的長度,與PKCS7Padding類似。
1.8 PKCS#7
加密消息的語法標(biāo)準(zhǔn)Cryptographic Message Syntax Version 1.5
結(jié)構(gòu):
typedef struct pkcs7_st
{
/* 其他項 */
ASN1_OBJECT *type;
union
{
char *ptr;
/* NID_pkcs7_data */
ASN1_OCTET_STRING *data;
/* NID_pkcs7_signed */
PKCS7_SIGNED *sign;
/* NID_pkcs7_enveloped */
PKCS7_ENVELOPE *enveloped;
/* NID_pkcs7_signedAndEnveloped */
PKCS7_SIGN_ENVELOPE *signed_and_enveloped;
/* NID_pkcs7_digest */
PKCS7_DIGEST *digest;
/* NID_pkcs7_encrypted */
PKCS7_ENCRYPT *encrypted;
/* Anything else */
ASN1_TYPE *other;
} d;
} PKCS7;
pkcs7 各種類型數(shù)據(jù)結(jié)構(gòu)的 DER 編解碼通過宏在 crypto/pkcs7/pk7_asn1.c 中實現(xiàn)
- 可以包含6種類型的數(shù)據(jù):
- id-data: 任意數(shù)據(jù),由應(yīng)用解析,可以是明文數(shù)據(jù)。
- id-signedData: 簽名數(shù)據(jù)
- id-envelopedData: 加密數(shù)據(jù)
- id-signedAndEnvelopedData: 簽名又加密數(shù)據(jù),數(shù)字信封
- id-digestedData: 摘要數(shù)據(jù),原文及摘要結(jié)果
- id-encryptedData: 只有加密數(shù)據(jù),密鑰在帶外傳送、管理
數(shù)字信封流程:(A:發(fā)送方;B:接收方;SK:私鑰;PK:公鑰)
A對明文進(jìn)行hash運(yùn)算,得到摘要
A用自己的私鑰A:SK對摘要進(jìn)行RSA私鑰加密運(yùn)算,得到A的數(shù)字簽名
A隨即產(chǎn)生一個用于特定加密算法的加密密鑰(DES密鑰),并使用該密鑰對明文進(jìn)行對稱加密,形成密文
A使用B的公鑰B:PK對隨機(jī)產(chǎn)生的加密密鑰進(jìn)行RSA公鑰加密運(yùn)算,并將結(jié)果與密文一同傳送給B
B用自己的私鑰B:SK對對稱加密的結(jié)果進(jìn)行RSA私鑰解密運(yùn)算,得到A隨機(jī)產(chǎn)生的對稱加密密鑰
B用加密密鑰對密文解密,得到明文
B用A的公鑰A:PK對A的數(shù)字簽名進(jìn)行RSA公鑰解密運(yùn)算,得到A的信息摘要
B用相同的hash算法對明文進(jìn)行hash運(yùn)算,得到新的信息摘要,并與收到的信息摘要比較,若一致,則說明明文未被修改,來自A。
常用的用途有:
- 證書鏈
- 數(shù)字信封
- 帶原文的簽名數(shù)據(jù)
PKCS#7結(jié)構(gòu)分析之?dāng)?shù)字信封
附:數(shù)字信封
構(gòu)造數(shù)字信封要能夠達(dá)到以下功能:
- 保密(對稱加密,RSA公鑰加密)
- 驗證完整性(MAC值)
- 驗證身份(簽名)
因此該結(jié)構(gòu)應(yīng)該包含:
- 明文加密后的密文cryptodata
- Hash函數(shù)生成的MAC值
- RSA私鑰加密的簽名值signdata
- (也應(yīng)該包含證書,由CA擔(dān)保身份)
1.8 PKCS#8
私鑰封裝格式Private_Key Information Syntax Specification Version 1.2
定義了私鑰信息語法和加密私鑰語法。
私鑰類型任意,對稱算法可設(shè)置
1.9 PKCS#10
證書請求格式(主題,公鑰,私鑰簽名)
RA注冊流程:注冊信息->審核通過->生成密鑰->生成PKCS10請求->將信息和P10請求的公鑰合并成CMP請求->發(fā)送到CA
1.10 PKCS#11
介質(zhì)接口格式:
- 硬件驅(qū)動
- 定義文件操作
- 權(quán)限管理
對應(yīng)于Windows的CSP,國密接口的SKF
1.11 PKCS#12
帶私鑰的個人證書格式,包含私鑰、證書、證書鏈、CRL...
1.12 X.509
X.509數(shù)字證書主體如下:
- 簽名前的證書申請(簽名對象的信息)
- 數(shù)字簽名的算法(CA對證書簽名使用的算法)
- 數(shù)字簽名(用于驗證證書的有效性,使用者使用CA的公鑰使用同種算法對證書簽名,查看和該數(shù)字簽名是否相同)
一個真實的X509數(shù)字證書包含:
- 證書版本(V3)
- 證書序列號
- 簽名算法(sha1RSA)
- 簽名哈希算法(sha1)
- 簽名
- 頒發(fā)者信息
- CN
- OU
- O組織
- L地點
- S州
- C
- 使用者信息
- 有效期
- 公鑰
- 密鑰用法
- Key Encipherment, Data Encipherment
- Digital Signature, Non-Repudiation
- CRL分發(fā)點
- 指紋算法
- 指紋
結(jié)構(gòu)
struct x509_st
{
X509_CINF *cert_info;
X509_ALGOR *sig_alg;
ASN1_BIT_STRING *signature;
int valid;
int references;
char *name;
CRYPTO_EX_DATA ex_data;
long ex_pathlen;
long ex_pcpathlen;
unsigned long ex_flags;
unsigned long ex_kusage;
unsigned long ex_xkusage;
unsigned long ex_nscert;
ASN1_OCTET_STRING *skid;
struct AUTHORITY_KEYID_st *akid;
X509_POLICY_CACHE *policy_cache;
#ifndef OPENSSL_NO_SHA
unsigned char sha1_hash[SHA_DIGEST_LENGTH];
#endif
X509_CERT_AUX *aux;
};
以上結(jié)構(gòu)表示一個完整的數(shù)字證書,主要項如下:
- cert_info:證書主體信息;
- sig_alg:簽名算法;
- signature:簽名值,存放CA對該證書采用sig_alg算法簽名的結(jié)果(驗證證書持有者身份時,使用該CA公鑰對該證書采用sig_alg簽名算法簽名得到signature1,將兩個簽名值比較,若相等,則表明是通過CA確認(rèn)的證書持有者);
- valid:是否是合法證書,1 為合法,0 為未知;
- references:引用次數(shù),被引用一次則加一;
- name:證書持有者信息該內(nèi)容在調(diào)用 d2i_X509的過程中,通過回調(diào)函數(shù) x509_cb(crypto/asn1/x_x509.c)調(diào)用 X509_NAME_oneline 來設(shè)置;
編程接口
DER 編解碼接口由宏在 crypto/asn1/x_x509.c 中實現(xiàn),包括各自的new、free、i2d 和 d2i 函數(shù):
- d2i_X509:解碼 DER 編碼的數(shù)字證書
- PEM_read_bio_X509:從PEM格式的數(shù)字證書中得到X509數(shù)據(jù)結(jié)構(gòu)
1.13 ASN.1
Abstract Syntax Notation One,抽象語法標(biāo)識,是與平臺、語言無關(guān)的數(shù)據(jù)結(jié)構(gòu)定義語法
編碼格式
BER、CER、DER、XER,可以編碼成XML格式,不僅僅是常用的二進(jìn)制流。
二進(jìn)制流的TLV方式表達(dá)數(shù)據(jù)結(jié)構(gòu),如下:
Identifier octets Type | Length octets Length | Contents octets Value | End-of-contents octets |
Personnel
Record Length Contents
60 8185
Name Length Contents
61 10
VisibleString Length Contents
1A 04 "John"
VisibleString Length Contents
1A 01 "P"
VisibleString Length Contents
1A 05 "Smith"
DateofBirth Length Contents
A0 0A
Date Length Contents
43 08 "19590717"
- BER: Basic Encoding Rules
- 基本編碼格式。
- 對相同的數(shù)據(jù),可以有多種編碼方式,比如長字節(jié)型、短字節(jié)型、不定長型等。
- DER: Distinguished Encoding Rules
- 是BER的一個子集,為更嚴(yán)格的一個變種版本。
- 和BER相比,DER的編碼格式只有固定一種。比如BER的Boolean變量編碼值是可以1~255的任意值,而DER只能是1。
- DER使用在有數(shù)據(jù)簽名的場合,以保證數(shù)據(jù)原文編碼后可以保持一致。
- X.509證書都是DER編碼。
- CER: Canonical Encoding Rules
- CER和DER一樣,都是BER的限定編碼規(guī)則的子集。
- CER和DER不同在于它是不定長編碼,可以用于大數(shù)據(jù)塊的封裝。
- PKCS#7數(shù)字信封可以用DER編碼,也可以用CER編碼。
- Privacy Enhanced Mail: 安全增強(qiáng)郵件,通過加密算法、證書加密郵件。
- 更常用的概念是一種文件格式,該文件格式使用一個頭、尾標(biāo)識文件的內(nèi)容,以方便解析。如下:
- 被加密的私鑰:
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
-----END ENCRYPTED PRIVATE KEY-----
- PEM格式的證書:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
- PEM格式的PKCS#10證書請求:
-----BEGIN CERTIFICATE REQUEST-----
...
-----END CERTIFICATE REQUEST-----
-
CER、DER、CRT、PEM的關(guān)系
- 所有X.509都是DER編碼,DER是指ASN.1的編碼規(guī)則,.der證書文件一般是二進(jìn)制文件。
- CER可用于PKCS#7證書(p7b)的編碼,但一般是指證書的文件后綴,.cer證書可以是純BASE64文件或二進(jìn)制文件。
- PEM通常也是指文件的后綴,為內(nèi)容使用BASE64編碼且?guī)ь^帶尾的特定格式,二進(jìn)制的文件不應(yīng)該命名為pem。
- CRT是微軟的證書后綴名,和.CER是一回事。
- 微軟的CryptAPI很強(qiáng)大,證書的各種格式都可以識別,比如純BASE64編碼的、標(biāo)準(zhǔn)PEM格式的、非標(biāo)識PEM格式的(不是64字節(jié)換行、沒有頭尾等)、二進(jìn)制格式的。
- 但openssl、JCE則不行,必須是標(biāo)準(zhǔn)的PEM格式和DER格式。
- references:
-
PFX
- Personal Information Exchange
- PKCS#12是PFX的后續(xù)版本,一般情況二者為等同概念。
- PFX或PKCS#12,是包括私鑰的個人證書,通過口令保護(hù)私鑰。
- 后綴名為.pfx或.p12
- 使用openssl、keytool、Portecle(KeyStore工具)都可以很方便生成PFX證書。
- references:
1.14 CRL
證書撤銷列表(Certificate Revocation List,簡稱 CRL),是一種包含撤銷的證書列表的簽名數(shù)據(jù)結(jié)構(gòu)?;镜?CRL 信息有:被撤銷證書序列號、撤銷時間、撤銷原因、簽名者以及 CRL 簽名等信息。
被撤銷證書的信息:X509_REVOKED
typedef struct X509_revoked_st
{
ASN1_INTEGER *serialNumber;
ASN1_TIME *revocationDate;
STACK_OF(X509_EXTENSION) *extensions;
int sequence;
} X509_REVOKED;
- serialNumber:被撤銷證書的序列號;
- revocationDate:撤銷時間;
- extensions:擴(kuò)展項,可選;
- sequence:順序號,用于排序,表示當(dāng)前被撤銷證書信息在 crl 中的順序。
crl信息主體:
typedef struct X509_crl_info_st
{
ASN1_INTEGER *version;
X509_ALGOR *sig_alg;
X509_NAME *issuer;
ASN1_TIME *lastUpdate;
ASN1_TIME *nextUpdate;
STACK_OF(X509_REVOKED) *revoked;
STACK_OF(X509_EXTENSION) *extensions;
ASN1_ENCODING enc;
} X509_CRL_INFO;
- version:crl 版本;
- sig_alg:crl 簽名法;
- issuer:簽發(fā)者信息;
- lastUpdate:上次更新時間;
- nextUpdate:下次更新時間;
- revoked:被撤銷證書信息;
- extensions:擴(kuò)展項,可選。
完整crl數(shù)據(jù)結(jié)構(gòu):
struct X509_crl_st
{
X509_CRL_INFO *crl;
X509_ALGOR *sig_alg;
ASN1_BIT_STRING *signature;
int references;
} ;
crl:crl 信息主體;
sig_alg:簽名算法,與 X509_CRL_INFO 中的一致;
signature:簽名值;
references:引用
附3 LDAP
輕量目錄訪問協(xié)議(Lightweight Directory Access Protocol),運(yùn)行于TCP/IP之上。
目錄的信息按照樹型結(jié)構(gòu)組織,數(shù)據(jù)結(jié)構(gòu):
條目entry->區(qū)別名DN->屬性Attribute->類型Type
|
->值Values
附4 OCSP
在線證書狀態(tài)協(xié)議(Online Certificate Status Protocol)
數(shù)據(jù)格式:
- 協(xié)議版本
- 服務(wù)請求
- 目標(biāo)證書標(biāo)識
- 可能被OCSP響應(yīng)器處理的可選擴(kuò)展
OCSP響應(yīng)端檢測:
- 信息正確格式化
- 響應(yīng)器被配置提供請求服務(wù)而且
- 請求包含了響應(yīng)器需要的信息,返回一個確定的回復(fù),OCSP響應(yīng)端回復(fù)的加密消息中包含證書的狀態(tài)可以是’good’,’revoked’或者’unknown’
- 如果任何一個先決條件沒有滿足,那么OCSP響應(yīng)器將產(chǎn)生一個錯誤信息,錯誤碼可能包含以下內(nèi)容:
- 未正確格式化的請求(malformedRequest)
- 內(nèi)部錯誤(internalError)
- 請稍后再試(trylater)
- 需要簽名(sigRequired)
- 未授權(quán)(unauthorized)
1.15 數(shù)字證書
發(fā)證流程:
- 申請者將合法的身份信息(參考X509章節(jié))以PKCS#10格式通過SCEP(簡單證書頒發(fā)協(xié)議,工作在HTTP之上)發(fā)送給CA,
- CA驗證申請者的合法性,滿足條件就會產(chǎn)生一個合法的證書,內(nèi)容包括身份信息、公鑰、CA信息、CA簽名、有效時間、序列號、CRL表的下載地址或查詢地址
- CA使用申請者公鑰將X.509v3加密得到密文格式證書,使用SCEP協(xié)議頒發(fā)給申請者
- 申請者使用自己的私鑰解密得到X.509v3證書并保存
雙證書:
雙證書即雙密鑰(簽名密鑰對,加密密鑰對)
- 簽名密鑰對用于數(shù)據(jù)完整性檢測,保證放偽造與防抵賴,若遺失,不影響以前數(shù)據(jù)的驗證。因此不需要第三方管理。
- 加密密鑰對用于數(shù)據(jù)的加密保護(hù),若遺失,將導(dǎo)致之前加密的數(shù)據(jù)無法解密。因此加密密鑰對應(yīng)有可信第三方(CA)產(chǎn)生備份。
(附:我曾今將整理的文件使用一款加密軟件加密,選擇加密密碼的時候由于自己記不住長密碼,又不想將長密碼以任何形式記錄下來,于是決定使用自認(rèn)為固定的文件作為密鑰,然后當(dāng)再次使用文件解密的時候,被告知不是該文件。才想起,這個當(dāng)時在我看來是固定的文件,由于版本需要被我修改了!整理的三個月的文件就這樣脫胎換骨成了0110...)
驗證過程
- 拆封證書
- 目的:獲取證書中的公鑰
- 驗證證書鏈
- 目的:驗證簽發(fā)用戶實體證書的CA是否是權(quán)威可信的CA
- 操作:使用每級CA的公鑰驗證每級數(shù)字簽名
- 驗證序列號
- 目的:檢查實體證書中的簽名實體序列號是否與簽發(fā)者證書的序列號相一致
- 操作:用戶實體證書中的Authority Key Identifier擴(kuò)展項Cert Serial Number,即簽發(fā)證書的序列號與CA證書中的Certificate Serial Number 證書序列號是否一致
- 證書廢止列表查詢(黑名單查詢,CRL)
- 目的:檢查用戶證書是否作廢
2 OpenSSL
2.1 命令行
構(gòu)建數(shù)字證書
主要操作包括產(chǎn)生私鑰(key),構(gòu)造證書請求(req),簽發(fā)用戶證書,自簽發(fā)根證書。
- 1.產(chǎn)生私鑰(帶密碼保護(hù)):
openssl genrsa -out mysite.key -des3 -passout pass:123456 1024
- 2.構(gòu)造證書請求
- 交互式輸入:
openssl req -key mysite.key -passin pass:123456 -new -out mysite.req
- 非交互式輸入,先編輯配置文件mysite.conf,然后生成請求:
openssl req -key mysite.key -passin pass:123456 -new -config mysite.conf -out mysite.req
- 交互式輸入:
- 3.簽發(fā)用戶證書:
openssl x509 -req -in mysite.req -CA testca.pem -CAkey testca.key -out mysite.pem -passin pass:abcdef -CAcreateserial
-days指定證書有效期 - 當(dāng)然,簽發(fā)用戶證書的前提是已經(jīng)自簽發(fā)根證書,先執(zhí)行1,2步生成根證書申請,然后自簽發(fā):
openssl x509 -req -in testCA.req -signkey testca.key -out testca.pem -passin pass:abcdef
2.2 編程
對稱算法和摘要算法全局初始化:OpenSSL_add_all_algorithms();
釋放句柄:EVP_MD_CTX_cleanup(&ctx);
2.2.1 加解密
int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char *key, unsigned char *iv, int enc)
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, unsigned char *in, int inl);
int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
2.2.2 摘要
int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
2.2.3 簽名驗簽(RSA/ECDSA)
EVP_SignInit ( &md_sign_ctx, md )
EVP_SignUpdate(&md_sign_ctx, data, data_cb)
EVP_SignFinal (&md_sign_ctx, sign, psign_cb, pPriKey )
EVP_VerifyInit( &md_verify_ctx, md )
EVP_VerifyUpdate(&md_verify_ctx, data, data_cb)
EVP_VerifyFinal(&md_verify_ctx, sign, sign_cb, pPubKey)
2.2.4 公鑰加密與私鑰解密(RSA算法)
int EVP_PKEY_encrypt ( EVP_PKEY_CTX * ctx, unsigned char * out, size_t * outlen, const unsigned char * in, size_t inlen )
2.2.5 PKCS7簽名驗簽(RSA/ECDSA)
p7 = PKCS7_sign(x, pPriKey, NULL, in, PKCS7_BINARY)
PKCS7_verify(p7, NULL, NULL, in, NULL, PKCS7_BINARY|PKCS7_NOVERIFY)
2.2.6 PKCS7數(shù)字信封加密解密(RSA)
p7 = PKCS7_encrypt(certs, in, EVP_des_cbc(), PKCS7_BINARY)
PKCS7_decrypt(p7, pPriKey, x, out, PKCS7_BINARY)
2.2.7解密公司的加密郵件(SMIME)
公司加密郵件為標(biāo)準(zhǔn)SMIME格式,導(dǎo)出后得到.eml文件
使用PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont)
將bio讀取到的SMIME格式保存在PKCS7格式內(nèi),然后通過PKCS7_dncrypt接口解密
2.2.8錯誤處理
錯誤處理應(yīng)該盡可能多的包含各種信息,包括:
- 錯誤碼;
- 出錯文件以及行號;
- 錯誤原因;
- 出錯函數(shù);
- 出錯庫;
- 出錯模塊與類別信息;
- 錯誤堆棧信息等。
ERR_get_error獲取第一個錯誤號
ERR_error_string根據(jù)錯誤碼獲取具體的錯誤信息,包括出錯的庫、出錯的函數(shù)以及出錯原因
ERR_print_errors_fp將錯誤打印到FILE中