Skip to content

Commit 21d8cce

Browse files
authored
Merge pull request #13 from cppalliance/sha1
Implement, test and fuzz SHA1
2 parents 5e3a728 + 90c6da8 commit 21d8cce

File tree

16 files changed

+1508
-16
lines changed

16 files changed

+1508
-16
lines changed

.drone.jsonnet

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,15 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
391391
"cppalliance/droneubuntu2404:1",
392392
{ TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '03,11,14,17,20,2b' },
393393
"clang-18",
394-
["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main"],
394+
["deb http://apt.llvm.org/noble/ llvm-toolchain-noble-18 main"],
395+
),
396+
397+
linux_pipeline(
398+
"Linux 24.04 Clang 19",
399+
"cppalliance/droneubuntu2404:1",
400+
{ TOOLSET: 'clang', COMPILER: 'clang++-19', CXXSTD: '03,11,14,17,20,2b' },
401+
"clang-19",
402+
["deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main"],
395403
),
396404

397405
macos_pipeline(

.github/workflows/fuzz.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,26 @@ jobs:
8686
- "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main"
8787
source_keys:
8888
- "https://apt.llvm.org/llvm-snapshot.gpg.key"
89+
- toolset: clang
90+
compiler: clang++-18
91+
cxxstd: "14,17,20"
92+
os: ubuntu-24.04
93+
install:
94+
- clang-18
95+
sources:
96+
- "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-18 main"
97+
source_keys:
98+
- "https://apt.llvm.org/llvm-snapshot.gpg.key"
99+
- toolset: clang
100+
compiler: clang++-19
101+
cxxstd: "14,17,20"
102+
os: ubuntu-24.04
103+
install:
104+
- clang-19
105+
sources:
106+
- "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main"
107+
source_keys:
108+
- "https://apt.llvm.org/llvm-snapshot.gpg.key"
89109

90110

91111
timeout-minutes: 60

doc/crypt.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ include::crypt/api_reference.adoc[]
2121

2222
include::crypt/md5.adoc[]
2323

24+
include::crypt/sha1.adoc[]
25+
2426
include::crypt/config.adoc[]
2527

2628
include::crypt/reference.adoc[]

doc/crypt/reference.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ The following books, papers and blog posts serve as the basis for the algorithms
1313
:linkattrs:
1414

1515
- Ronald L. Rivest, https://www.ietf.org/rfc/rfc1321.txt[RFC 1321: The MD5 Message-Digest Algorithm], 1992
16+
17+
- Donald E. Eastlake and Paul E. Jones, https://datatracker.ietf.org/doc/html/rfc3174[RFC 3174: US Secure Hash Algorithm 1 (SHA1)], 2001

doc/crypt/sha1.adoc

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
////
2+
Copyright 2024 Matt Borland
3+
Distributed under the Boost Software License, Version 1.0.
4+
https://www.boost.org/LICENSE_1_0.txt
5+
////
6+
7+
[#sha1]
8+
:idprefix: sha1_
9+
10+
= SHA1
11+
12+
This library supports SHA1 as described in https://datatracker.ietf.org/doc/html/rfc3174[RFC 3174].
13+
There is a wide range of acceptable inputs for the base sha1 function:
14+
15+
== Hashing Functions
16+
17+
[source, c++]
18+
----
19+
namespace boost {
20+
namespace crypt {
21+
22+
uisng return_type = boost::crypt::array<uint8_t, 20>;
23+
24+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char* str) noexcept -> return_type;
25+
26+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char* str, size_t len) noexcept -> return_type;
27+
28+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const unsigned char* str) noexcept -> return_type;
29+
30+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const unsigned char* str, size_t len) noexcept -> return_type;
31+
32+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char16_t* str) noexcept -> return_type;
33+
34+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char16_t* str, size_t len) noexcept -> return_type;
35+
36+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char32_t* str) noexcept -> return_type;
37+
38+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const char32_t* str, size_t len) noexcept -> return_type;
39+
40+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const wchar_t* str) noexcept -> return_type;
41+
42+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1(const wchar_t* str, size_t len) noexcept -> return_type;
43+
44+
inline auto sha1(const std::string& str) noexcept -> return_type;
45+
46+
inline auto sha1(const std::u16string& str) noexcept -> return_type;
47+
48+
inline auto sha1(const std::u32string& str) noexcept -> return_type;
49+
50+
inline auto sha1(const std::wstring& str) noexcept -> return_type;
51+
52+
#ifdef BOOST_CRYPT_HAS_STRING_VIEW
53+
54+
inline auto sha1(std::string_view str) noexcept -> return_type;
55+
56+
inline auto sha1(std::u16string_view str) noexcept -> return_type;
57+
58+
inline auto sha1(std::u32string_view str) noexcept -> return_type;
59+
60+
inline auto sha1(std::wstring_view str) noexcept -> return_type;
61+
62+
#endif // BOOST_CRYPT_HAS_STRING_VIEW
63+
64+
} //namespace crypt
65+
} //namespace boost
66+
----
67+
68+
== File Hashing Functions
69+
70+
We also have the ability to scan files and return the sha1 value:
71+
72+
[source, c++]
73+
----
74+
namespace boost {
75+
namespace crypt {
76+
77+
uisng return_type = boost::crypt::array<uint8_t, 16>;
78+
79+
inline auto sha1_file(const char* filepath) noexcept -> return_type;
80+
81+
inline auto sha1_file(const std::string& filepath) noexcept -> return_type;
82+
83+
inline auto sha1_file(std::string_view filepath) noexcept -> return_type;
84+
85+
} // namespace crypt
86+
} // namespace boost
87+
----
88+
89+
== Hashing Object
90+
91+
[#sha1_hasher]
92+
Lastly, there is also the ability to create a sha1 hashing object and feed it bytes as the user parses them.
93+
This class does not use any dynamic memory allocation.
94+
95+
[source, c++]
96+
----
97+
namespace boost {
98+
namespace crypt {
99+
100+
class sha1_hasher
101+
{
102+
init();
103+
104+
template <typename ByteType>
105+
BOOST_CRYPT_GPU_ENABLED constexpr auto process_byte(ByteType byte) noexcept -> void;
106+
107+
template <typename ForwardIter>
108+
BOOST_CRYPT_GPU_ENABLED constexpr auto process_bytes(ForwardIter buffer, size_t byte_count) noexcept -> void;
109+
110+
constexpr auto get_digest() noexcept -> boost::crypt::array<boost::crypt::uint8_t, 20>;
111+
};
112+
113+
} // namespace crypt
114+
} // namespace boost
115+
----

fuzzing/Jamfile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ local all_fuzzers = [ regex.replace-list
1515

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

2220
# Create the output corpus directories
2321
make /tmp/corpus/$(fuzzer) : : common.MkDir ;

fuzzing/fuzz_sha1.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2024 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#include <boost/crypt/hash/sha1.hpp>
6+
#include <iostream>
7+
#include <exception>
8+
#include <string>
9+
10+
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size)
11+
{
12+
try
13+
{
14+
auto c_data = reinterpret_cast<const char*>(data);
15+
std::string c_data_str {c_data, size}; // Guarantee null termination since we can't pass the size argument
16+
17+
boost::crypt::sha1(c_data_str);
18+
boost::crypt::sha1(c_data, size);
19+
boost::crypt::sha1(data, size);
20+
21+
#ifdef BOOST_CRYPT_HAS_STRING_VIEW
22+
std::string_view view {c_data_str};
23+
boost::crypt::sha1(view);
24+
#endif
25+
}
26+
catch(...)
27+
{
28+
std::cerr << "Error with: " << data << std::endl;
29+
std::terminate();
30+
}
31+
32+
return 0;
33+
}

fuzzing/seedcorpus/fuzz_sha1/sha1.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"The quick brown fox jumps over the lazy dog"
2+
"The quick brown fox jumps over the lazy dog."
3+
""
4+
"aB3$x9Yz"
5+
"12345"
6+
"!@#$%^&*()"
7+
"FuzzTest123"
8+
" "
9+
"Lorem ipsum dolor sit amet"
10+
"a"
11+
"9876543210"
12+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
13+
"ñÑáéíóúÁÉÍÓÚ"
14+
"\n\r\t"
15+
"0"
16+
"ThisIsAVeryLongStringWithNoSpacesOrPunctuationToTestEdgeCases"
17+
"<?php echo 'test'; ?>"
18+
"SELECT * FROM users;"
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2024 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
5+
#ifndef BOOST_CRYPT_HASH_HASHER_STATE_HPP
6+
#define BOOST_CRYPT_HASH_HASHER_STATE_HPP
7+
8+
#include <boost/crypt/utility/cstdint.hpp>
9+
10+
namespace boost {
11+
namespace crypt {
12+
13+
enum class hasher_state : boost::crypt::uint8_t
14+
{
15+
success, // no issues
16+
null, // nullptr as parameter
17+
input_too_long, // input data too long (exceeded size_t)
18+
state_error // added more input after get_digest without re-init
19+
};
20+
21+
} // namespace crypt
22+
} // namespace boost
23+
24+
#endif // BOOST_CRYPT_HASH_HASHER_STATE_HPP

0 commit comments

Comments
 (0)