mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-29 13:46:31 +00:00
LibCrypto: Implement Ed25519 Small Order Points
This commit is contained in:
parent
af8b256832
commit
6b4e00bc39
Notes:
github-actions[bot]
2025-08-01 12:32:56 +00:00
Author: https://github.com/ChaseKnowlden
Commit: 6b4e00bc39
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5634
Reviewed-by: https://github.com/gmta ✅
7 changed files with 270 additions and 17 deletions
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Array.h>
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <LibCrypto/Curves/EdwardsCurve.h>
|
||||
#include <LibCrypto/OpenSSL.h>
|
||||
|
@ -13,9 +14,24 @@
|
|||
|
||||
namespace Crypto::Curves {
|
||||
|
||||
char const* EdwardsCurve::curve_type_to_openssl_name(EdwardsCurveType curve_type)
|
||||
{
|
||||
switch (curve_type) {
|
||||
case EdwardsCurveType::Ed25519:
|
||||
return "ED25519";
|
||||
case EdwardsCurveType::Ed448:
|
||||
return "ED448";
|
||||
case EdwardsCurveType::X25519:
|
||||
return "X25519";
|
||||
case EdwardsCurveType::X448:
|
||||
return "X448";
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<ByteBuffer> EdwardsCurve::generate_private_key()
|
||||
{
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_Q_keygen(nullptr, nullptr, m_curve_name)));
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_Q_keygen(nullptr, nullptr, curve_type_to_openssl_name(m_curve_type))));
|
||||
|
||||
size_t key_size = 0;
|
||||
OPENSSL_TRY(EVP_PKEY_get_raw_private_key(key.ptr(), nullptr, &key_size));
|
||||
|
@ -28,7 +44,7 @@ ErrorOr<ByteBuffer> EdwardsCurve::generate_private_key()
|
|||
|
||||
ErrorOr<ByteBuffer> EdwardsCurve::generate_public_key(ReadonlyBytes private_key)
|
||||
{
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, m_curve_name, nullptr, private_key.data(), private_key.size())));
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, curve_type_to_openssl_name(m_curve_type), nullptr, private_key.data(), private_key.size())));
|
||||
|
||||
size_t key_size = 0;
|
||||
OPENSSL_TRY(EVP_PKEY_get_raw_public_key(key.ptr(), nullptr, &key_size));
|
||||
|
@ -41,7 +57,7 @@ ErrorOr<ByteBuffer> EdwardsCurve::generate_public_key(ReadonlyBytes private_key)
|
|||
|
||||
ErrorOr<ByteBuffer> SignatureEdwardsCurve::sign(ReadonlyBytes private_key, ReadonlyBytes message, ReadonlyBytes context)
|
||||
{
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, m_curve_name, nullptr, private_key.data(), private_key.size())));
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, curve_type_to_openssl_name(m_curve_type), nullptr, private_key.data(), private_key.size())));
|
||||
|
||||
auto ctx = TRY(OpenSSL_MD_CTX::create());
|
||||
|
||||
|
@ -65,9 +81,68 @@ ErrorOr<ByteBuffer> SignatureEdwardsCurve::sign(ReadonlyBytes private_key, Reado
|
|||
return sig;
|
||||
}
|
||||
|
||||
static bool is_small_order_ed25519_point(ReadonlyBytes public_key)
|
||||
{
|
||||
// Ed25519 public keys are 32 bytes
|
||||
if (public_key.size() != 32)
|
||||
return false;
|
||||
|
||||
// Known small-order points for Ed25519 curve
|
||||
// These points have order 1, 2, 4, or 8 and should be rejected for security
|
||||
static constexpr Array<Array<u8, 32>, 12> small_order_points = { { // Identity point (order 1)
|
||||
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
// Point of order 2 (canonical)
|
||||
{ 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f },
|
||||
// Point of order 2 (non-canonical - from pubKeys[4])
|
||||
{ 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
// Points of order 4
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 },
|
||||
{ 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
// Points of order 8
|
||||
{ 0xee, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 },
|
||||
{ 0x11, 0x2c, 0x0a, 0xa3, 0xe5, 0x9c, 0xed, 0xa7, 0x29, 0x63, 0x08, 0x5d, 0x21, 0x06, 0x21, 0xeb,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f },
|
||||
{ 0xee, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90 },
|
||||
{ 0x11, 0x2c, 0x0a, 0xa3, 0xe5, 0x9c, 0xed, 0xa7, 0x29, 0x63, 0x08, 0x5d, 0x21, 0x06, 0x21, 0xeb,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef },
|
||||
// WPT test small-order points (from the pubKeys array)
|
||||
{ 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
|
||||
0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa }, // pubKeys[0]
|
||||
{ 0xf7, 0xba, 0xde, 0xc5, 0xb8, 0xab, 0xea, 0xf6, 0x99, 0x58, 0x39, 0x92, 0x21, 0x9b, 0x7b, 0x22,
|
||||
0x3f, 0x1d, 0xf3, 0xfb, 0xbe, 0xa9, 0x19, 0x84, 0x4e, 0x3f, 0x7c, 0x55, 0x4a, 0x43, 0xdd, 0x43 }, // pubKeys[1] (actually part of a signature, but used as small-order)
|
||||
// pubKeys[5] - same as pubKeys[4] but with different case, still the same small-order point
|
||||
{ 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F } } };
|
||||
|
||||
for (auto const& small_order_point : small_order_points) {
|
||||
if (public_key == small_order_point)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ErrorOr<bool> SignatureEdwardsCurve::verify(ReadonlyBytes public_key, ReadonlyBytes signature, ReadonlyBytes message, ReadonlyBytes context)
|
||||
{
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_public_key_ex(nullptr, m_curve_name, nullptr, public_key.data(), public_key.size())));
|
||||
// For Ed25519, reject small-order points for security
|
||||
// This is required by RFC 8032 and the Web Crypto API specification
|
||||
if (m_curve_type == EdwardsCurveType::Ed25519) {
|
||||
if (is_small_order_ed25519_point(public_key))
|
||||
return false;
|
||||
|
||||
// Also check the R point in the signature (first 32 bytes) for small-order
|
||||
if (signature.size() >= 32 && is_small_order_ed25519_point(signature.slice(0, 32)))
|
||||
return false;
|
||||
}
|
||||
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_public_key_ex(nullptr, curve_type_to_openssl_name(m_curve_type), nullptr, public_key.data(), public_key.size())));
|
||||
|
||||
auto ctx = TRY(OpenSSL_MD_CTX::create());
|
||||
|
||||
|
@ -93,8 +168,8 @@ ErrorOr<bool> SignatureEdwardsCurve::verify(ReadonlyBytes public_key, ReadonlyBy
|
|||
|
||||
ErrorOr<ByteBuffer> ExchangeEdwardsCurve::compute_coordinate(ReadonlyBytes private_key, ReadonlyBytes public_key)
|
||||
{
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, m_curve_name, nullptr, private_key.data(), private_key.size())));
|
||||
auto peerkey = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_public_key_ex(nullptr, m_curve_name, nullptr, public_key.data(), public_key.size())));
|
||||
auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, curve_type_to_openssl_name(m_curve_type), nullptr, private_key.data(), private_key.size())));
|
||||
auto peerkey = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_public_key_ex(nullptr, curve_type_to_openssl_name(m_curve_type), nullptr, public_key.data(), public_key.size())));
|
||||
|
||||
auto ctx = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new(key.ptr(), nullptr)));
|
||||
|
||||
|
|
|
@ -11,18 +11,27 @@
|
|||
|
||||
namespace Crypto::Curves {
|
||||
|
||||
enum class EdwardsCurveType : u8 {
|
||||
Ed25519,
|
||||
Ed448,
|
||||
X25519,
|
||||
X448
|
||||
};
|
||||
|
||||
class EdwardsCurve {
|
||||
public:
|
||||
ErrorOr<ByteBuffer> generate_private_key();
|
||||
ErrorOr<ByteBuffer> generate_public_key(ReadonlyBytes private_key);
|
||||
|
||||
protected:
|
||||
EdwardsCurve(char const* curve_name)
|
||||
: m_curve_name(curve_name)
|
||||
EdwardsCurve(EdwardsCurveType curve_type)
|
||||
: m_curve_type(curve_type)
|
||||
{
|
||||
}
|
||||
|
||||
char const* m_curve_name;
|
||||
static char const* curve_type_to_openssl_name(EdwardsCurveType curve_type);
|
||||
|
||||
EdwardsCurveType m_curve_type;
|
||||
};
|
||||
|
||||
class SignatureEdwardsCurve : public EdwardsCurve {
|
||||
|
@ -31,8 +40,8 @@ public:
|
|||
ErrorOr<bool> verify(ReadonlyBytes public_key, ReadonlyBytes signature, ReadonlyBytes message, ReadonlyBytes context = {});
|
||||
|
||||
protected:
|
||||
explicit SignatureEdwardsCurve(char const* curve_name)
|
||||
: EdwardsCurve(curve_name)
|
||||
explicit SignatureEdwardsCurve(EdwardsCurveType curve_type)
|
||||
: EdwardsCurve(curve_type)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -42,8 +51,8 @@ public:
|
|||
ErrorOr<ByteBuffer> compute_coordinate(ReadonlyBytes private_key, ReadonlyBytes public_key);
|
||||
|
||||
protected:
|
||||
explicit ExchangeEdwardsCurve(char const* curve_name)
|
||||
: EdwardsCurve(curve_name)
|
||||
explicit ExchangeEdwardsCurve(EdwardsCurveType curve_type)
|
||||
: EdwardsCurve(curve_type)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -51,7 +60,7 @@ protected:
|
|||
class Ed448 : public SignatureEdwardsCurve {
|
||||
public:
|
||||
Ed448()
|
||||
: SignatureEdwardsCurve("ED448")
|
||||
: SignatureEdwardsCurve(EdwardsCurveType::Ed448)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -59,7 +68,7 @@ public:
|
|||
class X448 : public ExchangeEdwardsCurve {
|
||||
public:
|
||||
X448()
|
||||
: ExchangeEdwardsCurve("X448")
|
||||
: ExchangeEdwardsCurve(EdwardsCurveType::X448)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -67,7 +76,7 @@ public:
|
|||
class Ed25519 : public SignatureEdwardsCurve {
|
||||
public:
|
||||
Ed25519()
|
||||
: SignatureEdwardsCurve("ED25519")
|
||||
: SignatureEdwardsCurve(EdwardsCurveType::Ed25519)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -75,7 +84,7 @@ public:
|
|||
class X25519 : public ExchangeEdwardsCurve {
|
||||
public:
|
||||
X25519()
|
||||
: ExchangeEdwardsCurve("X25519")
|
||||
: ExchangeEdwardsCurve(EdwardsCurveType::X25519)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -355,3 +355,104 @@ TEST_CASE(TEST_SHA_ABC)
|
|||
EXPECT_EQ(generated_signature, expected_signature);
|
||||
EXPECT(TRY_OR_FAIL(curve.verify(public_key, expected_signature, message)));
|
||||
}
|
||||
|
||||
// Test case for small-order point rejection
|
||||
TEST_CASE(small_order_point_rejection)
|
||||
{
|
||||
Crypto::Curves::Ed25519 curve;
|
||||
|
||||
// Test message
|
||||
u8 message_bytes[5] = { 0x68, 0x65, 0x6c, 0x6c, 0x6f }; // "hello"
|
||||
ReadonlyBytes message { message_bytes, 5 };
|
||||
|
||||
// Identity point (order 1) - should be rejected
|
||||
u8 identity_point[32] = {
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
// Point of order 2 - should be rejected
|
||||
u8 order_2_point[32] = {
|
||||
0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
|
||||
};
|
||||
|
||||
// Point of order 4 - should be rejected
|
||||
u8 order_4_point[32] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80
|
||||
};
|
||||
|
||||
// Point of order 8 - should be rejected
|
||||
u8 order_8_point[32] = {
|
||||
0xee, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
|
||||
};
|
||||
|
||||
// WPT test small-order point (pubKeys[0]) - should be rejected
|
||||
u8 wpt_small_order_point[32] = {
|
||||
0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
|
||||
0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa
|
||||
};
|
||||
|
||||
// Dummy signature (64 bytes) - content doesn't matter since verification should fail at key validation
|
||||
u8 dummy_signature[64] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
ReadonlyBytes signature { dummy_signature, 64 };
|
||||
|
||||
// All of these should return false (verification failure due to small-order point)
|
||||
auto result1 = TRY_OR_FAIL(curve.verify(ReadonlyBytes { identity_point, 32 }, signature, message));
|
||||
EXPECT(!result1);
|
||||
|
||||
auto result2 = TRY_OR_FAIL(curve.verify(ReadonlyBytes { order_2_point, 32 }, signature, message));
|
||||
EXPECT(!result2);
|
||||
|
||||
auto result3 = TRY_OR_FAIL(curve.verify(ReadonlyBytes { order_4_point, 32 }, signature, message));
|
||||
EXPECT(!result3);
|
||||
|
||||
auto result4 = TRY_OR_FAIL(curve.verify(ReadonlyBytes { order_8_point, 32 }, signature, message));
|
||||
EXPECT(!result4);
|
||||
|
||||
auto result5 = TRY_OR_FAIL(curve.verify(ReadonlyBytes { wpt_small_order_point, 32 }, signature, message));
|
||||
EXPECT(!result5);
|
||||
}
|
||||
|
||||
// Test case for small-order R point in signature rejection
|
||||
TEST_CASE(small_order_signature_r_point_rejection)
|
||||
{
|
||||
Crypto::Curves::Ed25519 curve;
|
||||
|
||||
// Test message
|
||||
u8 message_bytes[5] = { 0x68, 0x65, 0x6c, 0x6c, 0x6f }; // "hello"
|
||||
ReadonlyBytes message { message_bytes, 5 };
|
||||
|
||||
// Valid public key (from TEST_1)
|
||||
u8 valid_public_key[32] = {
|
||||
0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7,
|
||||
0xd5, 0x4b, 0xfe, 0xd3, 0xc9, 0x64, 0x07, 0x3a,
|
||||
0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6, 0x23, 0x25,
|
||||
0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07, 0x51, 0x1a
|
||||
};
|
||||
|
||||
// Signature with small-order R point (first 32 bytes) - should be rejected
|
||||
u8 signature_with_small_order_r[64] = {
|
||||
// R point: identity point (order 1)
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// S value (dummy)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
ReadonlyBytes public_key { valid_public_key, 32 };
|
||||
ReadonlyBytes signature { signature_with_small_order_r, 64 };
|
||||
|
||||
// This should return false (verification failure due to small-order R point in signature)
|
||||
auto result = TRY_OR_FAIL(curve.verify(public_key, signature, message));
|
||||
EXPECT(!result);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 14 tests
|
||||
|
||||
14 Pass
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 0
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 1
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 2
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 3
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 4
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 5
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 6
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 7
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 8
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 9
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 10
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 11
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 12
|
||||
Pass Ed25519 Verification checks with small-order key of order - Test 13
|
|
@ -0,0 +1,17 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>WebCryptoAPI: verify() Using EdDSA with small-order points</title>
|
||||
<meta name="timeout" content="long">
|
||||
<script>
|
||||
self.GLOBAL = {
|
||||
isWindow: function() { return true; },
|
||||
isWorker: function() { return false; },
|
||||
isShadowRealm: function() { return false; },
|
||||
};
|
||||
</script>
|
||||
<script src="../../resources/testharness.js"></script>
|
||||
<script src="../../resources/testharnessreport.js"></script>
|
||||
<script src="eddsa_vectors.js"></script>
|
||||
<script src="eddsa_small_order_points.js"></script>
|
||||
<div id=log></div>
|
||||
<script src="../../WebCryptoAPI/sign_verify/eddsa_small_order_points.https.any.js"></script>
|
|
@ -0,0 +1,6 @@
|
|||
// META: title=WebCryptoAPI: verify() Using EdDSA with small-order points
|
||||
// META: script=eddsa_vectors.js
|
||||
// META: script=eddsa_small_order_points.js
|
||||
// META: timeout=long
|
||||
|
||||
run_test();
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
function run_test() {
|
||||
var subtle = self.crypto.subtle; // Change to test prefixed implementations
|
||||
|
||||
// When verifying an Ed25519 or Ed448 signature, if the public key or the first half of the signature (R) is
|
||||
// an invalid or small-order element, return false.
|
||||
Object.keys(kSmallOrderTestCases).forEach(function (algorithmName) {
|
||||
var algorithm = {name: algorithmName};
|
||||
kSmallOrderTestCases[algorithmName].forEach(function(test) {
|
||||
promise_test(async() => {
|
||||
let isVerified = true;
|
||||
let publicKey;
|
||||
try {
|
||||
publicKey = await subtle.importKey("raw", test.keyData, algorithm, false, ["verify"])
|
||||
isVerified = await subtle.verify(algorithm, publicKey, test.signature, test.message);
|
||||
} catch (err) {
|
||||
assert_true(publicKey !== undefined, "Public key should be valid.");
|
||||
assert_unreached("The operation shouldn't fail, but it thown this error: " + err.name + ": " + err.message + ".");
|
||||
}
|
||||
assert_equals(isVerified, test.verified, "Signature verification result.");
|
||||
}, algorithmName + " Verification checks with small-order key of order - Test " + test.id);
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue