mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 20:29:18 +00:00
LibCrypto+LibTLS+LibWeb: Store EC key size + refactor serialization
In order for public/private key serialization to work correctly we must store the size of the key because P-521 cannot be stored as full words inside `UnsignedBigInteger` and therefore is exported as the wrong length (68 instead of 66). This makes it also possible to refactor some methods and cleanup constants scattered around. Gets almost all import/export tests, expect the JWK ones that calculate the public key on export. The `SECPxxxr1` implementation currently fails to do calculations for P-521.
This commit is contained in:
parent
70db7772b8
commit
9240d38273
Notes:
github-actions[bot]
2024-12-14 00:53:11 +00:00
Author: https://github.com/devgianlu
Commit: 9240d38273
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2902
Reviewed-by: https://github.com/alimpfard
9 changed files with 146 additions and 110 deletions
|
@ -14,11 +14,6 @@
|
||||||
#include <LibCrypto/ASN1/PEM.h>
|
#include <LibCrypto/ASN1/PEM.h>
|
||||||
#include <LibCrypto/PK/EC.h>
|
#include <LibCrypto/PK/EC.h>
|
||||||
|
|
||||||
namespace {
|
|
||||||
// Used by ASN1 macros
|
|
||||||
static String s_error_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Crypto::Certificate {
|
namespace Crypto::Certificate {
|
||||||
|
|
||||||
static ErrorOr<Crypto::UnsignedBigInteger> parse_certificate_version(Crypto::ASN1::Decoder& decoder, Vector<StringView> current_scope)
|
static ErrorOr<Crypto::UnsignedBigInteger> parse_certificate_version(Crypto::ASN1::Decoder& decoder, Vector<StringView> current_scope)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, Michiel Visser <opensource@webmichiel.nl>
|
* Copyright (c) 2023, Michiel Visser <opensource@webmichiel.nl>
|
||||||
|
* Copyright (c) 2024, Altomani Gianluca <altomanigianluca@gmail.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -36,6 +37,22 @@ struct SECPxxxr1CurveParameters {
|
||||||
struct SECPxxxr1Point {
|
struct SECPxxxr1Point {
|
||||||
UnsignedBigInteger x;
|
UnsignedBigInteger x;
|
||||||
UnsignedBigInteger y;
|
UnsignedBigInteger y;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
static ErrorOr<ByteBuffer> scalar_to_bytes(UnsignedBigInteger const& a, size_t size)
|
||||||
|
{
|
||||||
|
auto a_bytes = TRY(ByteBuffer::create_uninitialized(a.byte_length()));
|
||||||
|
auto a_size = a.export_data(a_bytes.span());
|
||||||
|
VERIFY(a_size >= size);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < a_size - size; i++) {
|
||||||
|
if (a_bytes[i] != 0) {
|
||||||
|
return Error::from_string_literal("Scalar is too large for the given size");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return a_bytes.slice(a_size - size, size);
|
||||||
|
}
|
||||||
|
|
||||||
static ErrorOr<SECPxxxr1Point> from_uncompressed(ReadonlyBytes data)
|
static ErrorOr<SECPxxxr1Point> from_uncompressed(ReadonlyBytes data)
|
||||||
{
|
{
|
||||||
|
@ -46,16 +63,30 @@ struct SECPxxxr1Point {
|
||||||
return SECPxxxr1Point {
|
return SECPxxxr1Point {
|
||||||
UnsignedBigInteger::import_data(data.slice(1, half_size)),
|
UnsignedBigInteger::import_data(data.slice(1, half_size)),
|
||||||
UnsignedBigInteger::import_data(data.slice(1 + half_size, half_size)),
|
UnsignedBigInteger::import_data(data.slice(1 + half_size, half_size)),
|
||||||
|
half_size,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<ByteBuffer> x_bytes() const
|
||||||
|
{
|
||||||
|
return scalar_to_bytes(x, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<ByteBuffer> y_bytes() const
|
||||||
|
{
|
||||||
|
return scalar_to_bytes(y, size);
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<ByteBuffer> to_uncompressed() const
|
ErrorOr<ByteBuffer> to_uncompressed() const
|
||||||
{
|
{
|
||||||
auto bytes = TRY(ByteBuffer::create_uninitialized(1 + x.byte_length() + y.byte_length()));
|
auto x = TRY(x_bytes());
|
||||||
|
auto y = TRY(y_bytes());
|
||||||
|
|
||||||
|
auto bytes = TRY(ByteBuffer::create_uninitialized(1 + (size * 2)));
|
||||||
bytes[0] = 0x04; // uncompressed
|
bytes[0] = 0x04; // uncompressed
|
||||||
auto x_size = x.export_data(bytes.span().slice(1));
|
bytes.overwrite(1, x.data(), size);
|
||||||
auto y_size = y.export_data(bytes.span().slice(1 + x_size));
|
bytes.overwrite(1 + size, y.data(), size);
|
||||||
return bytes.slice(0, 1 + x_size + y_size);
|
return bytes;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -218,7 +249,11 @@ public:
|
||||||
{
|
{
|
||||||
VERIFY(scalar.byte_length() >= KEY_BYTE_SIZE);
|
VERIFY(scalar.byte_length() >= KEY_BYTE_SIZE);
|
||||||
|
|
||||||
return compute_coordinate_point(scalar, SECPxxxr1Point { UnsignedBigInteger::import_data(GENERATOR_POINT.data() + 1, KEY_BYTE_SIZE), UnsignedBigInteger::import_data(GENERATOR_POINT.data() + 1 + KEY_BYTE_SIZE, KEY_BYTE_SIZE) });
|
return compute_coordinate_point(scalar, SECPxxxr1Point {
|
||||||
|
UnsignedBigInteger::import_data(GENERATOR_POINT.data() + 1, KEY_BYTE_SIZE),
|
||||||
|
UnsignedBigInteger::import_data(GENERATOR_POINT.data() + 1 + KEY_BYTE_SIZE, KEY_BYTE_SIZE),
|
||||||
|
KEY_BYTE_SIZE,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<ByteBuffer> compute_coordinate(ReadonlyBytes scalar_bytes, ReadonlyBytes point_bytes) override
|
ErrorOr<ByteBuffer> compute_coordinate(ReadonlyBytes scalar_bytes, ReadonlyBytes point_bytes) override
|
||||||
|
@ -248,8 +283,9 @@ public:
|
||||||
auto result_point = TRY(compute_coordinate_internal(scalar_int, JacobianPoint { point_x_int, point_y_int, 1u }));
|
auto result_point = TRY(compute_coordinate_internal(scalar_int, JacobianPoint { point_x_int, point_y_int, 1u }));
|
||||||
|
|
||||||
return SECPxxxr1Point {
|
return SECPxxxr1Point {
|
||||||
.x = storage_type_to_unsigned_big_integer(result_point.x),
|
storage_type_to_unsigned_big_integer(result_point.x),
|
||||||
.y = storage_type_to_unsigned_big_integer(result_point.y),
|
storage_type_to_unsigned_big_integer(result_point.y),
|
||||||
|
KEY_BYTE_SIZE,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,6 @@
|
||||||
#include <LibCrypto/ASN1/DER.h>
|
#include <LibCrypto/ASN1/DER.h>
|
||||||
#include <LibCrypto/Certificate/Certificate.h>
|
#include <LibCrypto/Certificate/Certificate.h>
|
||||||
|
|
||||||
namespace {
|
|
||||||
// Used by ASN1 macros
|
|
||||||
static String s_error_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Crypto::PK {
|
namespace Crypto::PK {
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -23,9 +18,8 @@ ErrorOr<ByteBuffer> ECPrivateKey<IntegerType>::export_as_der() const
|
||||||
TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
|
TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
|
||||||
TRY(encoder.write(1u)); // version
|
TRY(encoder.write(1u)); // version
|
||||||
|
|
||||||
auto d_bytes = TRY(ByteBuffer::create_uninitialized(m_d.byte_length()));
|
auto d = TRY(d_bytes());
|
||||||
auto d_size = m_d.export_data(d_bytes.span());
|
TRY(encoder.write<ReadonlyBytes>(d));
|
||||||
TRY(encoder.write<ReadonlyBytes>(d_bytes.span().slice(0, d_size)));
|
|
||||||
|
|
||||||
if (m_parameters.has_value()) {
|
if (m_parameters.has_value()) {
|
||||||
TRY(encoder.write_constructed(ASN1::Class::Context, static_cast<ASN1::Kind>(0), [&]() -> ErrorOr<void> {
|
TRY(encoder.write_constructed(ASN1::Class::Context, static_cast<ASN1::Kind>(0), [&]() -> ErrorOr<void> {
|
||||||
|
@ -65,6 +59,7 @@ static ErrorOr<ECPublicKey<>> read_ec_public_key(ReadonlyBytes bytes, Vector<Str
|
||||||
return ::Crypto::PK::ECPublicKey<> {
|
return ::Crypto::PK::ECPublicKey<> {
|
||||||
UnsignedBigInteger::import_data(bytes.slice(1, half_size)),
|
UnsignedBigInteger::import_data(bytes.slice(1, half_size)),
|
||||||
UnsignedBigInteger::import_data(bytes.slice(1 + half_size, half_size)),
|
UnsignedBigInteger::import_data(bytes.slice(1 + half_size, half_size)),
|
||||||
|
half_size,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
ERROR_WITH_SCOPE("Unsupported public key format");
|
ERROR_WITH_SCOPE("Unsupported public key format");
|
||||||
|
@ -125,7 +120,7 @@ ErrorOr<EC::KeyPairType> EC::parse_ec_key(ReadonlyBytes der, bool is_private, Ve
|
||||||
|
|
||||||
keypair.public_key = maybe_public_key.release_value();
|
keypair.public_key = maybe_public_key.release_value();
|
||||||
public_key = keypair.public_key;
|
public_key = keypair.public_key;
|
||||||
if (keypair.public_key.x().byte_length() != private_key.byte_length() || keypair.public_key.y().byte_length() != private_key.byte_length()) {
|
if (keypair.public_key.scalar_size() != private_key_bytes.length()) {
|
||||||
ERROR_WITH_SCOPE("Invalid public key length");
|
ERROR_WITH_SCOPE("Invalid public key length");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +128,7 @@ ErrorOr<EC::KeyPairType> EC::parse_ec_key(ReadonlyBytes der, bool is_private, Ve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keypair.private_key = ECPrivateKey { private_key, parameters, public_key };
|
keypair.private_key = ECPrivateKey { private_key, private_key_bytes.length(), parameters, public_key };
|
||||||
|
|
||||||
EXIT_SCOPE();
|
EXIT_SCOPE();
|
||||||
return keypair;
|
return keypair;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <AK/ByteBuffer.h>
|
#include <AK/ByteBuffer.h>
|
||||||
#include <AK/StringView.h>
|
#include <AK/StringView.h>
|
||||||
#include <LibCrypto/ASN1/DER.h>
|
#include <LibCrypto/ASN1/DER.h>
|
||||||
|
#include <LibCrypto/Curves/SECPxxxr1.h>
|
||||||
#include <LibCrypto/PK/PK.h>
|
#include <LibCrypto/PK/PK.h>
|
||||||
|
|
||||||
namespace Crypto::PK {
|
namespace Crypto::PK {
|
||||||
|
@ -16,41 +17,62 @@ namespace Crypto::PK {
|
||||||
template<typename Integer = UnsignedBigInteger>
|
template<typename Integer = UnsignedBigInteger>
|
||||||
class ECPublicKey {
|
class ECPublicKey {
|
||||||
public:
|
public:
|
||||||
ECPublicKey(Integer x, Integer y)
|
ECPublicKey(Integer x, Integer y, size_t scalar_size)
|
||||||
: m_x(move(x))
|
: m_x(move(x))
|
||||||
, m_y(move(y))
|
, m_y(move(y))
|
||||||
|
, m_scalar_size(scalar_size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ECPublicKey(Curves::SECPxxxr1Point point)
|
||||||
|
: m_x(move(point.x))
|
||||||
|
, m_y(move(point.y))
|
||||||
|
, m_scalar_size(point.size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ECPublicKey()
|
ECPublicKey()
|
||||||
: m_x(0)
|
: m_x(0)
|
||||||
, m_y(0)
|
, m_y(0)
|
||||||
|
, m_scalar_size(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer const& x() const { return m_x; }
|
size_t scalar_size() const { return m_scalar_size; }
|
||||||
Integer const& y() const { return m_y; }
|
|
||||||
|
ErrorOr<ByteBuffer> x_bytes() const
|
||||||
|
{
|
||||||
|
return Curves::SECPxxxr1Point::scalar_to_bytes(m_x, m_scalar_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<ByteBuffer> y_bytes() const
|
||||||
|
{
|
||||||
|
return Curves::SECPxxxr1Point::scalar_to_bytes(m_y, m_scalar_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Curves::SECPxxxr1Point to_secpxxxr1_point() const
|
||||||
|
{
|
||||||
|
return Curves::SECPxxxr1Point { m_x, m_y, m_scalar_size };
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<ByteBuffer> to_uncompressed() const
|
ErrorOr<ByteBuffer> to_uncompressed() const
|
||||||
{
|
{
|
||||||
auto bytes = TRY(ByteBuffer::create_uninitialized(1 + m_x.byte_length() + m_y.byte_length()));
|
return to_secpxxxr1_point().to_uncompressed();
|
||||||
bytes[0] = 0x04; // uncompressed
|
|
||||||
auto x_size = m_x.export_data(bytes.span().slice(1));
|
|
||||||
auto y_size = m_y.export_data(bytes.span().slice(1 + x_size));
|
|
||||||
return bytes.slice(0, 1 + x_size + y_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Integer m_x;
|
Integer m_x;
|
||||||
Integer m_y;
|
Integer m_y;
|
||||||
|
size_t m_scalar_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://www.rfc-editor.org/rfc/rfc5915#section-3
|
// https://www.rfc-editor.org/rfc/rfc5915#section-3
|
||||||
template<typename Integer = UnsignedBigInteger>
|
template<typename Integer = UnsignedBigInteger>
|
||||||
class ECPrivateKey {
|
class ECPrivateKey {
|
||||||
public:
|
public:
|
||||||
ECPrivateKey(Integer d, Optional<Vector<int>> parameters, Optional<ECPublicKey<Integer>> public_key)
|
ECPrivateKey(Integer d, size_t scalar_size, Optional<Vector<int>> parameters, Optional<ECPublicKey<Integer>> public_key)
|
||||||
: m_d(move(d))
|
: m_d(move(d))
|
||||||
|
, m_scalar_size(scalar_size)
|
||||||
, m_parameters(parameters)
|
, m_parameters(parameters)
|
||||||
, m_public_key(public_key)
|
, m_public_key(public_key)
|
||||||
{
|
{
|
||||||
|
@ -59,6 +81,11 @@ public:
|
||||||
ECPrivateKey() = default;
|
ECPrivateKey() = default;
|
||||||
|
|
||||||
Integer const& d() const { return m_d; }
|
Integer const& d() const { return m_d; }
|
||||||
|
ErrorOr<ByteBuffer> d_bytes() const
|
||||||
|
{
|
||||||
|
return Curves::SECPxxxr1Point::scalar_to_bytes(m_d, m_scalar_size);
|
||||||
|
}
|
||||||
|
|
||||||
Optional<Vector<int> const&> parameters() const { return m_parameters; }
|
Optional<Vector<int> const&> parameters() const { return m_parameters; }
|
||||||
Optional<ECPublicKey<Integer> const&> public_key() const { return m_public_key; }
|
Optional<ECPublicKey<Integer> const&> public_key() const { return m_public_key; }
|
||||||
|
|
||||||
|
@ -66,6 +93,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Integer m_d;
|
Integer m_d;
|
||||||
|
size_t m_scalar_size;
|
||||||
|
|
||||||
Optional<Vector<int>> m_parameters;
|
Optional<Vector<int>> m_parameters;
|
||||||
Optional<ECPublicKey<Integer>> m_public_key;
|
Optional<ECPublicKey<Integer>> m_public_key;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,11 +13,6 @@
|
||||||
#include <LibCrypto/Certificate/Certificate.h>
|
#include <LibCrypto/Certificate/Certificate.h>
|
||||||
#include <LibCrypto/PK/RSA.h>
|
#include <LibCrypto/PK/RSA.h>
|
||||||
|
|
||||||
namespace {
|
|
||||||
// Used by ASN1 macros
|
|
||||||
static String s_error_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Crypto::PK {
|
namespace Crypto::PK {
|
||||||
|
|
||||||
ErrorOr<RSA::KeyPairType> RSA::parse_rsa_key(ReadonlyBytes der, bool is_private, Vector<StringView> current_scope)
|
ErrorOr<RSA::KeyPairType> RSA::parse_rsa_key(ReadonlyBytes der, bool is_private, Vector<StringView> current_scope)
|
||||||
|
|
|
@ -458,8 +458,7 @@ ssize_t TLSv12::verify_ecdsa_server_key_exchange(ReadonlyBytes server_key_info_b
|
||||||
dbgln("verify_ecdsa_server_key_exchange failed: Attempting to verify signature without certificates");
|
dbgln("verify_ecdsa_server_key_exchange failed: Attempting to verify signature without certificates");
|
||||||
return (i8)Error::NotSafe;
|
return (i8)Error::NotSafe;
|
||||||
}
|
}
|
||||||
auto server_public_key = m_context.certificates.first().public_key.ec;
|
auto server_point = m_context.certificates.first().public_key.ec.to_secpxxxr1_point();
|
||||||
auto server_point = Crypto::Curves::SECPxxxr1Point { server_public_key.x(), server_public_key.y() };
|
|
||||||
|
|
||||||
auto message_result = ByteBuffer::create_uninitialized(64 + server_key_info_buffer.size());
|
auto message_result = ByteBuffer::create_uninitialized(64 + server_key_info_buffer.size());
|
||||||
if (message_result.is_error()) {
|
if (message_result.is_error()) {
|
||||||
|
|
|
@ -371,8 +371,7 @@ bool Context::verify_certificate_pair(Certificate const& subject, Certificate co
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto public_key = issuer.public_key.ec;
|
auto public_point = issuer.public_key.ec.to_secpxxxr1_point();
|
||||||
auto public_point = Crypto::Curves::SECPxxxr1Point { public_key.x(), public_key.y() };
|
|
||||||
|
|
||||||
auto maybe_signature = Crypto::Curves::SECPxxxr1Signature::from_asn(subject.signature_value, {});
|
auto maybe_signature = Crypto::Curves::SECPxxxr1Signature::from_asn(subject.signature_value, {});
|
||||||
if (maybe_signature.is_error()) {
|
if (maybe_signature.is_error()) {
|
||||||
|
|
|
@ -2304,7 +2304,7 @@ WebIDL::ExceptionOr<Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>>> ECDSA::
|
||||||
return WebIDL::OperationError::create(m_realm, "Failed to create valid crypto instance"_string);
|
return WebIDL::OperationError::create(m_realm, "Failed to create valid crypto instance"_string);
|
||||||
|
|
||||||
auto public_key_data = maybe_public_key_data.release_value();
|
auto public_key_data = maybe_public_key_data.release_value();
|
||||||
auto ec_public_key = ::Crypto::PK::ECPublicKey<> { public_key_data.x, public_key_data.y };
|
auto ec_public_key = ::Crypto::PK::ECPublicKey<> { public_key_data };
|
||||||
|
|
||||||
// 7. Let algorithm be a new EcKeyAlgorithm object.
|
// 7. Let algorithm be a new EcKeyAlgorithm object.
|
||||||
auto algorithm = EcKeyAlgorithm::create(m_realm);
|
auto algorithm = EcKeyAlgorithm::create(m_realm);
|
||||||
|
@ -2331,7 +2331,7 @@ WebIDL::ExceptionOr<Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>>> ECDSA::
|
||||||
public_key->set_usages(usage_intersection(key_usages, { { Bindings::KeyUsage::Verify } }));
|
public_key->set_usages(usage_intersection(key_usages, { { Bindings::KeyUsage::Verify } }));
|
||||||
|
|
||||||
// 15. Let privateKey be a new CryptoKey representing the private key of the generated key pair.
|
// 15. Let privateKey be a new CryptoKey representing the private key of the generated key pair.
|
||||||
auto ec_private_key = ::Crypto::PK::ECPrivateKey<> { private_key_data, {}, ec_public_key };
|
auto ec_private_key = ::Crypto::PK::ECPrivateKey<> { private_key_data, public_key_data.size, {}, ec_public_key };
|
||||||
auto private_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { ec_private_key });
|
auto private_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { ec_private_key });
|
||||||
|
|
||||||
// 16. Set the [[type]] internal slot of privateKey to "private"
|
// 16. Set the [[type]] internal slot of privateKey to "private"
|
||||||
|
@ -2512,7 +2512,7 @@ WebIDL::ExceptionOr<JS::Value> ECDSA::verify(AlgorithmParams const& params, GC::
|
||||||
|
|
||||||
auto maybe_result = curve.visit(
|
auto maybe_result = curve.visit(
|
||||||
[](Empty const&) -> ErrorOr<bool> { return Error::from_string_literal("Failed to create valid crypto instance"); },
|
[](Empty const&) -> ErrorOr<bool> { return Error::from_string_literal("Failed to create valid crypto instance"); },
|
||||||
[&](auto instance) { return instance.verify_point(M, ::Crypto::Curves::SECPxxxr1Point { Q.x(), Q.y() }, ::Crypto::Curves::SECPxxxr1Signature { r, s }); });
|
[&](auto instance) { return instance.verify_point(M, Q.to_secpxxxr1_point(), ::Crypto::Curves::SECPxxxr1Signature { r, s }); });
|
||||||
|
|
||||||
if (maybe_result.is_error()) {
|
if (maybe_result.is_error()) {
|
||||||
auto error_message = MUST(String::from_utf8(maybe_result.error().string_literal()));
|
auto error_message = MUST(String::from_utf8(maybe_result.error().string_literal()));
|
||||||
|
@ -2839,6 +2839,7 @@ WebIDL::ExceptionOr<GC::Ref<CryptoKey>> ECDSA::import_key(AlgorithmParams const&
|
||||||
auto public_key = ::Crypto::PK::ECPublicKey<> {
|
auto public_key = ::Crypto::PK::ECPublicKey<> {
|
||||||
::Crypto::UnsignedBigInteger::import_data(x_bytes),
|
::Crypto::UnsignedBigInteger::import_data(x_bytes),
|
||||||
::Crypto::UnsignedBigInteger::import_data(y_bytes),
|
::Crypto::UnsignedBigInteger::import_data(y_bytes),
|
||||||
|
coord_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the d field is present:
|
// If the d field is present:
|
||||||
|
@ -2856,6 +2857,7 @@ WebIDL::ExceptionOr<GC::Ref<CryptoKey>> ECDSA::import_key(AlgorithmParams const&
|
||||||
// by interpreting jwk according to Section 6.2.2 of JSON Web Algorithms [JWA].
|
// by interpreting jwk according to Section 6.2.2 of JSON Web Algorithms [JWA].
|
||||||
auto private_key = ::Crypto::PK::ECPrivateKey<> {
|
auto private_key = ::Crypto::PK::ECPrivateKey<> {
|
||||||
::Crypto::UnsignedBigInteger::import_data(d_bytes),
|
::Crypto::UnsignedBigInteger::import_data(d_bytes),
|
||||||
|
coord_size,
|
||||||
{},
|
{},
|
||||||
public_key,
|
public_key,
|
||||||
};
|
};
|
||||||
|
@ -3130,46 +3132,39 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> ECDSA::export_key(Bindings::KeyFormat f
|
||||||
auto maybe_error = handle.visit(
|
auto maybe_error = handle.visit(
|
||||||
[&](::Crypto::PK::ECPublicKey<> const& public_key) -> ErrorOr<void> {
|
[&](::Crypto::PK::ECPublicKey<> const& public_key) -> ErrorOr<void> {
|
||||||
// 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA].
|
// 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA].
|
||||||
auto x_bytes = TRY(ByteBuffer::create_uninitialized(public_key.x().byte_length()));
|
auto x_bytes = TRY(public_key.x_bytes());
|
||||||
auto x_size = public_key.x().export_data(x_bytes);
|
jwk.x = TRY(encode_base64url(x_bytes, AK::OmitPadding::Yes));
|
||||||
jwk.x = TRY(encode_base64url(x_bytes.span().slice(0, x_size), AK::OmitPadding::Yes));
|
|
||||||
|
|
||||||
// 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA].
|
// 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA].
|
||||||
auto y_bytes = TRY(ByteBuffer::create_uninitialized(public_key.y().byte_length()));
|
auto y_bytes = TRY(public_key.y_bytes());
|
||||||
auto y_size = public_key.y().export_data(y_bytes);
|
jwk.y = TRY(encode_base64url(y_bytes, AK::OmitPadding::Yes));
|
||||||
jwk.y = TRY(encode_base64url(y_bytes.span().slice(0, y_size), AK::OmitPadding::Yes));
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
[&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr<void> {
|
[&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr<void> {
|
||||||
size_t coord_size;
|
|
||||||
Variant<Empty, ::Crypto::Curves::SECP256r1, ::Crypto::Curves::SECP384r1, ::Crypto::Curves::SECP521r1> curve;
|
Variant<Empty, ::Crypto::Curves::SECP256r1, ::Crypto::Curves::SECP384r1, ::Crypto::Curves::SECP521r1> curve;
|
||||||
if (algorithm.named_curve() == "P-256"sv) {
|
if (algorithm.named_curve() == "P-256"sv)
|
||||||
curve = ::Crypto::Curves::SECP256r1 {};
|
curve = ::Crypto::Curves::SECP256r1 {};
|
||||||
coord_size = 32;
|
else if (algorithm.named_curve() == "P-384"sv)
|
||||||
} else if (algorithm.named_curve() == "P-384"sv) {
|
|
||||||
curve = ::Crypto::Curves::SECP384r1 {};
|
curve = ::Crypto::Curves::SECP384r1 {};
|
||||||
coord_size = 48;
|
else if (algorithm.named_curve() == "P-521"sv)
|
||||||
} else if (algorithm.named_curve() == "P-521"sv) {
|
|
||||||
curve = ::Crypto::Curves::SECP521r1 {};
|
curve = ::Crypto::Curves::SECP521r1 {};
|
||||||
coord_size = 66;
|
else
|
||||||
} else {
|
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
|
||||||
|
|
||||||
auto maybe_public_key = curve.visit(
|
auto maybe_public_key = curve.visit(
|
||||||
[](Empty const&) -> ErrorOr<::Crypto::Curves::SECPxxxr1Point> { return Error::from_string_literal("noop error"); },
|
[](Empty const&) -> ErrorOr<::Crypto::Curves::SECPxxxr1Point> { return Error::from_string_literal("noop error"); },
|
||||||
[&](auto instance) { return instance.generate_public_key_point(private_key.d()); });
|
[&](auto instance) { return instance.generate_public_key_point(private_key.d()); });
|
||||||
|
|
||||||
auto public_key = TRY(maybe_public_key);
|
auto public_key = TRY(maybe_public_key);
|
||||||
auto public_key_bytes = TRY(public_key.to_uncompressed());
|
auto x_bytes = TRY(public_key.x_bytes());
|
||||||
VERIFY(public_key_bytes[0] == 0x04);
|
auto y_bytes = TRY(public_key.y_bytes());
|
||||||
|
|
||||||
// 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA].
|
// 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA].
|
||||||
jwk.x = TRY(encode_base64url(public_key_bytes.span().slice(1, coord_size), AK::OmitPadding::Yes));
|
jwk.x = TRY(encode_base64url(x_bytes, AK::OmitPadding::Yes));
|
||||||
|
|
||||||
// 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA].
|
// 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA].
|
||||||
jwk.y = TRY(encode_base64url(public_key_bytes.span().slice(1 + coord_size, coord_size), AK::OmitPadding::Yes));
|
jwk.y = TRY(encode_base64url(y_bytes, AK::OmitPadding::Yes));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
@ -3185,9 +3180,8 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> ECDSA::export_key(Bindings::KeyFormat f
|
||||||
auto maybe_error = handle.visit(
|
auto maybe_error = handle.visit(
|
||||||
[&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr<void> {
|
[&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr<void> {
|
||||||
// Set the d attribute of jwk according to the definition in Section 6.2.2.1 of JSON Web Algorithms [JWA].
|
// Set the d attribute of jwk according to the definition in Section 6.2.2.1 of JSON Web Algorithms [JWA].
|
||||||
auto d_bytes = TRY(ByteBuffer::create_uninitialized(private_key.d().byte_length()));
|
auto d_bytes = TRY(private_key.d_bytes());
|
||||||
auto d_size = private_key.d().export_data(d_bytes);
|
jwk.d = TRY(encode_base64url(d_bytes, AK::OmitPadding::Yes));
|
||||||
jwk.d = TRY(encode_base64url(d_bytes.span().slice(0, d_size), AK::OmitPadding::Yes));
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
@ -3320,7 +3314,7 @@ WebIDL::ExceptionOr<Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>>> ECDH::g
|
||||||
return WebIDL::OperationError::create(m_realm, "Failed to create valid crypto instance"_string);
|
return WebIDL::OperationError::create(m_realm, "Failed to create valid crypto instance"_string);
|
||||||
|
|
||||||
auto public_key_data = maybe_public_key_data.release_value();
|
auto public_key_data = maybe_public_key_data.release_value();
|
||||||
auto ec_public_key = ::Crypto::PK::ECPublicKey<> { public_key_data.x, public_key_data.y };
|
auto ec_public_key = ::Crypto::PK::ECPublicKey<> { public_key_data };
|
||||||
|
|
||||||
// 4. Let algorithm be a new EcKeyAlgorithm object.
|
// 4. Let algorithm be a new EcKeyAlgorithm object.
|
||||||
auto algorithm = EcKeyAlgorithm::create(m_realm);
|
auto algorithm = EcKeyAlgorithm::create(m_realm);
|
||||||
|
@ -3347,7 +3341,7 @@ WebIDL::ExceptionOr<Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>>> ECDH::g
|
||||||
public_key->set_usages({});
|
public_key->set_usages({});
|
||||||
|
|
||||||
// 12. Let privateKey be a new CryptoKey representing the private key of the generated key pair.
|
// 12. Let privateKey be a new CryptoKey representing the private key of the generated key pair.
|
||||||
auto ec_private_key = ::Crypto::PK::ECPrivateKey<> { private_key_data, {}, ec_public_key };
|
auto ec_private_key = ::Crypto::PK::ECPrivateKey<> { private_key_data, public_key_data.size, {}, ec_public_key };
|
||||||
auto private_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { ec_private_key });
|
auto private_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { ec_private_key });
|
||||||
|
|
||||||
// 13. Set the [[type]] internal slot of privateKey to "private"
|
// 13. Set the [[type]] internal slot of privateKey to "private"
|
||||||
|
@ -3424,7 +3418,7 @@ WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> ECDH::derive_bits(AlgorithmParams
|
||||||
|
|
||||||
auto maybe_secret = curve.visit(
|
auto maybe_secret = curve.visit(
|
||||||
[](Empty const&) -> ErrorOr<::Crypto::Curves::SECPxxxr1Point> { return Error::from_string_literal("noop error"); },
|
[](Empty const&) -> ErrorOr<::Crypto::Curves::SECPxxxr1Point> { return Error::from_string_literal("noop error"); },
|
||||||
[&private_key_data, &public_key_data](auto instance) { return instance.compute_coordinate_point(private_key_data.d(), ::Crypto::Curves::SECPxxxr1Point { public_key_data.x(), public_key_data.y() }); });
|
[&private_key_data, &public_key_data](auto instance) { return instance.compute_coordinate_point(private_key_data.d(), public_key_data.to_secpxxxr1_point()); });
|
||||||
|
|
||||||
if (maybe_secret.is_error()) {
|
if (maybe_secret.is_error()) {
|
||||||
auto message = TRY_OR_THROW_OOM(realm.vm(), String::formatted("Failed to compute secret: {}", maybe_secret.error()));
|
auto message = TRY_OR_THROW_OOM(realm.vm(), String::formatted("Failed to compute secret: {}", maybe_secret.error()));
|
||||||
|
@ -3741,6 +3735,7 @@ WebIDL::ExceptionOr<GC::Ref<CryptoKey>> ECDH::import_key(AlgorithmParams const&
|
||||||
auto public_key = ::Crypto::PK::ECPublicKey<> {
|
auto public_key = ::Crypto::PK::ECPublicKey<> {
|
||||||
::Crypto::UnsignedBigInteger::import_data(x_bytes),
|
::Crypto::UnsignedBigInteger::import_data(x_bytes),
|
||||||
::Crypto::UnsignedBigInteger::import_data(y_bytes),
|
::Crypto::UnsignedBigInteger::import_data(y_bytes),
|
||||||
|
coord_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the d field is present:
|
// If the d field is present:
|
||||||
|
@ -3758,6 +3753,7 @@ WebIDL::ExceptionOr<GC::Ref<CryptoKey>> ECDH::import_key(AlgorithmParams const&
|
||||||
// by interpreting jwk according to Section 6.2.2 of JSON Web Algorithms [JWA].
|
// by interpreting jwk according to Section 6.2.2 of JSON Web Algorithms [JWA].
|
||||||
auto private_key = ::Crypto::PK::ECPrivateKey<> {
|
auto private_key = ::Crypto::PK::ECPrivateKey<> {
|
||||||
::Crypto::UnsignedBigInteger::import_data(d_bytes),
|
::Crypto::UnsignedBigInteger::import_data(d_bytes),
|
||||||
|
coord_size,
|
||||||
{},
|
{},
|
||||||
public_key,
|
public_key,
|
||||||
};
|
};
|
||||||
|
@ -4023,46 +4019,39 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> ECDH::export_key(Bindings::KeyFormat fo
|
||||||
auto maybe_error = handle.visit(
|
auto maybe_error = handle.visit(
|
||||||
[&](::Crypto::PK::ECPublicKey<> const& public_key) -> ErrorOr<void> {
|
[&](::Crypto::PK::ECPublicKey<> const& public_key) -> ErrorOr<void> {
|
||||||
// 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA].
|
// 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA].
|
||||||
auto x_bytes = TRY(ByteBuffer::create_uninitialized(public_key.x().byte_length()));
|
auto x_bytes = TRY(public_key.x_bytes());
|
||||||
auto x_size = public_key.x().export_data(x_bytes);
|
jwk.x = TRY(encode_base64url(x_bytes, AK::OmitPadding::Yes));
|
||||||
jwk.x = TRY(encode_base64url(x_bytes.span().slice(0, x_size), AK::OmitPadding::Yes));
|
|
||||||
|
|
||||||
// 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA].
|
// 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA].
|
||||||
auto y_bytes = TRY(ByteBuffer::create_uninitialized(public_key.y().byte_length()));
|
auto y_bytes = TRY(public_key.y_bytes());
|
||||||
auto y_size = public_key.y().export_data(y_bytes);
|
jwk.y = TRY(encode_base64url(y_bytes, AK::OmitPadding::Yes));
|
||||||
jwk.y = TRY(encode_base64url(y_bytes.span().slice(0, y_size), AK::OmitPadding::Yes));
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
[&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr<void> {
|
[&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr<void> {
|
||||||
size_t coord_size;
|
|
||||||
Variant<Empty, ::Crypto::Curves::SECP256r1, ::Crypto::Curves::SECP384r1, ::Crypto::Curves::SECP521r1> curve;
|
Variant<Empty, ::Crypto::Curves::SECP256r1, ::Crypto::Curves::SECP384r1, ::Crypto::Curves::SECP521r1> curve;
|
||||||
if (algorithm.named_curve() == "P-256"sv) {
|
if (algorithm.named_curve() == "P-256"sv)
|
||||||
curve = ::Crypto::Curves::SECP256r1 {};
|
curve = ::Crypto::Curves::SECP256r1 {};
|
||||||
coord_size = 32;
|
else if (algorithm.named_curve() == "P-384"sv)
|
||||||
} else if (algorithm.named_curve() == "P-384"sv) {
|
|
||||||
curve = ::Crypto::Curves::SECP384r1 {};
|
curve = ::Crypto::Curves::SECP384r1 {};
|
||||||
coord_size = 48;
|
else if (algorithm.named_curve() == "P-521"sv)
|
||||||
} else if (algorithm.named_curve() == "P-521"sv) {
|
|
||||||
curve = ::Crypto::Curves::SECP521r1 {};
|
curve = ::Crypto::Curves::SECP521r1 {};
|
||||||
coord_size = 66;
|
else
|
||||||
} else {
|
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
|
||||||
|
|
||||||
auto maybe_public_key = curve.visit(
|
auto maybe_public_key = curve.visit(
|
||||||
[](Empty const&) -> ErrorOr<::Crypto::Curves::SECPxxxr1Point> { return Error::from_string_literal("noop error"); },
|
[](Empty const&) -> ErrorOr<::Crypto::Curves::SECPxxxr1Point> { return Error::from_string_literal("noop error"); },
|
||||||
[&](auto instance) { return instance.generate_public_key_point(private_key.d()); });
|
[&](auto instance) { return instance.generate_public_key_point(private_key.d()); });
|
||||||
|
|
||||||
auto public_key = TRY(maybe_public_key);
|
auto public_key = TRY(maybe_public_key);
|
||||||
auto public_key_bytes = TRY(public_key.to_uncompressed());
|
auto x_bytes = TRY(public_key.x_bytes());
|
||||||
VERIFY(public_key_bytes[0] == 0x04);
|
auto y_bytes = TRY(public_key.y_bytes());
|
||||||
|
|
||||||
// 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA].
|
// 2. Set the x attribute of jwk according to the definition in Section 6.2.1.2 of JSON Web Algorithms [JWA].
|
||||||
jwk.x = TRY(encode_base64url(public_key_bytes.span().slice(1, coord_size), AK::OmitPadding::Yes));
|
jwk.x = TRY(encode_base64url(x_bytes, AK::OmitPadding::Yes));
|
||||||
|
|
||||||
// 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA].
|
// 3. Set the y attribute of jwk according to the definition in Section 6.2.1.3 of JSON Web Algorithms [JWA].
|
||||||
jwk.y = TRY(encode_base64url(public_key_bytes.span().slice(1 + coord_size, coord_size), AK::OmitPadding::Yes));
|
jwk.y = TRY(encode_base64url(y_bytes, AK::OmitPadding::Yes));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
@ -4078,9 +4067,8 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> ECDH::export_key(Bindings::KeyFormat fo
|
||||||
auto maybe_error = handle.visit(
|
auto maybe_error = handle.visit(
|
||||||
[&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr<void> {
|
[&](::Crypto::PK::ECPrivateKey<> const& private_key) -> ErrorOr<void> {
|
||||||
// Set the d attribute of jwk according to the definition in Section 6.2.2.1 of JSON Web Algorithms [JWA].
|
// Set the d attribute of jwk according to the definition in Section 6.2.2.1 of JSON Web Algorithms [JWA].
|
||||||
auto d_bytes = TRY(ByteBuffer::create_uninitialized(private_key.d().byte_length()));
|
auto d_bytes = TRY(private_key.d_bytes());
|
||||||
auto d_size = private_key.d().export_data(d_bytes);
|
jwk.d = TRY(encode_base64url(d_bytes, AK::OmitPadding::Yes));
|
||||||
jwk.d = TRY(encode_base64url(d_bytes.span().slice(0, d_size), AK::OmitPadding::Yes));
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,8 +2,8 @@ Harness status: OK
|
||||||
|
|
||||||
Found 246 tests
|
Found 246 tests
|
||||||
|
|
||||||
174 Pass
|
192 Pass
|
||||||
24 Fail
|
6 Fail
|
||||||
48 Optional Feature Unsupported
|
48 Optional Feature Unsupported
|
||||||
Pass Good parameters: P-256 bits (spki, buffer(91), {name: ECDSA, namedCurve: P-256}, true, [verify])
|
Pass Good parameters: P-256 bits (spki, buffer(91), {name: ECDSA, namedCurve: P-256}, true, [verify])
|
||||||
Optional Feature Unsupported Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify])
|
Optional Feature Unsupported Good parameters: P-256 bits (spki, buffer(59, compressed), {name: ECDSA, namedCurve: P-256}, true, [verify])
|
||||||
|
@ -89,23 +89,23 @@ Pass Empty Usages: P-384 bits (pkcs8, buffer(185), {name: ECDSA, namedCurve: P-3
|
||||||
Pass Good parameters: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, [sign])
|
Pass Good parameters: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, [sign])
|
||||||
Pass Good parameters: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, [sign, sign])
|
Pass Good parameters: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, [sign, sign])
|
||||||
Pass Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, [])
|
Pass Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-384}, false, [])
|
||||||
Fail Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify])
|
Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify])
|
||||||
Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify])
|
Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify])
|
||||||
Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify])
|
Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify])
|
||||||
Fail Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify])
|
Pass Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify])
|
||||||
Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify])
|
Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify])
|
||||||
Fail Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [])
|
Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [])
|
||||||
Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [])
|
Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [])
|
||||||
Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [])
|
Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [])
|
||||||
Fail Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [])
|
Pass Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [])
|
||||||
Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [])
|
Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [])
|
||||||
Fail Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])
|
Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])
|
||||||
Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])
|
Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])
|
||||||
Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])
|
Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])
|
||||||
Fail Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])
|
Pass Good parameters: P-521 bits (raw, buffer(133), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])
|
||||||
Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])
|
Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDSA, namedCurve: P-521}, true, [verify, verify])
|
||||||
Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign])
|
Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign])
|
||||||
Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign, sign])
|
Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [sign, sign])
|
||||||
Pass Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [])
|
Pass Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDSA, namedCurve: P-521}, true, [])
|
||||||
Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign])
|
Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign])
|
||||||
Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign, sign])
|
Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDSA, namedCurve: P-521}, true, [sign, sign])
|
||||||
|
@ -211,16 +211,16 @@ Pass ECDH any JWK alg: P-384 bits (jwk, object(kty, crv, x, y, d, alg), {name: E
|
||||||
Pass Good parameters: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits])
|
Pass Good parameters: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits])
|
||||||
Pass ECDH any JWK alg: P-384 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits])
|
Pass ECDH any JWK alg: P-384 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-384}, false, [deriveKey, deriveBits, deriveKey, deriveBits])
|
||||||
Pass Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, false, [])
|
Pass Empty Usages: P-384 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-384}, false, [])
|
||||||
Fail Good parameters: P-521 bits (spki, buffer(158), {name: ECDH, namedCurve: P-521}, true, [])
|
Pass Good parameters: P-521 bits (spki, buffer(158), {name: ECDH, namedCurve: P-521}, true, [])
|
||||||
Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, true, [])
|
Optional Feature Unsupported Good parameters: P-521 bits (spki, buffer(90, compressed), {name: ECDH, namedCurve: P-521}, true, [])
|
||||||
Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDH, namedCurve: P-521}, true, [])
|
Pass Good parameters: P-521 bits (jwk, object(kty, crv, x, y), {name: ECDH, namedCurve: P-521}, true, [])
|
||||||
Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, alg), {name: ECDH, namedCurve: P-521}, true, [])
|
Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, alg), {name: ECDH, namedCurve: P-521}, true, [])
|
||||||
Fail Good parameters: P-521 bits (raw, buffer(133), {name: ECDH, namedCurve: P-521}, true, [])
|
Pass Good parameters: P-521 bits (raw, buffer(133), {name: ECDH, namedCurve: P-521}, true, [])
|
||||||
Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDH, namedCurve: P-521}, true, [])
|
Optional Feature Unsupported Good parameters: P-521 bits (raw, buffer(67, compressed), {name: ECDH, namedCurve: P-521}, true, [])
|
||||||
Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey])
|
Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey])
|
||||||
Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey])
|
Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits, deriveKey])
|
||||||
Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits])
|
Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveBits])
|
||||||
Fail Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits])
|
Pass Good parameters: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [deriveKey, deriveBits, deriveKey, deriveBits])
|
||||||
Pass Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [])
|
Pass Empty Usages: P-521 bits (pkcs8, buffer(241), {name: ECDH, namedCurve: P-521}, true, [])
|
||||||
Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey])
|
Fail Good parameters: P-521 bits (jwk, object(kty, crv, x, y, d), {name: ECDH, namedCurve: P-521}, true, [deriveKey])
|
||||||
Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveKey])
|
Pass ECDH any JWK alg: P-521 bits (jwk, object(kty, crv, x, y, d, alg), {name: ECDH, namedCurve: P-521}, true, [deriveKey])
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue