明文填充

对输入的字符串进行填充,首先在明文后面接上一比特的1,然后再添加若干个0使得总长度模512同余448,最后再添加64比特,其数值表示的是明文的长度。

因为输入的都是字符串,一个字符8个bit,我们首先可以算得:明文的比特数=字符数*8。从而可以计算出需要填充的0的个数为(447-明文比特数)%512

sha1面向字进行操作,因此我们可以创建一个关于字的vector作为返回结果。首先对于字符串,每4个字符为一个字,先将它们push进vector。然后讨论字符串剩余1,2,3个字符的情况,分别在其后面添加一个比特1和若干比特0,使得长度为32比特,作为一个字push进vector。接着,计算剩下还要push多少个字的0,把它们push进vector。最后分两个字来push那个表示明文原长度的64比特即可。

F函数

F函数读取B,C,D以及t的值作为输入,并根据t的不同值对BCD进行不同的运算并返回运算结果。实现的时候B,C,D都是bitset<32>,因此可以直接进行相对应的位运算。

Word F_function(Word B, Word C, Word D,int t){
    Word res(0);
    if(t <= 19)
        res = (B&C)|((~B)&D);
    else if(t <= 39)
        res = B^C^D;
    else if(t <= 59)
        res = (B&C)|(B&D)|(C&D);
    else
        res = B^C^D;
    return res;
}

加密算法

由于bitset没有内置的模2^32加法的功能,因此实现了一个add函数用于作模2^32加法操作。

设置全局变量H0,H1,H2,H3,H4和K数组,数值按照书上给出的来。

首先,对明文进行填充,填充的结果是一个关于字的vector,记为Y。由于512bit为一组,也就是16个字,计算n=Y.size()/16。进行n次的for循环,在每次循环中做如下操作:

  1. 计算W数组
  2. 通过一系列运算,更新H0,H1,H2,H3,H4的值

书上给出了伪代码,实现成c++具体的操作如下:

for(int i = 0; i < n; i++){
        vector<Word> W_array;
        for(int j = 0; j < 16; j++){
            W_array.push_back(Y[i*16+j]);
        }
        for(int t = 16; t < 80; t++){
            Word temp(0);
            temp = W_array[t-3]^W_array[t-8]^W_array[t-14]^W_array[t-16];
            temp = temp << 1 | temp >>(32-1);
            W_array.push_back(temp);
        }
        Word A = H0;
        Word B = H1;
        Word C = H2;
        Word D = H3;
        Word E = H4;
        for(int t = 0; t < 80; t++){
            Word temp = A << 5 | A >> (32-5);
            temp = add(temp,F_function(B,C,D,t));
            temp = add(temp,E);
            temp = add(temp,W_array[t]);
            temp = add(temp,K[t/20]);
            E = D;
            D = C;
            C = B << 30 | B >>(32-30);
            B = A;
            A = temp;
        }
        H0 = add(H0,A);
        H1 = add(H1,B);
        H2 = add(H2,C);
        H3 = add(H3,D);
        H4 = add(H4,E);
    }
循环进行完之后,输出H0   H1   H2   H3   H4的指即为所求得的哈希值

main函数

从plaintext.txt中读入内容,这里读入的最长为8192字节,即最大可读入8k的文件。将读入内容构造成字符串,传入加密函数中进行加密。