應用密碼學—(擴展)歐幾里得、DES、RSA、SHA-1算法

1. 歐幾里得算法

1.1 分析算法的實現原理

? ? ? 歐幾里德(Euclid)算法,也既常說的“輾轉相除法”,公式為gcd(m, n) { return gcd(n, m%n); },對于任意兩個正整數m、n,每次求的一個數字r = m % n,然后把n放到m的位置,把r放到n的位置,遞歸調用。當 m%n?== 0的時候停止。

1.2 代碼

#include<stdio.h>
int main()
{int m,n,r=0;printf("請輸入兩個正整數:");scanf("%d%d",&m,&n);while(n!=0){r=m%n;m=n;n=r;}	printf("最大公因子是:%d\n",m);return m;
}

1.3 運行結果

2. 擴展歐幾里得算法

?2.1 擴展歐幾里得原理

  1. 初始化
    • 設定兩個整數a和b,以及兩個變量x和y,初始時x和y的值與歐幾里得算法中的迭代過程相關。
    • 通常,當b為0時,設定x=1,y=0,因為此時a和0的最大公約數是a本身。
  2. 迭代計算
    • 使用歐幾里得算法計算a和b的商q和余數r。
    • 更新a和b的值,使a=b,b=r。
    • 同時,根據擴展歐幾里得算法的推導式更新x和y的值。通常這一步驟涉及到遞歸或迭代地求解上一輪ax + by = gcd(a, b)的解x'和y',然后用它們來計算當前輪的解x和y。
  3. 終止條件
    • 當b為0時,算法終止。此時a的值即為a和b的最大公約數,而x和y則是一組滿足貝祖等式的整數解。

2.2 代碼

