Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a07d589

Browse files
feat(hash): Add hashing library and new algorithms
1 parent 7bfd451 commit a07d589

24 files changed

+1894
-73
lines changed

‎CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ set(CORE_SRCS
5454
cores/esp32/freertos_stats.cpp
5555
cores/esp32/FunctionalInterrupt.cpp
5656
cores/esp32/HardwareSerial.cpp
57+
cores/esp32/HashBuilder.cpp
5758
cores/esp32/HEXBuilder.cpp
5859
cores/esp32/IPAddress.cpp
5960
cores/esp32/libb64/cdecode.c
@@ -62,7 +63,6 @@ set(CORE_SRCS
6263
cores/esp32/main.cpp
6364
cores/esp32/MD5Builder.cpp
6465
cores/esp32/Print.cpp
65-
cores/esp32/SHA1Builder.cpp
6666
cores/esp32/stdlib_noniso.c
6767
cores/esp32/Stream.cpp
6868
cores/esp32/StreamString.cpp
@@ -93,6 +93,7 @@ set(ARDUINO_ALL_LIBRARIES
9393
Ethernet
9494
FFat
9595
FS
96+
Hash
9697
HTTPClient
9798
HTTPUpdate
9899
Insights
@@ -154,6 +155,13 @@ set(ARDUINO_LIBRARY_FS_SRCS
154155
libraries/FS/src/FS.cpp
155156
libraries/FS/src/vfs_api.cpp)
156157

158+
set(ARDUINO_LIBRARY_Hash_SRCS
159+
libraries/Hash/src/SHA1Builder.cpp
160+
libraries/Hash/src/SHA2Builder.cpp
161+
libraries/Hash/src/SHA3Builder.cpp
162+
libraries/Hash/src/PBKDF2_HMACBuilder.cpp
163+
)
164+
157165
set(ARDUINO_LIBRARY_HTTPClient_SRCS libraries/HTTPClient/src/HTTPClient.cpp)
158166

159167
set(ARDUINO_LIBRARY_HTTPUpdate_SRCS libraries/HTTPUpdate/src/HTTPUpdate.cpp)

‎cores/esp32/HEXBuilder.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1818
*/
1919

20-
#include <Arduino.h>
21-
#include <HEXBuilder.h>
20+
#include "HEXBuilder.h"
2221

2322
static uint8_t hex_char_to_byte(uint8_t c) {
2423
return (c >= 'a' && c <= 'f') ? (c - ((uint8_t)'a' - 0xa))

‎cores/esp32/HEXBuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include <WString.h>
2424
#include <Stream.h>
2525

26+
// Basic hex/byte conversion class to be used by hash builders
27+
2628
class HEXBuilder {
2729
public:
2830
static size_t hex2bytes(unsigned char *out, size_t maxlen, String &in);

‎cores/esp32/HashBuilder.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2025 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "HashBuilder.h"
16+
17+
void HashBuilder::add(const char *data) {
18+
add((const uint8_t *)data, strlen(data));
19+
}
20+
21+
void HashBuilder::add(String data) {
22+
add(data.c_str());
23+
}
24+
25+
void HashBuilder::addHexString(const char *data) {
26+
size_t len = strlen(data);
27+
uint8_t *tmp = (uint8_t *)malloc(len / 2);
28+
if (tmp == NULL) {
29+
return;
30+
}
31+
hex2bytes(tmp, len / 2, data);
32+
add(tmp, len / 2);
33+
free(tmp);
34+
}
35+
36+
void HashBuilder::addHexString(String data) {
37+
addHexString(data.c_str());
38+
}

‎cores/esp32/HashBuilder.h

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,26 @@
2020

2121
#include "HEXBuilder.h"
2222

23+
// Base class for hash builders
24+
2325
class HashBuilder : public HEXBuilder {
2426
public:
2527
virtual ~HashBuilder() {}
2628
virtual void begin() = 0;
2729

2830
virtual void add(const uint8_t *data, size_t len) = 0;
29-
virtual void add(const char *data) {
30-
add((const uint8_t *)data, strlen(data));
31-
}
32-
virtual void add(String data) {
33-
add(data.c_str());
34-
}
35-
36-
virtual void addHexString(const char *data) = 0;
37-
virtual void addHexString(String data) {
38-
addHexString(data.c_str());
39-
}
31+
void add(const char *data);
32+
void add(String data);
33+
34+
void addHexString(const char *data);
35+
void addHexString(String data);
4036

4137
virtual bool addStream(Stream &stream, const size_t maxLen) = 0;
4238
virtual void calculate() = 0;
4339
virtual void getBytes(uint8_t *output) = 0;
4440
virtual void getChars(char *output) = 0;
4541
virtual String toString() = 0;
42+
virtual size_t getHashSize() const = 0;
4643
};
4744

4845
#endif

‎cores/esp32/MD5Builder.cpp

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@
1717
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1818
*/
1919

20-
#include <Arduino.h>
21-
#include <HEXBuilder.h>
22-
#include <MD5Builder.h>
20+
#include "HEXBuilder.h"
21+
#include "MD5Builder.h"
2322

2423
void MD5Builder::begin(void) {
2524
memset(_buf, 0x00, ESP_ROM_MD5_DIGEST_LEN);
@@ -30,17 +29,6 @@ void MD5Builder::add(const uint8_t *data, size_t len) {
3029
esp_rom_md5_update(&_ctx, data, len);
3130
}
3231

33-
void MD5Builder::addHexString(const char *data) {
34-
size_t len = strlen(data);
35-
uint8_t *tmp = (uint8_t *)malloc(len / 2);
36-
if (tmp == NULL) {
37-
return;
38-
}
39-
hex2bytes(tmp, len / 2, data);
40-
add(tmp, len / 2);
41-
free(tmp);
42-
}
43-
4432
bool MD5Builder::addStream(Stream &stream, const size_t maxLen) {
4533
const int buf_size = 512;
4634
int maxLengthLeft = maxLen;

‎cores/esp32/MD5Builder.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,16 @@ class MD5Builder : public HashBuilder {
3535
uint8_t _buf[ESP_ROM_MD5_DIGEST_LEN];
3636

3737
public:
38-
void begin(void) override;
39-
4038
using HashBuilder::add;
41-
void add(const uint8_t *data, size_t len) override;
42-
43-
using HashBuilder::addHexString;
44-
void addHexString(const char *data) override;
4539

40+
void begin(void) override;
41+
void add(const uint8_t *data, size_t len) override;
4642
bool addStream(Stream &stream, const size_t maxLen) override;
4743
void calculate(void) override;
4844
void getBytes(uint8_t *output) override;
4945
void getChars(char *output) override;
5046
String toString(void) override;
47+
size_t getHashSize() const override { return ESP_ROM_MD5_DIGEST_LEN; }
5148
};
5249

5350
#endif

‎libraries/ESP32/examples/Utilities/HEXBuilder/HEXBuilder.ino renamed to ‎libraries/Hash/examples/HEX/HEX.ino

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/*
2+
Usage example for the HEXBuilder class.
3+
4+
This example shows how to convert a HEX string to a binary buffer and vice versa.
5+
*/
6+
17
#include <HEXBuilder.h>
28

39
void setup() {
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*
2+
Usage example for the PBKDF2_HMACBuilder class.
3+
4+
This example shows how to use the Hash library to hash data using the PBKDF2_HMACBuilder class.
5+
PBKDF2_HMAC (Password-Based Key Derivation Function 2) is a key derivation function that uses a password and a salt to derive a key.
6+
7+
The PBKDF2_HMACBuilder class takes for arguments:
8+
- A HashBuilder object to use for the HMAC (SHA1Builder, SHA2Builder, SHA3Builder, etc.)
9+
- A password string (default: empty)
10+
- A salt string (default: empty)
11+
- The number of iterations (default: 1000)
12+
*/
13+
14+
#include <SHA1Builder.h>
15+
#include <SHA2Builder.h>
16+
#include <PBKDF2_HMACBuilder.h>
17+
18+
void setup() {
19+
Serial.begin(115200);
20+
Serial.println("\n\nPBKDF2-HMAC Example");
21+
Serial.println("===================");
22+
23+
// Test 1: Basic PBKDF2-HMAC-SHA1
24+
Serial.println("\n1. PBKDF2-HMAC-SHA1 Test (1 iteration)");
25+
{
26+
SHA1Builder sha1;
27+
PBKDF2_HMACBuilder pbkdf2(&sha1, "password", "salt", 1);
28+
29+
pbkdf2.begin();
30+
pbkdf2.calculate();
31+
32+
Serial.print("Password: ");
33+
Serial.println("password");
34+
Serial.print("Salt: ");
35+
Serial.println("salt");
36+
Serial.print("Iterations: ");
37+
Serial.println(1);
38+
Serial.print("Output (hex): ");
39+
Serial.println(pbkdf2.toString());
40+
41+
// Expected: 0c60c80f961f0e71f3a9b524af6012062fe037a6
42+
String expected = "0c60c80f961f0e71f3a9b524af6012062fe037a6";
43+
String result = pbkdf2.toString();
44+
45+
if (result.equalsIgnoreCase(expected)) {
46+
Serial.println("✓ PASS: Output matches expected value");
47+
} else {
48+
Serial.println("✗ FAIL: Output does not match expected value");
49+
Serial.print("Expected: ");
50+
Serial.println(expected);
51+
Serial.print("Got: ");
52+
Serial.println(result);
53+
}
54+
}
55+
56+
// Test 2: PBKDF2-HMAC-SHA1 with more iterations
57+
Serial.println("\n2. PBKDF2-HMAC-SHA1 Test (1000 iterations)");
58+
{
59+
SHA1Builder sha1;
60+
PBKDF2_HMACBuilder pbkdf2(&sha1);
61+
62+
const char* password = "password";
63+
const char* salt = "salt";
64+
65+
pbkdf2.begin();
66+
pbkdf2.setPassword(password);
67+
pbkdf2.setSalt(salt);
68+
pbkdf2.setIterations(1000);
69+
pbkdf2.calculate();
70+
71+
Serial.print("Password: ");
72+
Serial.println(password);
73+
Serial.print("Salt: ");
74+
Serial.println(salt);
75+
Serial.print("Iterations: ");
76+
Serial.println(1000);
77+
Serial.print("Output (hex): ");
78+
Serial.println(pbkdf2.toString());
79+
80+
// Expected: 6e88be8bad7eae9d9e10aa061224034fed48d03f
81+
String expected = "6e88be8bad7eae9d9e10aa061224034fed48d03f";
82+
String result = pbkdf2.toString();
83+
84+
if (result.equalsIgnoreCase(expected)) {
85+
Serial.println("✓ PASS: Output matches expected value");
86+
} else {
87+
Serial.println("✗ FAIL: Output does not match expected value");
88+
Serial.print("Expected: ");
89+
Serial.println(expected);
90+
Serial.print("Got: ");
91+
Serial.println(result);
92+
}
93+
}
94+
95+
// Test 3: PBKDF2-HMAC-SHA256 with different password and salt
96+
Serial.println("\n3. PBKDF2-HMAC-SHA256 Test");
97+
{
98+
SHA256Builder sha256;
99+
PBKDF2_HMACBuilder pbkdf2(&sha256, "mySecretPassword", "randomSalt123", 100);
100+
101+
pbkdf2.begin();
102+
pbkdf2.calculate();
103+
104+
Serial.print("Password: ");
105+
Serial.println("mySecretPassword");
106+
Serial.print("Salt: ");
107+
Serial.println("randomSalt123");
108+
Serial.print("Iterations: ");
109+
Serial.println(100);
110+
Serial.print("Output (hex): ");
111+
Serial.println(pbkdf2.toString());
112+
113+
// Expected: 4ce309e56a37e0a4b9b84b98ed4a94e6c5cd5926cfd3baca3a6dea8c5d7903e8
114+
String expected = "4ce309e56a37e0a4b9b84b98ed4a94e6c5cd5926cfd3baca3a6dea8c5d7903e8";
115+
String result = pbkdf2.toString();
116+
117+
if (result.equalsIgnoreCase(expected)) {
118+
Serial.println("✓ PASS: Output matches expected value");
119+
} else {
120+
Serial.println("✗ FAIL: Output does not match expected value");
121+
Serial.print("Expected: ");
122+
Serial.println(expected);
123+
Serial.print("Got: ");
124+
Serial.println(result);
125+
}
126+
}
127+
128+
// Test 4: PBKDF2-HMAC-SHA1 with byte arrays
129+
Serial.println("\n4. PBKDF2-HMAC-SHA1 Test (byte arrays)");
130+
{
131+
SHA1Builder sha1; // or any other hash algorithm based on HashBuilder
132+
PBKDF2_HMACBuilder pbkdf2(&sha1);
133+
134+
uint8_t password[] = {0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64}; // "password" in bytes
135+
uint8_t salt[] = {0x73, 0x61, 0x6c, 0x74}; // "salt" in bytes
136+
137+
pbkdf2.begin();
138+
pbkdf2.setPassword(password, sizeof(password));
139+
pbkdf2.setSalt(salt, sizeof(salt));
140+
pbkdf2.setIterations(1);
141+
pbkdf2.calculate();
142+
143+
Serial.print("Password (bytes): ");
144+
for (int i = 0; i < sizeof(password); i++) {
145+
Serial.print((char)password[i]);
146+
}
147+
Serial.println();
148+
Serial.print("Salt (bytes): ");
149+
for (int i = 0; i < sizeof(salt); i++) {
150+
Serial.print((char)salt[i]);
151+
}
152+
Serial.println();
153+
Serial.print("Iterations: ");
154+
Serial.println(1);
155+
Serial.print("Output (hex): ");
156+
Serial.println(pbkdf2.toString());
157+
158+
// Expected: 0c60c80f961f0e71f3a9b524af6012062fe037a6 (same as test 1)
159+
String expected = "0c60c80f961f0e71f3a9b524af6012062fe037a6";
160+
String result = pbkdf2.toString();
161+
162+
if (result.equalsIgnoreCase(expected)) {
163+
Serial.println("✓ PASS: Output matches expected value");
164+
} else {
165+
Serial.println("✗ FAIL: Output does not match expected value");
166+
Serial.print("Expected: ");
167+
Serial.println(expected);
168+
Serial.print("Got: ");
169+
Serial.println(result);
170+
}
171+
}
172+
173+
Serial.println("\nPBKDF2-HMAC tests completed!");
174+
}
175+
176+
void loop() {
177+
// Nothing to do in loop
178+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /