Skip to content

Commit

Permalink
Merge pull request #13 from cppalliance/sha1
Browse files Browse the repository at this point in the history
Implement, test and fuzz SHA1
  • Loading branch information
mborland authored Oct 18, 2024
2 parents 5e3a728 + 90c6da8 commit 21d8cce
Show file tree
Hide file tree
Showing 16 changed files with 1,508 additions and 16 deletions.
10 changes: 9 additions & 1 deletion .drone.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,15 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '03,11,14,17,20,2b' },
"clang-18",
["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main"],
["deb http://apt.llvm.org/noble/ llvm-toolchain-noble-18 main"],
),

linux_pipeline(
"Linux 24.04 Clang 19",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-19', CXXSTD: '03,11,14,17,20,2b' },
"clang-19",
["deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main"],
),

macos_pipeline(
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,26 @@ jobs:
- "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main"
source_keys:
- "https://apt.llvm.org/llvm-snapshot.gpg.key"
- toolset: clang
compiler: clang++-18
cxxstd: "14,17,20"
os: ubuntu-24.04
install:
- clang-18
sources:
- "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-18 main"
source_keys:
- "https://apt.llvm.org/llvm-snapshot.gpg.key"
- toolset: clang
compiler: clang++-19
cxxstd: "14,17,20"
os: ubuntu-24.04
install:
- clang-19
sources:
- "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main"
source_keys:
- "https://apt.llvm.org/llvm-snapshot.gpg.key"


timeout-minutes: 60
Expand Down
2 changes: 2 additions & 0 deletions doc/crypt.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ include::crypt/api_reference.adoc[]

include::crypt/md5.adoc[]

include::crypt/sha1.adoc[]

include::crypt/config.adoc[]

include::crypt/reference.adoc[]
Expand Down
2 changes: 2 additions & 0 deletions doc/crypt/reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ The following books, papers and blog posts serve as the basis for the algorithms
:linkattrs:

- Ronald L. Rivest, https://www.ietf.org/rfc/rfc1321.txt[RFC 1321: The MD5 Message-Digest Algorithm], 1992
- Donald E. Eastlake and Paul E. Jones, https://datatracker.ietf.org/doc/html/rfc3174[RFC 3174: US Secure Hash Algorithm 1 (SHA1)], 2001
115 changes: 115 additions & 0 deletions doc/crypt/sha1.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
////
Copyright 2024 Matt Borland
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////

[#sha1]
:idprefix: sha1_

= SHA1

This library supports SHA1 as described in https://datatracker.ietf.org/doc/html/rfc3174[RFC 3174].
There is a wide range of acceptable inputs for the base sha1 function:

== Hashing Functions

[source, c++]
----
namespace boost {
namespace crypt {
uisng return_type = boost::crypt::array<uint8_t, 20>;
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char* str) noexcept -> return_type;
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char* str, size_t len) noexcept -> return_type;
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const unsigned char* str) noexcept -> return_type;
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const unsigned char* str, size_t len) noexcept -> return_type;
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char16_t* str) noexcept -> return_type;
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char16_t* str, size_t len) noexcept -> return_type;
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char32_t* str) noexcept -> return_type;
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char32_t* str, size_t len) noexcept -> return_type;
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const wchar_t* str) noexcept -> return_type;
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const wchar_t* str, size_t len) noexcept -> return_type;
inline auto sha1(const std::string& str) noexcept -> return_type;
inline auto sha1(const std::u16string& str) noexcept -> return_type;
inline auto sha1(const std::u32string& str) noexcept -> return_type;
inline auto sha1(const std::wstring& str) noexcept -> return_type;
#ifdef BOOST_CRYPT_HAS_STRING_VIEW
inline auto sha1(std::string_view str) noexcept -> return_type;
inline auto sha1(std::u16string_view str) noexcept -> return_type;
inline auto sha1(std::u32string_view str) noexcept -> return_type;
inline auto sha1(std::wstring_view str) noexcept -> return_type;
#endif // BOOST_CRYPT_HAS_STRING_VIEW
} //namespace crypt
} //namespace boost
----

