1 // RIPEMD-160, based on the algorithm description
3 // this is around 2 times faster than `std.digest.ripemd`
6 public enum RIPEMD160_BITS
= 160;
8 // Buffer size for RIPEMD-160 hash, in bytes.
9 public enum RIPEMD160_BYTES
= (RIPEMD160_BITS
>>3);
11 // RIPEMD-160 context.
12 public struct RIPEMD160_Ctx
{
13 uint[RIPEMD160_BYTES
>>2] wkbuf
= [0x67452301U
, 0xefcdab89U
, 0x98badcfeU
, 0x10325476U
, 0xc3d2e1f0U
];
22 enum RIPEMD160_ROL(string x
, string n
) = `(((`~x
~`)<<(`~n
~`))|((`~x
~`)>>(32-(`~n
~`))))`;
24 template RIPEMD160_PRIM(string bop
, string x
, string y
, string z
) {
25 static if (bop
== "F") enum RIPEMD160_PRIM
= `((`~x
~`)^(`~y
~`)^(`~z
~`))`;
26 else static if (bop
== "G") enum RIPEMD160_PRIM
= `(((`~x
~`)&(`~y
~`))|(~(`~x
~`)&(`~z
~`)))`;
27 else static if (bop
== "H") enum RIPEMD160_PRIM
= `(((`~x
~`)|~(`~y
~`))^(`~z
~`))`;
28 else static if (bop
== "I") enum RIPEMD160_PRIM
= `(((`~x
~`)&(`~z
~`))|((`~y
~`)&~(`~z
~`)))`;
29 else static if (bop
== "J") enum RIPEMD160_PRIM
= `((`~x
~`)^((`~y
~`)|~(`~z
~`)))`;
30 else static assert(0, "invalid bop");
33 enum RIPEMD160_BOP(string bop
, string addconst
, string a
, string b
, string c
, string d
, string e
, string x
, string s
) =
34 `(`~a
~`) += `~RIPEMD160_PRIM
!(bop
, b
, c
, d
)~`+(`~x
~`)+`~addconst
~`;`~
35 `(`~a
~`) = `~RIPEMD160_ROL
!(a
, s
)~`+(`~e
~`);`~
36 `(`~c
~`) = `~RIPEMD160_ROL
!(c
, "10")~`;`;
38 enum RIPEMD160_FF(string a
, string b
, string c
, string d
, string e
, string x
, string s
) = RIPEMD160_BOP
!("F", "0U", a
, b
, c
, d
, e
, x
, s
);
39 enum RIPEMD160_GG(string a
, string b
, string c
, string d
, string e
, string x
, string s
) = RIPEMD160_BOP
!("G", "0x5a827999U", a
, b
, c
, d
, e
, x
, s
);
40 enum RIPEMD160_HH(string a
, string b
, string c
, string d
, string e
, string x
, string s
) = RIPEMD160_BOP
!("H", "0x6ed9eba1U", a
, b
, c
, d
, e
, x
, s
);
41 enum RIPEMD160_II(string a
, string b
, string c
, string d
, string e
, string x
, string s
) = RIPEMD160_BOP
!("I", "0x8f1bbcdcU", a
, b
, c
, d
, e
, x
, s
);
42 enum RIPEMD160_JJ(string a
, string b
, string c
, string d
, string e
, string x
, string s
) = RIPEMD160_BOP
!("J", "0xa953fd4eU", a
, b
, c
, d
, e
, x
, s
);
43 enum RIPEMD160_FFF(string a
, string b
, string c
, string d
, string e
, string x
, string s
) = RIPEMD160_BOP
!("F", "0U", a
, b
, c
, d
, e
, x
, s
);
44 enum RIPEMD160_GGG(string a
, string b
, string c
, string d
, string e
, string x
, string s
) = RIPEMD160_BOP
!("G", "0x7a6d76e9U", a
, b
, c
, d
, e
, x
, s
);
45 enum RIPEMD160_HHH(string a
, string b
, string c
, string d
, string e
, string x
, string s
) = RIPEMD160_BOP
!("H", "0x6d703ef3U", a
, b
, c
, d
, e
, x
, s
);
46 enum RIPEMD160_III(string a
, string b
, string c
, string d
, string e
, string x
, string s
) = RIPEMD160_BOP
!("I", "0x5c4dd124U", a
, b
, c
, d
, e
, x
, s
);
47 enum RIPEMD160_JJJ(string a
, string b
, string c
, string d
, string e
, string x
, string s
) = RIPEMD160_BOP
!("J", "0x50a28be6U", a
, b
, c
, d
, e
, x
, s
);
50 static void ripemd160_compress (uint *wkbuf
/*[RIPEMD160_BYTES>>2]*/, const uint* X
) nothrow @trusted @nogc {
63 mixin(RIPEMD160_FF
!("aa", "bb", "cc", "dd", "ee", "X[ 0]", "11"));
64 mixin(RIPEMD160_FF
!("ee", "aa", "bb", "cc", "dd", "X[ 1]", "14"));
65 mixin(RIPEMD160_FF
!("dd", "ee", "aa", "bb", "cc", "X[ 2]", "15"));
66 mixin(RIPEMD160_FF
!("cc", "dd", "ee", "aa", "bb", "X[ 3]", "12"));
67 mixin(RIPEMD160_FF
!("bb", "cc", "dd", "ee", "aa", "X[ 4]", " 5"));
68 mixin(RIPEMD160_FF
!("aa", "bb", "cc", "dd", "ee", "X[ 5]", " 8"));
69 mixin(RIPEMD160_FF
!("ee", "aa", "bb", "cc", "dd", "X[ 6]", " 7"));
70 mixin(RIPEMD160_FF
!("dd", "ee", "aa", "bb", "cc", "X[ 7]", " 9"));
71 mixin(RIPEMD160_FF
!("cc", "dd", "ee", "aa", "bb", "X[ 8]", "11"));
72 mixin(RIPEMD160_FF
!("bb", "cc", "dd", "ee", "aa", "X[ 9]", "13"));
73 mixin(RIPEMD160_FF
!("aa", "bb", "cc", "dd", "ee", "X[10]", "14"));
74 mixin(RIPEMD160_FF
!("ee", "aa", "bb", "cc", "dd", "X[11]", "15"));
75 mixin(RIPEMD160_FF
!("dd", "ee", "aa", "bb", "cc", "X[12]", " 6"));
76 mixin(RIPEMD160_FF
!("cc", "dd", "ee", "aa", "bb", "X[13]", " 7"));
77 mixin(RIPEMD160_FF
!("bb", "cc", "dd", "ee", "aa", "X[14]", " 9"));
78 mixin(RIPEMD160_FF
!("aa", "bb", "cc", "dd", "ee", "X[15]", " 8"));
81 mixin(RIPEMD160_GG
!("ee", "aa", "bb", "cc", "dd", "X[ 7]", " 7"));
82 mixin(RIPEMD160_GG
!("dd", "ee", "aa", "bb", "cc", "X[ 4]", " 6"));
83 mixin(RIPEMD160_GG
!("cc", "dd", "ee", "aa", "bb", "X[13]", " 8"));
84 mixin(RIPEMD160_GG
!("bb", "cc", "dd", "ee", "aa", "X[ 1]", "13"));
85 mixin(RIPEMD160_GG
!("aa", "bb", "cc", "dd", "ee", "X[10]", "11"));
86 mixin(RIPEMD160_GG
!("ee", "aa", "bb", "cc", "dd", "X[ 6]", " 9"));
87 mixin(RIPEMD160_GG
!("dd", "ee", "aa", "bb", "cc", "X[15]", " 7"));
88 mixin(RIPEMD160_GG
!("cc", "dd", "ee", "aa", "bb", "X[ 3]", "15"));
89 mixin(RIPEMD160_GG
!("bb", "cc", "dd", "ee", "aa", "X[12]", " 7"));
90 mixin(RIPEMD160_GG
!("aa", "bb", "cc", "dd", "ee", "X[ 0]", "12"));
91 mixin(RIPEMD160_GG
!("ee", "aa", "bb", "cc", "dd", "X[ 9]", "15"));
92 mixin(RIPEMD160_GG
!("dd", "ee", "aa", "bb", "cc", "X[ 5]", " 9"));
93 mixin(RIPEMD160_GG
!("cc", "dd", "ee", "aa", "bb", "X[ 2]", "11"));
94 mixin(RIPEMD160_GG
!("bb", "cc", "dd", "ee", "aa", "X[14]", " 7"));
95 mixin(RIPEMD160_GG
!("aa", "bb", "cc", "dd", "ee", "X[11]", "13"));
96 mixin(RIPEMD160_GG
!("ee", "aa", "bb", "cc", "dd", "X[ 8]", "12"));
99 mixin(RIPEMD160_HH
!("dd", "ee", "aa", "bb", "cc", "X[ 3]", "11"));
100 mixin(RIPEMD160_HH
!("cc", "dd", "ee", "aa", "bb", "X[10]", "13"));
101 mixin(RIPEMD160_HH
!("bb", "cc", "dd", "ee", "aa", "X[14]", " 6"));
102 mixin(RIPEMD160_HH
!("aa", "bb", "cc", "dd", "ee", "X[ 4]", " 7"));
103 mixin(RIPEMD160_HH
!("ee", "aa", "bb", "cc", "dd", "X[ 9]", "14"));
104 mixin(RIPEMD160_HH
!("dd", "ee", "aa", "bb", "cc", "X[15]", " 9"));
105 mixin(RIPEMD160_HH
!("cc", "dd", "ee", "aa", "bb", "X[ 8]", "13"));
106 mixin(RIPEMD160_HH
!("bb", "cc", "dd", "ee", "aa", "X[ 1]", "15"));
107 mixin(RIPEMD160_HH
!("aa", "bb", "cc", "dd", "ee", "X[ 2]", "14"));
108 mixin(RIPEMD160_HH
!("ee", "aa", "bb", "cc", "dd", "X[ 7]", " 8"));
109 mixin(RIPEMD160_HH
!("dd", "ee", "aa", "bb", "cc", "X[ 0]", "13"));
110 mixin(RIPEMD160_HH
!("cc", "dd", "ee", "aa", "bb", "X[ 6]", " 6"));
111 mixin(RIPEMD160_HH
!("bb", "cc", "dd", "ee", "aa", "X[13]", " 5"));
112 mixin(RIPEMD160_HH
!("aa", "bb", "cc", "dd", "ee", "X[11]", "12"));
113 mixin(RIPEMD160_HH
!("ee", "aa", "bb", "cc", "dd", "X[ 5]", " 7"));
114 mixin(RIPEMD160_HH
!("dd", "ee", "aa", "bb", "cc", "X[12]", " 5"));
117 mixin(RIPEMD160_II
!("cc", "dd", "ee", "aa", "bb", "X[ 1]", "11"));
118 mixin(RIPEMD160_II
!("bb", "cc", "dd", "ee", "aa", "X[ 9]", "12"));
119 mixin(RIPEMD160_II
!("aa", "bb", "cc", "dd", "ee", "X[11]", "14"));
120 mixin(RIPEMD160_II
!("ee", "aa", "bb", "cc", "dd", "X[10]", "15"));
121 mixin(RIPEMD160_II
!("dd", "ee", "aa", "bb", "cc", "X[ 0]", "14"));
122 mixin(RIPEMD160_II
!("cc", "dd", "ee", "aa", "bb", "X[ 8]", "15"));
123 mixin(RIPEMD160_II
!("bb", "cc", "dd", "ee", "aa", "X[12]", " 9"));
124 mixin(RIPEMD160_II
!("aa", "bb", "cc", "dd", "ee", "X[ 4]", " 8"));
125 mixin(RIPEMD160_II
!("ee", "aa", "bb", "cc", "dd", "X[13]", " 9"));
126 mixin(RIPEMD160_II
!("dd", "ee", "aa", "bb", "cc", "X[ 3]", "14"));
127 mixin(RIPEMD160_II
!("cc", "dd", "ee", "aa", "bb", "X[ 7]", " 5"));
128 mixin(RIPEMD160_II
!("bb", "cc", "dd", "ee", "aa", "X[15]", " 6"));
129 mixin(RIPEMD160_II
!("aa", "bb", "cc", "dd", "ee", "X[14]", " 8"));
130 mixin(RIPEMD160_II
!("ee", "aa", "bb", "cc", "dd", "X[ 5]", " 6"));
131 mixin(RIPEMD160_II
!("dd", "ee", "aa", "bb", "cc", "X[ 6]", " 5"));
132 mixin(RIPEMD160_II
!("cc", "dd", "ee", "aa", "bb", "X[ 2]", "12"));
135 mixin(RIPEMD160_JJ
!("bb", "cc", "dd", "ee", "aa", "X[ 4]", " 9"));
136 mixin(RIPEMD160_JJ
!("aa", "bb", "cc", "dd", "ee", "X[ 0]", "15"));
137 mixin(RIPEMD160_JJ
!("ee", "aa", "bb", "cc", "dd", "X[ 5]", " 5"));
138 mixin(RIPEMD160_JJ
!("dd", "ee", "aa", "bb", "cc", "X[ 9]", "11"));
139 mixin(RIPEMD160_JJ
!("cc", "dd", "ee", "aa", "bb", "X[ 7]", " 6"));
140 mixin(RIPEMD160_JJ
!("bb", "cc", "dd", "ee", "aa", "X[12]", " 8"));
141 mixin(RIPEMD160_JJ
!("aa", "bb", "cc", "dd", "ee", "X[ 2]", "13"));
142 mixin(RIPEMD160_JJ
!("ee", "aa", "bb", "cc", "dd", "X[10]", "12"));
143 mixin(RIPEMD160_JJ
!("dd", "ee", "aa", "bb", "cc", "X[14]", " 5"));
144 mixin(RIPEMD160_JJ
!("cc", "dd", "ee", "aa", "bb", "X[ 1]", "12"));
145 mixin(RIPEMD160_JJ
!("bb", "cc", "dd", "ee", "aa", "X[ 3]", "13"));
146 mixin(RIPEMD160_JJ
!("aa", "bb", "cc", "dd", "ee", "X[ 8]", "14"));
147 mixin(RIPEMD160_JJ
!("ee", "aa", "bb", "cc", "dd", "X[11]", "11"));
148 mixin(RIPEMD160_JJ
!("dd", "ee", "aa", "bb", "cc", "X[ 6]", " 8"));
149 mixin(RIPEMD160_JJ
!("cc", "dd", "ee", "aa", "bb", "X[15]", " 5"));
150 mixin(RIPEMD160_JJ
!("bb", "cc", "dd", "ee", "aa", "X[13]", " 6"));
153 mixin(RIPEMD160_JJJ
!("aaa", "bbb", "ccc", "ddd", "eee", "X[ 5]", " 8"));
154 mixin(RIPEMD160_JJJ
!("eee", "aaa", "bbb", "ccc", "ddd", "X[14]", " 9"));
155 mixin(RIPEMD160_JJJ
!("ddd", "eee", "aaa", "bbb", "ccc", "X[ 7]", " 9"));
156 mixin(RIPEMD160_JJJ
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 0]", "11"));
157 mixin(RIPEMD160_JJJ
!("bbb", "ccc", "ddd", "eee", "aaa", "X[ 9]", "13"));
158 mixin(RIPEMD160_JJJ
!("aaa", "bbb", "ccc", "ddd", "eee", "X[ 2]", "15"));
159 mixin(RIPEMD160_JJJ
!("eee", "aaa", "bbb", "ccc", "ddd", "X[11]", "15"));
160 mixin(RIPEMD160_JJJ
!("ddd", "eee", "aaa", "bbb", "ccc", "X[ 4]", " 5"));
161 mixin(RIPEMD160_JJJ
!("ccc", "ddd", "eee", "aaa", "bbb", "X[13]", " 7"));
162 mixin(RIPEMD160_JJJ
!("bbb", "ccc", "ddd", "eee", "aaa", "X[ 6]", " 7"));
163 mixin(RIPEMD160_JJJ
!("aaa", "bbb", "ccc", "ddd", "eee", "X[15]", " 8"));
164 mixin(RIPEMD160_JJJ
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 8]", "11"));
165 mixin(RIPEMD160_JJJ
!("ddd", "eee", "aaa", "bbb", "ccc", "X[ 1]", "14"));
166 mixin(RIPEMD160_JJJ
!("ccc", "ddd", "eee", "aaa", "bbb", "X[10]", "14"));
167 mixin(RIPEMD160_JJJ
!("bbb", "ccc", "ddd", "eee", "aaa", "X[ 3]", "12"));
168 mixin(RIPEMD160_JJJ
!("aaa", "bbb", "ccc", "ddd", "eee", "X[12]", " 6"));
171 mixin(RIPEMD160_III
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 6]", " 9"));
172 mixin(RIPEMD160_III
!("ddd", "eee", "aaa", "bbb", "ccc", "X[11]", "13"));
173 mixin(RIPEMD160_III
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 3]", "15"));
174 mixin(RIPEMD160_III
!("bbb", "ccc", "ddd", "eee", "aaa", "X[ 7]", " 7"));
175 mixin(RIPEMD160_III
!("aaa", "bbb", "ccc", "ddd", "eee", "X[ 0]", "12"));
176 mixin(RIPEMD160_III
!("eee", "aaa", "bbb", "ccc", "ddd", "X[13]", " 8"));
177 mixin(RIPEMD160_III
!("ddd", "eee", "aaa", "bbb", "ccc", "X[ 5]", " 9"));
178 mixin(RIPEMD160_III
!("ccc", "ddd", "eee", "aaa", "bbb", "X[10]", "11"));
179 mixin(RIPEMD160_III
!("bbb", "ccc", "ddd", "eee", "aaa", "X[14]", " 7"));
180 mixin(RIPEMD160_III
!("aaa", "bbb", "ccc", "ddd", "eee", "X[15]", " 7"));
181 mixin(RIPEMD160_III
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 8]", "12"));
182 mixin(RIPEMD160_III
!("ddd", "eee", "aaa", "bbb", "ccc", "X[12]", " 7"));
183 mixin(RIPEMD160_III
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 4]", " 6"));
184 mixin(RIPEMD160_III
!("bbb", "ccc", "ddd", "eee", "aaa", "X[ 9]", "15"));
185 mixin(RIPEMD160_III
!("aaa", "bbb", "ccc", "ddd", "eee", "X[ 1]", "13"));
186 mixin(RIPEMD160_III
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 2]", "11"));
189 mixin(RIPEMD160_HHH
!("ddd", "eee", "aaa", "bbb", "ccc", "X[15]", " 9"));
190 mixin(RIPEMD160_HHH
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 5]", " 7"));
191 mixin(RIPEMD160_HHH
!("bbb", "ccc", "ddd", "eee", "aaa", "X[ 1]", "15"));
192 mixin(RIPEMD160_HHH
!("aaa", "bbb", "ccc", "ddd", "eee", "X[ 3]", "11"));
193 mixin(RIPEMD160_HHH
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 7]", " 8"));
194 mixin(RIPEMD160_HHH
!("ddd", "eee", "aaa", "bbb", "ccc", "X[14]", " 6"));
195 mixin(RIPEMD160_HHH
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 6]", " 6"));
196 mixin(RIPEMD160_HHH
!("bbb", "ccc", "ddd", "eee", "aaa", "X[ 9]", "14"));
197 mixin(RIPEMD160_HHH
!("aaa", "bbb", "ccc", "ddd", "eee", "X[11]", "12"));
198 mixin(RIPEMD160_HHH
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 8]", "13"));
199 mixin(RIPEMD160_HHH
!("ddd", "eee", "aaa", "bbb", "ccc", "X[12]", " 5"));
200 mixin(RIPEMD160_HHH
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 2]", "14"));
201 mixin(RIPEMD160_HHH
!("bbb", "ccc", "ddd", "eee", "aaa", "X[10]", "13"));
202 mixin(RIPEMD160_HHH
!("aaa", "bbb", "ccc", "ddd", "eee", "X[ 0]", "13"));
203 mixin(RIPEMD160_HHH
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 4]", " 7"));
204 mixin(RIPEMD160_HHH
!("ddd", "eee", "aaa", "bbb", "ccc", "X[13]", " 5"));
207 mixin(RIPEMD160_GGG
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 8]", "15"));
208 mixin(RIPEMD160_GGG
!("bbb", "ccc", "ddd", "eee", "aaa", "X[ 6]", " 5"));
209 mixin(RIPEMD160_GGG
!("aaa", "bbb", "ccc", "ddd", "eee", "X[ 4]", " 8"));
210 mixin(RIPEMD160_GGG
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 1]", "11"));
211 mixin(RIPEMD160_GGG
!("ddd", "eee", "aaa", "bbb", "ccc", "X[ 3]", "14"));
212 mixin(RIPEMD160_GGG
!("ccc", "ddd", "eee", "aaa", "bbb", "X[11]", "14"));
213 mixin(RIPEMD160_GGG
!("bbb", "ccc", "ddd", "eee", "aaa", "X[15]", " 6"));
214 mixin(RIPEMD160_GGG
!("aaa", "bbb", "ccc", "ddd", "eee", "X[ 0]", "14"));
215 mixin(RIPEMD160_GGG
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 5]", " 6"));
216 mixin(RIPEMD160_GGG
!("ddd", "eee", "aaa", "bbb", "ccc", "X[12]", " 9"));
217 mixin(RIPEMD160_GGG
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 2]", "12"));
218 mixin(RIPEMD160_GGG
!("bbb", "ccc", "ddd", "eee", "aaa", "X[13]", " 9"));
219 mixin(RIPEMD160_GGG
!("aaa", "bbb", "ccc", "ddd", "eee", "X[ 9]", "12"));
220 mixin(RIPEMD160_GGG
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 7]", " 5"));
221 mixin(RIPEMD160_GGG
!("ddd", "eee", "aaa", "bbb", "ccc", "X[10]", "15"));
222 mixin(RIPEMD160_GGG
!("ccc", "ddd", "eee", "aaa", "bbb", "X[14]", " 8"));
225 mixin(RIPEMD160_FFF
!("bbb", "ccc", "ddd", "eee", "aaa", "X[12] ", " 8"));
226 mixin(RIPEMD160_FFF
!("aaa", "bbb", "ccc", "ddd", "eee", "X[15] ", " 5"));
227 mixin(RIPEMD160_FFF
!("eee", "aaa", "bbb", "ccc", "ddd", "X[10] ", "12"));
228 mixin(RIPEMD160_FFF
!("ddd", "eee", "aaa", "bbb", "ccc", "X[ 4] ", " 9"));
229 mixin(RIPEMD160_FFF
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 1] ", "12"));
230 mixin(RIPEMD160_FFF
!("bbb", "ccc", "ddd", "eee", "aaa", "X[ 5] ", " 5"));
231 mixin(RIPEMD160_FFF
!("aaa", "bbb", "ccc", "ddd", "eee", "X[ 8] ", "14"));
232 mixin(RIPEMD160_FFF
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 7] ", " 6"));
233 mixin(RIPEMD160_FFF
!("ddd", "eee", "aaa", "bbb", "ccc", "X[ 6] ", " 8"));
234 mixin(RIPEMD160_FFF
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 2] ", "13"));
235 mixin(RIPEMD160_FFF
!("bbb", "ccc", "ddd", "eee", "aaa", "X[13] ", " 6"));
236 mixin(RIPEMD160_FFF
!("aaa", "bbb", "ccc", "ddd", "eee", "X[14] ", " 5"));
237 mixin(RIPEMD160_FFF
!("eee", "aaa", "bbb", "ccc", "ddd", "X[ 0] ", "15"));
238 mixin(RIPEMD160_FFF
!("ddd", "eee", "aaa", "bbb", "ccc", "X[ 3] ", "13"));
239 mixin(RIPEMD160_FFF
!("ccc", "ddd", "eee", "aaa", "bbb", "X[ 9] ", "11"));
240 mixin(RIPEMD160_FFF
!("bbb", "ccc", "ddd", "eee", "aaa", "X[11] ", "11"));
243 ddd
+= cc
+wkbuf
[1]; // final result for wkbuf[0]
244 wkbuf
[1] = wkbuf
[2]+dd+eee
;
245 wkbuf
[2] = wkbuf
[3]+ee
+aaa;
246 wkbuf
[3] = wkbuf
[4]+aa
+bbb
;
247 wkbuf
[4] = wkbuf
[0]+bb
+ccc
;
252 // ////////////////////////////////////////////////////////////////////////// //
253 public void ripemd160_init (ref RIPEMD160_Ctx ctx
) nothrow @trusted @nogc {
254 import core
.stdc
.string
: memset
;
255 memset(cast(void*)&ctx
, 0, RIPEMD160_Ctx
.sizeof
);
256 ctx
.wkbuf
.ptr
[0] = 0x67452301U
;
257 ctx
.wkbuf
.ptr
[1] = 0xefcdab89U
;
258 ctx
.wkbuf
.ptr
[2] = 0x98badcfeU
;
259 ctx
.wkbuf
.ptr
[3] = 0x10325476U
;
260 ctx
.wkbuf
.ptr
[4] = 0xc3d2e1f0U
;
264 // ////////////////////////////////////////////////////////////////////////// //
265 public void ripemd160_putbyte (ref RIPEMD160_Ctx ctx
, in ubyte b
) nothrow @trusted @nogc {
266 pragma(inline
, true);
268 (cast(uint*)ctx
.chunkd
.ptr
)[ctx
.chunkpos
>>2] |
= (cast(uint)b
)<<((ctx
.chunkpos
&0x03U
)<<3);
270 ctx
.chunkd
.ptr
[ctx
.chunkpos
] = b
;
272 if (++ctx
.chunkpos
== 64U) {
273 ripemd160_compress(ctx
.wkbuf
.ptr
, cast(const uint*)ctx
.chunkd
.ptr
);
275 import core
.stdc
.string
: memset
;
276 memset(ctx
.chunkd
.ptr
, 0, ctx
.chunkd
.sizeof
);
283 // ////////////////////////////////////////////////////////////////////////// //
284 public void ripemd160_put (ref RIPEMD160_Ctx ctx
, const(void)[] data
) nothrow @trusted @nogc {
285 if (data
.length
== 0) return;
286 static if ((void*).sizeof
<= 4) {
287 if (ctx
.total
+data
.length
<= ctx
.total
) ++ctx
.totalhi
;
288 ctx
.total
+= data
.length
;
290 if (ctx
.total
+cast(uint)data
.length
<= ctx
.total
) ++ctx
.totalhi
;
291 ctx
.total
+= cast(uint)data
.length
;
292 ctx
.totalhi
+= cast(uint)(data
.length
>>32);
294 const(ubyte)* b
= cast(const(ubyte)*)data
.ptr
;
295 usize datasize
= data
.length
;
297 while (datasize
--) ripemd160_putbyte(ctx
, *b
++);
299 // process full chunks, if possible
300 if (ctx
.chunkpos
== 0 && datasize
>= cast(usize
)64) {
302 ripemd160_compress(ctx
.wkbuf
.ptr
, cast(const uint*)b
);
304 } while ((datasize
-= cast(usize
)64) >= cast(usize
)64);
305 if (datasize
== 0) return;
307 // we can use `memcpy()` here
308 import core
.stdc
.string
: memcpy
, memset
;
309 uint left
= 64U-ctx
.chunkpos
;
310 if (cast(usize
)left
> datasize
) left
= cast(uint)datasize
;
311 memcpy(ctx
.chunkd
.ptr
+ctx
.chunkpos
, b
, cast(usize
)left
);
312 if ((ctx
.chunkpos
+= left
) == 64U) {
313 ripemd160_compress(ctx
.wkbuf
.ptr
, cast(const uint*)ctx
.chunkd
.ptr
);
315 datasize
-= cast(usize
)left
;
316 while (datasize
>= cast(usize
)64) {
317 ripemd160_compress(ctx
.wkbuf
.ptr
, cast(const uint*)b
);
321 if ((ctx
.chunkpos
= cast(uint)datasize
) != 0) memcpy(ctx
.chunkd
.ptr
, b
, datasize
);
325 datasize
-= cast(usize
)left
;
326 if (datasize
) assert(0);
333 // ////////////////////////////////////////////////////////////////////////// //
334 public ubyte[RIPEMD160_BYTES
] ripemd160_finish (const ref RIPEMD160_Ctx ctx
) nothrow @trusted @nogc {
335 import core
.stdc
.string
: memcpy
, memset
;
337 RIPEMD160_Ctx rctx
= void;
338 memcpy(cast(void*)&rctx
, cast(void*)&ctx
, RIPEMD160_Ctx
.sizeof
);
340 // padding with `1` bit
341 ripemd160_putbyte(ref rctx
, 0x80);
342 // length in bits goes into two last dwords
344 if (64U-rctx
.chunkpos
< 8U) {
345 while (rctx
.chunkpos
) ripemd160_putbyte(&rctx
, 0);
346 ripemd160_compress(rctx
.wkbuf
.ptr
, cast(const uint*)rctx
.chunkd
.ptr
);
347 memset(rctx
.chunkd
.ptr
, 0, rctx
.chunkd
.sizeof
);
349 // chunk is guaranteed to be properly cleared here
350 immutable uint t0
= ctx
.total
<<3;
351 rctx
.chunkd
.ptr
[56U] = t0
&0xffU
;
352 rctx
.chunkd
.ptr
[57U] = (t0
>>8)&0xffU
;
353 rctx
.chunkd
.ptr
[58U] = (t0
>>16)&0xffU
;
354 rctx
.chunkd
.ptr
[59U] = (t0
>>24)&0xffU
;
355 immutable uint t1
= (ctx
.total
>>29)|
(ctx
.totalhi
<<3);
356 rctx
.chunkd
.ptr
[60U] = t1
&0xffU
;
357 rctx
.chunkd
.ptr
[61U] = (t1
>>8)&0xffU
;
358 rctx
.chunkd
.ptr
[62U] = (t1
>>16)&0xffU
;
359 rctx
.chunkd
.ptr
[63U] = (t1
>>24)&0xffU
;
361 uint left
= 64U-rctx
.chunkpos
;
363 if (left
) memset(rctx
.chunkd
.ptr
+64U-left
, 0, left
);
364 ripemd160_compress(rctx
.wkbuf
.ptr
, cast(const uint*)rctx
.chunkd
.ptr
);
368 if (left
) memset(rctx
.chunkd
.ptr
+64U-8U-left
, 0, left
);
369 (cast(uint*)rctx
.chunkd
.ptr
)[14] = ctx
.total
<<3;
370 (cast(uint*)rctx
.chunkd
.ptr
)[15] = (ctx
.total
>>29)|
(ctx
.totalhi
<<3);
372 ripemd160_compress(rctx
.wkbuf
.ptr
, cast(const uint*)rctx
.chunkd
);
374 ubyte[RIPEMD160_BYTES
] hash
= void;
375 memcpy(hash
.ptr
, cast(void*)rctx
.wkbuf
.ptr
, RIPEMD160_BYTES
);
380 public int ripemd160_canput (const ref RIPEMD160_Ctx ctx
, in usize datasize
) pure nothrow @trusted @nogc {
381 static if ((void*).sizeof
<= 4) {
382 return (ctx
.totalhi
< 0x1fffffffU
+(ctx
.total
+datasize
> ctx
.total
));
385 immutable uint lo
= cast(uint)datasize
;
386 immutable uint hi
= cast(uint)(datasize
>>32);
387 if (ctx
.totalhi
+hi
>= 0x20000000U
) return 0;
388 return ((hi
+ctx
.totalhi
) < 0x1fffffffU
+(ctx
.total
+lo
> ctx
.total
));
393 version(unittest_ripemd160
)
395 static void selftest_str (const(void)[] str, string res
) {
396 import core
.stdc
.stdio
: snprintf
;
397 import core
.stdc
.string
: memcmp
;
398 assert(res
.length
== RIPEMD160_BYTES
*2);
401 ubyte[RIPEMD160_BYTES
] hash
;
402 char[RIPEMD160_BYTES
*2+2] hhex
;
404 ripemd160_init(ref ctx
);
405 ripemd160_put(ref ctx
, str[]);
406 hash
= ripemd160_finish(ref ctx
);
407 foreach (immutable c
; 0..RIPEMD160_BYTES
) snprintf(hhex
.ptr
+c
*2, 3, "%02x", hash
[c
]);
409 if (memcmp(hhex
.ptr
, res
.ptr
, RIPEMD160_BYTES
*2) != 0) {
410 import core
.stdc
.stdio
: stderr
, fprintf
;
411 fprintf(stderr
, "FAILURE!\n");
412 fprintf(stderr
, "string : %.*s\n", cast(uint)str.length
, str.ptr
);
413 fprintf(stderr
, "result : %s\n", hhex
.ptr
);
414 fprintf(stderr
, "expected: %.*s\n", cast(uint)res
.length
, res
.ptr
);
420 static void selftest (void) {
421 selftest_str("", "9c1185a5c5e9fc54612808977ee8f548b2258d31");
422 selftest_str("abcdefghijklmnopqrstuvwxyz", "f71c27109c692c1b56bbdceb5b9d2865b3708dbc");
424 selftest_str("a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe");
425 selftest_str("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc");
426 selftest_str("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "12a053384a9c0c88e405a06c27dcf49ada62eb2b");
427 selftest_str("message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36");
428 selftest_str("abcdefghijklmnopqrstuvwxyz", "f71c27109c692c1b56bbdceb5b9d2865b3708dbc");
429 selftest_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "b0e20b6e3116640286ed3a87a5713079b21f5189");
430 selftest_str("1234567890123456789012345678901234567890"~"1234567890123456789012345678901234567890", "9b752e45573d4b39f4dbd3323cab82bf63326bfb");
433 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"~
434 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"~
435 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"~
436 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"~
437 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"~
438 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"~
439 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"~
440 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
441 , "160dd118d84b2ceff71261ab78fb9239e257c8d3");
444 char[160/8] zero
= 0;
445 selftest_str(zero
[], "5c00bd4aca04a9057c09b20b05f723f2e23deb65");
447 selftest_str("Alice", "b417ed99b95ce21448b7d789c50009e4f088e3a7");
448 selftest_str("Miriel", "c95659db5eb45fe56023c073e96ca597347860d9");