des加密實現
網路安全通信中要用到兩類密碼演算法,一類是對稱密碼演算法,另一類是非對稱密碼演算法。對稱密碼演算法有時又叫傳統密碼演算法、秘密密鑰演算法或單密鑰演算法,非對稱密碼演算法也叫公開密鑰密碼演算法或雙密鑰演算法。對稱密碼演算法的加密密鑰能夠從解密密鑰中推算出來,反過來也成立。在大多數對稱演算法中,加密解密密鑰是相同的。它要求發送者和接收者在安全通信之前,商定一個密鑰。對稱演算法的安全性依賴於密鑰,泄漏密鑰就意味著任何人都能對消息進行加密解密。只要通信需要保密,密鑰就必須保密。
對稱演算法又可分為兩類。一次只對明文中的單個位(有時對位元組)運算的演算法稱為序列演算法或序列密碼。另一類演算法是對明文的一組位進行運算,這些位組稱為分組,相應的演算法稱為分組演算法或分組密碼。現代計算機密碼演算法的典型分組長度為64位――這個長度既考慮到分析破譯密碼的難度,又考慮到使用的方便性。後來,隨著破譯能力的發展,分組長度又提高到128位或更長。
常用的採用對稱密碼術的加密方案有5個組成部分(如圖所示)
1)明文:原始信息。
2)加密演算法:以密鑰為參數,對明文進行多種置換和轉換的規則和步驟,變換結果為密文。
3)密鑰:加密與解密演算法的參數,直接影響對明文進行變換的結果。
4)密文:對明文進行變換的結果。
5)解密演算法:加密演算法的逆變換,以密文為輸入、密鑰為參數,變換結果為明文。
對稱密碼當中有幾種常用到的數學運算。這些運算的共同目的就是把被加密的明文數碼盡可能深地打亂,從而加大破譯的難度。
◆移位和循環移位
移位就是將一段數碼按照規定的位數整體性地左移或右移。循環右移就是當右移時,把數碼的最後的位移到數碼的最前頭,循環左移正相反。例如,對十進制數碼12345678循環右移1位(十進制位)的結果為81234567,而循環左移1位的結果則為23456781。
◆置換
就是將數碼中的某一位的值根據置換表的規定,用另一位代替。它不像移位操作那樣整齊有序,看上去雜亂無章。這正是加密所需,被經常應用。
◆擴展
就是將一段數碼擴展成比原來位數更長的數碼。擴展方法有多種,例如,可以用置換的方法,以擴展置換表來規定擴展後的數碼每一位的替代值。
◆壓縮
就是將一段數碼壓縮成比原來位數更短的數碼。壓縮方法有多種,例如,也可以用置換的方法,以表來規定壓縮後的數碼每一位的替代值。
◆異或
這是一種二進制布爾代數運算。異或的數學符號為⊕ ,它的運演算法則如下:
1⊕1 = 0
0⊕0 = 0
1⊕0 = 1
0⊕1 = 1
也可以簡單地理解為,參與異或運算的兩數位如相等,則結果為0,不等則為1。
◆迭代
迭代就是多次重復相同的運算,這在密碼演算法中經常使用,以使得形成的密文更加難以破解。
下面我們將介紹一種流行的對稱密碼演算法DES。
DES是Data Encryption Standard(數據加密標准)的縮寫。它是由IBM公司研製的一種對稱密碼演算法,美國國家標准局於1977年公布把它作為非機要部門使用的數據加密標准,三十年來,它一直活躍在國際保密通信的舞台上,扮演了十分重要的角色。
DES是一個分組加密演算法,典型的DES以64位為分組對數據加密,加密和解密用的是同一個演算法。它的密鑰長度是56位(因為每個第8 位都用作奇偶校驗),密鑰可以是任意的56位的數,而且可以任意時候改變。其中有極少數被認為是易破解的弱密鑰,但是很容易避開它們不用。所以保密性依賴於密鑰。
DES加密的演算法框架如下:
首先要生成一套加密密鑰,從用戶處取得一個64位長的密碼口令,然後通過等分、移位、選取和迭代形成一套16個加密密鑰,分別供每一輪運算中使用。
DES對64位(bit)的明文分組M進行操作,M經過一個初始置換IP,置換成m0。將m0明文分成左半部分和右半部分m0 = (L0,R0),各32位長。然後進行16輪完全相同的運算(迭代),這些運算被稱為函數f,在每一輪運算過程中數據與相應的密鑰結合。
在每一輪中,密鑰位移位,然後再從密鑰的56位中選出48位。通過一個擴展置換將數據的右半部分擴展成48位,並通過一個異或操作替代成新的48位數據,再將其壓縮置換成32位。這四步運算構成了函數f。然後,通過另一個異或運算,函數f的輸出與左半部分結合,其結果成為新的右半部分,原來的右半部分成為新的左半部分。將該操作重復16次。
經過16輪迭代後,左,右半部分合在一起經過一個末置換(數據整理),這樣就完成了加密過程。
加密流程如圖所示。
DES解密過程:
在了解了加密過程中所有的代替、置換、異或和循環迭代之後,讀者也許會認為,解密演算法應該是加密的逆運算,與加密演算法完全不同。恰恰相反,經過密碼學家精心設計選擇的各種操作,DES獲得了一個非常有用的性質:加密和解密使用相同的演算法!
DES加密和解密唯一的不同是密鑰的次序相反。如果各輪加密密鑰分別是K1,K2,K3…K16,那麼解密密鑰就是K16,K15,K14…K1。這也就是DES被稱為對稱演算法的理由吧。
至於對稱密碼為什麼能對稱? DES具體是如何操作的?本文附錄中將做進一步介紹,有興趣的讀者不妨去讀一讀探個究竟
4.DES演算法的安全性和發展
DES的安全性首先取決於密鑰的長度。密鑰越長,破譯者利用窮舉法搜索密鑰的難度就越大。目前,根據當今計算機的處理速度和能力,56位長度的密鑰已經能夠被破解,而128位的密鑰則被認為是安全的,但隨著時間的推移,這個數字也遲早會被突破。
另外,對DES演算法進行某種變型和改進也是提高DES演算法安全性的途徑。
例如後來演變出的3-DES演算法使用了3個獨立密鑰進行三重DES加密,這就比DES大大提高了安全性。如果56位DES用窮舉搜索來破譯需要2∧56次運算,而3-DES 則需要2∧112次。
又如,獨立子密鑰DES由於每輪都使用不同的子密鑰,這意味著其密鑰長度在56位的基礎上擴大到768位。DES還有DESX、CRYPT、GDES、RDES等變型。這些變型和改進的目的都是為了加大破譯難度以及提高密碼運算的效率
『貳』 des演算法加密解密的實現
本文介紹了一種國際上通用的加密演算法—DES演算法的原理,並給出了在VC++6.0語言環境下實現的源代碼。最後給出一個示例,以供參考。
關鍵字:DES演算法、明文、密文、密鑰、VC;
本文程序運行效果圖如下:
正文:
當今社會是信息化的社會。為了適應社會對計算機數據安全保密越來越高的要求,美國國家標准局(NBS)於1997年公布了一個由IBM公司研製的一種加密演算法,並且確定為非機要部門使用的數據加密標准,簡稱DES(Data Encrypton Standard)。自公布之日起,DES演算法作為國際上商用保密通信和計算機通信的最常用演算法,一直活躍在國際保密通信的舞台上,扮演了十分突出的角色。現將DES演算法簡單介紹一下,並給出實現DES演算法的VC源代碼。
DES演算法由加密、解密和子密鑰的生成三部分組成。
一.加密
DES演算法處理的數據對象是一組64比特的明文串。設該明文串為m=m1m2…m64 (mi=0或1)。明文串經過64比特的密鑰K來加密,最後生成長度為64比特的密文E。其加密過程圖示如下:
DES演算法加密過程
對DES演算法加密過程圖示的說明如下:待加密的64比特明文串m,經過IP置換後,得到的比特串的下標列表如下:
IP 58 50 42 34 26 18 10 2
60 52 44 36 28 20 12 4
62 54 46 38 30 22 14 6
64 56 48 40 32 24 16 8
57 49 41 33 25 17 9 1
59 51 43 35 27 19 11 3
61 53 45 37 29 21 13 5
63 55 47 39 31 23 15 7
該比特串被分為32位的L0和32位的R0兩部分。R0子密鑰K1(子密鑰的生成將在後面講)經過變換f(R0,K1)(f變換將在下面講)輸出32位的比特串f1,f1與L0做不進位的二進制加法運算。運算規則為:
f1與L0做不進位的二進制加法運算後的結果賦給R1,R0則原封不動的賦給L1。L1與R0又做與以上完全相同的運算,生成L2,R2…… 一共經過16次運算。最後生成R16和L16。其中R16為L15與f(R15,K16)做不進位二進制加法運算的結果,L16是R15的直接賦值。
R16與L16合並成64位的比特串。值得注意的是R16一定要排在L16前面。R16與L16合並後成的比特串,經過置換IP-1後所得比特串的下標列表如下:
IP-1 40 8 48 16 56 24 64 32
39 7 47 15 55 23 63 31
38 6 46 14 54 22 62 30
37 5 45 13 53 21 61 29
36 4 44 12 52 20 60 28
35 3 43 11 51 19 59 27
34 2 42 10 50 18 58 26
33 1 41 9 49 17 57 25
經過置換IP-1後生成的比特串就是密文e.。
下面再講一下變換f(Ri-1,Ki)。
它的功能是將32比特的輸入再轉化為32比特的輸出。其過程如圖所示:
對f變換說明如下:輸入Ri-1(32比特)經過變換E後,膨脹為48比特。膨脹後的比特串的下標列表如下:
E: 32 1 2 3 4 5
4 5 6 7 8 9
8 9 10 11 12 13
12 13 14 15 16 17
16 17 18 19 20 21
20 21 22 23 24 25
24 25 26 27 28 29
28 29 30 31 32 31
膨脹後的比特串分為8組,每組6比特。各組經過各自的S盒後,又變為4比特(具體過程見後),合並後又成為32比特。該32比特經過P變換後,其下標列表如下:
P: 16 7 20 21
29 12 28 17
1 15 23 26
5 18 31 10
2 8 24 14
32 27 3 9
19 13 30 6
22 11 4 25
經過P變換後輸出的比特串才是32比特的f (Ri-1,Ki)。
下面再講一下S盒的變換過程。任取一S盒。見圖:
在其輸入b1,b2,b3,b4,b5,b6中,計算出x=b1*2+b6, y=b5+b4*2+b3*4+b2*8,再從Si表中查出x 行,y 列的值Sxy。將Sxy化為二進制,即得Si盒的輸出。(S表如圖所示)
至此,DES演算法加密原理講完了。在VC++6.0下的程序源代碼為:
for(i=1;i<=64;i++)
m1[i]=m[ip[i-1]];//64位明文串輸入,經過IP置換。
下面進行迭代。由於各次迭代的方法相同只是輸入輸出不同,因此只給出其中一次。以第八次為例://進行第八次迭代。首先進行S盒的運算,輸入32位比特串。
for(i=1;i<=48;i++)//經過E變換擴充,由32位變為48位
RE1[i]=R7[E[i-1]];
for(i=1;i<=48;i++)//與K8按位作不進位加法運算
RE1[i]=RE1[i]+K8[i];
for(i=1;i<=48;i++)
{
if(RE1[i]==2)
RE1[i]=0;
}
for(i=1;i<7;i++)//48位分成8組
{
s11[i]=RE1[i];
s21[i]=RE1[i+6];
s31[i]=RE1[i+12];
s41[i]=RE1[i+18];
s51[i]=RE1[i+24];
s61[i]=RE1[i+30];
s71[i]=RE1[i+36];
s81[i]=RE1[i+42];
}//下面經過S盒,得到8個數。S1,s2,s3,s4,s5,s6,s7,s8分別為S表
s[1]=s1[s11[6]+s11[1]*2][s11[5]+s11[4]*2+s11[3]*4+s11[2]*8];
s[2]=s2[s21[6]+s21[1]*2][s21[5]+s21[4]*2+s21[3]*4+s21[2]*8];
s[3]=s3[s31[6]+s31[1]*2][s31[5]+s31[4]*2+s31[3]*4+s31[2]*8];
s[4]=s4[s41[6]+s41[1]*2][s41[5]+s41[4]*2+s41[3]*4+s41[2]*8];
s[5]=s5[s51[6]+s51[1]*2][s51[5]+s51[4]*2+s51[3]*4+s51[2]*8];
s[6]=s6[s61[6]+s61[1]*2][s61[5]+s61[4]*2+s61[3]*4+s61[2]*8];
s[7]=s7[s71[6]+s71[1]*2][s71[5]+s71[4]*2+s71[3]*4+s71[2]*8];
s[8]=s8[s81[6]+s81[1]*2][s81[5]+s81[4]*2+s81[3]*4+s81[2]*8];
for(i=0;i<8;i++)//8個數變換輸出二進制
{
for(j=1;j<5;j++)
{
temp[j]=s[i+1]%2;
s[i+1]=s[i+1]/2;
}
for(j=1;j<5;j++)
f[4*i+j]=temp[5-j];
}
for(i=1;i<33;i++)//經過P變換
frk[i]=f[P[i-1]];//S盒運算完成
for(i=1;i<33;i++)//左右交換
L8[i]=R7[i];
for(i=1;i<33;i++)//R8為L7與f(R,K)進行不進位二進制加法運算結果
{
R8[i]=L7[i]+frk[i];
if(R8[i]==2)
R8[i]=0;
}
[ 原創文檔 本文適合中級讀者 已閱讀21783次 ] 文檔 代碼 工具
DES演算法及其在VC++6.0下的實現(下)
作者:航天醫學工程研究所四室 朱彥軍
在《DES演算法及其在VC++6.0下的實現(上)》中主要介紹了DES演算法的基本原理,下面讓我們繼續:
二.子密鑰的生成
64比特的密鑰生成16個48比特的子密鑰。其生成過程見圖:
子密鑰生成過程具體解釋如下:
64比特的密鑰K,經過PC-1後,生成56比特的串。其下標如表所示:
PC-1 57 49 41 33 25 17 9
1 58 50 42 34 26 18
10 2 59 51 43 35 27
19 11 3 60 52 44 36
63 55 47 39 31 23 15
7 62 54 46 38 30 22
14 6 61 53 45 37 29
21 13 5 28 20 12 4
該比特串分為長度相等的比特串C0和D0。然後C0和D0分別循環左移1位,得到C1和D1。C1和D1合並起來生成C1D1。C1D1經過PC-2變換後即生成48比特的K1。K1的下標列表為:
PC-2 14 17 11 24 1 5
3 28 15 6 21 10
23 19 12 4 26 8
16 7 27 20 13 2
41 52 31 37 47 55
30 40 51 45 33 48
44 49 39 56 34 53
46 42 50 36 29 32
C1、D1分別循環左移LS2位,再合並,經過PC-2,生成子密鑰K2……依次類推直至生成子密鑰K16。
注意:Lsi (I =1,2,….16)的數值是不同的。具體見下表:
迭代順序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
左移位數 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1
生成子密鑰的VC程序源代碼如下:
for(i=1;i<57;i++)//輸入64位K,經過PC-1變為56位 k0[i]=k[PC_1[i-1]];
56位的K0,均分為28位的C0,D0。C0,D0生成K1和C1,D1。以下幾次迭代方法相同,僅以生成K8為例。 for(i=1;i<27;i++)//循環左移兩位
{
C8[i]=C7[i+2];
D8[i]=D7[i+2];
}
C8[27]=C7[1];
D8[27]=D7[1];
C8[28]=C7[2];
D8[28]=D7[2];
for(i=1;i<=28;i++)
{
C[i]=C8[i];
C[i+28]=D8[i];
}
for(i=1;i<=48;i++)
K8[i]=C[PC_2[i-1]];//生成子密鑰k8
注意:生成的子密鑰不同,所需循環左移的位數也不同。源程序中以生成子密鑰 K8為例,所以循環左移了兩位。但在編程中,生成不同的子密鑰應以Lsi表為准。
三.解密
DES的解密過程和DES的加密過程完全類似,只不過將16圈的子密鑰序列K1,K2……K16的順序倒過來。即第一圈用第16個子密鑰K16,第二圈用K15,其餘類推。
第一圈:
加密後的結果
L=R15, R=L15⊕f(R15,K16)⊕f(R15,K16)=L15
同理R15=L14⊕f(R14,K15), L15=R14。
同理類推:
得 L=R0, R=L0。
其程序源代碼與加密相同。在此就不重寫。
四.示例
例如:已知明文m=learning, 密鑰 k=computer。
明文m的ASCII二進製表示:
m= 01101100 01100101 01100001 01110010
01101110 01101001 01101110 01100111
密鑰k的ASCII二進製表示:
k=01100011 01101111 01101101 01110000
01110101 01110100 01100101 01110010
明文m經過IP置換後,得:
11111111 00001000 11010011 10100110 00000000 11111111 01110001 11011000
等分為左右兩段:
L0=11111111 00001000 11010011 10100110 R0=00000000 11111111 01110001 11011000
經過16次迭代後,所得結果為:
L1=00000000 11111111 01110001 11011000 R1=00110101 00110001 00111011 10100101
L2=00110101 00110001 00111011 10100101 R2=00010111 11100010 10111010 10000111
L3=00010111 11100010 10111010 10000111 R3=00111110 10110001 00001011 10000100
L4= R4=
L5= R5=
L6= R6=
L7= R7=
L8= R8=
L9= R9=
L10= R10=
L11= R11=
L12= R12=
L13= R13=
L14= R14=
L15= R15=
L16= R16=
其中,f函數的結果為:
f1= f2=
f3= f4=
f5= f6=
f7= f8=
f9= f10=
f11= f12=
f13= f14=
f15= f16=
16個子密鑰為:
K1= K2=
K3= K4=
K5= K6=
K7= K8=
K9= K10=
K11= K12=
K13= K14=
K15= K16=
S盒中,16次運算時,每次的8 個結果為:
第一次:5,11,4,1,0,3,13,9;
第二次:7,13,15,8,12,12,13,1;
第三次:8,0,0,4,8,1,9,12;
第四次:0,7,4,1,7,6,12,4;
第五次:8,1,0,11,5,0,14,14;
第六次:14,12,13,2,7,15,14,10;
第七次:12,15,15,1,9,14,0,4;
第八次:15,8,8,3,2,3,14,5;
第九次:8,14,5,2,1,15,5,12;
第十次:2,8,13,1,9,2,10,2;
第十一次:10,15,8,2,1,12,12,3;
第十二次:5,4,4,0,14,10,7,4;
第十三次:2,13,10,9,2,4,3,13;
第十四次:13,7,14,9,15,0,1,3;
第十五次:3,1,15,5,11,9,11,4;
第十六次:12,3,4,6,9,3,3,0;
子密鑰生成過程中,生成的數值為:
C0=0000000011111111111111111011 D0=1000001101110110000001101000
C1=0000000111111111111111110110 D1=0000011011101100000011010001
C2=0000001111111111111111101100 D2=0000110111011000000110100010
C3=0000111111111111111110110000 D3=0011011101100000011010001000
C4=0011111111111111111011000000 D4=1101110110000001101000100000
C5=1111111111111111101100000000 D5=0111011000000110100010000011
C6=1111111111111110110000000011 D6=1101100000011010001000001101
C7=1111111111111011000000001111 D7=0110000001101000100000110111
C8=1111111111101100000000111111 D8=1000000110100010000011011101
C9=1111111111011000000001111111 D9=0000001101000100000110111011
C10=1111111101100000000111111111 D10=0000110100010000011011101100
C11=1111110110000000011111111111 D11=0011010001000001101110110000
C12=1111011000000001111111111111 D12=1101000100000110111011000000
C13=1101100000000111111111111111 D13=0100010000011011101100000011
C14=0110000000011111111111111111 D14=0001000001101110110000001101
C15=1000000001111111111111111101 D15=0100000110111011000000110100
C16=0000000011111111111111111011 D16=1000001101110110000001101000
解密過程與加密過程相反,所得的數據的順序恰好相反。在此就不贅述。
參考書目:
《計算機系統安全》 重慶出版社 盧開澄等編著
《計算機密碼應用基礎》 科學出版社 朱文余等編著
《Visual C++ 6.0 編程實例與技巧》 機械工業出版社 王華等編著
『叄』 DES加密演算法C語言實現
#include<iostream.h>
class SubKey{ //定義子密鑰為一個類
public:
int key[8][6];
}subkey[16]; //定義子密鑰對象數組
class DES{
int encipher_decipher; //判斷加密還是解密
int key_in[8][8]; //用戶原始輸入的64位二進制數
int key_out[8][7]; //除去每行的最後一位校驗位
int c0_d0[8][7]; //存儲經PC-1轉換後的56位數據
int c0[4][7],d0[4][7]; //分別存儲c0,d0
int text[8][8]; //64位明文
int text_ip[8][8]; //經IP轉換過後的明文
int A[4][8],B[4][8]; //A,B分別存儲經IP轉換過後明文的兩部分,便於交換
int temp[8][6]; //存儲經擴展置換後的48位二進制值
int temp1[8][6]; //存儲和子密鑰異或後的結果
int s_result[8][4]; //存儲經S變換後的32位值
int text_p[8][4]; //經P置換後的32位結果
int secret_ip[8][8]; //經逆IP轉換後的密文
public:
void Key_Putting();
void PC_1();
int function(int,int); //異或
void SubKey_Proction();
void IP_Convert();
void f();
void _IP_Convert();
void Out_secret();
};
void DES::Key_Putting() //得到密鑰中對演算法有用的56位
{
cout<<"請輸入64位的密鑰(8行8列且每行都得有奇數個1):\n";
for(int i=0;i<8;i++)
for(int j=0;j<8;j++){
cin>>key_in[i][j];
if(j!=7) key_out[i][j]=key_in[i][j];
}
}
void DES::PC_1() //PC-1置換函數
{
int pc_1[8][7]={ //PC-1
{57, 49, 41, 33, 25, 17, 9},
{1, 58, 50, 42, 34, 26, 18},
{10, 2, 59, 51, 43, 35, 27},
{19, 11, 3, 60, 52, 44, 36},
{63, 55, 47, 39, 31, 23, 15},
{7, 62, 54, 46, 38, 30, 22},
{14, 6, 61, 53, 45, 37, 29},
{21, 13, 5, 28, 20, 12, 4}
};
int i,j;
for(i=0;i<8;i++)
for(j=0;j<7;j++)
c0_d0[i][j]=key_out[ (pc_1[i][j]-1)/8 ][ (pc_1[i][j]-1)%8 ];
}
int DES::function(int a,int b) //模擬二進制數的異或運算,a和b為整型的0和1,返回值為整型的0或1
{
if(a!=b)return 1;
else return 0;
}
void DES::SubKey_Proction() //生成子密鑰
{
int move[16][2]={ //循環左移的位數
1 , 1 , 2 , 1 ,
3 , 2 , 4 , 2 ,
5 , 2 , 6 , 2 ,
7 , 2 , 8 , 2 ,
9 , 1, 10 , 2,
11 , 2, 12 , 2,
13 , 2, 14 , 2,
15 , 2, 16 , 1
};
int pc_2[8][6]={ //PC-2
14, 17 ,11 ,24 , 1 , 5,
3 ,28 ,15 , 6 ,21 ,10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20 ,13 , 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
};
for(int i=0;i<16;i++) //生成子密鑰
{
int j,k;
int a[2],b[2];
int bb[28],cc[28];
for(j=0;j<4;j++)
for(k=0;k<7;k++)
c0[j][k]=c0_d0[j][k];
for(j=4;j<8;j++)
for(k=0;k<7;k++)
d0[j-4][k]=c0_d0[j][k];
for(j=0;j<4;j++)
for(k=0;k<7;k++){
bb[7*j+k]=c0[j][k];
cc[7*j+k]=d0[j][k];
}
for(j=0;j<move[i][1];j++){
a[j]=bb[j];
b[j]=cc[j];
}
for(j=0;j<28-move[i][1];j++){
bb[j]=bb[j+1];
cc[j]=cc[j+1];
}
for(j=0;j<move[i][1];j++){
bb[27-j]=a[j];
cc[27-j]=b[j];
}
for(j=0;j<28;j++){
c0[j/7][j%7]=bb[j];
d0[j/7][j%7]=cc[j];
}
for(j=0;j<4;j++) //L123--L128是把c0,d0合並成c0_d0
for(k=0;k<7;k++)
c0_d0[j][k]=c0[j][k];
for(j=4;j<8;j++)
for(k=0;k<7;k++)
c0_d0[j][k]=d0[j-4][k];
for(j=0;j<8;j++) //對Ci,Di進行PC-2置換
for(k=0;k<6;k++)
subkey[i].key[j][k]=c0_d0[ (pc_2[j][k]-1)/7 ][ (pc_2[j][k]-1)%7 ];
}
}
void DES::IP_Convert()
{
int IP[8][8]={ //初始置換IP矩陣
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
};
cout<<"你好,你要加密還是解密?加密請按1號鍵(輸入1),解密請按2號鍵,並確定."<<'\n';
cin>>encipher_decipher;
char * s;
if(encipher_decipher==1) s="明文";
else s="密文";
cout<<"請輸入64位"<<s<<"(二進制):\n";
int i,j;
for(i=0;i<8;i++)
for(j=0;j<8;j++)
cin>>text[i][j];
for(i=0;i<8;i++) //進行IP變換
for(j=0;j<8;j++)
text_ip[i][j]=text[ (IP[i][j]-1)/8 ][ (IP[i][j]-1)%8 ];
}
『肆』 推導DES加密演算法原理
密碼體制從原理上可分為2大類,即單鑰密碼體制和雙鑰密碼體制。
單鑰密碼體制是指信息的發送方和接受方共享一把鑰匙。在現代網路通信條件下,該 體制的一個關鍵問題是如何將密鑰安全可靠地分配給通信的對方,並進行密鑰管理。因此單 鑰密碼體制在實際應用中除了要設計出滿足安全性要求的加密演算法外,還必須解決好密碼的 產生、分配、傳輸、存儲和銷毀等多方面問題。單鑰密碼可分為古典密碼、流密碼和分組密 碼,DES就屬於分組密碼中的一種。
雙鑰密碼體制又稱公鑰密碼體制,其最大特點是採用2個密鑰將加密、解密分開。在 雙鑰體制下,每個用戶都擁有2把密鑰,—個公開,一個自己專用。當使用用戶專用密鑰加 密,而用該用戶公開密鑰解密時,則可實現一個被加密的消息能被多個用戶解讀;當使用 用戶公開密鑰加密,而用該用戶專用密鑰解密時,則可實現傳輸的信息只被一個用戶解讀。 前者常被用於數字簽名,後者常被用於保密通信。
DES演算法詳述
DES演算法把64位的明文輸入塊變為64位的密文輸出塊,他所使用的密鑰也是64位,DES對64 位的明文分組進行操作。通過一個初始置換,將明文分組分成左半部分和右半部分,各32位 長。然後進行16輪相同的運算,這些相同的運算被稱為函數f,在運算過程中數據和密 鑰相結合。經過16輪運算後左、右部分在一起經過一個置換(初始置換的逆置換),這樣算 法就完成了。
『伍』 DES加密演算法 java實現
package des;
import java.io.*;
import java.nio.*;
import java.nio.channels.FileChannel;
public class FileDES{
private static final boolean enc=true; //加密
private static final boolean dec=false; //解密
private String srcFileName;
private String destFileName;
private String inKey;
private boolean actionType;
private File srcFile;
private File destFile;
private Des des;
private void analyzePath(){
String dirName;
int pos=srcFileName.lastIndexOf("/");
dirName=srcFileName.substring(0,pos);
File dir=new File(dirName);
if (!dir.exists()){
System.err.println(dirName+" is not exist");
System.exit(1);
}else if(!dir.isDirectory()){
System.err.println(dirName+" is not a directory");
System.exit(1);
}
pos=destFileName.lastIndexOf("/");
dirName=destFileName.substring(0,pos);
dir=new File(dirName);
if (!dir.exists()){
if(!dir.mkdirs()){
System.out.println ("can not creat directory:"+dirName);
System.exit(1);
}
}else if(!dir.isDirectory()){
System.err.println(dirName+" is not a directory");
System.exit(1);
}
}
private static int replenish(FileChannel channel,ByteBuffer buf) throws IOException{
long byteLeft=channel.size()-channel.position();
if(byteLeft==0L)
return -1;
buf.position(0);
buf.limit(buf.position()+(byteLeft<8 ? (int)byteLeft :8));
return channel.read(buf);
}
private void file_operate(boolean flag){
des=new Des(inKey);
FileOutputStream outputFile=null;
try {
outputFile=new FileOutputStream(srcFile,true);
}catch (java.io.FileNotFoundException e) {
e.printStackTrace(System.err);
}
FileChannel outChannel=outputFile.getChannel();
try{
if(outChannel.size()%2!=0){
ByteBuffer bufTemp=ByteBuffer.allocate(1);
bufTemp.put((byte)32);
bufTemp.flip();
outChannel.position(outChannel.size());
outChannel.write(bufTemp);
bufTemp.clear();
}
}catch(Exception ex){
ex.printStackTrace(System.err);
System.exit(1);
}
FileInputStream inFile=null;
try{
inFile=new FileInputStream(srcFile);
}catch(java.io.FileNotFoundException e){
e.printStackTrace(System.err);
//System.exit(1);
}
outputFile=null;
try {
outputFile=new FileOutputStream(destFile,true);
}catch (java.io.FileNotFoundException e) {
e.printStackTrace(System.err);
}
FileChannel inChannel=inFile.getChannel();
outChannel=outputFile.getChannel();
ByteBuffer inBuf=ByteBuffer.allocate(8);
ByteBuffer outBuf=ByteBuffer.allocate(8);
try{
String srcStr;
String destStr;
while(true){
if (replenish(inChannel,inBuf)==-1) break;
srcStr=((ByteBuffer)(inBuf.flip())).asCharBuffer().toString();
inBuf.clear();
if (flag)
destStr=des.enc(srcStr,srcStr.length());
else
destStr=des.dec(srcStr,srcStr.length());
outBuf.clear();
if (destStr.length()==4){
for (int i = 0; i<4; i++) {
outBuf.putChar(destStr.charAt(i));
}
outBuf.flip();
}else{
outBuf.position(0);
outBuf.limit(2*destStr.length());
for (int i = 0; i<destStr.length(); i++) {
outBuf.putChar(destStr.charAt(i));
}
outBuf.flip();
}
try {
outChannel.write(outBuf);
outBuf.clear();
}catch (java.io.IOException ex) {
ex.printStackTrace(System.err);
}
}
System.out.println (inChannel.size());
System.out.println (outChannel.size());
System.out.println ("EoF reached.");
inFile.close();
outputFile.close();
}catch(java.io.IOException e){
e.printStackTrace(System.err);
System.exit(1);
}
}
public FileDES(String srcFileName,String destFileName,String inKey,boolean actionType){
this.srcFileName=srcFileName;
this.destFileName=destFileName;
this.actionType=actionType;
analyzePath();
srcFile=new File(srcFileName);
destFile=new File(destFileName);
this.inKey=inKey;
if (actionType==enc)
file_operate(enc);
else
file_operate(dec);
}
public static void main(String[] args){
String file1=System.getProperty("user.dir")+"/111.doc";
String file2=System.getProperty("user.dir")+"/222.doc";
String file3=System.getProperty("user.dir")+"/333.doc";
String passWord="1234ABCD";
FileDES fileDes=new FileDES(file1,file2,passWord,true);
FileDES fileDes1=new FileDES(file2,file3,passWord,false);
}
『陸』 DES演算法加密的演算法步驟是
#define READFILESIZE 512
步驟:
1.從文件中讀取READFILESIZE個位元組的數據
2.,如果從文件中讀出的數據少於READFILESIZE個,以0補足,然後根據用戶指定的類型對這READFILESIZE個位元組的數據進行操作.
3.判斷文件是否結束,沒有則執行步驟1
4.把加密後的文件實際長度添加到密文的末尾
5.結束
採用一次只從文件讀取READFILESIZE個位元組是在為了防止由於需要加密或解密的文件太大導致內存不夠的情況出現。
『柒』 Des加密解密方法 用java C#和C++三種方式實現
Solaris下的系統,有一個用C做的加密工具,調用Sunwcry的des(1)對文件進行加密,然後在java中對文件進行解密。java中用的是標準的DES/CBC/NoPadding演算法,可是解密後發現開頭有8byte的數據出錯了,請高人指點一下。
cbc_encrypt.c : 加密用的C程序
cbc_decrypt.c:解密用的C程序
TestDescbc.java:解密用的java程序
Test01.dat原始文件
Test03.dat cbc_encrypt加密後的文件
Test05.dat cbc_decrypt解密後的文件
Test06.dat TestDescbc解密後的文件
『捌』 c#的這段des加密,用C怎麼才能實現
C#中的des加密,最重要的就是DESCryptoServiceProvider
真正的加密,微軟已經做好了。我們要做的就是塞進去,拿出來。
如果C中有類似的類,就可以操作,否則就要把整個演算法重做了。
還有一種作法是,用C#包裝一個dll,讓C調用,不過這樣子的結果就是最後也要.net支撐。
『玖』 對稱加密演算法之DES介紹
DES (Data Encryption Standard)是分組對稱密碼演算法。
DES演算法利用 多次組合替代演算法 和 換位演算法 ,分散和錯亂的相互作用,把明文編製成密碼強度很高的密文,它的加密和解密用的是同一演算法。
DES演算法,是一種 乘積密碼 ,其在演算法結構上主要採用了 置換 、 代替 、 模二相加 等函數,通過 輪函數 迭代的方式來進行計算和工作。
DES演算法也會使用到數據置換技術,主要有初始置換 IP 和逆初始置換 IP^-1 兩種類型。DES演算法使用置換運算的目的是將原始明文的所有格式及所有數據全部打亂重排。而在輪加密函數中,即將數據全部打亂重排,同時在數據格式方面,將原有的32位數據格式,擴展成為48位數據格式,目的是為了滿足S盒組對數據長度和數據格式規范的要求。
一組數據信息經過一系列的非線性變換以後,很難從中推導出其計算的過程和使用的非線性組合;但是如果這組數據信息使用的是線性變換,計算就容易的多。在DES演算法中,屬於非線性變換的計算過程只有S盒,其餘的數據計算和變換都是屬於線性變換,所以DES演算法安全的關鍵在於S盒的安全強度。此外,S盒和置換IP相互配合,形成了很強的抗差分攻擊和抗線性攻擊能力,其中抗差分攻擊能力更強一些。
DES演算法是一種分組加密機制,將明文分成N個組,然後對各個組進行加密,形成各自的密文,最後把所有的分組密文進行合並,形成最終的密文。
DES加密是對每個分組進行加密,所以輸入的參數為分組明文和密鑰,明文分組需要置換和迭代,密鑰也需要置換和循環移位。在初始置換IP中,根據一張8*8的置換表,將64位的明文打亂、打雜,從而提高加密的強度;再經過16次的迭代運算,在這些迭代運算中,要運用到子密鑰;每組形成的初始密文,再次經過初始逆置換 IP^-1 ,它是初始置換的逆運算,最後得到分組的最終密文。
圖2右半部分,給出了作用56比特密鑰的過程。DES演算法的加密密鑰是64比特,但是由於密鑰的第n*8(n=1,2…8)是校驗(保證含有奇數個1),因此實際參與加密的的密鑰只有 56比特 。開始時,密鑰經過一個置換,然後經過循環左移和另一個置換分別得到子密鑰ki,供每一輪的迭代加密使用。每輪的置換函數都一樣,但是由於密鑰位的重復迭代使得子密鑰互不相同。
DES演算法 利用多次組合替代演算法和換位演算法,分散和錯亂的相互作用,把明文編製成密碼強度很高的密文,它的加密和解密用的是同一演算法。
DES演算法詳述:DES對64位明文分組(密鑰56bit)進行操作。
1、 初始置換函數IP:64位明文分組x經過一個初始置換函數IP,產生64位的輸出x0,再將分組x0分成左半部分L0和右半部分R0:即將輸入的第58位換到第一位,第50位換到第2位,…,依次類推,最後一位是原來的第7位。L0、R0則是換位輸出後的兩部分,L0是輸出的左32位,R0是右32位。例,設置換前的輸入值為D1D2D3…D64,則經過初始置換後的結果為:L0=D58D50…D8;R0=D57D49…D7.其置換規則如表1所示。
DES加密過程最後的逆置換 IP^-1 ,是表1的 逆過程 。就是把原來的每一位都恢復過去,即把第1位的數據,放回到第58位,把第2位的數據,放回到第50位。
2、 獲取子密鑰 Ki :DES加密演算法的密鑰長度為56位,一般表示為64位(每個第8位用於奇偶校驗),將用戶提供的64位初始密鑰經過一系列的處理得到K1,K2,…,K16,分別作為 1~16 輪運算的 16個子密鑰 。
(1). 將64位密鑰去掉8個校驗位,用密鑰置換 PC-1 (表2)置換剩下的56位密鑰;
(2). 將56位分成前28位C0和後28位D0,即 PC-1(K56)=C0D0 ;
(3). 根據輪數,這兩部分分別循環左移1位或2位,表3:
(4). 移動後,將兩部分合並成56位後通過壓縮置換PC-2(表4)後得到48位子密鑰,即Ki=PC-2(CiDi).
子密鑰產生如圖2所示:
3、 密碼函數F(非線性的)
(1). 函數F的操作步驟:密碼函數F 的輸入是32比特數據和48比特的子密鑰:
A.擴展置換(E):將數據的右半部分Ri從32位擴展為48位。位選擇函數(也稱E盒),如表5所示:
B.異或:擴展後的48位輸出E(Ri)與壓縮後的48位密鑰Ki作異或運算;
C.S盒替代:將異或得到的48位結果分成八個6位的塊,每一塊通過對應的一個S盒產生一個4位的輸出。
(2)、D、P盒置換:將八個S盒的輸出連在一起生成一個32位的輸出,輸出結果再通過置換P產生一個32位的輸出即:F(Ri,Ki),F(Ri,Ki)演算法描述如圖3,最後,將P盒置換的結果與最初的64位分組的左半部分異或,然後,左、右半部分交換,開始下一輪計算。
4、密文輸出:經過16次迭代運算後,得到L16、R16,將此作為輸入,進行逆置換,即得到密文輸出。逆置換正好是初始置的逆運算。例如,第1位經過初始置換後,處於第40位,而通過逆置換,又將第40位換回到第1位,其逆置換規則如表8所示:
圖4為DES演算法加密原理圖:
DES演算法加密和解密過程採用相同的演算法,並採用相同的加密密鑰和解密密鑰,兩者的區別是:(1)、DES加密是從L0、R0到L15、R15進行變換,而解密時是從L15、R15到L0、R0進行變換的;(2)、加密時各輪的加密密鑰為K0K1…K15,而解密時各輪的解密密鑰為K15K14…K0;(3)、加密時密鑰循環左移,解密時密鑰循環右移。
DES加密過程分析:
(1)、首先要生成64位密鑰,這64位的密鑰經過「子密鑰演算法」換轉後,將得到總共16個子密鑰。將這些子密鑰標識為Kn(n=1,2,…,16)。這些子密鑰主要用於總共十六次的加密迭代過程中的加密工具。
(2)、其次要將明文信息按64位數據格式為一組,對所有明文信息進行分組處理。每一段的64位明文都要經過初試置換IP,置換的目的是將數據信息全部打亂重排。然後將打亂的數據分為左右兩塊,左邊一塊共32位為一組,標識為L0;右邊一塊也是32位為一組,標識為R0.
(3)、置換後的數據塊總共要進行總共十六次的加密迭代過程。加密迭代主要由加密函數f來實現。首先使用子密鑰K1對右邊32位的R0進行加密處理,得到的結果也是32位的;然後再將這個32位的結果數據與左邊32位的L0進行模2處理,從而再次得到一個32位的數據組。我們將最終得到的這個32位組數據,作為第二次加密迭代的L1,往後的每一次迭代過程都與上述過程相同。
(4)、在結束了最後一輪加密迭代之後,會產生一個64位的數據信息組,然後我們將這個64位數據信息組按原有的數據排列順序平均分為左右兩等分,然後將左右兩等分的部分進行位置調換,即原來左等分的數據整體位移至右側,而原來右等分的數據則整體位移至左側,這樣經過合並後的數據將再次經過逆初始置換IP^-1的計算,我們最終將得到一組64位的密文。
DES解密過程分析:DES的解密過程與它的加密過程是一樣的,這是由於DES演算法本身屬於對稱密碼體制演算法,其加密和解密的過程可以共用同一個過程和運算。
DES加密函數f:在DES演算法中,要將64位的明文順利加密輸出成64位的密文,而完成這項任務的核心部分就是加密函數f。加密函數f的主要作用是在第m次的加密迭代中使用子密鑰Km對Km-1進行加密操作。加密函數f在加密過程中總共需要運行16輪。
十六輪迭代演算法:它先將經過置換後的明文分成兩組,每組32位;同時密鑰也被分成了兩組,每組28位,兩組密鑰經過運算,再聯合成一個48位的密鑰,參與到明文加密的運算當中。S盒子,它由8個4*16的矩陣構成,每一行放著0到15的數據,順序各個不同,是由IBM公司設計好的。經過異或運算的明文,是一個48位的數據,在送入到S盒子的時候,被分成了8份,每份6位,每一份經過一個S盒子,經過運算後輸出為4位,即是一個0到15的數字的二進製表示形式。具體運算過程為,將輸入的6位中的第1位為第6位合並成一個二進制數,表示行號,其餘4位也合並成一個二進制數,表示列號。在當前S盒子中,以這個行號和列號為准,取出相應的數,並以二進制的形式表示,輸出,即得到4位的輸出,8個S盒子共計32位。
DES演算法優缺點:
(1)、產生密鑰簡單,但密鑰必須高度保密,因而難以做到一次一密;
(2)、DES的安全性依賴於密鑰的保密。攻擊破解DES演算法的一個主要方法是通過密鑰搜索,使用運算速度非常高的計算機通過排列組合枚舉的方式不斷嘗試各種可能的密鑰,直到破解為止。一般,DES演算法使用56位長的密鑰,通過簡單計算可知所有可能的密鑰數量最多是2^56個。隨著巨型計算機運算速度的不斷提高,DES演算法的安全性也將隨之下降,然而在一般的民用商業場合,DES的安全性仍是足夠可信賴的。
(3)、DES演算法加密解密速度比較快,密鑰比較短,加密效率很高但通信雙方都要保持密鑰的秘密性,為了安全還需要經常更換DES密鑰。
參考鏈接 : https://blog.csdn.net/fengbingchun/article/details/42273257
『拾』 如何使用JAVA實現對字元串的DES加密和解密
java加密字元串可以使用des加密演算法,實例如下:
package test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.*;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
/**
* 加密解密
*
* @author shy.qiu
* @since http://blog.csdn.net/qiushyfm
*/
public class CryptTest {
/**
* 進行MD5加密
*
* @param info
* 要加密的信息
* @return String 加密後的字元串
*/
public String encryptToMD5(String info) {
byte[] digesta = null;
try {
// 得到一個md5的消息摘要
MessageDigest alga = MessageDigest.getInstance("MD5");
// 添加要進行計算摘要的信息
alga.update(info.getBytes());
// 得到該摘要
digesta = alga.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 將摘要轉為字元串
String rs = byte2hex(digesta);
return rs;
}
/**
* 進行SHA加密
*
* @param info
* 要加密的信息
* @return String 加密後的字元串
*/
public String encryptToSHA(String info) {
byte[] digesta = null;
try {
// 得到一個SHA-1的消息摘要
MessageDigest alga = MessageDigest.getInstance("SHA-1");
// 添加要進行計算摘要的信息
alga.update(info.getBytes());
// 得到該摘要
digesta = alga.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 將摘要轉為字元串
String rs = byte2hex(digesta);
return rs;
}
// //////////////////////////////////////////////////////////////////////////
/**
* 創建密匙
*
* @param algorithm
* 加密演算法,可用 DES,DESede,Blowfish
* @return SecretKey 秘密(對稱)密鑰
*/
public SecretKey createSecretKey(String algorithm) {
// 聲明KeyGenerator對象
KeyGenerator keygen;
// 聲明 密鑰對象
SecretKey deskey = null;
try {
// 返回生成指定演算法的秘密密鑰的 KeyGenerator 對象
keygen = KeyGenerator.getInstance(algorithm);
// 生成一個密鑰
deskey = keygen.generateKey();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 返回密匙
return deskey;
}
/**
* 根據密匙進行DES加密
*
* @param key
* 密匙
* @param info
* 要加密的信息
* @return String 加密後的信息
*/
public String encryptToDES(SecretKey key, String info) {
// 定義 加密演算法,可用 DES,DESede,Blowfish
String Algorithm = "DES";
// 加密隨機數生成器 (RNG),(可以不寫)
SecureRandom sr = new SecureRandom();
// 定義要生成的密文
byte[] cipherByte = null;
try {
// 得到加密/解密器
Cipher c1 = Cipher.getInstance(Algorithm);
// 用指定的密鑰和模式初始化Cipher對象
// 參數:(ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE,UNWRAP_MODE)
c1.init(Cipher.ENCRYPT_MODE, key, sr);
// 對要加密的內容進行編碼處理,
cipherByte = c1.doFinal(info.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
// 返回密文的十六進制形式
return byte2hex(cipherByte);
}
/**
* 根據密匙進行DES解密
*
* @param key
* 密匙
* @param sInfo
* 要解密的密文
* @return String 返回解密後信息
*/
public String decryptByDES(SecretKey key, String sInfo) {
// 定義 加密演算法,
String Algorithm = "DES";
// 加密隨機數生成器 (RNG)
SecureRandom sr = new SecureRandom();
byte[] cipherByte = null;
try {
// 得到加密/解密器
Cipher c1 = Cipher.getInstance(Algorithm);
// 用指定的密鑰和模式初始化Cipher對象
c1.init(Cipher.DECRYPT_MODE, key, sr);
// 對要解密的內容進行編碼處理
cipherByte = c1.doFinal(hex2byte(sInfo));
} catch (Exception e) {
e.printStackTrace();
}
// return byte2hex(cipherByte);
return new String(cipherByte);
}
// /////////////////////////////////////////////////////////////////////////////
/**
* 創建密匙組,並將公匙,私匙放入到指定文件中
*
* 默認放入mykeys.bat文件中
*/
public void createPairKey() {
try {
// 根據特定的演算法一個密鑰對生成器
KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA");
// 加密隨機數生成器 (RNG)
SecureRandom random = new SecureRandom();
// 重新設置此隨機對象的種子
random.setSeed(1000);
// 使用給定的隨機源(和默認的參數集合)初始化確定密鑰大小的密鑰對生成器
keygen.initialize(512, random);// keygen.initialize(512);
// 生成密鑰組
KeyPair keys = keygen.generateKeyPair();
// 得到公匙
PublicKey pubkey = keys.getPublic();
// 得到私匙
PrivateKey prikey = keys.getPrivate();
// 將公匙私匙寫入到文件當中
doObjToFile("mykeys.bat", new Object[] { prikey, pubkey });
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 利用私匙對信息進行簽名 把簽名後的信息放入到指定的文件中
*
* @param info
* 要簽名的信息
* @param signfile
* 存入的文件
*/
public void signToInfo(String info, String signfile) {
// 從文件當中讀取私匙
PrivateKey myprikey = (PrivateKey) getObjFromFile("mykeys.bat", 1);
// 從文件中讀取公匙
PublicKey mypubkey = (PublicKey) getObjFromFile("mykeys.bat", 2);
try {
// Signature 對象可用來生成和驗證數字簽名
Signature signet = Signature.getInstance("DSA");
// 初始化簽署簽名的私鑰
signet.initSign(myprikey);
// 更新要由位元組簽名或驗證的數據
signet.update(info.getBytes());
// 簽署或驗證所有更新位元組的簽名,返回簽名
byte[] signed = signet.sign();
// 將數字簽名,公匙,信息放入文件中
doObjToFile(signfile, new Object[] { signed, mypubkey, info });
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 讀取數字簽名文件 根據公匙,簽名,信息驗證信息的合法性
*
* @return true 驗證成功 false 驗證失敗
*/
public boolean validateSign(String signfile) {
// 讀取公匙
PublicKey mypubkey = (PublicKey) getObjFromFile(signfile, 2);
// 讀取簽名
byte[] signed = (byte[]) getObjFromFile(signfile, 1);
// 讀取信息
String info = (String) getObjFromFile(signfile, 3);
try {
// 初始一個Signature對象,並用公鑰和簽名進行驗證
Signature signetcheck = Signature.getInstance("DSA");
// 初始化驗證簽名的公鑰
signetcheck.initVerify(mypubkey);
// 使用指定的 byte 數組更新要簽名或驗證的數據
signetcheck.update(info.getBytes());
System.out.println(info);
// 驗證傳入的簽名
return signetcheck.verify(signed);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 將二進制轉化為16進制字元串
*
* @param b
* 二進制位元組數組
* @return String
*/
public String byte2hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
return hs.toUpperCase();
}
/**
* 十六進制字元串轉化為2進制
*
* @param hex
* @return
*/
public byte[] hex2byte(String hex) {
byte[] ret = new byte[8];
byte[] tmp = hex.getBytes();
for (int i = 0; i < 8; i++) {
ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
}
return ret;
}
/**
* 將兩個ASCII字元合成一個位元組; 如:"EF"--> 0xEF
*
* @param src0
* byte
* @param src1
* byte
* @return byte
*/
public static byte uniteBytes(byte src0, byte src1) {
byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 }))
.byteValue();
_b0 = (byte) (_b0 << 4);
byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 }))
.byteValue();
byte ret = (byte) (_b0 ^ _b1);
return ret;
}
/**
* 將指定的對象寫入指定的文件
*
* @param file
* 指定寫入的文件
* @param objs
* 要寫入的對象
*/
public void doObjToFile(String file, Object[] objs) {
ObjectOutputStream oos = null;
try {
FileOutputStream fos = new FileOutputStream(file);
oos = new ObjectOutputStream(fos);
for (int i = 0; i < objs.length; i++) {
oos.writeObject(objs[i]);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 返回在文件中指定位置的對象
*
* @param file
* 指定的文件
* @param i
* 從1開始
* @return
*/
public Object getObjFromFile(String file, int i) {
ObjectInputStream ois = null;
Object obj = null;
try {
FileInputStream fis = new FileInputStream(file);
ois = new ObjectInputStream(fis);
for (int j = 0; j < i; j++) {
obj = ois.readObject();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return obj;
}
/**
* 測試
*
* @param args
*/
public static void main(String[] args) {
CryptTest jiami = new CryptTest();
// 執行MD5加密"Hello world!"
System.out.println("Hello經過MD5:" + jiami.encryptToMD5("Hello"));
// 生成一個DES演算法的密匙
SecretKey key = jiami.createSecretKey("DES");
// 用密匙加密信息"Hello world!"
String str1 = jiami.encryptToDES(key, "Hello");
System.out.println("使用des加密信息Hello為:" + str1);
// 使用這個密匙解密
String str2 = jiami.decryptByDES(key, str1);
System.out.println("解密後為:" + str2);
// 創建公匙和私匙
jiami.createPairKey();
// 對Hello world!使用私匙進行簽名
jiami.signToInfo("Hello", "mysign.bat");
// 利用公匙對簽名進行驗證。
if (jiami.validateSign("mysign.bat")) {
System.out.println("Success!");
} else {
System.out.println("Fail!");
}
}
}