Tôi đã phát triển một ứng dụng đảo ngược một số biểu thức được sử dụng trong thuật toán băm. Ứng dụng không đảo ngược toàn bộ thuật toán, nhưng đảo ngược một số phần. Ứng dụng này tiết lộ rằng một số biểu thức trong thuật toán có thể được đảo ngược. Điều này có gây rủi ro cho các thuật toán băm sử dụng các biểu thức tương tự không?
Dưới đây là đầu ra ứng dụng và mã kiểm tra của một biểu thức được hình thành từ các biểu thức được sử dụng thường xuyên trong thuật toán băm. Có thể thấy rằng mỗi khóa cho cùng một giá trị băm khi được kiểm tra.Đối với tất cả các biểu thức của độ phức tạp này (chỉ hoạt động theo bit), ứng dụng có thể liệt kê tất cả các khóa có thể có cho mỗi giá trị băm.
Đầu ra ứng dụng:
Hàm băm : 817621565b0d4457402862cee209f1ab139bbd8caf2dc72ec172d4d90429c409
Danh sách khóa (3)
--------------------------------------------- ------------------------
1 Phím : 37639fed3f5c6b60c38a1aeb3589f3176e2b965d75b6a1214ec96b34ddebe005
2 Khóa: e23aab653bfe6aa1591496d880687ef17624366a6db9a4159e1bd4dfa879aad9
3 Khóa: 249d8cca4a00491c20af4cb0ba8d273518162e6ebddbfc2e243355fbfa179089
--------------------------------------------- ------------------------
Mã kiểm tra:
#include <stdio.h>
#include <stdlib.h>
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define ROTBYTE(x, y) (((x) << (y)) | ((x) >> ((8) - (y))))
// Thuật toán băm
int Prs(unsigned char * input,int input_len,unsigned char *output,int output_len) {
int tôi;
unsigned char pn[32] = {113,232,143,101, 58, 79,137, 10,145, 88,110, 97,203, 35,241,171,
221,156, 88, 39,122, 91,105,145,253,103,165, 26,197, 96, 74,131};
for(i=0; i<output_len; i++) {
đầu ra[i]=pn[i%32]^ROTBYTE(đầu vào[i%input_len],2)^ROTBYTE(đầu vào[(i+1)%input_len],3);
đầu ra[i]^=MAJ(đầu vào[(i)%input_len],đầu vào[(i+1)%input_len],đầu vào[(i+2)%input_len]);
}
trả về 0;
}
int HexToBin(ký tự không dấu m, ký tự không dấu l, ký tự không dấu * r) {
ký tự không dấu v;
if(m>='a' && m<='f') {
v=(m-'a'+10)<<4;
} khác nếu(m>='A' && m<='F') {
v=(m-'A'+10)<<4;
} khác nếu(m>='0' && m<='9') {
v=(m-'0')<<4;
}khác{
trả lại 1;
}
if(l>='a' && l<='f') {
v|=(l-'a'+10);
} other if(l>='A' && l<='F') {
v|=(l-'A'+10);
} other if(l>='0' && l<='9') {
v|=(l-'0');
}khác{
trả lại 1;
}
*r=v;
trả về 0;
}
int HexToBinArray(unsigned char * src, int len, unsigned char *out) {
int tôi;
for(i=0; i<len; i++) {
if(HexToBin(src[i*2],src[i*2+1],&out[i])){
trả lại 1;
}
}
trả về 0;
}
int BinToHex(unsigned char b) {
trong TV;
nếu((b>>4)>=10) {
v=((b>>4)+'a'-10)<<8;
} khác {
v=((b>>4)+'0')<<8;
}
nếu((b&15)>=10) {
v|=((b&15)+'a'-10);
} khác {
v|=((b&15)+'0');
}
trở lại v;
}
void BinToHexArray(unsigned char * in,int len,unsigned char *out) {
int tôi;
trong TV;
for(i=0; i<len; i++) {
v=BinToHex(trong[i]);
out[i*2]=v>>8;
ra[i*2+1]=v&0xff;
}
ra[i*2]=0;
trở lại;
}
int Slen(char *s){
đồ thị;
t=s;
trong khi(*s)
s++;
trả lại s-t;
}
int main() {
int input_len=32;
đầu ra int_len=32;
khóa ký tự không dấu [32];
băm char không dấu [32];
ký tự không dấu buf[1024];
int len;
trong khi(1) {
làm{
printf("\n\n\n");
printf(" -------8-------16------24------32------40------48--- ---56------64 \n");
printf(" | | | | | | | |\n");
printf("Khóa: ");
scanf("%s",buf);
slen=Slen(buf);
if(slen!=input_len*2){
printf(" Độ dài khóa phải là %d chữ số thập lục phân.",input_len*2);
}
} while(slen!=input_len*2);
//Chuyển đổi chuỗi hex thành nhị phân
if(HexToBinArray(buf,input_len,key)){
printf("Ký tự nước ngoài trong hệ thập lục phân. \n");
tiếp tục;
}
// Thuật toán băm
Prs(key,input_len,hash,output_len);
//Chuyển nhị phân sang chuỗi hex
BinToHexArray(hash,input_len,buf);
printf(" Hàm băm : %s\n",buf);
}
trả về 0;
}
Mã kiểm tra được viết chỉ để kiểm tra tính chính xác của đầu ra ứng dụng, trong mã, thuật toán băm nằm bên trong hàm "Prs", các hàm khác là cần thiết để mã hoạt động, nhưng chúng không quan trọng. Tính toán mã băm của các giá trị khóa 32 byte được ghi trong một vòng lặp vô tận khi mã được biên dịch và thực thi. Khi các khóa trên được kiểm tra, việc tìm thấy cùng một giá trị băm cho mỗi khóa chứng tỏ rằng biểu thức trong hàm "Prs" bị đảo ngược.