From 3cda05ce0a10bcfac24694b448504fd69413f0f2 Mon Sep 17 00:00:00 2001 From: Quoc Le Date: Tue, 24 Dec 2024 04:15:17 +0000 Subject: [PATCH] add rsa signature verification --- libraries/eosiolib/capi/eosio/crypto.h | 24 +++++++++++++++++++ libraries/eosiolib/core/eosio/crypto.hpp | 17 +++++++++++++ libraries/eosiolib/crypto.cpp | 18 ++++++++++++++ libraries/native/intrinsics.cpp | 6 +++++ .../native/native/eosio/intrinsics_def.hpp | 1 + tests/unit/test_contracts/capi/crypto.c | 1 + 6 files changed, 67 insertions(+) diff --git a/libraries/eosiolib/capi/eosio/crypto.h b/libraries/eosiolib/capi/eosio/crypto.h index fff817b79b..f33a3642ca 100644 --- a/libraries/eosiolib/capi/eosio/crypto.h +++ b/libraries/eosiolib/capi/eosio/crypto.h @@ -186,6 +186,30 @@ void sha512( const char* data, uint32_t length, struct capi_checksum512* hash ); __attribute__((eosio_wasm_import)) void ripemd160( const char* data, uint32_t length, struct capi_checksum160* hash ); +/** + * Verifies the RSA SHA-256 signature for a given message using the provided public key components (exponent and modulus). + * + * @param message - The original message that was signed. + * @param message_len - Length of the message in bytes. + * @param signature - The RSA signature to verify. + * @param signature_len - Length of the signature in bytes. + * @param exponent - The public key exponent. + * @param exponent_len - Length of the exponent in bytes. + * @param modulus - The public key modulus. + * @param modulus_len - Length of the modulus in bytes. + * @return int - Returns 1 if the signature is valid, 0 if invalid. + * + * Example: + * + * @code + * @endcode + */ +__attribute__((eosio_wasm_import)) +int32_t verify_rsa_sha256_sig( const void* message, uint32_t message_len, + const char* signature, uint32_t signature_len, + const char* exponent, uint32_t exponent_len, + const char* modulus, uint32_t modulus_len); + /** * Calculates the public key used for a given signature and hash used to create a message. * diff --git a/libraries/eosiolib/core/eosio/crypto.hpp b/libraries/eosiolib/core/eosio/crypto.hpp index b7ca46a980..58053e2097 100644 --- a/libraries/eosiolib/core/eosio/crypto.hpp +++ b/libraries/eosiolib/core/eosio/crypto.hpp @@ -317,6 +317,23 @@ namespace eosio { */ eosio::checksum160 ripemd160( const char* data, uint32_t length ); + /** + * Verifies an RSA signature using SHA-256 hashing. + * + * @ingroup crypto + * @param message - Pointer to the message data to be verified + * @param message_len - Length of the message data + * @param signature - RSA signature to verify + * @param exponent - RSA public key exponent + * @param modulus - RSA public key modulus + * @return bool - `true` if the signature is valid, `false` otherwise + */ + bool verify_rsa_sha256_sig( const void* message, + uint32_t message_len, + std::string_view signature, + std::string_view exponent, + std::string_view modulus); + /** * Calculates the public key used for a given signature on a given digest. * diff --git a/libraries/eosiolib/crypto.cpp b/libraries/eosiolib/crypto.cpp index bc96fbd0db..5a3285943a 100644 --- a/libraries/eosiolib/crypto.cpp +++ b/libraries/eosiolib/crypto.cpp @@ -35,6 +35,12 @@ extern "C" { __attribute__((eosio_wasm_import)) void ripemd160( const char* data, uint32_t length, capi_checksum160* hash ); + __attribute__((eosio_wasm_import)) + int32_t verify_rsa_sha256_sig( const void* message, uint32_t message_len, + const char* signature, uint32_t signature_len, + const char* exponent, uint32_t exponent_len, + const char* modulus, uint32_t modulus_len); + __attribute__((eosio_wasm_import)) int recover_key( const capi_checksum256* digest, const char* sig, size_t siglen, char* pub, size_t publen ); @@ -90,6 +96,18 @@ namespace eosio { return {hash.hash}; } + bool verify_rsa_sha256_sig( const void* message, + uint32_t message_len, + std::string_view signature, + std::string_view exponent, + std::string_view modulus) { + return ::verify_rsa_sha256_sig( + message, message_len, + signature.data(), signature.size(), + exponent.data(), exponent.size(), + modulus.data(), modulus.size()); + } + eosio::public_key recover_key( const eosio::checksum256& digest, const eosio::signature& sig ) { auto digest_data = digest.extract_as_byte_array(); diff --git a/libraries/native/intrinsics.cpp b/libraries/native/intrinsics.cpp index 0d5a80786a..d63d2fc866 100644 --- a/libraries/native/intrinsics.cpp +++ b/libraries/native/intrinsics.cpp @@ -259,6 +259,12 @@ extern "C" { void ripemd160( const char* data, uint32_t length, capi_checksum160* hash ) { return intrinsics::get().call(data, length, hash); } + int32_t verify_rsa_sha256_sig( const void* message, uint32_t message_len, + const char* signature, uint32_t signature_len, + const char* exponent, uint32_t exponent_len, + const char* modulus, uint32_t modulus_len){ + return intrinsics::get().call(message, message_len, signature, signature_len, exponent, exponent_len, modulus, modulus_len); + } int32_t check_transaction_authorization( const char* trx_data, uint32_t trx_size, const char* pubkeys_data, uint32_t pubkeys_size, const char* perms_data, uint32_t perms_size diff --git a/libraries/native/native/eosio/intrinsics_def.hpp b/libraries/native/native/eosio/intrinsics_def.hpp index 4dd728117e..4b85ecb0ba 100644 --- a/libraries/native/native/eosio/intrinsics_def.hpp +++ b/libraries/native/native/eosio/intrinsics_def.hpp @@ -124,6 +124,7 @@ intrinsic_macro(sha1) \ intrinsic_macro(sha256) \ intrinsic_macro(sha512) \ intrinsic_macro(ripemd160) \ +intrinsic_macro(verify_rsa_sha256_sig) \ intrinsic_macro(check_transaction_authorization) \ intrinsic_macro(check_permission_authorization) \ intrinsic_macro(get_permission_last_used) \ diff --git a/tests/unit/test_contracts/capi/crypto.c b/tests/unit/test_contracts/capi/crypto.c index cbe7784c9b..f09f920f17 100644 --- a/tests/unit/test_contracts/capi/crypto.c +++ b/tests/unit/test_contracts/capi/crypto.c @@ -10,6 +10,7 @@ void test_crypto( void ) { sha1( NULL, 0, NULL ); sha512( NULL, 0, NULL ); ripemd160( NULL, 0, NULL ); + verify_rsa_sha256_sig( NULL, 0, NULL, 0, NULL, 0, NULL, 0); recover_key( NULL, NULL, 0, NULL, 0 ); assert_recover_key( NULL, NULL, 0, NULL, 0 ); }