#include <stdio.h>// 擴展歐幾里得算法
void extendedEuclid(int a, int b, int *x, int *y, int *gcd) {if (b == 0) {*x = 1;*y = 0;*gcd = a;} else {int x1, y1;extendedEuclid(b, a % b, &x1, &y1, gcd);// 更新x和y的值*x = y1;*y = x1 - (a / b) * y1;}
}int main() {int a , b ;int x, y, gcd;printf("請輸入兩個不為0的整數:\n");scanf("%d %d",&a,&b); // 調用函數extendedEuclid(a, b, &x, &y, &gcd);printf("%d 和 %d 的最大公約數是: %d\n", a, b, gcd);printf("\n此時,x = %d, y = %d\n", x, y);// 驗證結果if (a*x + b*y == gcd) {printf("方程 %dx + %dy = %d 成立.\n", a, b, gcd);} else {printf("這個等式不成立,請檢查執行情況。\n");}return 0;
}

2.3 運行結果

3. DES算法

? ? DES(Data Encryption Standard,數據加密標準)是一種對稱密鑰加密算法,由IBM公司研發并在1977年被美國政府采用為聯邦信息處理標準。DES算法主要應用于保證數據的機密性,盡管現在因其密鑰長度較短而逐漸被AES(Advanced Encryption Standard,高級加密標準)取代,但其基本原理仍然是密碼學中的一個重要基礎。

?3.1 DES算法原理

? ? DES算法基于Feistel結構,其核心是一個分組密碼,即它以固定長度的塊(64位)對數據進行加密,常見的塊大小為64位,而密鑰長度為56位(實際密鑰輸入為64位,其中有8位用于奇偶校驗,因此有效密鑰長度為56位)。DES加密和解密過程非常相似,解密時使用的是與加密時相同的密鑰,但密鑰的使用順序相反。

? ? DES算法將輸入的明文分為64位的數據分組(最后一個分組不足64位則補0),使用一個56+8 (第8i位為奇偶校驗位,i=1,2,…)=64位的密鑰進行變換,每個64位明文分組數據經過初始置換、16次迭代和逆初始置換3個主要階段,最后輸出得到64位密文。

加密流程:

  1. 初始置換(Initial Permutation, IP):首先,對明文塊進行一個固定的置換,將64位明文按照一定規則重新排列。

  2. 循環迭代(Round):接下來,數據塊經過16輪完全相同的迭代運算,每輪包括以下步驟:

    • 分組:將數據分為左右兩半,每半32位。
    • 擴展置換(Expansion):左半部分經過擴展置換變為48位。
    • 密鑰混淆(Key Mixing):擴展后的數據與經過密鑰調度產生的本輪子密鑰(48位)進行異或操作。
    • S盒變換(Substitution):結果被分割成8組6位數據,每組通過查S盒(替代盒)轉換為4位,實現非線性變換。
    • P盒變換(Permutation):上述32位結果經過P盒進行重新排列。
    • 左右合并:上述得到的32位結果與原始右半部分進行交換,然后與原始左半部分合并,準備進入下一輪迭代。
  3. 最終置換(Final Permutation, FP):經過16輪迭代后,最后一次的左右部分合并后,再進行一次與初始置換相反的置換,得到最終的密文。

密鑰調度:

? ? 在DES算法中,一個主密鑰通過一個密鑰調度算法被擴展并轉化為16個不同的子密鑰,每輪迭代使用一個子密鑰。這一過程增強了安全性,使得直接從密文推算密鑰更為困難。

3.2 代碼

#include <iostream>
#include <bitset>
#include <string>
#include <cmath>
#include<stdlib.h>
#include <cstdlib>
using namespace std;
/**
*函數聲明
*/
string hexToTwo(string str);  //十六進制轉二進制string int2BinString(int n);  //int轉四位stringstring exchange(string str, int rule[], int x);  //置換string circleMove(string str, int j);  //單步移位string spiltShift(string str, int j);  // 左右分別移位string XOR(string str1, string str2);  //異或string SBoxWork(string str, int SBox[][4][16]);  //S盒工作int binToDec(string bin);  //二進制轉十進制string Bin2Hex(string strBin);   //二進制轉十六進制int str2Dec(string str);  // string字符串轉十進制void printMenu();  //打印功能菜單void controller();  //功能控制器void encryption(); //加密void decryption(); //解密/**
*全局變量
*/
const int Key_SIZE = 16;/**
*8張表
*/
//交換規則表(8*7)
const int ExchangeRules_SIZE = 56;
int ExchangeRules[56] =
{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
};
//移位表
const int ShiftTable_SIZE = 16;
int ShiftTable[16] =
{1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
//PC-2(8*6)
const int PC_2_SIZE = 48;
int PC_2[48] =
{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
};
//IP(8*8)
const int IP_SIZE = 64;
int IP[64] =
{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
};
//擴展置換E(8*6)
const int E_SIZE = 48;
int E[48] =
{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,  1
};
//S盒
int SBox[8][4][16] =
{{{14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7},{0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8},{4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0},{15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13}},{{15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10},{3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5},{0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15},{13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9}},{{10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8},{13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1},{13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7},{1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12}},{{7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15},{13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9},{10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4},{3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14}},{{2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9},{14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6},{4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14},{11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3}},{{12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11},{10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8},{9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6},{4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13}},{{4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1},{13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6},{1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2},{6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12}},{{13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7},{1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2},{7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8},{2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}}
};
//P盒(8*4)
const int P_SIZE = 32;
int P[32] =
{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
};
//IP-1(8*8)
const int IP_1_SIZE = 64;
int IP_1[64] =
{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
};
int main()
{printMenu();return 0;
}
/**
*打印功能菜單
**/
void printMenu()
{cout<<"歡迎來到DES加密解密系統! "<<endl;cout<<"請選擇系統功能:"<<endl;cout<<"1. 加密"<<endl;cout<<"2. 解密"<<endl;cout<<"3. 退出系統"<<endl;controller();
}
/**
*功能控制器
**/
void controller()
{cout<<"———————————————————— "<<endl;int choice;cin>>choice;if(choice == 1) encryption();else if(choice == 2) decryption();else if(choice == 3) {cout<<"感謝您的使用,再見!"<<endl;exit(0);}else{cout<<"錯誤!未知選項,請重新選擇:"<<endl;controller();}
}/**
*加密
**/
void encryption()
{/***初始條件**//* 輸入明文MingWen(十六進制),密鑰Key(十六進制) */string MingWen ;string Key;cout<<"輸入明文: "<<endl;cin>>MingWen;cout<<"輸入密鑰: "<<endl;cin>>Key;string M = hexToTwo(MingWen);string K = hexToTwo(Key);/***處理密鑰,生成16個子密鑰 **//* 利用規則交換表(8*7)將K轉換成 K0 ;  K0(56位) = C0(28位) + D0(28位) */string KKK = exchange(K, ExchangeRules, ExchangeRules_SIZE);/* 利用移位表轉換得C1D1----C16D16,存入K_arr */int i = 0;string K_arr[Key_SIZE+1];K_arr[0] = KKK;for(i=1; i<=Key_SIZE; i++){K_arr[i] = spiltShift(K_arr[i-1], ShiftTable[i-1]);}/* Kn(48位)= PC-2(8*6)處理 CnDn得16個子密鑰,存入Key_arr */string Key_arr[Key_SIZE];for(i=0; i<Key_SIZE; i++){Key_arr[i] = exchange(K_arr[i+1], PC_2, PC_2_SIZE);}/*** 用子密鑰對明文加密**//* 通過IP(8*8)處理M得L0(32位)  R0(32位) */string IP_M = exchange(M, IP, IP_SIZE);/* Ln= R(n-1); Rn= L(n-1) + f(R(n- 1); Kn)迭代16次 */string L[Key_SIZE+1];string R[Key_SIZE+1];L[0] = IP_M.substr(0, M.length()/2);R[0] = IP_M.substr(M.length()/2);string it = "";for(i=1; i<=Key_SIZE; i++){//將R0通過擴展置換E(8*6)從32位擴展到48位it = exchange(R[i-1], E, E_SIZE);//R0(48位)與 K1異或得E0(48位)it = XOR(it, Key_arr[i-1]);//將E0(48位)通過S盒轉換成32位it = SBoxWork(it, SBox);//P盒(8*4)置換,得P0it = exchange(it, P, P_SIZE);//P0與L0進行異或,得J0it = XOR(it, L[i-1]);//左右交換位置,即R1 = J0; L1 = R0L[i] = R[i-1];R[i] = it;}/* 對R16 L16進行一次IP-1(8*8)排序得密文 */string res = "";res += R[16];res += L[16];string finalRes = Bin2Hex(exchange(res, IP_1, IP_1_SIZE));cout<<"得到的密文如下: "<<endl;cout<<finalRes<<endl;cout<<"------------------------"<<endl;printMenu();
}/**
*解密
**/
void decryption()
{string MiWen;string Key;cout<<"輸入密文: "<<endl;cin>>MiWen;cout<<"輸入密鑰: "<<endl;cin>>Key;string M = hexToTwo(MiWen);string K = hexToTwo(Key);/***處理密鑰,生成16個子密鑰 **//* 利用規則交換表(8*7)將K轉換成 K0 ; K0(56位) = C0(28位) + D0(28位) */string KKK = exchange(K, ExchangeRules, ExchangeRules_SIZE);/* 利用移位表轉換得C1D1----C16D16,存入K_arr */int i = 0;string K_arr[Key_SIZE+1];K_arr[0] = KKK;for(i=1; i<=Key_SIZE; i++){K_arr[i] = spiltShift(K_arr[i-1], ShiftTable[i-1]);}/* Kn(48位)= PC-2(8*6)處理 CnDn得16個子密鑰,存入Key_arr */string Key_arr[Key_SIZE];for(i=0; i<Key_SIZE; i++){Key_arr[i] = exchange(K_arr[i+1], PC_2, PC_2_SIZE);}/*** 用子密鑰對明文加密**//* 通過IP(8*8)處理M得L0(32位)  R0(32位) */string IP_M = exchange(M, IP, IP_SIZE);/* Ln= R(n-1); Rn= L(n-1) + f(R(n- 1); Kn)迭代16次 */string L[Key_SIZE+1];string R[Key_SIZE+1];L[0] = IP_M.substr(0, M.length()/2);R[0] = IP_M.substr(M.length()/2);string it = "";for(i=1; i<=Key_SIZE; i++){//將R0通過擴展置換E(8*6)從32位擴展到48位it = exchange(R[i-1], E, E_SIZE);//R0(48位)與 K1異或得E0(48位)it = XOR(it, Key_arr[16-i]);//將E0(48位)通過S盒轉換成32位it = SBoxWork(it, SBox);//P盒(8*4)置換,得P0it = exchange(it, P, P_SIZE);//P0與L0進行異或,得J0it = XOR(it, L[i-1]);//左右交換位置,即R1 = J0; L1 = R0L[i] = R[i-1];R[i] = it;}/* 對R16 L16進行一次IP-1(8*8)排序得密文 */string res = "";res += R[16];res += L[16];string finalRes = Bin2Hex(exchange(res, IP_1, IP_1_SIZE));cout<<"得到的明文如下: "<<endl;cout<<finalRes<<endl;cout<<"------------------------"<<endl;printMenu();}/**
*int轉四位string  +  int十進制轉string二進制
**/
string int2BinString(int n)
{bitset<4> bit(n);return bit.to_string();
}
/**
*string十六進制轉string二進制
**/
string hexToTwo(string str)
{string twoBin = "";int i;for(i=0; i<16; i++){if(str[i]>='0'&&str[i]<='9')twoBin.append(int2BinString(str[i]));else if(str[i]>='A'&&str[i]<='Z')twoBin.append(int2BinString(str[i]-'A'+10));else if(str[i]>='a'&&str[i]<='z')twoBin.append(int2BinString(str[i]-'a'+10));}return twoBin;
}
/**
* string二進制轉int十進制
**/
int binToDec(string bin)
{int sum = 0;for(int i=0; i<bin.size(); i++){if(bin[i]=='0' || bin[i]=='1'){sum += (bin[i]-'0') * pow(2, bin.size()-i-1);}else{cout<<"非法二進制字符!"<<endl;return 0;}}return sum;
}/**
* 01字符轉十進制
**/
int str2Dec(string str)
{bitset<64> bst(str);return (int)bst.to_ulong();
}
/**
* 64位密文轉十六進制
**/
//Bin2Hex轉換表
const static string Bin_Hex[16]
{"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"
};
string Bin2Hex(string strBin)
{string hex;int a = strBin.length()/4;string trans;for(int i = 0; i < a; i++){trans.clear();trans = strBin.substr(i*4, 4);hex += Bin_Hex[str2Dec(trans)];}return hex;
}/**
*利用交換表進行置換
**/
string exchange(string str, int rule[], int x)
{string exchangedStr = "";int i, temp;for(i=0; i<x; i++){temp = rule[i]-1;exchangedStr.append(1, str[temp]);}return exchangedStr;
}/**
*依據移位表進行移位
**/
string circleMove(string str, int j)
{string targetString = "";targetString.append(str.substr(j));targetString.append(str.substr(0, j));return targetString;
}
/**
*左右兩部分移位
**/
string spiltShift(string str, int j)
{string targetStr = "";string leftString = str.substr(0, str.length()/2);string rightString = str.substr(str.length()/2);targetStr.append(circleMove(leftString, j));targetStr.append(circleMove(rightString, j));return targetStr;
}
/**
* string 異或
**/
string XOR(string str1, string str2)
{string targetString = "";for(int j=0; j<str1.length(); j++){targetString += ((str1[j] - '0') ^ (str2[j] - '0')) + '0';}return targetString;
}
/**
* S盒工作
**/
string SBoxWork(string str, int SBox[][4][16])
{string targetString = "";string temp = "";string x = "", y = "";int col = 0, row = 0;for(int i=0; i<str.size()/6; i++){temp = str.substr(6*i, 6);x = temp.substr(0, 1)+temp.substr(5, 1);y = temp.substr(1, 4);row = binToDec(x);col = binToDec(y);targetString.append(int2BinString(SBox[i][row][col]));}return targetString;
}

3.3 運行結果

4. RSA算法

? ? RSA算法是一種非對稱加密算法,由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)在1977年提出,廣泛應用于現代信息安全體系中,特別是在數據加密、數字簽名和安全認證等領域。

? ? RSA算法作為一種國際標準算法,廣泛應用于信息安全領域。其優點主要表現在以下幾個方面:首先,RSA算法是一種非對稱加密算法,公鑰和私鑰不同,公鑰可以公開,但私鑰只有擁有者才能使用,這樣可以有效地保護通信的安全性;其次,由于RSA是國際標準算法,因此相對來說它會更為普及,也不容易受到其他問題的限制。

? ? 然而,RSA算法也存在一些缺點。最主要的一點就是加解密速度較慢,因為進行的都是大數計算,使得RSA最快的情況也比DES慢上好幾倍,無論是軟件還是硬件實現。這使得RSA一般只適用于少量數據的加密。另外,雖然私鑰的安全由用戶自行保管可以在一定程度上防止信息泄露,但如果私鑰在使用過程中被泄露,那么對應的信息也將處于極大的風險之中。

?4.1 RSA算法原理

密鑰對的生成:

(1)選取兩個大素數p和q(目前兩個數的長度都接近512bit是安全的)

(2)計算乘積n=p*q,Φ(n)=(p-1)(q-1),其中Φ(n)為n的歐拉函數(因為兩素數乘積的歐拉函數等于兩數分別減一后的乘積)

(3)隨機選取整數e(1<e<Φ(n))作為公鑰d,要求滿足e與Φ(n)的最大公約數為1,即兩者互素

(4)用Euclid擴展算法計算私鑰d,已滿足d * e ≡ 1 (mod Φ(n)),即d ≡ e^(-1) (mod Φ(n))。則e與n是公鑰,d是私鑰

注意:e與n應公開,兩個素數p和q不再需要,可銷毀,但絕不可泄露。

加密過程:

將接收到的明文轉換成特定的編碼方式。如p=43,q=59,e=2,明文為majiaqizuisuai,?

按照如上英文字母表的順序進行編碼后為1200090800160825200818200008。

???然后將轉碼后的字符串分塊,分組要求:每個分組對應的十進制數小于0。上文字符串分組如下1200 0908 0016 0825 2008 1820 0008。每一分組的數都小于n(2537),而2537能接受的最大的數為2525(也就是‘zz’的情況),所以是4位1組,即兩字符一組。這樣一來,m1=1200,m2=0908,...?,m6=0008

????現在可以加密了,加密算法就是這個式子----ci ≡ mi^e (mod n),如第一分組 1200^2?≡ mod 2537 ≡ 1521=c1,第二組0908^2?≡ mod 2537 ≡ 2476=c2……

?4.2?代碼

#include<stdio.h>
#include<stdlib.h>/* 函數申明 */
int long_n(int n);
int shuru(char *arr, int k, char *wei, int is_first);
void jiami(char *arr, int k, int e, int n);int primeNum(int num)   //判斷素數
{int i =2;if (num == 1 || num == 0){return 0;}for (i = 2; i <= num-1; i++){if (num % i == 0){printf("輸入的值不是素數\n");return 0;}}printf("輸入的值為素數,請繼續...\n");
}
int coprime(int a, int b)  //判斷互質
{int t=0,c=a,d=b;if (a < b){t = a; a = b; b = t;}while (a % b){t = b;b = a % b;a = t;}printf("(p-1)*(q-1)與e互質,請繼續...\n");
}int shuru(char *arr, int k, char *wei, int is_first)//獲取明文并分組 
{int i;char ch;/*判斷是否為第一分組的輸入,如果是則獲取輸入的字符,否則就將上一分組最后獲取的字符作為這一分組的第一個字符*/if (is_first == 1)    ch = getchar();elsech = *wei;for (i = 0; (i < k) && (ch != '\n');i++)  //獲取字符直到獲取到回車符為止{arr[i] = ch;ch = getchar();}*wei = ch;  //最后獲取到的字符準備作為下一分組的第一個字符for (i = i; i < k; i++)arr[i] = 0;  //輸入不夠一組個數的整數倍則補零if (ch == '\n')  //接收到回車符返回0,否則為1return 0;elsereturn 1;
}int v=0;
void jiami(char *arr, int k, int e, int n)//加密 
{	while(v==0) {printf("\n密文為:\n");v++;}	int m = 0,c=1, i, j,t=0, shu,temp,num=0;int *array;for (i = 0; i < k; i++)     /*Mi賦值過程*/{temp = 1;for (j = 0; j < (k-i-1)*2; j++)temp = temp * 10;shu = (int)arr[i] - 97;m = m + temp * shu;}temp = e;do{	        /*獲取e的二進制表達形式的位數*/temp = temp / 2;num++;} while (temp != 0);array = (int *)malloc(sizeof(int)*k);   //申請動態數組temp = e;for (i = 0; i < num; i++)	/*動態數組存儲e的二進制表達形式*/{array[i] = temp % 2;temp = temp / 2;}for (i = num - 1; i >= 0; i--) //快速取模算法,避免出現天文數字{	t = t * 2;temp = c*c;if (temp > n){	for (j = 0; temp - n*j >= 0; j++);j--;c = temp - n*j;}elsec = temp;if (array[i] == 1){	t = t + 1;temp = c*m;if (temp > n){	for (j = 0; temp - n*j >= 0; j++);j--;c = temp - n*j;}elsec = temp;		}	e = e / 2;}temp = c;i = 0;do{	      /*c的位數小于分組長度則在前補零*/temp = temp / 10;i++;} while (temp != 0);for (i; i < num; i++)printf("0");printf("%d", c);
}int long_n(int n)//獲取分組的長度
{int temp,i,j,k,shi,comp=0;temp = n;for (i = 1; temp / 10 != 0; i++)	/*獲取n的位數*/{temp = temp / 10;}temp = i;if (i % 2 != 0)	/*若n的位數為基數*/{i = i - 1;return i;}else	/*若位數為偶數*/{for (j = 0; j < i/2; j++){shi = 1;for (k = 0; k < temp - 2; k++)shi = shi * 10;comp = comp + shi * 25;temp = temp - 2;}if (comp <= n)return i;else{i = i - 2;return i;}}
}/*主函數*/
int main()
{int p, q, e, d, n, fai_n, k, i,is_first=1;char ch,*arr,wei='a';printf("請輸入兩個不相等的素數p、q值:\n");scanf_s("%d", &p); primeNum(p);scanf_s("%d", &q); primeNum(q); n = p*q;  fai_n = (p-1)*(q-1);   //Φ(n)printf("\n請輸入e值:\n");scanf_s("%d", &e);  coprime(fai_n,e);for (k = 0; (k*n + 1) % e != 0; k++);if ((k*n + 1) % e == 0)d = (k*n + 1) / e;  //d * e ≡ 1 (mod Φ(n))k = long_n(n);k = k / 2;  //分組的長度ch = getchar(); //緩沖回車符arr = (char *)malloc(sizeof(char)*k);  //申請動態數組printf("\n請輸入明文:\n");while (1){i=shuru(arr,k,&wei,is_first);  //調用輸入字符的函數,接收到回車符返回0,否則為1is_first = 0;  //第一分組錄入結束設為0jiami(arr,k,e,n);  //調用加密函數if (i == 0)  //接收到返回值為0跳出循環break;}printf("\n");return 0;
}

4.3 運行結果

5. SHA-1算法

?5.1 SHA-1算法原理

? ? 安全哈希算法(Secure Hash Algorithm)主要適用于數字簽名標準(Digital Signature Standard DSS)里面定義的數字簽名算法(Digital Signature Algorithm DSA)。對于長度小于2^64位的消息,SHA1會產生一個160位的消息摘要。當接收到消息的時候,這個消息摘要可以用來驗證數據的完整性。在傳輸的過程中,數據很可能會發生變化,那么這時候就會產生不同的消息摘要。

? ? SHA-1算法,全稱Secure Hash Algorithm 1,是一種密碼散列函數,由美國國家安全局設計,并由美國國家標準技術研究所(NIST)發布為聯邦資料處理標準(FIPS)。它可以生成一個被稱為消息摘要的160位(20字節)散列值,通常以40個十六進制數的形式呈現。

? ? 優點:①安全性較高:SHA-1算法的哈希函數具有不可逆性,因此被廣泛應用于數字簽名和數據完整性校驗等領域。②哈希速度較快:由于SHA-1算法中的運算相對簡單,其哈希速度相對較快。

? ? 缺點:①安全性不足:近年來,SHA-1算法的安全性受到了挑戰。據報道,SHA-1算法存在多個漏洞,可能會被攻擊者利用。②容易受到碰撞攻擊:碰撞攻擊是指兩個不同的輸入通過哈希函數得到相同的輸出。SHA-1算法雖然相對抵抗碰撞攻擊,但并非完全免疫。

5.2 代碼

#include<stdio.h>
#include <string.h>
#include <conio.h>
#include <wtypes.h>
void creat_w(unsigned char input[64],unsigned long w[80])//分組處理 
{int i,j;unsigned long temp,temp1;for(i=0;i<16;i++)//將 Mi 分成16個32bit數據 W0, W1, … , W15。 {j=4*i;w[i]=((long)input[j])<<24 |((long)input[1+j])<<16|((long)input[2+j])<<8|((long)input[3+j])<<0;}for(i=16;i<80;i++)//對于 t=16到79 令 Wt=S1(Wt-3 XOR Wt-8 XOR Wt- 14 XOR Wt-16).{w[i]=w[i-16]^w[i-14]^w[i-8]^w[i-3];temp=w[i]<<1;temp1=w[i]>>31;w[i]=temp|temp1;}
}
char ms_len(long a,char intput[64]) 
{unsigned long temp3,p1;  int i,j;temp3=0;p1=~(~temp3<<8);for(i=0;i<4;i++){j=8*i;intput[63-i]=(char)((a&(p1<<j))>>j);}return '0';
}
int main(int argc, int* argv[])//計算消息摘要
{unsigned long H0=0x67452301,H1=0xefcdab89,//5個寄存器的緩沖區初始化 H2=0x98badcfe,H3=0x10325476,H4=0xc3d2e1f0;unsigned long A,B,C,D,E,temp,temp1,temp2,temp3,k,f;int i,flag;unsigned long w[80];unsigned char input[64]; long x;int n;printf("input message:\n");scanf("%s",input);n=strlen((LPSTR)input);if(n<57)//字符串擴充 {x=n*8;ms_len(x,(char*)input);if(n==56)for(i=n;i<60;i++)input[i]=0;else{input[n]=128;for(i=n+1;i<60;i++)input[i]=0;}}creat_w(input,w);printf("\n");A=H0;B=H1;C=H2;D=H3;E=H4;for(i=0;i<80;i++)//每次循環開始將H寄存器數據拷貝到ABCDE寄存器,計算結束后累加到H寄存器,然后進入下一輪計算,{flag=i/20;switch(flag)//在SHA1中需要一系列的函數 Ft(0<=t<= 79)都操作32位數據B,C,D并且產生32位數據作為輸出。 {case 0: k=0x5a827999;f=(B&C)|(~B&D);break;case 1: k=0x6ed9eba1;f=B^C^D;break;case 2: k=0x8f1bbcdc;f=(B&C)|(B&D)|(C&D);break;case 3: k=0xca62c1d6;f=B^C^D;break;}temp1=A<<5;temp2=A>>27;temp3=temp1|temp2;temp=temp3+f+E+w[i]+k;//循環計算 E=D;D=C;temp1=B<<30;temp2=B>>2;C=temp1|temp2;B=A;A=temp;}H0=H0+A;  H1=H1+B;  H2=H2+C;  H3=H3+D;  H4=H4+E;printf("output hash value:\n");printf("%lx%lx%lx%lx%lx",H0,H1,H2,H3,H4);getch();
}

5.3 運行結果

與SHA-1在線加密工具的結果做對比:?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/39827.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/39827.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/39827.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

教育場景中的自動化分揀系統!基于大象機器人UltraArm P340機械臂和傳送帶的實現

引言 今天我們將展示一個高度自動化的模擬場景&#xff0c;展示多個機械臂與傳送帶協同工作的高效分揀系統。在這個場景中&#xff0c;機械臂通過視覺識別技術對物體進行分類&#xff0c;并通過精確的機械操作將它們放置在指定的位置。這一系統不僅提高了分揀的速度和準確性&am…

PTrade怎么獲取KDJ隨機指標?想做量化策略怎么申請PTrade量化軟件?

get_KDJ - 隨機指標 get_KDJ(high, low, close, n9, m13, m23) 使用場景 該函數僅在回測、交易模塊可用 接口說明 獲取隨機指標KDJ指標的計算結果 PTrade是恒生公司開發的一款專業量化軟件&#xff0c;部分合作券商可提供&#xff0c;↑↑↑&#xff01; 參數 high&…

什么是分庫分表?它有哪些實現類型?

假如你正在使用關系型數據庫開發一款健康類系統。業務發展很好&#xff0c;系統有很多活躍的新老用戶&#xff0c;這些用戶會和平臺的醫生團隊進行交互&#xff0c;每天可能會生成數萬甚至數十萬級別的業務數據。這樣的話&#xff0c;隨著數據量越來越大&#xff0c;系統中的某…

如何在返利App中進行高效的異常處理與監控

如何在返利App中進行高效的異常處理與監控 大家好&#xff0c;我是微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 在開發返利App過程中&#xff0c;高效的異常處理與監控是確保系統穩定性和用戶體驗的關鍵。本文將深入探討…

被?絡罪犯利?的5?ChatGPT越獄提?

?ChatGPT發布的近18個月以來&#xff0c;?絡罪犯們已經能夠利??成式AI進?攻擊。OpenAI在其內容政策中制定了限制措施&#xff0c;以阻??成惡意內容。作為回應&#xff0c;攻擊者們創建了??的?成式AI平臺&#xff0c;如 WormGPT和FraudGPT&#xff0c;并且他們還分享了…

IP地址定位中多源數據融合的應用

IP地址定位如今在諸如網絡安全、地理信息服務、智能交通等領域發揮著關鍵作用。然而&#xff0c;傳統的基于單一數據源&#xff08;如IP數據庫&#xff09;的定位方法往往存在精度有限、可靠性不足等問題。多源數據融合技術的出現為解決這些問題提供了新的思路和方法。今天我們…

石墨烯分散液制備方法眾多 應用領域廣泛

石墨烯分散液制備方法眾多 應用領域廣泛 石墨烯分散液指將石墨烯納米片均勻分散在特定溶劑中制成的溶液。石墨烯分散液具有化學穩定性好、生物相容性好、熱穩定性好等優勢&#xff0c;未來有望在涂料、纖維制品、電池制造、油墨等領域獲得廣泛應用。 石墨烯分散液以石墨…

深入解析某音item_search_video接口:技術原理與應用探索

item_search_video接口是某音提供的一個用于根據關鍵詞搜索相關視頻內容的API。通過該接口&#xff0c;用戶可以獲取到與搜索關鍵詞相關的視頻列表&#xff0c;包括視頻的基本信息&#xff08;如標題、描述、封面圖URL&#xff09;、發布者信息以及視頻的播放和互動數據等。這為…

絕區零卡頓嚴重、延遲高的解決方法提前看

絕區零這款游戲背后是一個錯綜復雜的架空世界&#xff0c;仿佛一幅波瀾壯闊的史詩畫卷緩緩展開。在這個世界中&#xff0c;神秘莫測的“空洞”災害如影隨形&#xff0c;給大地帶來了無盡的破壞和混沌。經過米哈游團隊的精心雕琢&#xff0c;無論是畫面UI的細膩呈現&#xff0c;…

C++ 左值右值

文章目錄 概述左值右值右值引用左值和右值的互換 小結 概述 左值和右值屬于2中不同的表達式類型&#xff1b;它們在表達式中扮演不同的角色&#xff0c;特別是在賦值操作和函數參數傳遞中。 左值 定義&#xff1a;左值是指那些在內存中有確定位置的表達式&#xff0c;可以出…

灌區量測水管理系統是如何實現灌區節水?

隨著全球水資源日益緊張&#xff0c;節水已成為農業生產中不可忽視的一環。在灌區管理中&#xff0c;量測水管理系統以其精準的數據監測和科學的灌溉管理&#xff0c;為實現灌區節水提供了強有力的技術支持。 灌區量測水管理系統是一套集成了自動化監測、數據傳輸、數據分析和…

Springboot交流論壇網站00304

Springboot交流論壇網站 摘要 隨著信息技術在管理上越來越深入而廣泛的應用&#xff0c;管理信息系統的實施在技術上已逐步成熟。本文介紹了交流論壇網站的開發全過程。通過分析交流論壇網站管理的不足&#xff0c;創建了一個計算機管理交流論壇網站的方案。文章介紹了交流論壇…

x-ray投影圖文件.raw轉換成.tif文件【python代碼】

如下&#xff1a; path 輸入文件所在的文件夾路徑import os import numpy as np import tifffile as tiffdef read_raw_data(path, dimensions, dtype):"""讀取 .raw 文件并返回圖像數據:param path: .raw 文件路徑:param dimensions: 圖像的行數和列數 (hei…

elementui中table組件合并行(看就懂)

做一個動態合并的table表格, 如下圖 1.首先定義需要合并的字段及合并后的對象 data(){return {mergeFields: [name, amount3],mergeObj: {}} }2.分配合并項函數, data為數據源 //獲取合并序號getSpanArr(data []) {this.mergeFields.forEach(key > {// 用來記錄合并行的起…

數據類型的分類和查看

數據類型是指定程序在運行過程中&#xff0c;將各種數據根據表示形式和組織形式劃分為不同的分類。 例如&#xff0c;一個人的姓名可以用字符類型存儲&#xff0c;年齡可以用數值類型存儲&#xff0c;而婚否可以用布爾類型存儲&#xff0c;這些都是 Python 中的 標準數據類型…

為什么我感覺 C 語言在 Linux 下執行效率比 Windows 快得多?

在開始前剛好我有一些資料&#xff0c;是我根據網友給的問題精心整理了一份「Linux的資料從專業入門到高級教程」&#xff0c; 點個關注在評論區回復“888”之后私信回復“888”&#xff0c;全部無償共享給大家&#xff01;&#xff01;&#xff01;Windows的終端或者叫控制臺…

c++初級-2-引用

文章目錄 引用一、引用的定義二、引用做函數參數三、引用作為返回對象四、引用的本質五、常量引用 引用 即給一個變量起別名。 一、引用的定義 int a 10;//引用int& b a;cout << "a " << a << endl;cout << "b " <&l…

時間12小時和24時轉換方法

24小時時間轉為12小時制 function convertTo12Hour(time24h){let [hours, minutes] time24h.split(:);let modifier 上午;if (parseInt(hours, 10) > 12) {modifier 下午;hours (parseInt(hours, 10) - 12).toString();}if (parseInt(hours, 10) 12) {modifier 下午;}…

新手入門:無服務器函數和FaaS簡介

無服務器&#xff08;Serverless&#xff09;架構的價值在于其成本效益、彈性和擴展性、簡化的開發和部署流程、高可用性和可靠性以及使開發者能夠專注于業務邏輯。通過自動化資源調配和按需計費&#xff0c;無服務器架構能夠降低成本并適應流量變化&#xff0c;同時簡化開發流…

《昇思25天學習打卡營第01天|sun65535》

開始 昇思25天打卡訓練營&#xff0c;讓我第一次了解了華為昇思的平臺&#xff0c;之前也有自己本地使用4060訓練了一些“小模型”&#xff0c;但是都是比較皮毛的知識&#xff0c;只是根據教程去搭建。很少了解到具體的過程。昇思25天打卡訓練營給了一個比較全面的訓練課程。…