3des演算法c語言實現
DES加密經過下面的步驟
1、提供明文和密鑰,將明文按照64bit分塊(對應8個位元組),不足8個位元組的可以進行填充(填充方式多種),密鑰必須為8個位元組共64bit
填充方式:
當明文長度不為分組長度的整數倍時,需要在最後一個分組中填充一些數據使其湊滿一個分組長度。
* NoPadding
API或演算法本身不對數據進行處理,加密數據由加密雙方約定填補演算法。例如若對字元串數據進行加解密,可以補充\0或者空格,然後trim
* PKCS5Padding
加密前:數據位元組長度對8取余,余數為m,若m>0,則補足8-m個位元組,位元組數值為8-m,即差幾個位元組就補幾個位元組,位元組數值即為補充的位元組數,若為0則補充8個位元組的8
解密後:取最後一個位元組,值為m,則從數據尾部刪除m個位元組,剩餘數據即為加密前的原文。
例如:加密字元串為為AAA,則補位為AAA55555;加密字元串為BBBBBB,則補位為BBBBBB22;加密字元串為CCCCCCCC,則補位為CCCCCCCC88888888。
* PKCS7Padding
PKCS7Padding 的填充方式和PKCS5Padding 填充方式一樣。只是加密塊的位元組數不同。PKCS5Padding明確定義了加密塊是8位元組,PKCS7Padding加密快可以是1-255之間。
2、選擇加密模式
**ECB模式** 全稱Electronic Codebook模式,譯為電子密碼本模式
**CBC模式** 全稱Cipher Block Chaining模式,譯為密文分組鏈接模式
**CFB模式** 全稱Cipher FeedBack模式,譯為密文反饋模式
**OFB模式** 全稱Output Feedback模式,譯為輸出反饋模式。
**CTR模式** 全稱Counter模式,譯為計數器模式。
3、開始加密明文(內部原理--加密步驟,加密演算法實現不做講解)
image
1、將分塊的64bit一組組加密,示列其中一組:將此組進行初始置換(IP置換),目的是將輸入的64位數據塊按位重新組合,並把輸出分為L0、R0兩部分,每部分各長32位。
2、開始Feistel結構的16次轉換,第一次轉換為:右側數據R0和子密鑰經過輪函數f生成用於加密左側數據的比特序列,與左側數據L0異或運算,
運算結果輸出為加密後的左側L0,右側數據則直接輸出為右側R0。由於一次Feistel輪並不會加密右側,因此需要將上一輪輸出後的左右兩側對調後才正式完成一次Feistel加密,
3、DES演算法共計進行16次Feistel輪,最後一輪輸出後左右兩側無需對調,每次加密的子密鑰不相同,子密鑰是通過秘鑰計算得到的。
4、末置換是初始置換的逆過程,DES最後一輪後,左、右兩半部分並未進行交換,而是兩部分合並形成一個分組做為末置換的輸入
DES解密經過下面的步驟
1、拿到密文和加密的密鑰
2、解密:DES加密和解密的過程一致,均使用Feistel網路實現,區別僅在於解密時,密文作為輸入,並逆序使用子密鑰。
3、講解密後的明文去填充 (padding)得到的即為明文
Golang實現DES加密解密
package main
import (
"fmt"
"crypto/des"
"bytes"
"crypto/cipher"
)
func main() {
var miwen,_= DESEncode([]byte("hello world"),[]byte("12345678"))
fmt.Println(miwen) // [11 42 146 232 31 180 156 225 164 50 102 170 202 234 123 129],密文:最後5位是補碼
var txt,_ = DESDecode(miwen,[]byte("12345678"))
fmt.Println(txt) // [104 101 108 108 111 32 119 111 114 108 100]明碼
fmt.Printf("%s",txt) // hello world
}
// 加密函數
func DESEncode(orignData, key []byte)([]byte,error){
// 建立密碼塊
block ,err:=des.NewCipher(key)
if err!=nil{ return nil,err}
// 明文分組,不足的部分加padding
txt := PKCS5Padding(orignData,block.BlockSize())
// 設定加密模式,為了方便,初始向量直接使用key充當了(實際項目中,最好別這么做)
blockMode := cipher.NewCBCEncrypter(block,key)
// 創建密文長度的切片,用來存放密文位元組
crypted :=make([]byte,len(txt))
// 開始加密,將txt作為源,crypted作為目的切片輸入
blockMode.CryptBlocks(crypted,txt)
// 將加密後的切片返回
return crypted,nil
}
// 加密所需padding
func PKCS5Padding(ciphertext []byte,size int)[]byte{
padding := size - len(ciphertext)%size
padTex := bytes.Repeat([]byte{byte(padding)},padding)
return append(ciphertext,padTex...)
}
// 解密函數
func DESDecode(cripter, key []byte) ([]byte,error) {
// 建立密碼塊
block ,err:=des.NewCipher(key)
if err!=nil{ return nil,err}
// 設置解密模式,加密模式和解密模式要一樣
blockMode := cipher.NewCBCDecrypter(block,key)
// 設置切片長度,用來存放明文位元組
originData := make([]byte,len(cripter))
// 使用解密模式解密,將解密後的明文位元組放入originData 切片中
blockMode.CryptBlocks(originData,cripter)
// 去除加密的padding部分
strByt := UnPKCS5Padding(origenData)
return strByt,nil
}
// 解密所需要的Unpadding
func UnPKCS5Padding(origin []byte) []byte{
// 獲取最後一位轉為整型,然後根據這個整型截取掉整型數量的長度
// 若此數為5,則減掉轉換明文後的最後5位,即為我們輸入的明文
var last = int(origin[len(origin)-1])
return origin[:len(origin)-last]
}
注意:在設置加密模式為CBC的時候,我們需要設置一個初始化向量,這個量的意思 在對稱加密演算法中,如果只有一個密鑰來加密數據的話,明文中的相同文字就會也會被加密成相同的密文,這樣密文和明文就有完全相同的結構,容易破解,如果給一個初始化向量,第一個明文使用初始化向量混合並加密,第二個明文用第一個明文的加密後的密文與第二個明文混合加密,這樣加密出來的密文的結構則完全與明文不同,更加安全可靠。CBC模式圖如下
CBC
3DES
DES 的常見變體是三重 DES,使用 168 位的密鑰對資料進行三次加密的一種機制;它通常(但非始終)提供極其強大的安全性。如果三個 56 位的子元素都相同,則三重 DES 向後兼容 DES。
對比DES,發現只是換了NewTripleDESCipher。不過,需要注意的是,密鑰長度必須24byte,否則直接返回錯誤。關於這一點,PHP中卻不是這樣的,只要是8byte以上就行;而Java中,要求必須是24byte以上,內部會取前24byte(相當於就是24byte)。另外,初始化向量長度是8byte(目前各個語言都是如此,不是8byte會有問題)
㈡ 對稱加密演算法的加密演算法主要有哪些
1、3DES演算法
3DES(即Triple DES)是DES向AES過渡的加密演算法(1999年,NIST將3-DES指定為過渡的加密標准),加密演算法,其具體實現如下:設Ek()和Dk()代表DES演算法的加密和解密過程,K代表DES演算法使用的密鑰,M代表明文,C代表密文,這樣:
3DES加密過程為:C=Ek3(Dk2(Ek1(M)))
3DES解密過程為:M=Dk1(EK2(Dk3(C)))
2、Blowfish演算法
BlowFish演算法用來加密64Bit長度的字元串。
BlowFish演算法使用兩個「盒」——unsignedlongpbox[18]和unsignedlongsbox[4,256]。
BlowFish演算法中,有一個核心加密函數:BF_En(後文詳細介紹)。該函數輸入64位信息,運算後,以64位密文的形式輸出。用BlowFish演算法加密信息,需要兩個過程:密鑰預處理和信息加密。
分別說明如下:
密鑰預處理:
BlowFish演算法的源密鑰——pbox和sbox是固定的。我們要加密一個信息,需要自己選擇一個key,用這個key對pbox和sbox進行變換,得到下一步信息加密所要用的key_pbox和key_sbox。具體的變化演算法如下:
1)用sbox填充key_sbox
2)用自己選擇的key8個一組地去異或pbox,用異或的結果填充key_pbox。key可以循環使用。
比如說:選的key是"abcdefghijklmn"。則異或過程為:
key_pbox[0]=pbox[0]abcdefgh;
key_pbox[1]=pbox[1]ijklmnab;
…………
…………
如此循環,直到key_pbox填充完畢。
3)用BF_En加密一個全0的64位信息,用輸出的結果替換key_pbox[0]和key_pbox[1],i=0;
4)用BF_En加密替換後的key_pbox,key_pbox[i+1],用輸出替代key_pbox[i+2]和key_pbox[i+3];
5)i+2,繼續第4步,直到key_pbox全部被替換;
6)用key_pbox[16]和key_pbox[17]做首次輸入(相當於上面的全0的輸入),用類似的方法,替換key_sbox信息加密。
信息加密就是用函數把待加密信息x分成32位的兩部分:xL,xRBF_En對輸入信息進行變換。
3、RC5演算法
RC5是種比較新的演算法,Rivest設計了RC5的一種特殊的實現方式,因此RC5演算法有一個面向字的結構:RC5-w/r/b,這里w是字長其值可以是16、32或64對於不同的字長明文和密文塊的分組長度為2w位,r是加密輪數,b是密鑰位元組長度。
(2)3des演算法c語言實現擴展閱讀:
普遍而言,有3個獨立密鑰的3DES(密鑰選項1)的密鑰長度為168位(三個56位的DES密鑰),但由於中途相遇攻擊,它的有效安全性僅為112位。密鑰選項2將密鑰長度縮短到了112位,但該選項對特定的選擇明文攻擊和已知明文攻擊的強度較弱,因此NIST認定它只有80位的安全性。
對密鑰選項1的已知最佳攻擊需要約2組已知明文,2部,2次DES加密以及2位內存(該論文提到了時間和內存的其它分配方案)。
這在現在是不現實的,因此NIST認為密鑰選項1可以使用到2030年。若攻擊者試圖在一些可能的(而不是全部的)密鑰中找到正確的,有一種在內存效率上較高的攻擊方法可以用每個密鑰對應的少數選擇明文和約2次加密操作找到2個目標密鑰中的一個。
㈢ 如何用C實現3DES演算法..
//功能:實現DES及3DES加解密的演算法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "des.h"
//函數聲明
int Do_DES(char* strSrc, char* strKey, char* strDest, char flag);
int Do_3DES(char* strSrc, char* strKey, char* strDest, char flag);
//主函數
int main(int argc, char** argv)
{
char src16[16+1],key16[16+1],key48[48+1],dest16[16+1];
if(argc != 3)
{
fprintf(stderr,"Usage: [%s -e|-d s|3]\n",argv[0]);
exit(1);
}
if(strcmp(argv[2],"-s") == 0)
{
if(strcmp(argv[1],"-e") == 0)
{
fprintf(stderr,"Please input the string that you want to encrypt(16 hex number):\n");
memset(src16,0,sizeof(src16));
scanf("%s",src16);
fprintf(stderr,"Please input the Key string(16 hex number):\n");
memset(key16,0,sizeof(key16));
scanf("%s",key16);
memset(dest16,0,sizeof(dest16));
Do_DES(src16,key16,dest16,'e');
fprintf(stderr,"Result: [%s]\n",dest16);
}
else if(strcmp(argv[1],"-d") == 0)
{
fprintf(stderr,"Please input the string that you want to decrypt(16 hex number):\n");
memset(src16,0,sizeof(src16));
scanf("%s",src16);
fprintf(stderr,"Please input the Key string(16 hex number):\n");
memset(key16,0,sizeof(key16));
scanf("%s",key16);
memset(dest16,0,sizeof(dest16));
Do_DES(src16,key16,dest16,'d');
fprintf(stderr,"Result: [%s]\n",dest16);
}
else
return -1;
}
else if(strcmp(argv[2],"-3") == 0)
{
if(strcmp(argv[1],"-e") == 0)
{
fprintf(stderr,"Please input the string that you want to encrypt(16 hex number):\n");
memset(src16,0,sizeof(src16));
scanf("%s",src16);
fprintf(stderr,"Please input the Key string(16 hex number):\n");
memset(key48,0,sizeof(key48));
scanf("%s",key48);
memset(dest16,0,sizeof(dest16));
Do_3DES(src16,key48,dest16,'e');
fprintf(stderr,"Result: [%s]\n",dest16);
}
else if(strcmp(argv[1],"-d") == 0)
{
fprintf(stderr,"Please input the string that you want to decrypt(16 hex number):\n");
memset(src16,0,sizeof(src16));
scanf("%s",src16);
fprintf(stderr,"Please input the Key string(16 hex number):\n");
memset(key48,0,sizeof(key48));
scanf("%s",key48);
memset(dest16,0,sizeof(dest16));
Do_3DES(src16,key48,dest16,'d');
fprintf(stderr,"Result: [%s]\n",dest16);
}
else
return -1;
}
else
return -1;
return 0;
}
//做DES加密或解密運算
int Do_DES(char* strSrc, char* strKey, char* strDest, char flag)
{
int i,j;
unsigned char subKey[16][48+1],byte8[8+1],bits[64+1],strTmp[64+1];
unsigned char L0[32+1],R0[32+1],Lx[32+1],Rx[32+1];
if(!( flag == 'e' || flag == 'E' || flag == 'd' || flag == 'D'))
return -1;
if(strSrc == NULL || strKey == NULL)
return -2;
if(flag == 'e' || flag == 'E')
{
memset(byte8,0,sizeof(byte8));
BCDToByte(strKey, 16, byte8);
memset(bits,0,sizeof(bits));
ByteToBit(byte8, 8, bits);
Des_GenSubKey(bits,subKey);
BCDToByte(strSrc, 16, byte8);
ByteToBit(byte8, 8, bits);
Des_IP(bits, strTmp);
memcpy(L0,strTmp,32);
memcpy(R0,strTmp+32,32);
for(i=0;i<16;i++)
{
memcpy(Lx,R0,32);
Des_F(R0,subKey[i],Rx);
Do_XOR(L0,32,Rx);
memcpy(L0,Lx,32);
memcpy(R0,Rx,32);
}
memcpy(bits,R0,32);
memcpy(bits+32,L0,32);
Des_IP_1(bits,strTmp);
BitToByte(strTmp,64,byte8);
ByteToBCD(byte8,8,strDest);
}
else
{
memset(byte8,0,sizeof(byte8));
BCDToByte(strKey, 16, byte8);
memset(bits,0,sizeof(bits));
ByteToBit(byte8, 8, bits);
Des_GenSubKey(bits,subKey);
BCDToByte(strSrc, 16, byte8);
ByteToBit(byte8, 8, bits);
Des_IP(bits, strTmp);
memcpy(L0,strTmp,32);
memcpy(R0,strTmp+32,32);
for(i=0;i<16;i++)
{
memcpy(Lx,R0,32);
Des_F(R0,subKey[15-i],Rx);
Do_XOR(L0,32,Rx);
memcpy(L0,Lx,32);
memcpy(R0,Rx,32);
}
memcpy(bits,R0,32);
memcpy(bits+32,L0,32);
Des_IP_1(bits,strTmp);
BitToByte(strTmp,64,byte8);
ByteToBCD(byte8,8,strDest);
}
return 0;
}
//做3DES加密或解密運算
int Do_3DES(char* strSrc, char* strKey, char* strDest, char flag)
{
unsigned char strBCDKey[32+1],strByteKey[16+1];
unsigned char strMidDest1[16+1],strMidDest2[16+1];
unsigned char strLKey[16+1],strMKey[16+1],strRKey[16+1];
if(!( flag == 'e' || flag == 'E' || flag == 'd' || flag == 'D'))
return -1;
if(strSrc == NULL || strKey == NULL)
return -2;
if(strlen(strKey) < 32)
return -3;
if(flag == 'e' || flag == 'E')
{
memset(strBCDKey,0,sizeof(strBCDKey));
memcpy(strBCDKey,strKey,32);
memset(strLKey,0,sizeof(strLKey));
memcpy(strLKey,strBCDKey,16);
memset(strRKey,0,sizeof(strRKey));
memcpy(strRKey,strBCDKey+16,16);
Do_DES(strSrc,strLKey,strMidDest1,'e');
Do_DES(strMidDest1,strRKey,strMidDest2,'d');
Do_DES(strMidDest2,strLKey,strMidDest1,'e');
memcpy(strDest,strMidDest1,16);
}
else
{
memset(strBCDKey,0,sizeof(strBCDKey));
memcpy(strBCDKey,strKey,32);
memset(strLKey,0,sizeof(strLKey));
memcpy(strLKey,strBCDKey,16);
memset(strRKey,0,sizeof(strRKey));
memcpy(strRKey,strBCDKey+16,16);
Do_DES(strSrc,strLKey,strMidDest1,'d');
Do_DES(strMidDest1,strRKey,strMidDest2,'e');
Do_DES(strMidDest2,strLKey,strMidDest1,'d');
memcpy(strDest,strMidDest1,16);
}
return 0;
}
㈣ 哪位編程高手,幫我用C++編寫一個完整的能運行的3DES加密演算法,謝謝!
/*在TC2 和 VC6下都可以順利運行。做了一個下午。一定要用我這個噢。有簡單的輸入錯誤檢測。有完整的說明和注釋*/#include<stdio.h> /*庫文件包含*/#include<string.h> /*用於字元串操作*/#include<stdlib.h> /*用於exit函數*//**************************************************************************int check(char *c)輸入參數: char *c: 輸入的字元串返回參數: 0:字元串中有不符合規定的字元 1: 字元串字元符合規定,沒有不符合規定的字元.功能: 檢查字元串中有否除了 0-9, +,-,*,/,(,),之外的其他字元, 如果有,則返回0, 表示出現錯誤。 若沒有,則返回1,表式字元串符合規定。**************************************************************************/int check(char *c){ int k=0; while(*c!='\0') { if((*c>='0' && *c<='9') || *c=='+' || *c=='-' || *c=='*' || *c=='/' || *c=='.' || *c=='(' || *c==')' ) { } else { printf("input error, there have the char not the math expression char!\n"); return 0; } if(*c=='(') k++; else if(*c==')') k--; c++; } if(k!=0) { printf("input error, there is not have correct bracket '()'!\n"); return 0; } return 1;}/**************************************************************************void move(char *f, double *s,int p) 輸入參數: char *f : 運算符數組 double *s: 數值數組 int p: 當前運算符數組位置。返回參數: 無功能: 將當前已經完成運算的運算符消去,同時將數值數組的位置調整以進行下一次運算。 傳入值p若為3 則當前符號的數組位置為3. f[3]=f[3+1].......f[len-2]=f[len-1] f[len-1]='\0'; s[i]=s[i+1].......s[len-1]=s[len] 因為數值比運算符多一個。***************************************************************************/void move(char *f, double *s,int p) { int i=0,len=strlen(f); for(i=p; i<len; i++) /*將已經運算過的符號,空出來的位置用後面的符號來填充,*/ { /*即把乘和除號的位置用後面的加和減號填充*/ f[i]=f[i+1]; s[i]=s[i+1]; } s[i]=s[i+1]; f[len-1]='\0';}/**************************************************************************double convnum(char *c)輸入參數: char *c :由數字和小數點組成的字元,用以轉換成double型的數值。返回參數: num:返回轉換好的值。功能: 將輸入的字元串先將其小數點以前的部分復制到temp[]數組中, 若有小數點,則將小數點之後的數值,也就是小數部分先進行計算,值存入num中 計算完成後,再對整數部分進行計算,值加上小數部分的值,存入num中。***************************************************************************/double convnum(char *c){ double num=0.0; double a=1.0; int i=0,p=0,len=0; char temp[100]; int tempi=0; int start=0; int f=1; /*正負符號指示器,若為1則為正數,為-1,此數為負數*/ len=strlen©; if(c[0]=='-') { start=1; f=-1; } for(i=start; i<len; i++) { if(c[i]=='.') { p=i; break; } temp[tempi++]=c[i]; /*將整數部分復制到temp[]中*/ } temp[tempi]='\0'; if(p!=0) { for(i=p+1;i<len;i++) /*將小數部分計算出來*/ { if(c[i]=='.') /*如果有多餘的小數點,則表示輸入錯誤*/ { printf("there is more that one dot '.' in number!error!\n"); exit(0); } a=a*0.1; num+=(a*(c[i]-48)); } } a=1.0; len=strlen(temp); /*計算整數部分*/ for(i=len-1;i>=0; i--) { num=num+(a*(temp[i]-48)); a*=10; } num=num*f; return num;}/**************************************************************************double good(char *c)輸入參數: char *c :即將進行運算的字元串型數學表達式。如3.5+(2*3/5)返回參數: s[0]:計算結果將放入s[0]中功能: 將輸入的字元串中的數字分別調用convnum(char *c)函數進行數值變換,再將其依 次存入doulbe s[i]中,將加減乘除運算符依次存入字元串符號數組 char f[i]中, 然後如果遇到括弧,則將括弧內的字元串存入另一字元數組中,然後用此 good(char *c) 遞歸函數進行遞歸運算。 然後根據先乘除,後加減的順序對已 存入數組的數值根 據存入字元串符號數組的運算符進行運算。結果存入s[0]中。 返回最終結果。***************************************************************************/double good(char *c) /*可遞歸函數*/{ /*取得數值字元串,並調用convnum轉換成double*/ char g[100],number[30]; /*g,保存當前的表達式串,number保存一個數的所有字元*/ char f[80]; /*保存所有的符號的堆棧*/ int fi=0; /*保存符號的位置指針*/ double s[80]; /*保存當前所有的數的一個堆棧*/ int si=0; /*保存數字位置指針*/ int k=0; /* 若k=1則表示有一對括弧*/ int num=0,i=0; /*num保存新括弧內的字元數,i 保存number里的字元位置*/ int cc=0; /*乘除符號數量*/ int jj=0; /*加減符號數量*/ while(*c!='\0')/*當p==1 和k==0時,表示已經把括弧里的內容全部復制到g[100]中了*/ { k=0; num=0; switch(*c) { case '+': /*當前字元為+-乘除時則表示*/ case '-': case '*': case'/': f[fi++]=*c; if(*c=='*' || *c=='/') cc++; else jj++; if(*(c-1)!=')') { number[i]='\0'; i=0;/*完成一個數字的復制,其位置指針i=0*/ s[si++]=convnum(number); } break; case'(': /*有括弧,則將當前括弧作用范圍內的全部字元保存,作為*/ k++; /*一個新的字元表達式進行遞歸調用good函數計算。*/ while(k>0) { c++; g[num]=*c; num++; if(*c==')') { k--; } else if(*c=='(') { k++; } } g[num-1]='\0'; num=0;/*完成一個括弧內容的復制,其位置指針num=0*/ s[si++]=good(g); break; default: number[i++]=*c; if(*(c+1)=='\0') { number[i]='\0'; s[si++]=convnum(number); } break; } c++; } f[fi]='\0'; i=0; while(cc>0) { switch(f[i]) { case '*': cc--; s[i+1]=s[i]*s[i+1]; move(f,s,i); break; case '/': cc--; s[i+1]=s[i]/(float)s[i+1]; move(f,s,i); break; default: i++; break; } } i=0; while(jj>0) { switch(f[i]) { case '+': s[i+1]=s[i]+s[i+1]; jj--; move(f,s,i); break; case '-': s[i+1]=s[i]-s[i+1]; jj--; move(f,s,i); break; default: printf("operator error!"); break; } } return s[0];}void main(){ char str[100]; double sum=0; int p=1; while(1) { printf("enter expression: enter 'exit' end of program\n"); scanf("%s",str); p=strcmp(str,"exit"); if(p==0) break; p=check(str); if(p==0) continue; sum=good(str); printf("%s=%f",str,sum); printf("\n"); } printf("good bye!\n");}例:enter expression: enter 'exit' end of program3.5+(12.3*15+8-(3/2+1))*2+(3.2*3-5)/6(輸入)3.5+(12.3*15+8-(3/2+1))*2+(3.2*3-5)/6=384.266667enter expression: enter 'exit' end of programchina(輸入)input error, there have the char not the math expression char!enter expression: enter 'exit' end of programexit(輸入)good bye!
如果你還有什麼不懂的,可以網路搜下:編程回憶錄,他們現在正在錄制這方面的教程,都是零基礎開始,由淺入深。
㈤ 3DES的演算法介紹
3DES又稱Triple DES,是DES加密演算法的一種模式,它使用3條56位的密鑰對數據進行三次加密。數據加密標准(DES)是美國的一種由來已久的加密標准,它使用對稱密鑰加密法,並於1981年被ANSI組織規范為ANSI X.3.92。DES使用56位密鑰和密碼塊的方法,而在密碼塊的方法中,文本被分成64位大小的文本塊然後再進行加密。比起最初的DES,3DES更為安全。
3DES(即Triple DES)是DES向AES過渡的加密演算法(1999年,NIST將3-DES指定為過渡的加密標准),加密演算法,其具體實現如下:設Ek()和Dk()代表DES演算法的加密和解密過程,K代表DES演算法使用的密鑰,P代表明文,C代表密文,這樣:
3DES加密過程為:C=Ek3(Dk2(Ek1(P)))
3DES解密過程為:P=Dk1(EK2(Dk3(C)))
㈥ 2.2 DES/3DES演算法 -- 演算法介紹
DES 演算法和 DESSede 演算法統稱DES系列演算法,是對稱加密演算法領域的經典加密演算法。 DESSede (又稱 3DES )使用三次迭代增加演算法安全性。DES演算法是眾多對稱加密演算法的基礎,很多演算法都是基於該演算法演變而來。
雖然DES被取代了,但是DES的CBC工作模式是基礎性的演算法和工作模型,有很強的意義,在遺留系統中也有一些使用的。
DES的演算法是採用分組加密工作模式,流程比較復雜,大致流程如下:
DES 和 3DES 適合一般加密性場景,當前大部分是遺留系統在使用,還有一部分可能是系統沒有支持 AES 等其他加密手段被迫使用。
JDK僅支持 56位的密鑰長度 (出口限制),對稱加密系列演算法的特點是:密鑰長度越高安全性越高,因此JDK本身自帶的 DES 和 3DES 演算法僅適合學術和一般場景使用,Bouncy Castle提供了64位密鑰長度的支持。
3DES 是對 DES 的一種改良演算法,針對 DES 演算法密鑰短,迭代次數少的缺點做了改進。但是 3DES 演算法速度慢,密鑰計算時間長,加密效率不高,實際使用也不多。
DES 的 3 大安全痛點:
㈦ c語言3des加密時生成密鑰
好像是有個這樣的函數,你自己查一查
㈧ 3des加密原理
使用3Des加密演算法前,我們需要了解一下當前主流的加密模式:單向加密和雙向加密,兩者最大的區別在於加密的密文是否具有可逆性。
單向加密:將需要加密的數據進行加密,並且密文不可進行解密,像我們常用的加密演算法MD5就屬於這種。
雙向加密:和單向加密不同的是可以通過某些方式進行加解密的操作,其中分為對稱加密和非對稱加密。
對稱加密:指數據使用者必須擁有相同的密鑰才可以進行加密解密,就像彼此約定的一串暗號,本文介紹的3Des加密就屬於這種。
非對稱加密:通過一組包含公鑰和私鑰的密碼來加密解密,用公鑰加密,私鑰解密,首推的就是RSA加密
---------------------------------------------------------------------------------------------------------------------------------------
3Des加密演算法,由於可以逆推原文,所以主要通過本地的唯一密鑰來保證數據的安全性,我這邊通過生成隨機的256位加密字元串存儲在本地,代碼讀取時將其通過md5加密成32位的字元串(由於本地有原始密鑰,不必擔心md5加密不可逆),最後以這32位加密字元串作為密鑰進行加解密的操作。
㈨ C語言實現,24位密鑰,3DES CBC模式
ca,我有一個開源庫,不過沒時間公開到網上, libdes吧
㈩ OpenSSL之3DES用法
3DES(或稱為Triple DES)是三重數據加密演算法(TDEA,Triple Data Encryption Algorithm)塊密碼的通稱。它相當於是對每個數據塊應用三次DES加密演算法。由於計算機運算能力的增強,原版DES密碼的密鑰長度變得容易被暴力破解;3DES即是設計用來提供一種相對簡單的方法,即通過增加DES的密鑰長度來避免類似的攻擊,而不是設計一種全新的塊密碼演算法。
其具體實現如下:設Ek()和Dk()代表DES演算法的加密和解密過程,K代表DES演算法使用的密鑰,P代表明文,C代表密文,這樣:
3DES加密過程為:C=Ek3(Dk2(Ek1(P)))
3DES解密過程為:P=Dk1(EK2(Dk3(C)))
本文假設你已經安裝好了OpenSSL,並且持有一份1.1.1的源碼。
3DES相關的頭文件在des.h中、源文件在crypto/des目錄中。
# define DES_ENCRYPT 1
# define DES_DECRYPT 0
這里定義了加密和解密的類型。
typedef unsigned int DES_LONG;
這個結構定義了DES的密鑰上下文。相關欄位含義:
ks —— 16輪子密鑰。
在1.1.1中,大多數的數據結構已經不再向使用者開放,從封裝的角度來看,這是更合理的。如果你在頭文件中找不到結構定義,不妨去源碼中搜一搜。
void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
DES_key_schele *ks1, DES_key_schele *ks2,
DES_key_schele *ks3, int enc);
使用電子密碼本方式加解密一個分組。
ks1、ks2、ks3分別為傳入的三個64位密鑰。
其內部實現為:
可以看到內部使用了DES_encrypt3()這個內部分組加密函數,並且傳入了3個密鑰。
我們繼續來看DES_encrypt3()是如何利用這3個密鑰的。
void DES_encrypt3(DES_LONG *data, DES_key_schele *ks1,
DES_key_schele *ks2, DES_key_schele *ks3)
其內部實現為:
可以看到內部又繼續使用了DES_encrypt2()這個分組加密函數。沒有必要再繼續解開DES_encrypt2()了,因為它主要根據密鑰做分組的加解密處理。
關於三個密鑰的利用關系,在DES_encrypt3()中主要是做三次疊加運算:
使用第一個密鑰做分組加密運算。
使用第二個密鑰做分組解密運算。
使用第三個密鑰做分組加密運算。
3DES的疊加運算,根據密鑰的組合關系,經常又表現為以下模式:
void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output,
long length,
DES_key_schele *ks1, DES_key_schele *ks2,
DES_key_schele *ks3, DES_cblock *ivec, int enc);
使用密文分組鏈加解密。
參數ivec為初使化向量,在本函數返回時會被更新,可用於下一次分組運算。
註:
從源碼實現來看,雖然DES_ede3_cbc_encrypt()自身支持明文長度多於一個分組的計算,但是卻沒有處理填充,所以從統一封裝來看,建議開發者在使用這個函數時,同DES_ecb_encrypt()的用法一樣,傳入單個分組。
下面這個例子演示了使用普通DES加密,3DES的DES的兼容模式解密(即3個密鑰完全相同)。
輸出:
f8a8707fea7d45cd
3132333435363738