我在MATLAB中编写了自己的SHA1实现,它能够正确生成哈希值。但是它非常慢(一个1000个字符的字符串需要9.9秒在我的Core i7-2760QM上运行),我认为这种缓慢是由于MATLAB如何实现位逻辑操作(
通过使用
bitand
、bitor
、bitxor
、bitcmp
)和位移操作(bitshift
、bitrol
、bitror
)的整数。特别是我想知道为什么需要使用fi
命令构建bitrol
和bitror
的定点数对象,因为在Intel x86汇编中,对于所有大小的寄存器和内存地址都有rol
和ror
。然而,bitshift
非常快(不需要任何定点数构造,普通的uint64
变量就可以工作),这使得情况更加奇怪:为什么在MATLAB中,bitrol
和bitror
需要使用fi
构造定点数对象,而bitshift
则不需要,在汇编级别上,所有这些操作都归结为shl
、shr
、rol
和ror
?因此,在将此函数编写为C/C++的.mex文件之前,我想知道是否有任何方法可以提高此函数的性能。我知道有一些特定于SHA1的优化,但这不是问题所在,如果基本的位旋转实现如此缓慢。通过使用
tic
和toc
进行少量测试,很明显使其变慢的是bitrol
和fi
中的循环。这里有两个这样的循环:%# Define some variables.
FFFFFFFF = uint64(hex2dec('FFFFFFFF'));
%# constants: K(1), K(2), K(3), K(4).
K(1) = uint64(hex2dec('5A827999'));
K(2) = uint64(hex2dec('6ED9EBA1'));
K(3) = uint64(hex2dec('8F1BBCDC'));
K(4) = uint64(hex2dec('CA62C1D6'));
W = uint64(zeros(1, 80));
... some other code here ...
%# First slow loop begins here.
for index = 17:80
W(index) = uint64(bitrol(fi(bitxor(bitxor(bitxor(W(index-3), W(index-8)), W(index-14)), W(index-16)), 0, 32, 0), 1));
end
%# First slow loop ends here.
H = sha1_handle_block_struct.H;
A = H(1);
B = H(2);
C = H(3);
D = H(4);
E = H(5);
%# Second slow loop begins here.
for index = 1:80
rotatedA = uint64(bitrol(fi(A, 0, 32, 0), 5));
if (index <= 20)
% alternative #1.
xorPart = bitxor(D, (bitand(B, (bitxor(C, D)))));
xorPart = bitand(xorPart, FFFFFFFF);
temp = rotatedA + xorPart + E + W(index) + K(1);
elseif ((index >= 21) && (index <= 40))
% FIPS.
xorPart = bitxor(bitxor(B, C), D);
xorPart = bitand(xorPart, FFFFFFFF);
temp = rotatedA + xorPart + E + W(index) + K(2);
elseif ((index >= 41) && (index <= 60))
% alternative #2.
xorPart = bitor(bitand(B, C), bitand(D, bitxor(B, C)));
xorPart = bitand(xorPart, FFFFFFFF);
temp = rotatedA + xorPart + E + W(index) + K(3);
elseif ((index >= 61) && (index <= 80))
% FIPS.
xorPart = bitxor(bitxor(B, C), D);
xorPart = bitand(xorPart, FFFFFFFF);
temp = rotatedA + xorPart + E + W(index) + K(4);
else
error('error in the code of sha1_handle_block.m!');
end
temp = bitand(temp, FFFFFFFF);
E = D;
D = C;
C = uint64(bitrol(fi(B, 0, 32, 0), 30));
B = A;
A = temp;
end
%# Second slow loop ends here.
使用 tic
和 toc
进行测量,我的笔记本电脑计算消息 abc
的 SHA1 哈希需要大约 0.63 秒,其中第一个慢循环花费了约 0.23 秒,第二个慢循环花费了约 0.38 秒。那么,在编写 .mex 文件之前,是否有一些方法可以优化 MATLAB 中的这些循环呢?
java.security.MessageDigest
库或编写MEX函数。由于我计划使我的MATLAB代码与GNU Octave兼容(并希望将GNU Octave用作开发环境),而且似乎MATLAB和Octave在处理Java方面存在一些差异,因此使用Java库不是理想的解决方案。但是,DataHash
非常快,因此在我实现MEX解决方案或找到其他有效实现SHA1的方法之前,它可以胜任工作,而无需使用Java。 - nrzDataHash
是一个可行的解决方案。 - nrzDataHash
,在Octave中使用SHA1
。但是,在我的计算机上,SHA1
(/usr/lib/x86_64-linux-gnu/octave/packages/general-1.3.1/x86_64-pc-linux-gnu-api-v48+/SHA1.oct
)会导致Octave 3.6.2崩溃,但这个错误可能很快就会被修复。 - nrz