wolfssl-examples/signature/ecc-compare/ecc-verify-wolfssl.c

230 lines
7.0 KiB
C

/* ecc-verify-wolfssl.c
*
* Copyright (C) 2006-2025 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/coding.h>
/* Helper function to convert hex string to binary */
static int hex2bin(const char *hex, unsigned char *bin, int bin_size)
{
int i;
int hex_len = strlen(hex);
if (hex_len % 2 != 0) {
fprintf(stderr, "Error: Hex string must have even length\n");
return -1;
}
if (bin_size < hex_len / 2) {
fprintf(stderr, "Error: Binary buffer too small\n");
return -1;
}
for (i = 0; i < hex_len / 2; i++) {
unsigned char byte = 0;
int j;
for (j = 0; j < 2; j++) {
char c = hex[i * 2 + j];
byte <<= 4;
if (c >= '0' && c <= '9')
byte |= c - '0';
else if (c >= 'a' && c <= 'f')
byte |= c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
byte |= c - 'A' + 10;
else {
fprintf(stderr, "Error: Invalid hex character: %c\n", c);
return -1;
}
}
bin[i] = byte;
}
return hex_len / 2;
}
/* Fixed test data in hex format (pre-computed hash) */
static const char *fixed_data_hex =
"E7BD43AEE750B0DA4B3F537E152C4A7407764037A57447CACD2096A5D60994BA";
/* Fixed ECC public key in hex format (uncompressed format for P-256 curve) */
static const char *fixed_pubkey_hex =
"042FBFB32C9E2890FD742D991FD43B889191791E18337AD408CB12CA79325E88DD"
"7D20A5182318EC9BD696DDF41128D8BF1A137D2446C7A5AF6AA60AFEF3E8610E";
/* Fixed signature in hex format (DER format) */
static const char *fixed_signature_hex =
"30450220763B61459CF2FC3E821053702CC24C0E378C976FC6F83F0F0FF05BD85203B958"
"022100A40A0A3AF50769EE740CBA8F9B5F4530F5E5A93EDEBBAB14A1F3BECE93FB5A47";
/* Sample message that was signed (for display purposes) */
static const char *sample_message = "sample message for signing";
/* Helper function to print wolfSSL errors */
static void print_wolfssl_error(int err)
{
fprintf(stderr, "wolfSSL error: %d (%s)\n", err, wc_GetErrorString(err));
}
/* Helper function to print binary data in hex format */
static void print_hex(const char *label, const unsigned char *data, size_t len)
{
size_t i;
printf("%s (length=%zu):\n", label, len);
for (i = 0; i < len; i++) {
printf("%02X", data[i]);
if ((i + 1) % 16 == 0 || i == len - 1)
printf("\n");
else if ((i + 1) % 8 == 0)
printf(" ");
else
printf(" ");
}
printf("\n");
}
int verify_ecc_signature(void)
{
int ret = 0;
unsigned char fixed_data[128];
unsigned char fixed_pubkey[128];
unsigned char fixed_signature[128];
int data_len, pubkey_len, sig_len;
ecc_key eccKey;
int verify_status = 0;
word32 idx = 0;
/* Convert hex strings to binary */
data_len = hex2bin(fixed_data_hex, fixed_data, sizeof(fixed_data));
if (data_len < 0) {
printf("Error: Failed to convert data hex string\n");
ret = -1;
goto cleanup;
}
pubkey_len = hex2bin(fixed_pubkey_hex, fixed_pubkey, sizeof(fixed_pubkey));
if (pubkey_len < 0) {
printf("Error: Failed to convert pubkey hex string\n");
ret = -1;
goto cleanup;
}
sig_len = hex2bin(fixed_signature_hex, fixed_signature, sizeof(fixed_signature));
if (sig_len < 0) {
printf("Error: Failed to convert signature hex string\n");
ret = -1;
goto cleanup;
}
/* Print the binary data for verification */
printf("Data to verify: \"%s\"\n\n", sample_message);
print_hex("Data (pre-computed hash)", fixed_data, data_len);
print_hex("Public Key (uncompressed format)", fixed_pubkey, pubkey_len);
print_hex("Signature (DER format)", fixed_signature, sig_len);
/* Initialize wolfSSL */
ret = wc_ecc_init(&eccKey);
if (ret != 0) {
printf("Error: Failed to initialize ECC key\n");
print_wolfssl_error(ret);
goto cleanup;
}
/* Import the public key */
ret = wc_ecc_import_x963(fixed_pubkey, pubkey_len, &eccKey);
if (ret != 0) {
printf("Error: Failed to import public key\n");
print_wolfssl_error(ret);
goto cleanup;
}
/* Extract r and s components from DER signature for display purposes */
printf("\nExtracting r and s components from DER signature...\n");
/* Create temporary buffer for r and s components */
byte r_buf[MAX_ECC_BYTES];
byte s_buf[MAX_ECC_BYTES];
word32 r_size = sizeof(r_buf);
word32 s_size = sizeof(s_buf);
/* Decode the DER signature to extract r and s components */
ret = wc_ecc_sig_to_rs(fixed_signature, sig_len, r_buf, &r_size, s_buf, &s_size);
if (ret != 0) {
printf("Error: Failed to decode signature\n");
print_wolfssl_error(ret);
goto cleanup;
}
/* Display the r and s components */
print_hex("Signature r component", r_buf, r_size);
print_hex("Signature s component", s_buf, s_size);
/* Verify the signature using wc_ecc_verify_hash */
printf("\nVerifying signature using wc_ecc_verify_hash...\n");
ret = wc_ecc_verify_hash(fixed_signature, sig_len, fixed_data, data_len, &verify_status, &eccKey);
if (ret == 0) {
if (verify_status == 1) {
printf("Signature verification successful!\n");
ret = 0; /* Success */
} else {
printf("Signature verification failed - invalid signature\n");
ret = -1;
}
} else {
printf("Signature verification error\n");
print_wolfssl_error(ret);
ret = -1;
}
cleanup:
/* Clean up */
wc_ecc_free(&eccKey);
return ret;
}
int main(void)
{
int ret;
printf("wolfSSL ECC Signature Verification Example\n");
printf("Using fixed test values for public key, signature, and data\n\n");
ret = verify_ecc_signature();
printf("\nVerification result: %s (ret = %d)\n",
(ret == 0) ? "SUCCESS" : "FAILURE", ret);
return (ret == 0) ? 0 : 1;
}