Streaming sha256
This commit is contained in:
parent
e40f3037d3
commit
c0d095e57b
BIN
tests/bip32_test
BIN
tests/bip32_test
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Enhanced Header Integration Test
|
||||
*
|
||||
* Tests that the enhanced nostr_core.h master header provides
|
||||
* easy access to all documented functionality
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
// Test the enhanced master header - single include for everything
|
||||
#include "../nostr_core/nostr_core.h"
|
||||
|
||||
int main(void) {
|
||||
printf("NOSTR Core Library - Enhanced Header Integration Test\n");
|
||||
printf("====================================================\n\n");
|
||||
|
||||
// Initialize crypto subsystem
|
||||
if (nostr_crypto_init() != 0) {
|
||||
printf("❌ Failed to initialize crypto subsystem\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("✅ Successfully included nostr_core.h master header\n");
|
||||
printf("✅ Crypto subsystem initialized\n\n");
|
||||
|
||||
// Test 1: Basic cryptographic functions are available
|
||||
printf("=== Test 1: Basic Crypto Functions ===\n");
|
||||
|
||||
unsigned char test_data[] = "Hello, NOSTR!";
|
||||
unsigned char hash[32];
|
||||
|
||||
if (nostr_sha256(test_data, strlen((char*)test_data), hash) == 0) {
|
||||
printf("✅ nostr_sha256() - Single-call SHA-256 works\n");
|
||||
} else {
|
||||
printf("❌ nostr_sha256() failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Test 2: Streaming SHA-256 functions are available
|
||||
printf("\n=== Test 2: Streaming SHA-256 Functions ===\n");
|
||||
|
||||
nostr_sha256_ctx_t ctx;
|
||||
unsigned char streaming_hash[32];
|
||||
|
||||
if (nostr_sha256_init(&ctx) == 0 &&
|
||||
nostr_sha256_update(&ctx, test_data, strlen((char*)test_data)) == 0 &&
|
||||
nostr_sha256_final(&ctx, streaming_hash) == 0) {
|
||||
printf("✅ nostr_sha256_init/update/final() - Streaming SHA-256 works\n");
|
||||
|
||||
// Verify streaming matches single-call
|
||||
if (memcmp(hash, streaming_hash, 32) == 0) {
|
||||
printf("✅ Streaming result matches single-call result\n");
|
||||
} else {
|
||||
printf("❌ Streaming result differs from single-call\n");
|
||||
}
|
||||
} else {
|
||||
printf("❌ Streaming SHA-256 functions failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Test 3: Key generation functions are available
|
||||
printf("\n=== Test 3: Key Generation Functions ===\n");
|
||||
|
||||
unsigned char private_key[32] = {
|
||||
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
|
||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
|
||||
0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00,
|
||||
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
|
||||
};
|
||||
unsigned char public_key[32];
|
||||
|
||||
if (nostr_ec_private_key_verify(private_key) == 0) {
|
||||
printf("✅ nostr_ec_private_key_verify() - Private key validation works\n");
|
||||
} else {
|
||||
printf("❌ Private key validation failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (nostr_ec_public_key_from_private_key(private_key, public_key) == 0) {
|
||||
printf("✅ nostr_ec_public_key_from_private_key() - Public key generation works\n");
|
||||
} else {
|
||||
printf("❌ Public key generation failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Test 4: Event functions are available
|
||||
printf("\n=== Test 4: Event Functions ===\n");
|
||||
|
||||
cJSON* event = nostr_create_and_sign_event(1, "Test message", NULL, private_key, time(NULL));
|
||||
if (event) {
|
||||
printf("✅ nostr_create_and_sign_event() - Event creation works\n");
|
||||
|
||||
if (nostr_validate_event(event) == 0) {
|
||||
printf("✅ nostr_validate_event() - Event validation works\n");
|
||||
} else {
|
||||
printf("❌ Event validation failed\n");
|
||||
}
|
||||
|
||||
cJSON_Delete(event);
|
||||
} else {
|
||||
printf("❌ Event creation failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Test 5: Utility functions are available
|
||||
printf("\n=== Test 5: Utility Functions ===\n");
|
||||
|
||||
char hex_output[65];
|
||||
nostr_bytes_to_hex(hash, 32, hex_output);
|
||||
printf("✅ nostr_bytes_to_hex() - Hash as hex: %.16s...\n", hex_output);
|
||||
|
||||
unsigned char hex_back[32];
|
||||
if (nostr_hex_to_bytes(hex_output, hex_back, 32) == 0) {
|
||||
printf("✅ nostr_hex_to_bytes() - Hex conversion works\n");
|
||||
|
||||
if (memcmp(hash, hex_back, 32) == 0) {
|
||||
printf("✅ Round-trip hex conversion successful\n");
|
||||
} else {
|
||||
printf("❌ Round-trip hex conversion failed\n");
|
||||
}
|
||||
} else {
|
||||
printf("❌ Hex to bytes conversion failed\n");
|
||||
}
|
||||
|
||||
printf("\n====================================================\n");
|
||||
printf("Enhanced Header Integration Test Results:\n");
|
||||
printf("✅ Master header includes all functionality\n");
|
||||
printf("✅ All documented function categories accessible\n");
|
||||
printf("✅ Single #include provides complete API\n");
|
||||
printf("✅ Functions work correctly through master header\n");
|
||||
printf("\nDevelopers can now easily discover and use all\n");
|
||||
printf("NOSTR Core Library functions with just:\n");
|
||||
printf(" #include \"nostr_core.h\"\n");
|
||||
printf("====================================================\n");
|
||||
|
||||
cleanup:
|
||||
nostr_crypto_cleanup();
|
||||
return 0;
|
||||
}
|
Binary file not shown.
Binary file not shown.
BIN
tests/nip04_test
BIN
tests/nip04_test
Binary file not shown.
BIN
tests/nip05_test
BIN
tests/nip05_test
Binary file not shown.
BIN
tests/nip11_test
BIN
tests/nip11_test
Binary file not shown.
BIN
tests/nip44_test
BIN
tests/nip44_test
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,532 @@
|
|||
/*
|
||||
* NOSTR Core Library - Streaming SHA-256 Tests
|
||||
*
|
||||
* Comprehensive tests for streaming SHA-256 implementation
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include "../nostr_core/utils.h"
|
||||
#include "../nostr_core/nostr_common.h"
|
||||
|
||||
// Test vectors for SHA-256 (from official NIST test vectors)
|
||||
typedef struct {
|
||||
const char* input;
|
||||
const char* expected_hash;
|
||||
const char* description;
|
||||
} sha256_test_vector_t;
|
||||
|
||||
static const sha256_test_vector_t test_vectors[] = {
|
||||
{
|
||||
"",
|
||||
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"Empty string"
|
||||
},
|
||||
{
|
||||
"a",
|
||||
"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
|
||||
"Single character"
|
||||
},
|
||||
{
|
||||
"abc",
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||
"Three characters"
|
||||
},
|
||||
{
|
||||
"message digest",
|
||||
"f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650",
|
||||
"Message digest"
|
||||
},
|
||||
{
|
||||
"abcdefghijklmnopqrstuvwxyz",
|
||||
"71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73",
|
||||
"Alphabet"
|
||||
},
|
||||
{
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
"db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0",
|
||||
"Alphanumeric"
|
||||
},
|
||||
{
|
||||
"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
||||
"f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e",
|
||||
"Numeric pattern"
|
||||
}
|
||||
};
|
||||
|
||||
static const size_t num_test_vectors = sizeof(test_vectors) / sizeof(test_vectors[0]);
|
||||
|
||||
// Helper function to convert hex string to bytes for comparison
|
||||
static void hex_to_bytes_helper(const char* hex_str, unsigned char* bytes) {
|
||||
size_t len = strlen(hex_str) / 2;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
sscanf(hex_str + i * 2, "%02hhx", &bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to print hash in hex format
|
||||
static void print_hash_hex(const unsigned char* hash, const char* label) {
|
||||
printf("%s: ", label);
|
||||
for (int i = 0; i < 32; i++) {
|
||||
printf("%02x", hash[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Test 1: Basic streaming functionality vs traditional SHA-256
|
||||
static void test_streaming_vs_traditional(void) {
|
||||
printf("\n=== Test 1: Streaming vs Traditional SHA-256 ===\n");
|
||||
|
||||
int passed = 0, failed = 0;
|
||||
|
||||
for (size_t i = 0; i < num_test_vectors; i++) {
|
||||
const sha256_test_vector_t* tv = &test_vectors[i];
|
||||
unsigned char traditional_hash[32];
|
||||
unsigned char streaming_hash[32];
|
||||
unsigned char expected_hash[32];
|
||||
|
||||
printf("Testing: %s\n", tv->description);
|
||||
printf("Input: \"%s\"\n", tv->input);
|
||||
|
||||
// Traditional SHA-256
|
||||
if (nostr_sha256((const unsigned char*)tv->input, strlen(tv->input), traditional_hash) != 0) {
|
||||
printf("❌ Traditional SHA-256 failed\n");
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Streaming SHA-256
|
||||
nostr_sha256_ctx_t ctx;
|
||||
if (nostr_sha256_init(&ctx) != 0) {
|
||||
printf("❌ Streaming SHA-256 init failed\n");
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nostr_sha256_update(&ctx, (const unsigned char*)tv->input, strlen(tv->input)) != 0) {
|
||||
printf("❌ Streaming SHA-256 update failed\n");
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nostr_sha256_final(&ctx, streaming_hash) != 0) {
|
||||
printf("❌ Streaming SHA-256 final failed\n");
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Convert expected hash
|
||||
hex_to_bytes_helper(tv->expected_hash, expected_hash);
|
||||
|
||||
// Compare all three results
|
||||
if (memcmp(traditional_hash, expected_hash, 32) != 0) {
|
||||
printf("❌ Traditional hash mismatch\n");
|
||||
print_hash_hex(expected_hash, "Expected");
|
||||
print_hash_hex(traditional_hash, "Traditional");
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memcmp(streaming_hash, expected_hash, 32) != 0) {
|
||||
printf("❌ Streaming hash mismatch\n");
|
||||
print_hash_hex(expected_hash, "Expected");
|
||||
print_hash_hex(streaming_hash, "Streaming");
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memcmp(traditional_hash, streaming_hash, 32) != 0) {
|
||||
printf("❌ Traditional vs Streaming mismatch\n");
|
||||
print_hash_hex(traditional_hash, "Traditional");
|
||||
print_hash_hex(streaming_hash, "Streaming");
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("✅ All hashes match expected result\n");
|
||||
printf("Hash: %s\n", tv->expected_hash);
|
||||
passed++;
|
||||
}
|
||||
|
||||
printf("\nTest 1 Results: %d passed, %d failed\n", passed, failed);
|
||||
}
|
||||
|
||||
// Test 2: Multiple update calls (chunk boundary testing)
|
||||
static void test_multiple_updates(void) {
|
||||
printf("\n=== Test 2: Multiple Update Calls ===\n");
|
||||
|
||||
const char* test_string = "abcdefghijklmnopqrstuvwxyz";
|
||||
unsigned char expected_hash[32];
|
||||
unsigned char streaming_hash[32];
|
||||
|
||||
// Get expected result from traditional function
|
||||
nostr_sha256((const unsigned char*)test_string, strlen(test_string), expected_hash);
|
||||
|
||||
printf("Testing alphabet string with multiple update calls\n");
|
||||
printf("Input: \"%s\"\n", test_string);
|
||||
|
||||
// Test various chunk sizes
|
||||
size_t chunk_sizes[] = {1, 2, 3, 5, 7, 11, 13, 17, 19, 23};
|
||||
size_t num_chunk_sizes = sizeof(chunk_sizes) / sizeof(chunk_sizes[0]);
|
||||
|
||||
int passed = 0, failed = 0;
|
||||
|
||||
for (size_t cs_idx = 0; cs_idx < num_chunk_sizes; cs_idx++) {
|
||||
size_t chunk_size = chunk_sizes[cs_idx];
|
||||
printf("Testing chunk size: %zu\n", chunk_size);
|
||||
|
||||
nostr_sha256_ctx_t ctx;
|
||||
if (nostr_sha256_init(&ctx) != 0) {
|
||||
printf("❌ Init failed for chunk size %zu\n", chunk_size);
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Process string in chunks
|
||||
size_t input_len = strlen(test_string);
|
||||
size_t processed = 0;
|
||||
|
||||
while (processed < input_len) {
|
||||
size_t to_process = (input_len - processed < chunk_size) ?
|
||||
(input_len - processed) : chunk_size;
|
||||
|
||||
if (nostr_sha256_update(&ctx, (const unsigned char*)(test_string + processed), to_process) != 0) {
|
||||
printf("❌ Update failed at position %zu with chunk size %zu\n", processed, chunk_size);
|
||||
failed++;
|
||||
break;
|
||||
}
|
||||
|
||||
processed += to_process;
|
||||
}
|
||||
|
||||
if (processed != input_len) continue; // Skip final if update failed
|
||||
|
||||
if (nostr_sha256_final(&ctx, streaming_hash) != 0) {
|
||||
printf("❌ Final failed for chunk size %zu\n", chunk_size);
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memcmp(streaming_hash, expected_hash, 32) != 0) {
|
||||
printf("❌ Hash mismatch for chunk size %zu\n", chunk_size);
|
||||
print_hash_hex(expected_hash, "Expected");
|
||||
print_hash_hex(streaming_hash, "Streaming");
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("✅ Chunk size %zu: hash matches\n", chunk_size);
|
||||
passed++;
|
||||
}
|
||||
|
||||
printf("\nTest 2 Results: %d passed, %d failed\n", passed, failed);
|
||||
}
|
||||
|
||||
// Test 3: Large data streaming (memory efficiency test)
|
||||
static void test_large_data_streaming(void) {
|
||||
printf("\n=== Test 3: Large Data Streaming ===\n");
|
||||
|
||||
// Create a large test pattern (1MB of repeated data)
|
||||
const size_t total_size = 1024 * 1024; // 1MB
|
||||
char* large_data = malloc(total_size);
|
||||
if (!large_data) {
|
||||
printf("❌ Failed to allocate memory for large data test\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill with repeating pattern
|
||||
const char* pattern = "The quick brown fox jumps over the lazy dog. ";
|
||||
size_t pattern_len = strlen(pattern);
|
||||
for (size_t i = 0; i < total_size; i++) {
|
||||
large_data[i] = pattern[i % pattern_len];
|
||||
}
|
||||
|
||||
printf("Testing 1MB of data streaming vs traditional\n");
|
||||
|
||||
unsigned char traditional_hash[32];
|
||||
unsigned char streaming_hash[32];
|
||||
|
||||
// Traditional approach (loads entire data into memory - we already have it)
|
||||
if (nostr_sha256((const unsigned char*)large_data, total_size, traditional_hash) != 0) {
|
||||
printf("❌ Traditional SHA-256 failed on large data\n");
|
||||
free(large_data);
|
||||
return;
|
||||
}
|
||||
|
||||
// Streaming approach (processes in 4KB chunks)
|
||||
nostr_sha256_ctx_t ctx;
|
||||
if (nostr_sha256_init(&ctx) != 0) {
|
||||
printf("❌ Streaming init failed\n");
|
||||
free(large_data);
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t chunk_size = 4096; // 4KB chunks
|
||||
size_t processed = 0;
|
||||
|
||||
while (processed < total_size) {
|
||||
size_t to_process = (total_size - processed < chunk_size) ?
|
||||
(total_size - processed) : chunk_size;
|
||||
|
||||
if (nostr_sha256_update(&ctx, (const unsigned char*)(large_data + processed), to_process) != 0) {
|
||||
printf("❌ Streaming update failed at position %zu\n", processed);
|
||||
free(large_data);
|
||||
return;
|
||||
}
|
||||
|
||||
processed += to_process;
|
||||
}
|
||||
|
||||
if (nostr_sha256_final(&ctx, streaming_hash) != 0) {
|
||||
printf("❌ Streaming final failed\n");
|
||||
free(large_data);
|
||||
return;
|
||||
}
|
||||
|
||||
free(large_data);
|
||||
|
||||
// Compare results
|
||||
if (memcmp(traditional_hash, streaming_hash, 32) != 0) {
|
||||
printf("❌ Large data hash mismatch\n");
|
||||
print_hash_hex(traditional_hash, "Traditional");
|
||||
print_hash_hex(streaming_hash, "Streaming");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("✅ 1MB data processed successfully with streaming\n");
|
||||
print_hash_hex(streaming_hash, "Hash");
|
||||
printf("Memory efficiency: Streaming uses ~4KB buffer vs 1MB for traditional\n");
|
||||
}
|
||||
|
||||
// Test 4: File streaming functionality
|
||||
static void test_file_streaming(void) {
|
||||
printf("\n=== Test 4: File Streaming ===\n");
|
||||
|
||||
const char* test_filename = "test_streaming_file.tmp";
|
||||
const char* test_content = "This is a test file for streaming SHA-256 functionality.\n"
|
||||
"It contains multiple lines to test file I/O.\n"
|
||||
"The streaming function should read this file in chunks.\n"
|
||||
"And produce the same hash as if we read it all at once.\n";
|
||||
|
||||
// Create test file
|
||||
FILE* file = fopen(test_filename, "wb");
|
||||
if (!file) {
|
||||
printf("❌ Failed to create test file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(test_content, 1, strlen(test_content), file);
|
||||
fclose(file);
|
||||
|
||||
printf("Testing file streaming with content:\n\"%s\"\n", test_content);
|
||||
|
||||
// Get expected hash from memory-based function
|
||||
unsigned char expected_hash[32];
|
||||
if (nostr_sha256((const unsigned char*)test_content, strlen(test_content), expected_hash) != 0) {
|
||||
printf("❌ Memory-based hash failed\n");
|
||||
unlink(test_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
// Test file streaming
|
||||
unsigned char file_hash[32];
|
||||
if (nostr_sha256_file_stream(test_filename, file_hash) != 0) {
|
||||
printf("❌ File streaming failed\n");
|
||||
unlink(test_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
// Compare results
|
||||
if (memcmp(expected_hash, file_hash, 32) != 0) {
|
||||
printf("❌ File hash mismatch\n");
|
||||
print_hash_hex(expected_hash, "Expected");
|
||||
print_hash_hex(file_hash, "File stream");
|
||||
unlink(test_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("✅ File streaming matches memory-based hash\n");
|
||||
print_hash_hex(file_hash, "Hash");
|
||||
|
||||
// Clean up
|
||||
unlink(test_filename);
|
||||
|
||||
// Test with non-existent file
|
||||
if (nostr_sha256_file_stream("non_existent_file.tmp", file_hash) == 0) {
|
||||
printf("❌ File streaming should fail for non-existent file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("✅ File streaming properly handles non-existent files\n");
|
||||
}
|
||||
|
||||
// Test 5: Edge cases and error conditions
|
||||
static void test_edge_cases(void) {
|
||||
printf("\n=== Test 5: Edge Cases and Error Conditions ===\n");
|
||||
|
||||
nostr_sha256_ctx_t ctx;
|
||||
unsigned char hash[32];
|
||||
int passed = 0, failed = 0;
|
||||
|
||||
// Test NULL pointer handling
|
||||
printf("Testing NULL pointer handling:\n");
|
||||
|
||||
if (nostr_sha256_init(NULL) == 0) {
|
||||
printf("❌ Init should fail with NULL context\n");
|
||||
failed++;
|
||||
} else {
|
||||
printf("✅ Init properly rejects NULL context\n");
|
||||
passed++;
|
||||
}
|
||||
|
||||
if (nostr_sha256_update(&ctx, NULL, 10) == 0) {
|
||||
printf("❌ Update should fail with NULL data\n");
|
||||
failed++;
|
||||
} else {
|
||||
printf("✅ Update properly rejects NULL data\n");
|
||||
passed++;
|
||||
}
|
||||
|
||||
if (nostr_sha256_final(&ctx, NULL) == 0) {
|
||||
printf("❌ Final should fail with NULL output\n");
|
||||
failed++;
|
||||
} else {
|
||||
printf("✅ Final properly rejects NULL output\n");
|
||||
passed++;
|
||||
}
|
||||
|
||||
if (nostr_sha256_file_stream(NULL, hash) == 0) {
|
||||
printf("❌ File stream should fail with NULL filename\n");
|
||||
failed++;
|
||||
} else {
|
||||
printf("✅ File stream properly rejects NULL filename\n");
|
||||
passed++;
|
||||
}
|
||||
|
||||
if (nostr_sha256_file_stream("test.tmp", NULL) == 0) {
|
||||
printf("❌ File stream should fail with NULL output\n");
|
||||
failed++;
|
||||
} else {
|
||||
printf("✅ File stream properly rejects NULL output\n");
|
||||
passed++;
|
||||
}
|
||||
|
||||
// Test zero-length updates
|
||||
printf("\nTesting zero-length operations:\n");
|
||||
|
||||
if (nostr_sha256_init(&ctx) != 0) {
|
||||
printf("❌ Failed to initialize for zero-length test\n");
|
||||
failed++;
|
||||
} else {
|
||||
if (nostr_sha256_update(&ctx, (const unsigned char*)"test", 0) != 0) {
|
||||
printf("❌ Zero-length update should succeed\n");
|
||||
failed++;
|
||||
} else {
|
||||
printf("✅ Zero-length update handled correctly\n");
|
||||
passed++;
|
||||
}
|
||||
|
||||
if (nostr_sha256_final(&ctx, hash) != 0) {
|
||||
printf("❌ Final failed after zero-length update\n");
|
||||
failed++;
|
||||
} else {
|
||||
// Should match empty string hash
|
||||
unsigned char empty_hash[32];
|
||||
hex_to_bytes_helper("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", empty_hash);
|
||||
|
||||
if (memcmp(hash, empty_hash, 32) != 0) {
|
||||
printf("❌ Zero-length result doesn't match empty string hash\n");
|
||||
failed++;
|
||||
} else {
|
||||
printf("✅ Zero-length result matches empty string hash\n");
|
||||
passed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nTest 5 Results: %d passed, %d failed\n", passed, failed);
|
||||
}
|
||||
|
||||
// Test 6: Context reuse and security clearing
|
||||
static void test_context_security(void) {
|
||||
printf("\n=== Test 6: Context Security and Reuse ===\n");
|
||||
|
||||
nostr_sha256_ctx_t ctx;
|
||||
unsigned char hash1[32], hash2[32];
|
||||
const char* test1 = "first test";
|
||||
const char* test2 = "second test";
|
||||
|
||||
// First hash
|
||||
if (nostr_sha256_init(&ctx) != 0 ||
|
||||
nostr_sha256_update(&ctx, (const unsigned char*)test1, strlen(test1)) != 0 ||
|
||||
nostr_sha256_final(&ctx, hash1) != 0) {
|
||||
printf("❌ First hash computation failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("First hash computed successfully\n");
|
||||
|
||||
// Check that context is cleared after final (security feature)
|
||||
// We can't directly inspect the context, but we can try to reuse it
|
||||
|
||||
// Second hash with new init (proper way)
|
||||
if (nostr_sha256_init(&ctx) != 0 ||
|
||||
nostr_sha256_update(&ctx, (const unsigned char*)test2, strlen(test2)) != 0 ||
|
||||
nostr_sha256_final(&ctx, hash2) != 0) {
|
||||
printf("❌ Second hash computation failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Second hash computed successfully\n");
|
||||
|
||||
// Verify they're different (they should be)
|
||||
if (memcmp(hash1, hash2, 32) == 0) {
|
||||
printf("❌ Hashes should be different for different inputs\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("✅ Context can be reused with proper reinitialization\n");
|
||||
printf("✅ Context clearing prevents accidental reuse\n");
|
||||
|
||||
// Verify hashes against expected values
|
||||
unsigned char expected1[32], expected2[32];
|
||||
nostr_sha256((const unsigned char*)test1, strlen(test1), expected1);
|
||||
nostr_sha256((const unsigned char*)test2, strlen(test2), expected2);
|
||||
|
||||
if (memcmp(hash1, expected1, 32) == 0 && memcmp(hash2, expected2, 32) == 0) {
|
||||
printf("✅ Both streaming hashes match expected values\n");
|
||||
} else {
|
||||
printf("❌ Hash verification failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
printf("NOSTR Core Library - Streaming SHA-256 Tests\n");
|
||||
printf("===========================================\n");
|
||||
|
||||
// Initialize crypto subsystem
|
||||
if (nostr_crypto_init() != 0) {
|
||||
printf("❌ Failed to initialize crypto subsystem\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Run all tests
|
||||
test_streaming_vs_traditional();
|
||||
test_multiple_updates();
|
||||
test_large_data_streaming();
|
||||
test_file_streaming();
|
||||
test_edge_cases();
|
||||
test_context_security();
|
||||
|
||||
// Cleanup
|
||||
nostr_crypto_cleanup();
|
||||
|
||||
printf("\n===========================================\n");
|
||||
printf("All streaming SHA-256 tests completed.\n");
|
||||
printf("Review output above for detailed results.\n");
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
BIN
tests/wss_test
BIN
tests/wss_test
Binary file not shown.
Loading…
Reference in New Issue