Skip to content

Commit

Permalink
Merge pull request #12 from snej/blake3
Browse files Browse the repository at this point in the history
Blake3 hash
  • Loading branch information
snej authored May 28, 2024
2 parents 1176915 + c5677d2 commit 4567563
Show file tree
Hide file tree
Showing 10 changed files with 349 additions and 33 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "vendor/monocypher"]
path = vendor/monocypher
url = https://github.com/snej/Monocypher.git
[submodule "vendor/BLAKE3"]
path = vendor/BLAKE3
url = https://github.com/BLAKE3-team/BLAKE3.git
34 changes: 33 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
cmake_minimum_required(VERSION 3.16)

project(MonocypherCpp)
project(MonocypherCpp
VERSION 1.2
DESCRIPTION "C++ bindings for Monocypher crypto library, and more"
LANGUAGES C CXX
)

option(MONOCYPHER_ENABLE_BLAKE3 "Adds the Blake3 digest algorithm" ON)

if (MONOCYPHER_ENABLE_BLAKE3)
add_subdirectory(vendor/BLAKE3/c)
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand All @@ -19,6 +28,9 @@ include_directories(
)


#### MAIN LIBRARY


add_library( MonocypherCpp STATIC
src/Monocypher.cc
src/Monocypher-ed25519.cc
Expand All @@ -32,13 +44,33 @@ if (NOT MSVC)
)
endif()

if (MONOCYPHER_ENABLE_BLAKE3)
target_sources( MonocypherCpp PRIVATE
src/Monocypher+blake3.cc
)
target_include_directories( MonocypherCpp PRIVATE
vendor/BLAKE3/c/
)
target_link_libraries( MonocypherCpp INTERFACE
blake3
)
endif()


#### TESTS


add_executable( MonocypherCppTests
tests/MonocypherCppTests.cc
tests/tests_main.cc
)

if (MONOCYPHER_ENABLE_BLAKE3)
target_sources( MonocypherCppTests PRIVATE
tests/Test_Blake3.cc
)
endif()

target_include_directories( MonocypherCppTests PRIVATE
"vendor/catch2/"
)
Expand Down
88 changes: 88 additions & 0 deletions include/monocypher/ext/blake3.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//
// monocypher/ext/blake3.hh
//
// Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher
// <https://monocypher.org>
//
// Copyright (c) 2024 Jens Alfke. All rights reserved.
//
// --- Standard 2-clause BSD licence follows ---
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#pragma once
#include "../hash.hh"
#include <memory>

namespace monocypher::ext {

struct Blake3Base {
static constexpr const char* name = "BLAKE3";
using context = byte_array<1912>;
static void init_fn (context *ctx);
static void update_fn(context *ctx, const uint8_t *message, size_t message_size);
protected:
static void final_fn(context *ctx, uint8_t *hash, size_t hash_size);
static void create_fn(uint8_t *hash, size_t hash_size, const uint8_t *msg, size_t msg_size);
static void init_mac_fn(context *ctx, const uint8_t *key, size_t key_size);
static void create_mac_fn(uint8_t *hash, size_t hash_size,
const uint8_t *key, size_t key_size,
const uint8_t *message, size_t message_size);
};

/// The BLAKE3 digest algorithm, for use as the template parameter to `hash`.
///
/// @note This functionality is NOT part of Monocypher itself.
/// It uses the C reference implementation, <https://github.com/BLAKE3-team/BLAKE3>
template <size_t Size = 32>
struct Blake3 : public Blake3Base {
static constexpr size_t hash_size = Size;

static void final_fn (context *ctx, uint8_t hash[Size]) {
Blake3Base::final_fn(ctx, hash, hash_size);
}
static void create_fn(uint8_t hash[Size], const uint8_t *message, size_t message_size) {
Blake3Base::create_fn(hash, hash_size, message, message_size);
}

/// Note: BLAKE3's HMAC algorithm requires the key to be exactly 32 bytes.
struct mac {
using context = Blake3::context;

static void create_fn(uint8_t *hash, const uint8_t *key, size_t key_size,
const uint8_t *message, size_t message_size)
{
Blake3Base::create_mac_fn(hash, hash_size, key, key_size, message, message_size);
}
static void init_fn(context *ctx, const uint8_t *key, size_t key_size) {
Blake3Base::init_mac_fn(ctx, key, key_size);
}
static constexpr auto update_fn = Blake3::update_fn;
static constexpr auto final_fn = Blake3::final_fn;
};
};

/// Blake3 hash class with default 256-bit (32-byte) hash size..
using blake3 = hash<Blake3<>>;
}
22 changes: 0 additions & 22 deletions include/monocypher/ext/ed25519.hh
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,4 @@ namespace monocypher {
using key_pair = monocypher::key_pair<Ed25519>;
};


/// SHA-512 algorithm, for use as the template parameter to `hash`.
struct SHA512 {
static constexpr const char* name = "SHA-512";
static constexpr size_t hash_size = 512 / 8;

using context = c::crypto_sha512_ctx;
static constexpr auto create_fn = c::crypto_sha512;
static constexpr auto init_fn = c::crypto_sha512_init;
static constexpr auto update_fn = c::crypto_sha512_update;
static constexpr auto final_fn = c::crypto_sha512_final;

struct mac {
using context = c::crypto_sha512_hmac_ctx;
static constexpr auto create_fn = c::crypto_sha512_hmac;
static constexpr auto init_fn = c::crypto_sha512_hmac_init;
static constexpr auto update_fn = c::crypto_sha512_hmac_update;
static constexpr auto final_fn = c::crypto_sha512_hmac_final;
};
};

