78d04f1seqlab: write and view pulseq MRI sequences in the browserJeremy Magland 1function digest = md5(message, noBuiltIn)
2 % digest = md5(message)
3 % Compute the MD5 digest of the message, as a hexadecimal digest.
4 % Per default uses built-in functions if available, but can be
5 % forced to use the explicit source-code Matlab/Octave compatible
6 % implementation by setting the optional parameter noBuiltIn to true.
7 % Note that the built-in functions are much faster than the
8 % pure source-code implementation of the MD5 algorithm.
9 % The latter is based on the source code from https://rosettacode.org/wiki/MD5
11 if size(message,1)~=1 || ndims(message)~=2
12 message=message(:).';
13 end
15 if ~exist('noBuiltIn','var') || ~noBuiltIn
16 if mr.aux.isOctave()
17 digest=hash('MD5',char(message)); % Octave-specific function
18 return;
19 else
20 if ~isempty(message) % java function fails for the empty string so we revert to the source-code implementation
21 digest=md5_java(message); % Matlab Java hack
22 return;
23 end
24 end
25 end
27 % Follow the MD5 algorithm from RFC 1321 [1] and Wikipedia [2].
28 % [1] http://tools.ietf.org/html/rfc1321
29 % [2] http://en.wikipedia.org/wiki/MD5
31 % m is the modulus for 32-bit unsigned arithmetic.
32 m = 2 ^ 32;
34 % s is the shift table for circshift(). Each shift is negative
35 % because it is a left shift.
36 s = [-7, -12, -17, -22
37 -5, -9, -14, -20
38 -4, -11, -16, -23
39 -6, -10, -15, -21];
41 % t is the sine table. Each sine is a 32-bit integer, unsigned.
42 t = floor(abs(sin(1:64)) .* m);
44 % Initialize the hash, as a row vector of 32-bit integers.
45 digest = [hex2dec('67452301') ...
46 hex2dec('EFCDAB89') ...
47 hex2dec('98BADCFE') ...
48 hex2dec('10325476')];
50 % If message contains characters, convert them to ASCII values.
51 message = double(message);
52 bytelen = numel(message);
54 % Pad the message by appending a 1, then appending enough 0s to make
55 % the bit length congruent to 448 mod 512. Because we have bytes, we
56 % append 128 '10000000', then append enough 0s '00000000's to make
57 % the byte length congruent to 56 mod 64.
58 message = [message, 128, zeros(1, mod(55 - bytelen, 64))];
60 % Convert the message to 32-bit integers, little endian.
61 % For little endian, first byte is least significant byte.
62 message = reshape(message, 4, numel(message) / 4);
63 message = message(1,:) + ... % least significant byte
64 message(2,:) * 256 + ...
65 message(3,:) * 65536 + ...
66 message(4,:) * 16777216; % most significant byte
68 % Append the bit length as a 64-bit integer, little endian.
69 bitlen = bytelen * 8;
70 message = [message, mod(bitlen, m), mod(bitlen / m, m)];
72 % Process each 512-bit block. Because we have 32-bit integers, each
73 % block has 16 elements, message(k + (0:15)).
74 for k = 1:16:numel(message)
75 % Copy hash.
76 a = digest(1); b = digest(2); c = digest(3); d = digest(4);
78 % Do 64 operations.
79 for i = (1:64)
80 % Convert b, c, d to row vectors of bits (0s and 1s).
81 bv = dec2bin(b, 32) - '0';
82 cv = dec2bin(c, 32) - '0';
83 dv = dec2bin(d, 32) - '0';
85 % Find f = mix of b, c, d.
86 % ki = index in 0:15, to message(k + ki).
87 % sr = row in 1:4, to s(sr, :).
88 if i <= 16 % Round 1
89 f = (bv & cv) | (~bv & dv);
90 ki = i - 1;
91 sr = 1;
92 elseif i <= 32 % Round 2
93 f = (bv & dv) | (cv & ~dv);
94 ki = mod(5 * i - 4, 16);
95 sr = 2;
96 elseif i <= 48 % Round 3
97 f = xor(bv, xor(cv, dv));
98 ki = mod(3 * i + 2, 16);
99 sr = 3;
100 else % Round 4
101 f = xor(cv, bv | ~dv);
102 ki = mod(7 * i - 7, 16);
103 sr = 4;
104 end
106 % Convert f, from row vector of bits, to 32-bit integer.
107 f = bin2dec(char(f + '0'));
109 % Do circular shift of sum.
110 sc = mod(i - 1, 4) + 1;
111 sum = mod(a + f + message(k + ki) + t(i), m);
112 sum = dec2bin(sum, 32);
113 sum = circshift(sum, [0, s(sr, sc)]);
114 sum = bin2dec(sum);
116 % Update a, b, c, d.
117 temp = d;
118 d = c;
119 c = b;
120 b = mod(b + sum, m);
121 a = temp;
122 end %for i
124 % Add hash of this block to hash of previous blocks.
125 digest = mod(digest + [a, b, c, d], m);
126 end %for k
128 % Convert hash from 32-bit integers, little endian, to bytes.
129 digest = [digest % least significant byte
130 digest / 256
131 digest / 65536
132 digest / 16777216]; % most significant byte
133 digest = reshape(mod(floor(digest), 256), 1, numel(digest));
135 % Convert hash to hexadecimal.
136 digest = dec2hex(digest);
137 digest = lower(reshape(transpose(digest), 1, numel(digest)));
138end %md5
140function out=md5_java(buf)
141 import java.security.*;
142 import java.math.*;
143 import java.lang.String;
145 md = MessageDigest.getInstance('MD5');
146 hash = md.digest(double(buf));
147 bi = BigInteger(1, hash);
149 out=char(String.format('%032x', bi));
150end