== File Hashing Functions

We also have the ability to scan files and return the sha1 value:

[source, c++]
----
namespace boost {
namespace crypt {
uisng return_type = boost::crypt::array<uint8_t, 16>;
inline auto sha1_file(const char* filepath) noexcept -> return_type;
inline auto sha1_file(const std::string& filepath) noexcept -> return_type;
inline auto sha1_file(std::string_view filepath) noexcept -> return_type;
} // namespace crypt
} // namespace boost
----

== Hashing Object

[#sha1_hasher]
Lastly, there is also the ability to create a sha1 hashing object and feed it bytes as the user parses them.
This class does not use any dynamic memory allocation.

[source, c++]
----
namespace boost {
namespace crypt {
class sha1_hasher
{
init();
template <typename ByteType>
BOOST_CRYPT_GPU_ENABLED constexpr auto process_byte(ByteType byte) noexcept -> void;
template <typename ForwardIter>
BOOST_CRYPT_GPU_ENABLED constexpr auto process_bytes(ForwardIter buffer, size_t byte_count) noexcept -> void;
constexpr auto get_digest() noexcept -> boost::crypt::array<boost::crypt::uint8_t, 20>;
};
} // namespace crypt
} // namespace boost
----
4 changes: 1 addition & 3 deletions fuzzing/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ local all_fuzzers = [ regex.replace-list

for local fuzzer in $(all_fuzzers)
{
# These two fuzzers are the most complex ones. The rest are really
# simple, so less time is enough
local fuzz_time = 30 ;
local fuzz_time = 120 ;

# Create the output corpus directories
make /tmp/corpus/$(fuzzer) : : common.MkDir ;
Expand Down
33 changes: 33 additions & 0 deletions fuzzing/fuzz_sha1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2024 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#include <boost/crypt/hash/sha1.hpp>
#include <iostream>
#include <exception>
#include <string>

extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size)
{
try
{
auto c_data = reinterpret_cast<const char*>(data);
std::string c_data_str {c_data, size}; // Guarantee null termination since we can't pass the size argument

boost::crypt::sha1(c_data_str);
boost::crypt::sha1(c_data, size);
boost::crypt::sha1(data, size);

#ifdef BOOST_CRYPT_HAS_STRING_VIEW
std::string_view view {c_data_str};
boost::crypt::sha1(view);
#endif
}
catch(...)
{
std::cerr << "Error with: " << data << std::endl;
std::terminate();
}

return 0;
}
18 changes: 18 additions & 0 deletions fuzzing/seedcorpus/fuzz_sha1/sha1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"The quick brown fox jumps over the lazy dog"
"The quick brown fox jumps over the lazy dog."
""
"aB3$x9Yz"
"12345"
"!@#$%^&*()"
"FuzzTest123"
" "
"Lorem ipsum dolor sit amet"
"a"
"9876543210"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"ñÑáéíóúÁÉÍÓÚ"
"\n\r\t"
"0"
"ThisIsAVeryLongStringWithNoSpacesOrPunctuationToTestEdgeCases"
"<?php echo 'test'; ?>"
"SELECT * FROM users;"
24 changes: 24 additions & 0 deletions include/boost/crypt/hash/hasher_state.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2024 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#ifndef BOOST_CRYPT_HASH_HASHER_STATE_HPP
#define BOOST_CRYPT_HASH_HASHER_STATE_HPP

#include <boost/crypt/utility/cstdint.hpp>

namespace boost {
namespace crypt {

enum class hasher_state : boost::crypt::uint8_t
{
success, // no issues
null, // nullptr as parameter
input_too_long, // input data too long (exceeded size_t)
state_error // added more input after get_digest without re-init
};

} // namespace crypt
} // namespace boost

#endif // BOOST_CRYPT_HASH_HASHER_STATE_HPP
Loading

0 comments on commit 21d8cce

Please sign in to comment.