《openssl编程》之基础知识
第一章?基礎知識
1.1?對稱算法
?對稱算法使用一個密鑰。給定一個明文和一個密鑰,加密產生密文,其長度和明文大致相同。解密時,使用讀密鑰與加密密鑰相同。
?對稱算法主要有四種加密模式:
(1)?電子密碼本模式??Electronic?Code?Book(ECB)
這種模式是最早采用和最簡單的模式,它將加密的數據分成若干組,每組的大小跟加密密鑰長度相同,然后每組都用相同的密鑰進行加密。
其缺點是:電子編碼薄模式用一個密鑰加密消息的所有塊,如果原消息中重復明文塊,則加密消息中的相應密文塊也會重復,因此,電子編碼薄模式適于加密小消息。
(2)加密塊鏈模式?Cipher?Block?Chaining(CBC)
CBC模式的加密首先也是將明文分成固定長度的塊,然后將前面一個加密塊輸出的密文與下一個要加密的明文塊進行異或操作,將計算結果再用密鑰進行加密得到密文。第一明文塊加密的時候,因為前面沒有加密的密文,所以需要一個初始化向量。跟ECB方式不一樣,通過連接關系,使得密文跟明文不再是一一對應的關系,破解起來更困難,而且克服了只要簡單調換密文塊可能達到目的的攻擊。
(3)加密反饋模式??????????Cipher?Feedback?Mode(CFB)
面向字符的應用程序的加密要使用流加密法,可以使用加密反饋模式。在此模式下,數據用更小的單元加密,如可以是8位,這個長度小于定義的塊長(通常是64位)。其加密步驟是:
a)?使用64位的初始化向量。初始化向量放在移位寄存器中,在第一步加密,產生相應的64位初始化密文; b)?始化向量最左邊的8位與明文前8位進行異或運算,產生密文第一部分(假設為c),然后將c傳輸到接收方;
c)?向量的位(即初始化向量所在的移位寄存器內容)左移8位,使移位寄存器最右邊的8位為不可預測的數據,在其中填入c的內容; d)?第1-3步,直到加密所有的明文單元。
解密過程相反
4)輸出反饋模式??????????Output?Feedback?Mode(OFB)
輸出反饋模式與CFB相似,惟一差別是,CFB中密文填入加密過程下一階段,而在OFB中,初始化向量加密過程的輸入填入加密過程下一階段。
1.2?摘要算法
?摘要算法是一種能產生特殊輸出格式的算法,這種算法的特點是:無論用戶輸入什么長度的原始數據,經過計算后輸出的密文都是固定長度的,這種算法的原理是根據一定的運算規則對原數據進行某種形式的提取,這種提取就是摘要,被摘要的數據內容與原數據有密切聯系,只要原數據稍有改變,輸出的“摘要”便完全不同,因此,基于這種原理的算法便能對數據完整性提供較為健全的保障。但是,由于輸出的密文是提取原數據經過處理的定長值,所以它已經不能還原為原數據,即消息摘要算法是不可逆的,理論上無法通過反向運算取得原數據內容,因此它通常只能被用來做數據完整性驗證。
如今常用的“消息摘要”算法經歷了多年驗證發展而保留下來的算法已經不多,這其中包括MD2、MD4、MD5、SHA、SHA-1/256/383/512等。
?常用的摘要算法主要有MD5和SHA1。D5的輸出結果為16字節,sha1的輸出結果為20字節。
1.3?公鑰算法
在公鑰密碼系統中,加密和解密使用的是不同的密鑰,這兩個密鑰之間存在著相互依存關系:即用其中任一個密鑰加密的信息只能用另一個密鑰進行解密。這使得通信雙方無需事先交換密鑰就可進行保密通信。其中加密密鑰和算法是對外公開的,人人都可以通過這個密鑰加密文件然后發給收信者,這個加密密鑰又稱為公鑰;而收信者收到加密文件后,它可以使用他的解密密鑰解密,這個密鑰是由他自己私人掌管的,并不需要分發,因此又成稱為私鑰,這就解決了密鑰分發的問題。
主要的公鑰算法有:RSA、DSA、DH和ECC。
(1)RSA算法
當前最著名、應用最廣泛的公鑰系統RSA是在1978年,由美國麻省理工學院(MIT)的Rivest、Shamir和Adleman在題為《獲得數字簽名和公開鑰密碼系統的方法》的論文中提出的。它是一個基于數論的非對稱(公開鑰)密碼體制,是一種分組密碼體制。其名稱來自于三個發明者的姓名首字母。?它的安全性是基于大整數素因子分解的困難性,而大整數因子分解問題是數學上的著名難題,至今沒有有效的方法予以解決,因此可以確保RSA算法的安全性。RSA系統是公鑰系統的最具有典型意義的方法,大多數使用公鑰密碼進行加密和數字簽名的產品和標準使用的都是RSA算法。
RSA算法是第一個既能用于數據加密也能用于數字簽名的算法,因此它為公用網絡上信息的加密和鑒別提供了一種基本的方法。它通常是先生成一對RSA?密鑰,其中之一是保密密鑰,由用戶保存;另一個為公開密鑰,可對外公開,甚至可在網絡服務器中注冊,人們用公鑰加密文件發送給個人,個人就可以用私鑰解密接受。為提高保密強度,RSA密鑰至少為500位長,一般推薦使用1024位。
RSA算法是R.Rivest、A.Shamir和L.Adleman于1977年在美國麻省理工學院開發,于1978年首次公布。
RSA公鑰密碼算法是目前網絡上進行保密通信和數字簽名的最有效的安全算法之一。RSA算法的安全性基于數論中大素數分解的困難性,所以,RSA需采用足夠大的整數。因子分解越困難,密碼就越難以破譯,加密強度就越高。?
其算法如下:
A.?選擇兩質數p、q
B.?計算n?=?p?*?q
C.?計算n的歐拉函數Φ(n)?=?(p?-?1)(q?-?1)
D.?選擇整數e,使e與Φ(n)互質,且1?<?e?<?Φ(n)
E.?計算d,使d?*?e?=?1?mod?Φ(n)
其中,公鑰KU={e,?n},私鑰KR={d,?n}。
加密/解密過程:
利用RSA加密,首先需將明文數字化,取長度小于log2n位的數字作為明文塊。
對于明文塊M和密文塊C,加/解密的形式如下:
加密:?C?=?Me?mod?n
解密:?M?=?Cd?mod?n?=?(Me)d?mod?n?=?Med?mod?n
RSA的安全性基于大數分解質因子的困難性。因為若n被分解為n?=?p?*?q,則Φ(n)、e、d可依次求得。目前,因式分解速度最快的方法的時間復雜性為exp(sqrt(ln(n)lnln(n)))。統計數據表明,在重要應用中,使用512位的密鑰已不安全,需要采用1024位的密鑰。
(2)DSA算法
DSA(Digital?Signature?Algorithm,數字簽名算法,用作數字簽名標準的一部分),它是另一種公開密鑰算法,它不能用作加密,只用作數字簽名。DSA使用公開密鑰,為接受者驗證數據的完整性和數據發送者的身份。它也可用于由第三方去確定簽名和所簽數據的真實性。DSA算法的安全性基于解離散對數的困難性,這類簽字標準具有較大的兼容性和適用性,成為網絡安全體系的基本構件之一。??
DSA簽名算法中用到了以下參數:?
p是L位長的素數,其中L從512到1024且是64的倍數。?
q是160位長且與p-1互素的因子?,其中h是小于p-1并且滿足?大于1的任意數。??
x是小于q的數。??
另外,算法使用一個單向散列函數H(m)。標準指定了安全散列算法(SHA)。三個參數p,q和g是公開的,且可以被網絡中所有的用戶公有。私人密鑰是x,公開密鑰是y。??
對消息m簽名時:??
(1)?發送者產生一個小于q的隨機數k。??
(2)?發送者產生:?
r和s就是發送者的簽名,發送者將它們發送給接受者。??
(3)?接受者通過計算來驗證簽名:
如果v=r,則簽名有效。?
(3)Diffie-Hellman密鑰交換
DH算法是W.Diffie和M.Hellman提出的。此算法是最早的公鑰算法。它實質是一個通信雙方進行密鑰協定的協議:兩個實體中的任何一個使用自己的私鑰和另一實體的公鑰,得到一個對稱密鑰,這一對稱密鑰其它實體都計算不出來。DH算法的安全性基于有限域上計算離散對數的困難性。離散對數的研究現狀表明:所使用的DH密鑰至少需要1024位,才能保證有足夠的中、長期安全。
(4)?橢圓曲線密碼體制(ECC)
1985年,N.?Koblitz和V.?Miller分別獨立提出了橢圓曲線密碼體制(ECC),其依據就是定義在橢圓曲線點群上的離散對數問題的難解性。?
為了用橢圓曲線構造密碼系統,首先需要找到一個單向陷門函數,橢圓曲線上的數量乘就是這樣的單向陷門函數。
橢圓曲線的數量乘是這樣定義的:設E為域K上的橢圓曲線,G為E上的一點,這個點被一個正整數k相乘的乘法定義為?k個G相加,因而有
kG?=?G?+?G?+?…?+?G???????(共有k個G)
若存在橢圓曲線上的另一點N?≠?G,滿足方程kG?=?N。容易看出,給定k和G,計算N相對容易。而給定N和G,計算k?=?logG?N相對困難。這就是橢圓曲線離散對數問題。
離散對數求解是非常困難的。橢圓曲線離散對數問題比有限域上的離散對數問題更難求解。對于有理點數有大素數因子的橢圓離散對數問題,目前還沒有有效的攻擊方法。
1.4?回調函數
?Openssl中大量用到了回調函數。回調函數一般定義在數據結構中,是一個函數指針。通過回調函數,客戶可以自行編寫函數,讓openssl函數來調用它,即用戶調用openssl提供的函數,openssl函數再回調用戶提供的函數。這樣方便了用戶對openssl函數操作的控制。在openssl實現函數中,它一般會實現一個默認的函數來進行處理,如果用戶不設置回調函數,則采用它默認的函數。
?回調函數舉例:
頭文件:
#ifndef?RANDOM_H
#define?RANDOM_H?1
typedef?int?*callback_random(char?*random,int?len);
void????set_callback(callback_random?*cb);
int?????genrate_random(char?*random,int?len);
#endif
源代碼:
#include?"random.h"
#include?<stdio.h>
callback_random?*cb_rand=NULL;
static?int?default_random(char?*random,int?len
{
????????memset(random,0x01,len);
????????return?0; }
void????set_callback(callback_random?*cb)
{
????????cb_rand=cb;
}
int?????genrate_random(char?*random,int?len) {
????????if(cb_rand==NULL)
????????????????return?default_random(random,len);
????????else
????????????????return?cb_rand(random,len);
????????return?0;
}
測試代碼:
#include?"random.h"
static?int?my_rand(char?*rand,int?len)
{
????????memset(rand,0x02,len);
????????return?0;
}
int?????main()
{
????????char????random[10];
????????int?????ret;
set_callback(my_rand);
????????ret=genrate_random(random,10);
????????return?0;
}
本例子用來生產簡單的隨機數,如果用戶提供了生成隨機數回調函數,則生成隨機數采用用戶的方法,否則采用默認的方法。
總結
以上是生活随笔為你收集整理的《openssl编程》之基础知识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IOCP不可忽视的细节
- 下一篇: 《openssl编程》之openssl简