1 //==- BLAKE3.h - BLAKE3 C++ wrapper for LLVM ---------------------*- C++ -*-==// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This is a C++ wrapper of the BLAKE3 C interface. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_SUPPORT_BLAKE3_H 14 #define LLVM_SUPPORT_BLAKE3_H 15 16 #include "llvm-c/blake3.h" 17 #include "llvm/ADT/ArrayRef.h" 18 #include "llvm/ADT/StringRef.h" 19 20 namespace llvm { 21 22 /// The constant \p LLVM_BLAKE3_OUT_LEN provides the default output length, 23 /// 32 bytes, which is recommended for most callers. 24 /// 25 /// Outputs shorter than the default length of 32 bytes (256 bits) provide 26 /// less security. An N-bit BLAKE3 output is intended to provide N bits of 27 /// first and second preimage resistance and N/2 bits of collision 28 /// resistance, for any N up to 256. Longer outputs don't provide any 29 /// additional security. 30 /// 31 /// Shorter BLAKE3 outputs are prefixes of longer ones. Explicitly 32 /// requesting a short output is equivalent to truncating the default-length 33 /// output. 34 template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN> 35 using BLAKE3Result = std::array<uint8_t, NumBytes>; 36 37 /// A class that wraps the BLAKE3 algorithm. 38 class BLAKE3 { 39 public: 40 BLAKE3() { init(); } 41 42 /// Reinitialize the internal state 43 void init() { llvm_blake3_hasher_init(&Hasher); } 44 45 /// Digest more data. 46 void update(ArrayRef<uint8_t> Data) { 47 llvm_blake3_hasher_update(&Hasher, Data.data(), Data.size()); 48 } 49 50 /// Digest more data. 51 void update(StringRef Str) { 52 llvm_blake3_hasher_update(&Hasher, Str.data(), Str.size()); 53 } 54 55 /// Finalize the hasher and put the result in \p Result. 56 /// This doesn't modify the hasher itself, and it's possible to finalize again 57 /// after adding more input. 58 template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN> 59 void final(BLAKE3Result<NumBytes> &Result) { 60 llvm_blake3_hasher_finalize(&Hasher, Result.data(), Result.size()); 61 } 62 63 /// Finalize the hasher and return an output of any length, given in bytes. 64 /// This doesn't modify the hasher itself, and it's possible to finalize again 65 /// after adding more input. 66 template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN> 67 BLAKE3Result<NumBytes> final() { 68 BLAKE3Result<NumBytes> Result; 69 llvm_blake3_hasher_finalize(&Hasher, Result.data(), Result.size()); 70 return Result; 71 } 72 73 /// Return the current output for the digested data since the last call to 74 /// init(). 75 /// 76 /// Other hash functions distinguish between \p result() and \p final(), with 77 /// \p result() allowing more calls into \p update(), but there's no 78 // difference for the BLAKE3 hash function. 79 template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN> 80 BLAKE3Result<NumBytes> result() { 81 return final<NumBytes>(); 82 } 83 84 /// Returns a BLAKE3 hash for the given data. 85 template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN> 86 static BLAKE3Result<NumBytes> hash(ArrayRef<uint8_t> Data) { 87 BLAKE3 Hasher; 88 Hasher.update(Data); 89 return Hasher.final<NumBytes>(); 90 } 91 92 private: 93 llvm_blake3_hasher Hasher; 94 }; 95 96 /// Like \p BLAKE3 but using a class-level template parameter for specifying the 97 /// hash size of the \p final() and \p result() functions. 98 /// 99 /// This is useful for using BLAKE3 as the hasher type for \p HashBuilder with 100 /// non-default hash sizes. 101 template <size_t NumBytes> class TruncatedBLAKE3 : public BLAKE3 { 102 public: 103 /// Finalize the hasher and put the result in \p Result. 104 /// This doesn't modify the hasher itself, and it's possible to finalize again 105 /// after adding more input. 106 void final(BLAKE3Result<NumBytes> &Result) { return BLAKE3::final(Result); } 107 108 /// Finalize the hasher and return an output of any length, given in bytes. 109 /// This doesn't modify the hasher itself, and it's possible to finalize again 110 /// after adding more input. 111 BLAKE3Result<NumBytes> final() { return BLAKE3::final<NumBytes>(); } 112 113 /// Return the current output for the digested data since the last call to 114 /// init(). 115 /// 116 /// Other hash functions distinguish between \p result() and \p final(), with 117 /// \p result() allowing more calls into \p update(), but there's no 118 // difference for the BLAKE3 hash function. 119 BLAKE3Result<NumBytes> result() { return BLAKE3::result<NumBytes>(); } 120 }; 121 122 } // namespace llvm 123 124 #endif 125