1 /**
2  * This module describes the _digest APIs used in Phobos. All digests follow
3  * these APIs. Additionally, this module contains useful helper methods which
4  * can be used with every _digest type.
5  *
6 $(SCRIPT inhibitQuickIndex = 1;)
7 
8 $(DIVC quickindex,
9 $(BOOKTABLE ,
10 $(TR $(TH Category) $(TH Functions)
11 )
12 $(TR $(TDNW Template API) $(TD $(MYREF isDigest) $(MYREF DigestType) $(MYREF hasPeek)
13   $(MYREF hasBlockSize)
14   $(MYREF ExampleDigest) $(MYREF _digest) $(MYREF hexDigest) $(MYREF makeDigest)
15 )
16 )
17 $(TR $(TDNW OOP API) $(TD $(MYREF Digest)
18 )
19 )
20 $(TR $(TDNW Helper functions) $(TD $(MYREF toHexString))
21 )
22 $(TR $(TDNW Implementation helpers) $(TD $(MYREF digestLength) $(MYREF WrapperDigest))
23 )
24 )
25 )
26 
27  * APIs:
28  * There are two APIs for digests: The template API and the OOP API. The template API uses structs
29  * and template helpers like $(LREF isDigest). The OOP API implements digests as classes inheriting
30  * the $(LREF Digest) interface. All digests are named so that the template API struct is called "$(B x)"
31  * and the OOP API class is called "$(B x)Digest". For example we have $(D MD5) <--> $(D MD5Digest),
32  * $(D CRC32) <--> $(D CRC32Digest), etc.
33  *
34  * The template API is slightly more efficient. It does not have to allocate memory dynamically,
35  * all memory is allocated on the stack. The OOP API has to allocate in the finish method if no
36  * buffer was provided. If you provide a buffer to the OOP APIs finish function, it doesn't allocate,
37  * but the $(LREF Digest) classes still have to be created using $(D new) which allocates them using the GC.
38  *
39  * The OOP API is useful to change the _digest function and/or _digest backend at 'runtime'. The benefit here
40  * is that switching e.g. Phobos MD5Digest and an OpenSSLMD5Digest implementation is ABI compatible.
41  *
42  * If just one specific _digest type and backend is needed, the template API is usually a good fit.
43  * In this simplest case, the template API can even be used without templates: Just use the "$(B x)" structs
44  * directly.
45  *
46  * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
47  * Authors:
48  * Johannes Pfau
49  *
50  * Source:    $(PHOBOSSRC std/_digest/_package.d)
51  *
52  * CTFE:
53  * Digests do not work in CTFE
54  *
55  * TODO:
56  * Digesting single bits (as opposed to bytes) is not implemented. This will be done as another
57  * template constraint helper (hasBitDigesting!T) and an additional interface (BitDigest)
58  */
59 /*          Copyright Johannes Pfau 2012.
60  * Distributed under the Boost Software License, Version 1.0.
61  *    (See accompanying file LICENSE_1_0.txt or copy at
62  *          http://www.boost.org/LICENSE_1_0.txt)
63  */
64 module std.digest;
65 
66 public import std.ascii : LetterCase;
67 import std.meta : allSatisfy;
68 import std.range.primitives;
69 import std.traits;
70 
71 
72 ///
73 @system unittest
74 {
75     import std.digest.crc;
76 
77     //Simple example
78     char[8] hexHash = hexDigest!CRC32("The quick brown fox jumps over the lazy dog");
79     assert(hexHash == "39A34F41");
80 
81     //Simple example, using the API manually
82     CRC32 context = makeDigest!CRC32();
83     context.put(cast(ubyte[])"The quick brown fox jumps over the lazy dog");
84     ubyte[4] hash = context.finish();
85     assert(toHexString(hash) == "39A34F41");
86 }
87 
88 ///
89 @system unittest
90 {
91     //Generating the hashes of a file, idiomatic D way
92     import std.digest.crc, std.digest.md, std.digest.sha;
93     import std.stdio;
94 
95     // Digests a file and prints the result.
96     void digestFile(Hash)(string filename)
97     if (isDigest!Hash)
98     {
99         auto file = File(filename);
100         auto result = digest!Hash(file.byChunk(4096 * 1024));
101         writefln("%s (%s) = %s", Hash.stringof, filename, toHexString(result));
102     }
103 
main(string[]args)104     void main(string[] args)
105     {
106         foreach (name; args[1 .. $])
107         {
108             digestFile!MD5(name);
109             digestFile!SHA1(name);
110             digestFile!CRC32(name);
111         }
112     }
113 }
114 ///
115 @system unittest
116 {
117     //Generating the hashes of a file using the template API
118     import std.digest.crc, std.digest.md, std.digest.sha;
119     import std.stdio;
120     // Digests a file and prints the result.
121     void digestFile(Hash)(ref Hash hash, string filename)
122     if (isDigest!Hash)
123     {
124         File file = File(filename);
125 
126         //As digests imlement OutputRange, we could use std.algorithm.copy
127         //Let's do it manually for now
128         foreach (buffer; file.byChunk(4096 * 1024))
129             hash.put(buffer);
130 
131         auto result = hash.finish();
132         writefln("%s (%s) = %s", Hash.stringof, filename, toHexString(result));
133     }
134 
uMain(string[]args)135     void uMain(string[] args)
136     {
137         MD5 md5;
138         SHA1 sha1;
139         CRC32 crc32;
140 
141         md5.start();
142         sha1.start();
143         crc32.start();
144 
145         foreach (arg; args[1 .. $])
146         {
147             digestFile(md5, arg);
148             digestFile(sha1, arg);
149             digestFile(crc32, arg);
150         }
151     }
152 }
153 
154 ///
155 @system unittest
156 {
157     import std.digest.crc, std.digest.md, std.digest.sha;
158     import std.stdio;
159 
160     // Digests a file and prints the result.
digestFile(Digest hash,string filename)161     void digestFile(Digest hash, string filename)
162     {
163         File file = File(filename);
164 
165         //As digests implement OutputRange, we could use std.algorithm.copy
166         //Let's do it manually for now
167         foreach (buffer; file.byChunk(4096 * 1024))
168           hash.put(buffer);
169 
170         ubyte[] result = hash.finish();
171         writefln("%s (%s) = %s", typeid(hash).toString(), filename, toHexString(result));
172     }
173 
umain(string[]args)174     void umain(string[] args)
175     {
176         auto md5 = new MD5Digest();
177         auto sha1 = new SHA1Digest();
178         auto crc32 = new CRC32Digest();
179 
180         foreach (arg; args[1 .. $])
181         {
182           digestFile(md5, arg);
183           digestFile(sha1, arg);
184           digestFile(crc32, arg);
185         }
186     }
187 }
188 
189 version (StdDdoc)
190     version = ExampleDigest;
191 
version(ExampleDigest)192 version (ExampleDigest)
193 {
194     /**
195      * This documents the general structure of a Digest in the template API.
196      * All digest implementations should implement the following members and therefore pass
197      * the $(LREF isDigest) test.
198      *
199      * Note:
200      * $(UL
201      * $(LI A digest must be a struct (value type) to pass the $(LREF isDigest) test.)
202      * $(LI A digest passing the $(LREF isDigest) test is always an $(D OutputRange))
203      * )
204      */
205     struct ExampleDigest
206     {
207         public:
208             /**
209              * Use this to feed the digest with data.
210              * Also implements the $(REF isOutputRange, std,range,primitives)
211              * interface for $(D ubyte) and $(D const(ubyte)[]).
212              * The following usages of $(D put) must work for any type which
213              * passes $(LREF isDigest):
214              * Example:
215              * ----
216              * ExampleDigest dig;
217              * dig.put(cast(ubyte) 0); //single ubyte
218              * dig.put(cast(ubyte) 0, cast(ubyte) 0); //variadic
219              * ubyte[10] buf;
220              * dig.put(buf); //buffer
221              * ----
222              */
223             @trusted void put(scope const(ubyte)[] data...)
224             {
225 
226             }
227 
228             /**
229              * This function is used to (re)initialize the digest.
230              * It must be called before using the digest and it also works as a 'reset' function
231              * if the digest has already processed data.
232              */
233             @trusted void start()
234             {
235 
236             }
237 
238             /**
239              * The finish function returns the final hash sum and resets the Digest.
240              *
241              * Note:
242              * The actual type returned by finish depends on the digest implementation.
243              * $(D ubyte[16]) is just used as an example. It is guaranteed that the type is a
244              * static array of ubytes.
245              *
246              * $(UL
247              * $(LI Use $(LREF DigestType) to obtain the actual return type.)
248              * $(LI Use $(LREF digestLength) to obtain the length of the ubyte array.)
249              * )
250              */
251             @trusted ubyte[16] finish()
252             {
253                 return (ubyte[16]).init;
254             }
255     }
256 }
257 
258 ///
259 @system unittest
260 {
261     //Using the OutputRange feature
262     import std.algorithm.mutation : copy;
263     import std.digest.md;
264     import std.range : repeat;
265 
266     auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
267     auto ctx = makeDigest!MD5();
268     copy(oneMillionRange, &ctx); //Note: You must pass a pointer to copy!
269     assert(ctx.finish().toHexString() == "7707D6AE4E027C70EEA2A935C2296F21");
270 }
271 
272 /**
273  * Use this to check if a type is a digest. See $(LREF ExampleDigest) to see what
274  * a type must provide to pass this check.
275  *
276  * Note:
277  * This is very useful as a template constraint (see examples)
278  *
279  * BUGS:
280  * $(UL
281  * $(LI Does not yet verify that put takes scope parameters.)
282  * $(LI Should check that finish() returns a ubyte[num] array)
283  * )
284  */
285 template isDigest(T)
286 {
287     import std.range : isOutputRange;
288     enum bool isDigest = isOutputRange!(T, const(ubyte)[]) && isOutputRange!(T, ubyte) &&
289         is(T == struct) &&
290         is(typeof(
291         {
292             T dig = void; //Can define
293             dig.put(cast(ubyte) 0, cast(ubyte) 0); //varags
294             dig.start(); //has start
295             auto value = dig.finish(); //has finish
296         }));
297 }
298 
299 ///
300 @system unittest
301 {
302     import std.digest.crc;
303     static assert(isDigest!CRC32);
304 }
305 ///
306 @system unittest
307 {
308     import std.digest.crc;
309     void myFunction(T)()
310     if (isDigest!T)
311     {
312         T dig;
313         dig.start();
314         auto result = dig.finish();
315     }
316     myFunction!CRC32();
317 }
318 
319 /**
320  * Use this template to get the type which is returned by a digest's $(LREF finish) method.
321  */
322 template DigestType(T)
323 {
324     static if (isDigest!T)
325     {
326         alias DigestType =
327             ReturnType!(typeof(
328             {
329                 T dig = void;
330                 return dig.finish();
331             }));
332     }
333     else
334         static assert(false, T.stringof ~ " is not a digest! (fails isDigest!T)");
335 }
336 
337 ///
338 @system unittest
339 {
340     import std.digest.crc;
341     assert(is(DigestType!(CRC32) == ubyte[4]));
342 }
343 ///
344 @system unittest
345 {
346     import std.digest.crc;
347     CRC32 dig;
348     dig.start();
349     DigestType!CRC32 result = dig.finish();
350 }
351 
352 /**
353  * Used to check if a digest supports the $(D peek) method.
354  * Peek has exactly the same function signatures as finish, but it doesn't reset
355  * the digest's internal state.
356  *
357  * Note:
358  * $(UL
359  * $(LI This is very useful as a template constraint (see examples))
360  * $(LI This also checks if T passes $(LREF isDigest))
361  * )
362  */
363 template hasPeek(T)
364 {
365     enum bool hasPeek = isDigest!T &&
366         is(typeof(
367         {
368             T dig = void; //Can define
369             DigestType!T val = dig.peek();
370         }));
371 }
372 
373 ///
374 @system unittest
375 {
376     import std.digest.crc, std.digest.md;
377     assert(!hasPeek!(MD5));
378     assert(hasPeek!CRC32);
379 }
380 ///
381 @system unittest
382 {
383     import std.digest.crc;
384     void myFunction(T)()
385     if (hasPeek!T)
386     {
387         T dig;
388         dig.start();
389         auto result = dig.peek();
390     }
391     myFunction!CRC32();
392 }
393 
394 /**
395  * Checks whether the digest has a $(D blockSize) member, which contains the
396  * digest's internal block size in bits. It is primarily used by $(REF HMAC, std,digest,hmac).
397  */
398 
399 template hasBlockSize(T)
400 if (isDigest!T)
401 {
402     enum bool hasBlockSize = __traits(compiles, { size_t blockSize = T.blockSize; });
403 }
404 
405 ///
406 @system unittest
407 {
408     import std.digest.hmac, std.digest.md;
409     static assert(hasBlockSize!MD5        && MD5.blockSize      == 512);
410     static assert(hasBlockSize!(HMAC!MD5) && HMAC!MD5.blockSize == 512);
411 }
412 
413 package template isDigestibleRange(Range)
414 {
415     import std.digest.md;
416     import std.range : isInputRange, ElementType;
417     enum bool isDigestibleRange = isInputRange!Range && is(typeof(
418           {
419           MD5 ha; //Could use any conformant hash
420           ElementType!Range val;
421           ha.put(val);
422           }));
423 }
424 
425 /**
426  * This is a convenience function to calculate a hash using the template API.
427  * Every digest passing the $(LREF isDigest) test can be used with this function.
428  *
429  * Params:
430  *  range= an $(D InputRange) with $(D ElementType) $(D ubyte), $(D ubyte[]) or $(D ubyte[num])
431  */
432 DigestType!Hash digest(Hash, Range)(auto ref Range range)
433 if (!isArray!Range
434     && isDigestibleRange!Range)
435 {
436     import std.algorithm.mutation : copy;
437     Hash hash;
438     hash.start();
439     copy(range, &hash);
440     return hash.finish();
441 }
442 
443 ///
444 @system unittest
445 {
446     import std.digest.md;
447     import std.range : repeat;
448     auto testRange = repeat!ubyte(cast(ubyte)'a', 100);
449     auto md5 = digest!MD5(testRange);
450 }
451 
452 /**
453  * This overload of the digest function handles arrays.
454  *
455  * Params:
456  *  data= one or more arrays of any type
457  */
458 DigestType!Hash digest(Hash, T...)(scope const T data)
459 if (allSatisfy!(isArray, typeof(data)))
460 {
461     Hash hash;
462     hash.start();
463     foreach (datum; data)
464         hash.put(cast(const(ubyte[]))datum);
465     return hash.finish();
466 }
467 
468 ///
469 @system unittest
470 {
471     import std.digest.crc, std.digest.md, std.digest.sha;
472     auto md5   = digest!MD5(  "The quick brown fox jumps over the lazy dog");
473     auto sha1  = digest!SHA1( "The quick brown fox jumps over the lazy dog");
474     auto crc32 = digest!CRC32("The quick brown fox jumps over the lazy dog");
475     assert(toHexString(crc32) == "39A34F41");
476 }
477 
478 ///
479 @system unittest
480 {
481     import std.digest.crc;
482     auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog");
483     assert(toHexString(crc32) == "39A34F41");
484 }
485 
486 /**
487  * This is a convenience function similar to $(LREF digest), but it returns the string
488  * representation of the hash. Every digest passing the $(LREF isDigest) test can be used with this
489  * function.
490  *
491  * Params:
492  *  order= the order in which the bytes are processed (see $(LREF toHexString))
493  *  range= an $(D InputRange) with $(D ElementType) $(D ubyte), $(D ubyte[]) or $(D ubyte[num])
494  */
495 char[digestLength!(Hash)*2] hexDigest(Hash, Order order = Order.increasing, Range)(ref Range range)
496 if (!isArray!Range && isDigestibleRange!Range)
497 {
498     return toHexString!order(digest!Hash(range));
499 }
500 
501 ///
502 @system unittest
503 {
504     import std.digest.md;
505     import std.range : repeat;
506     auto testRange = repeat!ubyte(cast(ubyte)'a', 100);
507     assert(hexDigest!MD5(testRange) == "36A92CC94A9E0FA21F625F8BFB007ADF");
508 }
509 
510 /**
511  * This overload of the hexDigest function handles arrays.
512  *
513  * Params:
514  *  order= the order in which the bytes are processed (see $(LREF toHexString))
515  *  data= one or more arrays of any type
516  */
517 char[digestLength!(Hash)*2] hexDigest(Hash, Order order = Order.increasing, T...)(scope const T data)
518 if (allSatisfy!(isArray, typeof(data)))
519 {
520     return toHexString!order(digest!Hash(data));
521 }
522 
523 ///
524 @system unittest
525 {
526     import std.digest.crc;
527     assert(hexDigest!(CRC32, Order.decreasing)("The quick brown fox jumps over the lazy dog") == "414FA339");
528 }
529 ///
530 @system unittest
531 {
532     import std.digest.crc;
533     assert(hexDigest!(CRC32, Order.decreasing)("The quick ", "brown ", "fox jumps over the lazy dog") == "414FA339");
534 }
535 
536 /**
537  * This is a convenience function which returns an initialized digest, so it's not necessary to call
538  * start manually.
539  */
540 Hash makeDigest(Hash)()
541 {
542     Hash hash;
543     hash.start();
544     return hash;
545 }
546 
547 ///
548 @system unittest
549 {
550     import std.digest.md;
551     auto md5 = makeDigest!MD5();
552     md5.put(0);
553     assert(toHexString(md5.finish()) == "93B885ADFE0DA089CDF634904FD59F71");
554 }
555 
556 /*+*************************** End of template part, welcome to OOP land **************************/
557 
558 /**
559  * This describes the OOP API. To understand when to use the template API and when to use the OOP API,
560  * see the module documentation at the top of this page.
561  *
562  * The Digest interface is the base interface which is implemented by all digests.
563  *
564  * Note:
565  * A Digest implementation is always an $(D OutputRange)
566  */
567 interface Digest
568 {
569     public:
570         /**
571          * Use this to feed the digest with data.
572          * Also implements the $(REF isOutputRange, std,range,primitives)
573          * interface for $(D ubyte) and $(D const(ubyte)[]).
574          *
575          * Example:
576          * ----
577          * void test(Digest dig)
578          * {
579          *     dig.put(cast(ubyte) 0); //single ubyte
580          *     dig.put(cast(ubyte) 0, cast(ubyte) 0); //variadic
581          *     ubyte[10] buf;
582          *     dig.put(buf); //buffer
583          * }
584          * ----
585          */
586         @trusted nothrow void put(scope const(ubyte)[] data...);
587 
588         /**
589          * Resets the internal state of the digest.
590          * Note:
591          * $(LREF finish) calls this internally, so it's not necessary to call
592          * $(D reset) manually after a call to $(LREF finish).
593          */
594         @trusted nothrow void reset();
595 
596         /**
597          * This is the length in bytes of the hash value which is returned by $(LREF finish).
598          * It's also the required size of a buffer passed to $(LREF finish).
599          */
600         @trusted nothrow @property size_t length() const;
601 
602         /**
603          * The finish function returns the hash value. It takes an optional buffer to copy the data
604          * into. If a buffer is passed, it must be at least $(LREF length) bytes big.
605          */
606         @trusted nothrow ubyte[] finish();
607         ///ditto
608         nothrow ubyte[] finish(ubyte[] buf);
609         //@@@BUG@@@ http://d.puremagic.com/issues/show_bug.cgi?id=6549
610         /*in
611         {
612             assert(buf.length >= this.length);
613         }*/
614 
615         /**
616          * This is a convenience function to calculate the hash of a value using the OOP API.
617          */
618         final @trusted nothrow ubyte[] digest(scope const(void[])[] data...)
619         {
620             this.reset();
621             foreach (datum; data)
622                 this.put(cast(ubyte[]) datum);
623             return this.finish();
624         }
625 }
626 
627 ///
628 @system unittest
629 {
630     //Using the OutputRange feature
631     import std.algorithm.mutation : copy;
632     import std.digest.md;
633     import std.range : repeat;
634 
635     auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
636     auto ctx = new MD5Digest();
637     copy(oneMillionRange, ctx);
638     assert(ctx.finish().toHexString() == "7707D6AE4E027C70EEA2A935C2296F21");
639 }
640 
641 ///
642 @system unittest
643 {
644     import std.digest.crc, std.digest.md, std.digest.sha;
645     ubyte[] md5   = (new MD5Digest()).digest("The quick brown fox jumps over the lazy dog");
646     ubyte[] sha1  = (new SHA1Digest()).digest("The quick brown fox jumps over the lazy dog");
647     ubyte[] crc32 = (new CRC32Digest()).digest("The quick brown fox jumps over the lazy dog");
648     assert(crcHexString(crc32) == "414FA339");
649 }
650 
651 ///
652 @system unittest
653 {
654     import std.digest.crc;
655     ubyte[] crc32 = (new CRC32Digest()).digest("The quick ", "brown ", "fox jumps over the lazy dog");
656     assert(crcHexString(crc32) == "414FA339");
657 }
658 
659 @system unittest
660 {
661     import std.range : isOutputRange;
662     assert(!isDigest!(Digest));
663     assert(isOutputRange!(Digest, ubyte));
664 }
665 
666 ///
667 @system unittest
668 {
669     void test(Digest dig)
670     {
671         dig.put(cast(ubyte) 0); //single ubyte
672         dig.put(cast(ubyte) 0, cast(ubyte) 0); //variadic
673         ubyte[10] buf;
674         dig.put(buf); //buffer
675     }
676 }
677 
678 /*+*************************** End of OOP part, helper functions follow ***************************/
679 
680 /**
681  * See $(LREF toHexString)
682  */
683 enum Order : bool
684 {
685     increasing, ///
686     decreasing ///
687 }
688 
689 
690 /**
691  * Used to convert a hash value (a static or dynamic array of ubytes) to a string.
692  * Can be used with the OOP and with the template API.
693  *
694  * The additional order parameter can be used to specify the order of the input data.
695  * By default the data is processed in increasing order, starting at index 0. To process it in the
696  * opposite order, pass Order.decreasing as a parameter.
697  *
698  * The additional letterCase parameter can be used to specify the case of the output data.
699  * By default the output is in upper case. To change it to the lower case
700  * pass LetterCase.lower as a parameter.
701  *
702  * Note:
703  * The function overloads returning a string allocate their return values
704  * using the GC. The versions returning static arrays use pass-by-value for
705  * the return value, effectively avoiding dynamic allocation.
706  */
707 char[num*2] toHexString(Order order = Order.increasing, size_t num, LetterCase letterCase = LetterCase.upper)
708 (in ubyte[num] digest)
709 {
710     static if (letterCase == LetterCase.upper)
711     {
712         import std.ascii : hexDigits = hexDigits;
713     }
714     else
715     {
716         import std.ascii : hexDigits = lowerHexDigits;
717     }
718 
719 
720     char[num*2] result;
721     size_t i;
722 
723     static if (order == Order.increasing)
724     {
725         foreach (u; digest)
726         {
727             result[i++] = hexDigits[u >> 4];
728             result[i++] = hexDigits[u & 15];
729         }
730     }
731     else
732     {
733         size_t j = num - 1;
734         while (i < num*2)
735         {
736             result[i++] = hexDigits[digest[j] >> 4];
737             result[i++] = hexDigits[digest[j] & 15];
738             j--;
739         }
740     }
741     return result;
742 }
743 
744 ///ditto
745 char[num*2] toHexString(LetterCase letterCase, Order order = Order.increasing, size_t num)(in ubyte[num] digest)
746 {
747     return toHexString!(order, num, letterCase)(digest);
748 }
749 
750 ///ditto
751 string toHexString(Order order = Order.increasing, LetterCase letterCase = LetterCase.upper)
752 (in ubyte[] digest)
753 {
754     static if (letterCase == LetterCase.upper)
755     {
756         import std.ascii : hexDigits = hexDigits;
757     }
758     else
759     {
760         import std.ascii : hexDigits = lowerHexDigits;
761     }
762 
763     auto result = new char[digest.length*2];
764     size_t i;
765 
766     static if (order == Order.increasing)
767     {
768         foreach (u; digest)
769         {
770             result[i++] = hexDigits[u >> 4];
771             result[i++] = hexDigits[u & 15];
772         }
773     }
774     else
775     {
776         import std.range : retro;
777         foreach (u; retro(digest))
778         {
779             result[i++] = hexDigits[u >> 4];
780             result[i++] = hexDigits[u & 15];
781         }
782     }
783     import std.exception : assumeUnique;
784     // memory was just created, so casting to immutable is safe
785     return () @trusted { return assumeUnique(result); }();
786 }
787 
788 ///ditto
789 string toHexString(LetterCase letterCase, Order order = Order.increasing)(in ubyte[] digest)
790 {
791     return toHexString!(order, letterCase)(digest);
792 }
793 
794 //For more example unittests, see Digest.digest, digest
795 
796 ///
797 @safe unittest
798 {
799     import std.digest.crc;
800     //Test with template API:
801     auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog");
802     //Lower case variant:
803     assert(toHexString!(LetterCase.lower)(crc32) == "39a34f41");
804     //Usually CRCs are printed in this order, though:
805     assert(toHexString!(Order.decreasing)(crc32) == "414FA339");
806     assert(toHexString!(LetterCase.lower, Order.decreasing)(crc32) == "414fa339");
807 }
808 
809 ///
810 @safe unittest
811 {
812     import std.digest.crc;
813     // With OOP API
814     auto crc32 = (new CRC32Digest()).digest("The quick ", "brown ", "fox jumps over the lazy dog");
815     //Usually CRCs are printed in this order, though:
816     assert(toHexString!(Order.decreasing)(crc32) == "414FA339");
817 }
818 
819 @safe unittest
820 {
821     ubyte[16] data;
822     assert(toHexString(data) == "00000000000000000000000000000000");
823 
824     assert(toHexString(cast(ubyte[4])[42, 43, 44, 45]) == "2A2B2C2D");
825     assert(toHexString(cast(ubyte[])[42, 43, 44, 45]) == "2A2B2C2D");
826     assert(toHexString!(Order.decreasing)(cast(ubyte[4])[42, 43, 44, 45]) == "2D2C2B2A");
827     assert(toHexString!(Order.decreasing, LetterCase.lower)(cast(ubyte[4])[42, 43, 44, 45]) == "2d2c2b2a");
828     assert(toHexString!(Order.decreasing)(cast(ubyte[])[42, 43, 44, 45]) == "2D2C2B2A");
829 }
830 
831 /*+*********************** End of public helper part, private helpers follow ***********************/
832 
833 /*
834  * Used to convert from a ubyte[] slice to a ref ubyte[N].
835  * This helper is used internally in the WrapperDigest template to wrap the template API's
836  * finish function.
837  */
838 ref T[N] asArray(size_t N, T)(ref T[] source, string errorMsg = "")
839 {
840      assert(source.length >= N, errorMsg);
841      return *cast(T[N]*) source.ptr;
842 }
843 
844 /*
845  * Returns the length (in bytes) of the hash value produced by T.
846  */
847 template digestLength(T)
848 if (isDigest!T)
849 {
850     enum size_t digestLength = (ReturnType!(T.finish)).length;
851 }
852 
853 @safe pure nothrow @nogc
854 unittest
855 {
856     import std.digest.md : MD5;
857     import std.digest.sha : SHA1, SHA256, SHA512;
858     assert(digestLength!MD5 == 16);
859     assert(digestLength!SHA1 == 20);
860     assert(digestLength!SHA256 == 32);
861     assert(digestLength!SHA512 == 64);
862 }
863 
864 /**
865  * Wraps a template API hash struct into a Digest interface.
866  * Modules providing digest implementations will usually provide
867  * an alias for this template (e.g. MD5Digest, SHA1Digest, ...).
868  */
869 class WrapperDigest(T)
870 if (isDigest!T) : Digest
871 {
872     protected:
873         T _digest;
874 
875     public final:
876         /**
877          * Initializes the digest.
878          */
879         this()
880         {
881             _digest.start();
882         }
883 
884         /**
885          * Use this to feed the digest with data.
886          * Also implements the $(REF isOutputRange, std,range,primitives)
887          * interface for $(D ubyte) and $(D const(ubyte)[]).
888          */
889         @trusted nothrow void put(scope const(ubyte)[] data...)
890         {
891             _digest.put(data);
892         }
893 
894         /**
895          * Resets the internal state of the digest.
896          * Note:
897          * $(LREF finish) calls this internally, so it's not necessary to call
898          * $(D reset) manually after a call to $(LREF finish).
899          */
900         @trusted nothrow void reset()
901         {
902             _digest.start();
903         }
904 
905         /**
906          * This is the length in bytes of the hash value which is returned by $(LREF finish).
907          * It's also the required size of a buffer passed to $(LREF finish).
908          */
909         @trusted nothrow @property size_t length() const pure
910         {
911             return digestLength!T;
912         }
913 
914         /**
915          * The finish function returns the hash value. It takes an optional buffer to copy the data
916          * into. If a buffer is passed, it must have a length at least $(LREF length) bytes.
917          *
918          * Example:
919          * --------
920          *
921          * import std.digest.md;
922          * ubyte[16] buf;
923          * auto hash = new WrapperDigest!MD5();
924          * hash.put(cast(ubyte) 0);
925          * auto result = hash.finish(buf[]);
926          * //The result is now in result (and in buf). If you pass a buffer which is bigger than
927          * //necessary, result will have the correct length, but buf will still have it's original
928          * //length
929          * --------
930          */
931         nothrow ubyte[] finish(ubyte[] buf)
932         in
933         {
934             assert(buf.length >= this.length);
935         }
936         body
937         {
938             enum string msg = "Buffer needs to be at least " ~ digestLength!(T).stringof ~ " bytes " ~
939                 "big, check " ~ typeof(this).stringof ~ ".length!";
940             asArray!(digestLength!T)(buf, msg) = _digest.finish();
941             return buf[0 .. digestLength!T];
942         }
943 
944         ///ditto
945         @trusted nothrow ubyte[] finish()
946         {
947             enum len = digestLength!T;
948             auto buf = new ubyte[len];
949             asArray!(digestLength!T)(buf) = _digest.finish();
950             return buf;
951         }
952 
953         version (StdDdoc)
954         {
955             /**
956              * Works like $(D finish) but does not reset the internal state, so it's possible
957              * to continue putting data into this WrapperDigest after a call to peek.
958              *
959              * These functions are only available if $(D hasPeek!T) is true.
960              */
961             @trusted ubyte[] peek(ubyte[] buf) const;
962             ///ditto
963             @trusted ubyte[] peek() const;
964         }
965         else static if (hasPeek!T)
966         {
967             @trusted ubyte[] peek(ubyte[] buf) const
968             in
969             {
970                 assert(buf.length >= this.length);
971             }
972             body
973             {
974                 enum string msg = "Buffer needs to be at least " ~ digestLength!(T).stringof ~ " bytes " ~
975                     "big, check " ~ typeof(this).stringof ~ ".length!";
976                 asArray!(digestLength!T)(buf, msg) = _digest.peek();
977                 return buf[0 .. digestLength!T];
978             }
979 
980             @trusted ubyte[] peek() const
981             {
982                 enum len = digestLength!T;
983                 auto buf = new ubyte[len];
984                 asArray!(digestLength!T)(buf) = _digest.peek();
985                 return buf;
986             }
987         }
988 }
989 
990 ///
991 @system unittest
992 {
993     import std.digest.md;
994     //Simple example
995     auto hash = new WrapperDigest!MD5();
996     hash.put(cast(ubyte) 0);
997     auto result = hash.finish();
998 }
999 
1000 ///
1001 @system unittest
1002 {
1003     //using a supplied buffer
1004     import std.digest.md;
1005     ubyte[16] buf;
1006     auto hash = new WrapperDigest!MD5();
1007     hash.put(cast(ubyte) 0);
1008     auto result = hash.finish(buf[]);
1009     //The result is now in result (and in buf). If you pass a buffer which is bigger than
1010     //necessary, result will have the correct length, but buf will still have it's original
1011     //length
1012 }
1013 
1014 @safe unittest
1015 {
1016     // Test peek & length
1017     import std.digest.crc;
1018     auto hash = new WrapperDigest!CRC32();
1019     assert(hash.length == 4);
1020     hash.put(cast(const(ubyte[]))"The quick brown fox jumps over the lazy dog");
1021     assert(hash.peek().toHexString() == "39A34F41");
1022     ubyte[5] buf;
1023     assert(hash.peek(buf).toHexString() == "39A34F41");
1024 }
1025 
1026 /**
1027  * Securely compares two digest representations while protecting against timing
1028  * attacks. Do not use `==` to compare digest representations.
1029  *
1030  * The attack happens as follows:
1031  *
1032  * $(OL
1033  *     $(LI An attacker wants to send harmful data to your server, which
1034  *     requires a integrity HMAC SHA1 token signed with a secret.)
1035  *     $(LI The length of the token is known to be 40 characters long due to its format,
1036  *     so the attacker first sends `"0000000000000000000000000000000000000000"`,
1037  *     then `"1000000000000000000000000000000000000000"`, and so on.)
1038  *     $(LI The given HMAC token is compared with the expected token using the
1039  *     `==` string comparison, which returns `false` as soon as the first wrong
1040  *     element is found. If a wrong element is found, then a rejection is sent
1041  *     back to the sender.)
1042  *     $(LI Eventually, the attacker is able to determine the first character in
1043  *     the correct token because the sever takes slightly longer to return a
1044  *     rejection. This is due to the comparison moving on to second item in
1045  *     the two arrays, seeing they are different, and then sending the rejection.)
1046  *     $(LI It may seem like too small of a difference in time for the attacker
1047  *     to notice, but security researchers have shown that differences as
1048  *     small as $(LINK2 http://www.cs.rice.edu/~dwallach/pub/crosby-timing2009.pdf,
1049  *     20µs can be reliably distinguished) even with network inconsistencies.)
1050  *     $(LI Repeat the process for each character until the attacker has the whole
1051  *     correct token and the server accepts the harmful data. This can be done
1052  *     in a week with the attacker pacing the attack to 10 requests per second
1053  *     with only one client.)
1054  * )
1055  *
1056  * This function defends against this attack by always comparing every single
1057  * item in the array if the two arrays are the same length. Therefore, this
1058  * function is always $(BIGOH n) for ranges of the same length.
1059  *
1060  * This attack can also be mitigated via rate limiting and banning IPs which have too
1061  * many rejected requests. However, this does not completely solve the problem,
1062  * as the attacker could be in control of a bot net. To fully defend against
1063  * the timing attack, rate limiting, banning IPs, and using this function
1064  * should be used together.
1065  *
1066  * Params:
1067  *     r1 = A digest representation
1068  *     r2 = A digest representation
1069  * Returns:
1070  *     `true` if both representations are equal, `false` otherwise
1071  * See_Also:
1072  *     $(LINK2 https://en.wikipedia.org/wiki/Timing_attack, The Wikipedia article
1073  *     on timing attacks).
1074  */
1075 bool secureEqual(R1, R2)(R1 r1, R2 r2)
1076 if (isInputRange!R1 && isInputRange!R2 && !isInfinite!R1 && !isInfinite!R2 &&
1077     (isIntegral!(ElementEncodingType!R1) || isSomeChar!(ElementEncodingType!R1)) &&
1078     !is(CommonType!(ElementEncodingType!R1, ElementEncodingType!R2) == void))
1079 {
1080     static if (hasLength!R1 && hasLength!R2)
1081         if (r1.length != r2.length)
1082             return false;
1083 
1084     int result;
1085 
1086     static if (isRandomAccessRange!R1 && isRandomAccessRange!R2 &&
1087                hasLength!R1 && hasLength!R2)
1088     {
1089         foreach (i; 0 .. r1.length)
1090             result |= r1[i] ^ r2[i];
1091     }
1092     else static if (hasLength!R1 && hasLength!R2)
1093     {
1094         // Lengths are the same so we can squeeze out a bit of performance
1095         // by not checking if r2 is empty
1096         for (; !r1.empty; r1.popFront(), r2.popFront())
1097         {
1098             result |= r1.front ^ r2.front;
1099         }
1100     }
1101     else
1102     {
1103         // Generic case, walk both ranges
1104         for (; !r1.empty; r1.popFront(), r2.popFront())
1105         {
1106             if (r2.empty) return false;
1107             result |= r1.front ^ r2.front;
1108         }
1109         if (!r2.empty) return false;
1110     }
1111 
1112     return result == 0;
1113 }
1114 
1115 ///
1116 @system pure unittest
1117 {
1118     import std.digest.hmac : hmac;
1119     import std.digest.sha : SHA1;
1120     import std.string : representation;
1121 
1122     // a typical HMAC data integrity verification
1123     auto secret = "A7GZIP6TAQA6OHM7KZ42KB9303CEY0MOV5DD6NTV".representation;
1124     auto data = "data".representation;
1125 
1126     string hex1 = data.hmac!SHA1(secret).toHexString;
1127     string hex2 = data.hmac!SHA1(secret).toHexString;
1128     string hex3 = "data1".representation.hmac!SHA1(secret).toHexString;
1129 
1130     assert( secureEqual(hex1, hex2));
1131     assert(!secureEqual(hex1, hex3));
1132 }
1133 
1134 @system pure unittest
1135 {
1136     import std.internal.test.dummyrange : ReferenceInputRange;
1137     import std.range : takeExactly;
1138     import std.string : representation;
1139     import std.utf : byWchar, byDchar;
1140 
1141     {
1142         auto hex1 = "02CA3484C375EDD3C0F08D3F50D119E61077".representation;
1143         auto hex2 = "02CA3484C375EDD3C0F08D3F50D119E610779018".representation;
1144         assert(!secureEqual(hex1, hex2));
1145     }
1146     {
1147         auto hex1 = "02CA3484C375EDD3C0F08D3F50D119E610779018"w.representation;
1148         auto hex2 = "02CA3484C375EDD3C0F08D3F50D119E610779018"d.representation;
1149         assert(secureEqual(hex1, hex2));
1150     }
1151     {
1152         auto hex1 = "02CA3484C375EDD3C0F08D3F50D119E610779018".byWchar;
1153         auto hex2 = "02CA3484C375EDD3C0F08D3F50D119E610779018".byDchar;
1154         assert(secureEqual(hex1, hex2));
1155     }
1156     {
1157         auto hex1 = "02CA3484C375EDD3C0F08D3F50D119E61077".byWchar;
1158         auto hex2 = "02CA3484C375EDD3C0F08D3F50D119E610779018".byDchar;
1159         assert(!secureEqual(hex1, hex2));
1160     }
1161     {
1162         auto hex1 = new ReferenceInputRange!int([0, 1, 2, 3, 4, 5, 6, 7, 8]).takeExactly(9);
1163         auto hex2 = new ReferenceInputRange!int([0, 1, 2, 3, 4, 5, 6, 7, 8]).takeExactly(9);
1164         assert(secureEqual(hex1, hex2));
1165     }
1166     {
1167         auto hex1 = new ReferenceInputRange!int([0, 1, 2, 3, 4, 5, 6, 7, 8]).takeExactly(9);
1168         auto hex2 = new ReferenceInputRange!int([0, 1, 2, 3, 4, 5, 6, 7, 9]).takeExactly(9);
1169         assert(!secureEqual(hex1, hex2));
1170     }
1171 }
1172