using sha512 = hash<SHA512>;
}
64 changes: 64 additions & 0 deletions include/monocypher/ext/sha512.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// monocypher/ext/sha512.hh
//
// Monocypher-Cpp: Unofficial idiomatic C++17 wrapper for Monocypher
// <https://monocypher.org>
//
// Copyright (c) 2022 Jens Alfke. All rights reserved.
//
// --- Standard 2-clause BSD licence follows ---
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#pragma once
#include "../hash.hh"
#include "../../../vendor/monocypher/src/optional/monocypher-ed25519.h"

namespace monocypher {

// This functionality is an extension that comes with Monocypher.
// It's not considered part of the core API, but is provided for compatibility.

/// SHA-512 algorithm, for use as the template parameter to `hash`.
struct SHA512 {
static constexpr const char* name = "SHA-512";
static constexpr size_t hash_size = 512 / 8;

using context = c::crypto_sha512_ctx;
static constexpr auto create_fn = c::crypto_sha512;
static constexpr auto init_fn = c::crypto_sha512_init;
static constexpr auto update_fn = c::crypto_sha512_update;
static constexpr auto final_fn = c::crypto_sha512_final;

struct mac {
using context = c::crypto_sha512_hmac_ctx;
static constexpr auto create_fn = c::crypto_sha512_hmac;
static constexpr auto init_fn = c::crypto_sha512_hmac_init;
static constexpr auto update_fn = c::crypto_sha512_hmac_update;
static constexpr auto final_fn = c::crypto_sha512_hmac_final;
};
};

using sha512 = hash<SHA512>;
}
24 changes: 14 additions & 10 deletions include/monocypher/hash.hh
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ namespace monocypher {
using namespace MONOCYPHER_CPP_NAMESPACE;

/// Cryptographic hash class, templated by algorithm and size.
/// The only `Algorithm` currently available is `Blake2b`.
/// The `Size` is in bytes and must be between 1 and 64. Sizes below 32 are not recommended.
/// The `Size` is in bytes and must be between 1 and 64.
///
/// Monocypher provides algorithms `Blake2b` (below) and `SHA512` (in ext/sha512.hh).
/// Extra algorithms SHA256 (ext/sha256.hh) and Blake3 (ext/blake3.hh) are implemented by
/// other codebases, not Monocypher.
template <class HashAlgorithm>
class hash : public byte_array<HashAlgorithm::hash_size> {
public:
Expand All @@ -49,18 +52,20 @@ namespace monocypher {
explicit hash(const std::array<uint8_t,Size> &a) :byte_array<Size>(a) { }
hash(const void *data, size_t size) :byte_array<Size>(data, size) { }

/// Returns the Blake2b hash of a message.
/// Returns the hash of a message.
static hash create(const void *message, size_t message_size) noexcept {
hash result;
HashAlgorithm::create_fn(result.data(), u8(message), message_size);
return result;
}

/// Returns the hash of a message.
static hash create(input_bytes message) noexcept {
return create(message.data, message.size);
}

/// Returns the hash of a message and a secret key, for use as a MAC.
/// @warning Some algorithms only work with specific key sizes.
template <size_t KeySize>
static hash createMAC(const void *message, size_t message_size,
const byte_array<KeySize> &key) noexcept {
Expand All @@ -87,11 +92,12 @@ namespace monocypher {
return *this;
}

/// Hashes more data.
_builder& update(input_bytes message) {
return update(message.data, message.size);
}

/// Returns the final hash of all the data passed to `update`.
/// Returns the final hash of all the data.
[[nodiscard]]
hash final() {
hash result;
Expand All @@ -106,7 +112,7 @@ namespace monocypher {
/// Incrementally constructs a hash.
class builder : public _builder<HashAlgorithm> {
public:
/// Constructs a Blake2b builder.
/// Constructs a hash builder.
/// Call `update` one or more times to hash data, then `final` to get the hash.
builder() {
HashAlgorithm::init_fn(&this->_ctx);
Expand All @@ -116,9 +122,10 @@ namespace monocypher {
/// Incrementally constructs a MAC.
class mac_builder : public _builder<typename HashAlgorithm::mac> {
public:
/// Constructs a Blake2b builder with a secret key, for creating MACs.
/// Constructs a hash builder with a secret key, for creating MACs.
/// Call `update` one or more times to hash data, then `final` to get the hash.
template <size_t KeySize>
/// @warning Some algorithms only work with specific key sizes.
template <size_t KeySize>
mac_builder(const byte_array<KeySize> &key) {
HashAlgorithm::mac::init_fn(&this->_ctx, key.data(), key.size());
}
Expand Down Expand Up @@ -166,7 +173,4 @@ namespace monocypher {
/// Blake2b-32 hash class.
using blake2b32 = hash<Blake2b<32>>;

// Note: See Monocypher-ed25519.hh for SHA-512, and Monocypher+sha256.hh for SHA-256.


}
Loading

0 comments on commit 4567563

Please sign in to comment.