mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-22 09:12:13 -05:00
LibWeb: Add Ed448 support in WebCryptoAPI
Add full support for Ed448 and import relevant tests.
This commit is contained in:
parent
c23765c8f2
commit
b9ba1b3f72
Notes:
github-actions[bot]
2025-01-11 10:14:12 +00:00
Author: https://github.com/devgianlu Commit: https://github.com/LadybirdBrowser/ladybird/commit/b9ba1b3f725 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3009 Reviewed-by: https://github.com/ADKaster Reviewed-by: https://github.com/alimpfard Reviewed-by: https://github.com/rmg-x
15 changed files with 1521 additions and 7 deletions
|
@ -18,6 +18,7 @@
|
|||
#include <LibCrypto/Certificate/Certificate.h>
|
||||
#include <LibCrypto/Cipher/AES.h>
|
||||
#include <LibCrypto/Curves/Ed25519.h>
|
||||
#include <LibCrypto/Curves/Ed448.h>
|
||||
#include <LibCrypto/Curves/SECPxxxr1.h>
|
||||
#include <LibCrypto/Curves/X25519.h>
|
||||
#include <LibCrypto/Curves/X448.h>
|
||||
|
@ -626,6 +627,23 @@ JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> HmacKeyGenParams::from_val
|
|||
return adopt_own<AlgorithmParams>(*new HmacKeyGenParams { hash, maybe_length });
|
||||
}
|
||||
|
||||
Ed448Params::~Ed448Params() = default;
|
||||
|
||||
JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> Ed448Params::from_value(JS::VM& vm, JS::Value value)
|
||||
{
|
||||
auto& object = value.as_object();
|
||||
|
||||
auto maybe_context = Optional<ByteBuffer> {};
|
||||
if (MUST(object.has_property("context"))) {
|
||||
auto context_value = TRY(object.get("context"));
|
||||
if (!context_value.is_object() || !(is<JS::TypedArrayBase>(context_value.as_object()) || is<JS::ArrayBuffer>(context_value.as_object()) || is<JS::DataView>(context_value.as_object())))
|
||||
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "BufferSource");
|
||||
maybe_context = TRY_OR_THROW_OOM(vm, WebIDL::get_buffer_source_copy(context_value.as_object()));
|
||||
}
|
||||
|
||||
return adopt_own<AlgorithmParams>(*new Ed448Params { maybe_context });
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webcrypto/#rsa-oaep-operations
|
||||
WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> RSAOAEP::encrypt(AlgorithmParams const& params, GC::Ref<CryptoKey> key, ByteBuffer const& plaintext)
|
||||
{
|
||||
|
@ -4951,6 +4969,511 @@ WebIDL::ExceptionOr<JS::Value> ED25519::verify([[maybe_unused]] AlgorithmParams
|
|||
return JS::Value(result);
|
||||
}
|
||||
|
||||
// https://wicg.github.io/webcrypto-secure-curves/#ed448-operations
|
||||
WebIDL::ExceptionOr<Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>>> ED448::generate_key([[maybe_unused]] AlgorithmParams const& params, bool extractable, Vector<Bindings::KeyUsage> const& key_usages)
|
||||
{
|
||||
// 1. If usages contains a value which is not one of "sign" or "verify", then throw a SyntaxError.
|
||||
for (auto const& usage : key_usages) {
|
||||
if (usage != Bindings::KeyUsage::Sign && usage != Bindings::KeyUsage::Verify) {
|
||||
return WebIDL::SyntaxError::create(m_realm, MUST(String::formatted("Invalid key usage '{}'", idl_enum_to_string(usage))));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Generate an Ed448 key pair, as defined in [RFC8032], section 5.1.5.
|
||||
::Crypto::Curves::Ed448 curve;
|
||||
auto maybe_private_key = curve.generate_private_key();
|
||||
if (maybe_private_key.is_error())
|
||||
return WebIDL::OperationError::create(m_realm, "Failed to generate private key"_string);
|
||||
auto private_key_data = maybe_private_key.release_value();
|
||||
|
||||
auto maybe_public_key = curve.generate_public_key(private_key_data);
|
||||
if (maybe_public_key.is_error())
|
||||
return WebIDL::OperationError::create(m_realm, "Failed to generate public key"_string);
|
||||
auto public_key_data = maybe_public_key.release_value();
|
||||
|
||||
// 3. Let algorithm be a new KeyAlgorithm object.
|
||||
auto algorithm = KeyAlgorithm::create(m_realm);
|
||||
|
||||
// 4. Set the name attribute of algorithm to "Ed448".
|
||||
algorithm->set_name("Ed448"_string);
|
||||
|
||||
// 5. Let publicKey be a new CryptoKey associated with the relevant global object of this [HTML],
|
||||
// and representing the public key of the generated key pair.
|
||||
auto public_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { public_key_data });
|
||||
|
||||
// 6. Set the [[type]] internal slot of publicKey to "public"
|
||||
public_key->set_type(Bindings::KeyType::Public);
|
||||
|
||||
// 7. Set the [[algorithm]] internal slot of publicKey to algorithm.
|
||||
public_key->set_algorithm(algorithm);
|
||||
|
||||
// 8. Set the [[extractable]] internal slot of publicKey to true.
|
||||
public_key->set_extractable(true);
|
||||
|
||||
// 9. Set the [[usages]] internal slot of publicKey to be the usage intersection of usages and [ "verify" ].
|
||||
public_key->set_usages(usage_intersection(key_usages, { { Bindings::KeyUsage::Verify } }));
|
||||
|
||||
// 10. Let privateKey be a new CryptoKey associated with the relevant global object of this [HTML],
|
||||
// and representing the private key of the generated key pair.
|
||||
auto private_key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { private_key_data });
|
||||
|
||||
// 11. Set the [[type]] internal slot of privateKey to "private"
|
||||
private_key->set_type(Bindings::KeyType::Private);
|
||||
|
||||
// 12. Set the [[algorithm]] internal slot of privateKey to algorithm.
|
||||
private_key->set_algorithm(algorithm);
|
||||
|
||||
// 13. Set the [[extractable]] internal slot of privateKey to extractable.
|
||||
private_key->set_extractable(extractable);
|
||||
|
||||
// 14. Set the [[usages]] internal slot of privateKey to be the usage intersection of usages and [ "sign" ].
|
||||
private_key->set_usages(usage_intersection(key_usages, { { Bindings::KeyUsage::Sign } }));
|
||||
|
||||
// 15. Let result be a new CryptoKeyPair dictionary.
|
||||
// 16. Set the publicKey attribute of result to be publicKey.
|
||||
// 17. Set the privateKey attribute of result to be privateKey.
|
||||
// 18. Return the result of converting result to an ECMAScript Object, as defined by [WebIDL].
|
||||
return Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>> { CryptoKeyPair::create(m_realm, public_key, private_key) };
|
||||
}
|
||||
|
||||
// https://wicg.github.io/webcrypto-secure-curves/#ed448-operations
|
||||
WebIDL::ExceptionOr<GC::Ref<CryptoKey>> ED448::import_key(
|
||||
[[maybe_unused]] Web::Crypto::AlgorithmParams const& params,
|
||||
Bindings::KeyFormat format,
|
||||
CryptoKey::InternalKeyData key_data,
|
||||
bool extractable,
|
||||
Vector<Bindings::KeyUsage> const& usages)
|
||||
{
|
||||
GC::Ptr<CryptoKey> key = nullptr;
|
||||
|
||||
// 1. Let keyData be the key data to be imported.
|
||||
|
||||
// 2. If format is "spki":
|
||||
if (format == Bindings::KeyFormat::Spki) {
|
||||
// 1. If usages contains a value which is not "verify" then throw a SyntaxError.
|
||||
for (auto const& usage : usages) {
|
||||
if (usage != Bindings::KeyUsage::Verify) {
|
||||
return WebIDL::SyntaxError::create(m_realm, MUST(String::formatted("Invalid key usage '{}'", idl_enum_to_string(usage))));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Let spki be the result of running the parse a subjectPublicKeyInfo algorithm over keyData.
|
||||
// 3. If an error occurred while parsing, then throw a DataError.
|
||||
auto spki = TRY(parse_a_subject_public_key_info(m_realm, key_data.get<ByteBuffer>()));
|
||||
|
||||
// 4. If the algorithm object identifier field of the algorithm AlgorithmIdentifier field of spki
|
||||
// is not equal to the id-Ed448 object identifier defined in [RFC8410], then throw a DataError.
|
||||
if (spki.algorithm.identifier != ::Crypto::ASN1::ed448_oid)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid algorithm identifier"_string);
|
||||
|
||||
// 5. If the parameters field of the algorithm AlgorithmIdentifier field of spki is present, then throw a DataError.
|
||||
if (spki.algorithm.ec_parameters.has_value())
|
||||
return WebIDL::DataError::create(m_realm, "Invalid algorithm parameters"_string);
|
||||
|
||||
// 6. Let publicKey be the Ed448 public key identified by the subjectPublicKey field of spki.
|
||||
auto const& public_key = spki.raw_key;
|
||||
|
||||
// 7. Let key be a new CryptoKey associated with the relevant global object of this [HTML],
|
||||
// and that represents publicKey.
|
||||
key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { public_key });
|
||||
|
||||
// 8. Set the [[type]] internal slot of key to "public"
|
||||
key->set_type(Bindings::KeyType::Public);
|
||||
|
||||
// 9. Let algorithm be a new KeyAlgorithm.
|
||||
auto algorithm = KeyAlgorithm::create(m_realm);
|
||||
|
||||
// 10. Set the name attribute of algorithm to "Ed448".
|
||||
algorithm->set_name("Ed448"_string);
|
||||
|
||||
// 11. Set the [[algorithm]] internal slot of key to algorithm.
|
||||
key->set_algorithm(algorithm);
|
||||
}
|
||||
|
||||
// 2. If format is "pkcs8":
|
||||
else if (format == Bindings::KeyFormat::Pkcs8) {
|
||||
// 1. If usages contains a value which is not "sign" then throw a SyntaxError.
|
||||
for (auto const& usage : usages) {
|
||||
if (usage != Bindings::KeyUsage::Sign) {
|
||||
return WebIDL::SyntaxError::create(m_realm, MUST(String::formatted("Invalid key usage '{}'", idl_enum_to_string(usage))));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Let privateKeyInfo be the result of running the parse a privateKeyInfo algorithm over keyData.
|
||||
// 3. If an error occurs while parsing, then throw a DataError.
|
||||
auto private_key_info = TRY(parse_a_private_key_info(m_realm, key_data.get<ByteBuffer>()));
|
||||
|
||||
// 4. If the algorithm object identifier field of the privateKeyAlgorithm PrivateKeyAlgorithm field
|
||||
// of privateKeyInfo is not equal to the id-Ed448 object identifier defined in [RFC8410], then throw a DataError.
|
||||
if (private_key_info.algorithm.identifier != ::Crypto::ASN1::ed448_oid)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid algorithm identifier"_string);
|
||||
|
||||
// 5. If the parameters field of the privateKeyAlgorithm PrivateKeyAlgorithmIdentifier field of privateKeyInfo is present,
|
||||
// then throw a DataError.
|
||||
if (private_key_info.algorithm.ec_parameters.has_value())
|
||||
return WebIDL::DataError::create(m_realm, "Invalid algorithm parameters"_string);
|
||||
|
||||
// 6. Let curvePrivateKey be the result of performing the parse an ASN.1 structure algorithm,
|
||||
// with data as the privateKey field of privateKeyInfo, structure as the ASN.1 CurvePrivateKey structure
|
||||
// specified in Section 7 of [RFC8410], and exactData set to true.
|
||||
// 7. If an error occurred while parsing, then throw a DataError.
|
||||
auto curve_private_key = TRY(parse_an_ASN1_structure<StringView>(m_realm, private_key_info.raw_key, true));
|
||||
auto curve_private_key_bytes = TRY_OR_THROW_OOM(m_realm->vm(), ByteBuffer::copy(curve_private_key.bytes()));
|
||||
|
||||
// 8. Let key be a new CryptoKey associated with the relevant global object of this [HTML],
|
||||
// and that represents the Ed448 private key identified by curvePrivateKey.
|
||||
key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { curve_private_key_bytes });
|
||||
|
||||
// 9. Set the [[type]] internal slot of key to "private"
|
||||
key->set_type(Bindings::KeyType::Private);
|
||||
|
||||
// 10. Let algorithm be a new KeyAlgorithm.
|
||||
auto algorithm = KeyAlgorithm::create(m_realm);
|
||||
|
||||
// 11. Set the name attribute of algorithm to "Ed448".
|
||||
algorithm->set_name("Ed448"_string);
|
||||
|
||||
// 12. Set the [[algorithm]] internal slot of key to algorithm.
|
||||
key->set_algorithm(algorithm);
|
||||
}
|
||||
|
||||
// 2. If format is "jwk":
|
||||
else if (format == Bindings::KeyFormat::Jwk) {
|
||||
// 1. If keyData is a JsonWebKey dictionary: Let jwk equal keyData.
|
||||
// Otherwise: Throw a DataError.
|
||||
if (!key_data.has<Bindings::JsonWebKey>())
|
||||
return WebIDL::DataError::create(m_realm, "keyData is not a JsonWebKey dictionary"_string);
|
||||
auto& jwk = key_data.get<Bindings::JsonWebKey>();
|
||||
|
||||
// 2. If the d field is present and usages contains a value which is not "sign",
|
||||
// or, if the d field is not present and usages contains a value which is not "verify" then throw a SyntaxError.
|
||||
if (jwk.d.has_value()) {
|
||||
for (auto const& usage : usages) {
|
||||
if (usage != Bindings::KeyUsage::Sign) {
|
||||
return WebIDL::SyntaxError::create(m_realm, MUST(String::formatted("Invalid key usage '{}'", idl_enum_to_string(usage))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto const& usage : usages) {
|
||||
if (usage != Bindings::KeyUsage::Verify) {
|
||||
return WebIDL::SyntaxError::create(m_realm, MUST(String::formatted("Invalid key usage '{}'", idl_enum_to_string(usage))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. If the kty field of jwk is not "OKP", then throw a DataError.
|
||||
if (jwk.kty != "OKP"sv)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid key type"_string);
|
||||
|
||||
// 4. If the crv field of jwk is not "Ed448", then throw a DataError.
|
||||
if (jwk.crv != "Ed448"sv)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid curve"_string);
|
||||
|
||||
// 5. If usages is non-empty and the use field of jwk is present and is not "sig", then throw a DataError.
|
||||
if (!usages.is_empty() && jwk.use.has_value() && jwk.use.value() != "sig")
|
||||
return WebIDL::DataError::create(m_realm, "Invalid key usage"_string);
|
||||
|
||||
// 6. If the key_ops field of jwk is present, and is invalid according to the requirements of JSON Web Key [JWK],
|
||||
// or it does not contain all of the specified usages values, then throw a DataError.
|
||||
TRY(validate_jwk_key_ops(m_realm, jwk, usages));
|
||||
|
||||
// 7. If the ext field of jwk is present and has the value false and extractable is true, then throw a DataError.
|
||||
if (jwk.ext.has_value() && !jwk.ext.value() && extractable)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid extractable"_string);
|
||||
|
||||
// 8. If the d field is present:
|
||||
if (jwk.d.has_value()) {
|
||||
// 1. If jwk does not meet the requirements of the JWK private key format described in Section 2 of [RFC8037],
|
||||
// then throw a DataError.
|
||||
// o The parameter "kty" MUST be "OKP".
|
||||
if (jwk.kty != "OKP"sv)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid key type"_string);
|
||||
|
||||
// https://www.iana.org/assignments/jose/jose.xhtml#web-key-elliptic-curve
|
||||
// o The parameter "crv" MUST be present and contain the subtype of the key (from the "JSON Web Elliptic Curve" registry).
|
||||
if (jwk.crv != "Ed448"sv)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid curve"_string);
|
||||
|
||||
// o The parameter "x" MUST be present and contain the public key encoded using the base64url [RFC4648] encoding.
|
||||
if (!jwk.x.has_value())
|
||||
return WebIDL::DataError::create(m_realm, "Missing x field"_string);
|
||||
|
||||
// o The parameter "d" MUST be present for private keys and contain the private key encoded using the base64url encoding.
|
||||
// This parameter MUST NOT be present for public keys.
|
||||
if (!jwk.d.has_value())
|
||||
return WebIDL::DataError::create(m_realm, "Present d field"_string);
|
||||
|
||||
// 2. Let key be a new CryptoKey object that represents the Ed448 private key identified by interpreting jwk according to Section 2 of [RFC8037].
|
||||
auto private_key_base_64 = jwk.d.value();
|
||||
auto private_key_or_error = decode_base64url(private_key_base_64);
|
||||
if (private_key_or_error.is_error()) {
|
||||
return WebIDL::DataError::create(m_realm, "Failed to decode base64"_string);
|
||||
}
|
||||
auto private_key = private_key_or_error.release_value();
|
||||
key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { private_key });
|
||||
|
||||
// 3. Set the [[type]] internal slot of Key to "private".
|
||||
key->set_type(Bindings::KeyType::Private);
|
||||
}
|
||||
// Otherwise:
|
||||
else {
|
||||
// 1. If jwk does not meet the requirements of the JWK public key format described in Section 2 of [RFC8037], then throw a DataError.
|
||||
// o The parameter "kty" MUST be "OKP".
|
||||
if (jwk.kty != "OKP"sv)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid key type"_string);
|
||||
|
||||
// https://www.iana.org/assignments/jose/jose.xhtml#web-key-elliptic-curve
|
||||
// o The parameter "crv" MUST be present and contain the subtype of the key (from the "JSON Web Elliptic Curve" registry).
|
||||
if (jwk.crv != "Ed448"sv)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid curve"_string);
|
||||
|
||||
// o The parameter "x" MUST be present and contain the public key encoded using the base64url [RFC4648] encoding.
|
||||
if (!jwk.x.has_value())
|
||||
return WebIDL::DataError::create(m_realm, "Missing x field"_string);
|
||||
|
||||
// o The parameter "d" MUST be present for private keys and contain the private key encoded using the base64url encoding.
|
||||
// This parameter MUST NOT be present for public keys.
|
||||
if (jwk.d.has_value())
|
||||
return WebIDL::DataError::create(m_realm, "Present d field"_string);
|
||||
|
||||
// 2. Let key be a new CryptoKey object that represents the Ed448 public key identified by interpreting jwk according to Section 2 of [RFC8037].
|
||||
auto public_key_base_64 = jwk.x.value();
|
||||
auto public_key_or_error = decode_base64url(public_key_base_64);
|
||||
if (public_key_or_error.is_error()) {
|
||||
return WebIDL::DataError::create(m_realm, "Failed to decode base64"_string);
|
||||
}
|
||||
auto public_key = public_key_or_error.release_value();
|
||||
key = CryptoKey::create(m_realm, CryptoKey::InternalKeyData { public_key });
|
||||
|
||||
// 3. Set the [[type]] internal slot of Key to "public".
|
||||
key->set_type(Bindings::KeyType::Public);
|
||||
}
|
||||
|
||||
// 9. Let algorithm be a new instance of a KeyAlgorithm object.
|
||||
auto algorithm = KeyAlgorithm::create(m_realm);
|
||||
|
||||
// 10. Set the name attribute of algorithm to "Ed448".
|
||||
algorithm->set_name("Ed448"_string);
|
||||
|
||||
// 11. Set the [[algorithm]] internal slot of key to algorithm.
|
||||
key->set_algorithm(algorithm);
|
||||
}
|
||||
|
||||
// 2. If format is "raw":
|
||||
else if (format == Bindings::KeyFormat::Raw) {
|
||||
// 1. If usages contains a value which is not "verify" then throw a SyntaxError.
|
||||
for (auto const& usage : usages) {
|
||||
if (usage != Bindings::KeyUsage::Verify) {
|
||||
return WebIDL::SyntaxError::create(m_realm, MUST(String::formatted("Invalid key usage '{}'", idl_enum_to_string(usage))));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Let algorithm be a new KeyAlgorithm object.
|
||||
auto algorithm = KeyAlgorithm::create(m_realm);
|
||||
|
||||
// 3. Set the name attribute of algorithm to "Ed448".
|
||||
algorithm->set_name("Ed448"_string);
|
||||
|
||||
// 4. Let key be a new CryptoKey associated with the relevant global object of this [HTML], and representing the key data provided in keyData.
|
||||
key = CryptoKey::create(m_realm, key_data);
|
||||
|
||||
// 5. Set the [[type]] internal slot of key to "public"
|
||||
key->set_type(Bindings::KeyType::Public);
|
||||
|
||||
// 6. Set the [[algorithm]] internal slot of key to algorithm.
|
||||
key->set_algorithm(algorithm);
|
||||
}
|
||||
|
||||
// 2. Otherwise:
|
||||
else {
|
||||
// throw a NotSupportedError.
|
||||
return WebIDL::NotSupportedError::create(m_realm, "Invalid key format"_string);
|
||||
}
|
||||
|
||||
return GC::Ref { *key };
|
||||
}
|
||||
|
||||
// https://wicg.github.io/webcrypto-secure-curves/#ed448-operations
|
||||
WebIDL::ExceptionOr<GC::Ref<JS::Object>> ED448::export_key(Bindings::KeyFormat format, GC::Ref<CryptoKey> key)
|
||||
{
|
||||
auto& vm = m_realm->vm();
|
||||
|
||||
// 1. Let key be the CryptoKey to be exported.
|
||||
|
||||
// 2. If the underlying cryptographic key material represented by the [[handle]] internal slot of key cannot be accessed, then throw an OperationError.
|
||||
// Note: In our impl this is always accessible
|
||||
auto const& key_data = key->handle().get<ByteBuffer>();
|
||||
|
||||
// 3. If format is "spki":
|
||||
if (format == Bindings::KeyFormat::Spki) {
|
||||
// 1. If the [[type]] internal slot of key is not "public", then throw an InvalidAccessError.
|
||||
if (key->type() != Bindings::KeyType::Public)
|
||||
return WebIDL::InvalidAccessError::create(m_realm, "Key is not a public key"_string);
|
||||
|
||||
// 2. Let data be an instance of the subjectPublicKeyInfo ASN.1 structure defined in [RFC5280] with the following properties:
|
||||
// * Set the algorithm field to an AlgorithmIdentifier ASN.1 type with the following properties:
|
||||
// * Set the algorithm object identifier to the id-Ed448 OID defined in [RFC8410].
|
||||
// * Set the subjectPublicKey field to keyData.
|
||||
auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_subject_public_key_info(key_data, ::Crypto::ASN1::ed448_oid));
|
||||
|
||||
// 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
|
||||
return JS::ArrayBuffer::create(m_realm, move(data));
|
||||
}
|
||||
|
||||
// 3. If format is "pkcs8":
|
||||
if (format == Bindings::KeyFormat::Pkcs8) {
|
||||
// 1. If the [[type]] internal slot of key is not "private", then throw an InvalidAccessError.
|
||||
if (key->type() != Bindings::KeyType::Private)
|
||||
return WebIDL::InvalidAccessError::create(m_realm, "Key is not a private key"_string);
|
||||
|
||||
// 2. Let data be an instance of the privateKeyInfo ASN.1 structure defined in [RFC5208] with the following properties:
|
||||
// * Set the version field to 0.
|
||||
// * Set the privateKeyAlgorithm field to a PrivateKeyAlgorithmIdentifier ASN.1 type with the following properties:
|
||||
// * Set the algorithm object identifier to the id-Ed448 OID defined in [RFC8410].
|
||||
// * Set the privateKey field to the result of DER-encoding a CurvePrivateKey ASN.1 type,
|
||||
// as defined in Section 7 of [RFC8410], that represents the Ed448 private key
|
||||
// represented by the [[handle]] internal slot of key
|
||||
::Crypto::ASN1::Encoder encoder;
|
||||
TRY_OR_THROW_OOM(vm, encoder.write(key_data.bytes()));
|
||||
|
||||
auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_private_key_info(encoder.finish(), ::Crypto::ASN1::ed448_oid));
|
||||
|
||||
// 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
|
||||
return JS::ArrayBuffer::create(m_realm, move(data));
|
||||
}
|
||||
|
||||
// 2. If format is "jwk":
|
||||
if (format == Bindings::KeyFormat::Jwk) {
|
||||
// 1. Let jwk be a new JsonWebKey dictionary.
|
||||
Bindings::JsonWebKey jwk;
|
||||
|
||||
// 2. Set the kty attribute of jwk to "OKP".
|
||||
jwk.kty = "OKP"_string;
|
||||
|
||||
// 3. Set the crv attribute of jwk to "Ed448".
|
||||
jwk.crv = "Ed448"_string;
|
||||
|
||||
// 4. Set the x attribute of jwk according to the definition in Section 2 of [RFC8037].
|
||||
if (key->type() == Bindings::KeyType::Public) {
|
||||
jwk.x = TRY_OR_THROW_OOM(vm, encode_base64url(key_data, AK::OmitPadding::Yes));
|
||||
} else {
|
||||
// The "x" parameter of the "epk" field is set as follows:
|
||||
// Apply the appropriate ECDH function to the ephemeral private key (as scalar input)
|
||||
// and the standard base point (as u-coordinate input).
|
||||
// The base64url encoding of the output is the value for the "x" parameter of the "epk" field.
|
||||
::Crypto::Curves::Ed448 curve;
|
||||
auto public_key = TRY_OR_THROW_OOM(vm, curve.generate_public_key(key_data));
|
||||
jwk.x = TRY_OR_THROW_OOM(vm, encode_base64url(public_key, AK::OmitPadding::Yes));
|
||||
}
|
||||
|
||||
// 5. If the [[type]] internal slot of key is "private"
|
||||
if (key->type() == Bindings::KeyType::Private) {
|
||||
// 1. Set the d attribute of jwk according to the definition in Section 2 of [RFC8037].
|
||||
jwk.d = TRY_OR_THROW_OOM(vm, encode_base64url(key_data, AK::OmitPadding::Yes));
|
||||
}
|
||||
|
||||
// 6. Set the key_ops attribute of jwk to the usages attribute of key.
|
||||
jwk.key_ops = Vector<String> {};
|
||||
jwk.key_ops->ensure_capacity(key->internal_usages().size());
|
||||
for (auto const& usage : key->internal_usages())
|
||||
jwk.key_ops->append(Bindings::idl_enum_to_string(usage));
|
||||
|
||||
// 7. Set the ext attribute of jwk to the [[extractable]] internal slot of key.
|
||||
jwk.ext = key->extractable();
|
||||
|
||||
// 8. Let result be the result of converting jwk to an ECMAScript Object, as defined by [WebIDL].
|
||||
return TRY(jwk.to_object(m_realm));
|
||||
}
|
||||
|
||||
// 2. If format is "raw":
|
||||
if (format == Bindings::KeyFormat::Raw) {
|
||||
// 1. If the [[type]] internal slot of key is not "public", then throw an InvalidAccessError.
|
||||
if (key->type() != Bindings::KeyType::Public)
|
||||
return WebIDL::InvalidAccessError::create(m_realm, "Key is not a public key"_string);
|
||||
|
||||
// 2. Let data be an octet string representing the Ed448 public key represented by the [[handle]] internal slot of key.
|
||||
// 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
|
||||
return JS::ArrayBuffer::create(m_realm, key_data);
|
||||
}
|
||||
|
||||
// 2. Otherwise:
|
||||
// throw a NotSupportedError.
|
||||
return WebIDL::NotSupportedError::create(m_realm, "Invalid key format"_string);
|
||||
}
|
||||
|
||||
// https://wicg.github.io/webcrypto-secure-curves/#ed448-operations
|
||||
WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> ED448::sign(AlgorithmParams const& params, GC::Ref<CryptoKey> key, ByteBuffer const& message)
|
||||
{
|
||||
auto& realm = *m_realm;
|
||||
|
||||
// 1. If the [[type]] internal slot of key is not "private", then throw an InvalidAccessError.
|
||||
if (key->type() != Bindings::KeyType::Private)
|
||||
return WebIDL::InvalidAccessError::create(realm, "Key is not a private key"_string);
|
||||
|
||||
// 2. Let context be the contents of the context member of normalizedAlgorithm
|
||||
// or the empty octet string if the context member of normalizedAlgorithm is not present.
|
||||
auto const& algorithm = static_cast<Ed448Params const&>(params);
|
||||
auto context = algorithm.context.value_or(ByteBuffer());
|
||||
|
||||
// 3. If context has a length greater than 255 bytes, then throw an OperationError.
|
||||
if (context.size() > 255)
|
||||
return WebIDL::OperationError::create(realm, "Context is too long"_string);
|
||||
|
||||
// 4. Perform the Ed448 signing process, as specified in [RFC8032], Section 5.2.6,
|
||||
// with message as M and context as C, using the Ed448 private key associated with key.
|
||||
::Crypto::Curves::Ed448 curve;
|
||||
auto maybe_signature = curve.sign(key->handle().get<ByteBuffer>(), message, context);
|
||||
if (maybe_signature.is_error()) {
|
||||
return WebIDL::OperationError::create(realm, "Failed to sign message"_string);
|
||||
}
|
||||
|
||||
// 5. Return a new ArrayBuffer associated with the relevant global object of this [HTML],
|
||||
// and containing the bytes of the signature resulting from performing the Ed448 signing process.
|
||||
return JS::ArrayBuffer::create(m_realm, maybe_signature.release_value());
|
||||
}
|
||||
|
||||
// https://wicg.github.io/webcrypto-secure-curves/#ed448-operations
|
||||
WebIDL::ExceptionOr<JS::Value> ED448::verify(AlgorithmParams const& params, GC::Ref<CryptoKey> key, ByteBuffer const& signature, ByteBuffer const& message)
|
||||
{
|
||||
auto& realm = *m_realm;
|
||||
|
||||
// 1. If the [[type]] internal slot of key is not "public", then throw an InvalidAccessError.
|
||||
if (key->type() != Bindings::KeyType::Public)
|
||||
return WebIDL::InvalidAccessError::create(realm, "Key is not a public key"_string);
|
||||
|
||||
// 2. Let context be the contents of the context member of normalizedAlgorithm
|
||||
// or the empty octet string if the context member of normalizedAlgorithm is not present.
|
||||
auto const& algorithm = static_cast<Ed448Params const&>(params);
|
||||
auto context = algorithm.context.value_or(ByteBuffer());
|
||||
|
||||
// 3. If context has a length greater than 255 bytes, then throw an OperationError.
|
||||
if (context.size() > 255)
|
||||
return WebIDL::OperationError::create(realm, "Context is too long"_string);
|
||||
|
||||
// 4. If the key data of key represents an invalid point or a small-order element
|
||||
// on the Elliptic Curve of Ed448, return false.
|
||||
// NOTE: https://github.com/WICG/webcrypto-secure-curves/issues/27
|
||||
|
||||
// 5. If the point R, encoded in the first half of signature, represents an invalid point
|
||||
// or a small-order element on the Elliptic Curve of Ed448, return false.
|
||||
// NOTE: https://github.com/WICG/webcrypto-secure-curves/issues/27
|
||||
|
||||
// 6. Perform the Ed448 verification steps, as specified in [RFC8032], Section 5.2.7, using
|
||||
// the cofactorless (unbatched) equation, [S]B = R + [k]A', on the signature,
|
||||
// with message as M and context as C, using the Ed448 public key associated with key.
|
||||
::Crypto::Curves::Ed448 curve;
|
||||
auto maybe_verified = curve.verify(key->handle().get<ByteBuffer>(), signature, message, context);
|
||||
if (maybe_verified.is_error()) {
|
||||
auto error_message = MUST(String::from_utf8(maybe_verified.error().string_literal()));
|
||||
return WebIDL::OperationError::create(realm, error_message);
|
||||
}
|
||||
|
||||
// 7. Let result be a boolean with the value true if the signature is valid
|
||||
// and the value false otherwise.
|
||||
// 8. Return result.
|
||||
return maybe_verified.release_value();
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webcrypto/#hkdf-operations
|
||||
WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> HKDF::derive_bits(AlgorithmParams const& params, GC::Ref<CryptoKey> key, Optional<u32> length_optional)
|
||||
{
|
||||
|
|
|
@ -544,6 +544,24 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
class ED448 : public AlgorithmMethods {
|
||||
public:
|
||||
virtual WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> sign(AlgorithmParams const&, GC::Ref<CryptoKey>, ByteBuffer const&) override;
|
||||
virtual WebIDL::ExceptionOr<JS::Value> verify(AlgorithmParams const&, GC::Ref<CryptoKey>, ByteBuffer const&, ByteBuffer const&) override;
|
||||
|
||||
virtual WebIDL::ExceptionOr<Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
|
||||
virtual WebIDL::ExceptionOr<GC::Ref<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&) override;
|
||||
virtual WebIDL::ExceptionOr<GC::Ref<JS::Object>> export_key(Bindings::KeyFormat, GC::Ref<CryptoKey>) override;
|
||||
|
||||
static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new ED448(realm)); }
|
||||
|
||||
private:
|
||||
explicit ED448(JS::Realm& realm)
|
||||
: AlgorithmMethods(realm)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class X25519 : public AlgorithmMethods {
|
||||
public:
|
||||
virtual WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> derive_bits(AlgorithmParams const&, GC::Ref<CryptoKey>, Optional<u32>) override;
|
||||
|
@ -620,6 +638,20 @@ struct EcKeyImportParams : public AlgorithmParams {
|
|||
static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
|
||||
};
|
||||
|
||||
// https://wicg.github.io/webcrypto-secure-curves/#dfn-Ed448Params
|
||||
struct Ed448Params : public AlgorithmParams {
|
||||
virtual ~Ed448Params() override;
|
||||
|
||||
Ed448Params(Optional<ByteBuffer>& context)
|
||||
: context(context)
|
||||
{
|
||||
}
|
||||
|
||||
Optional<ByteBuffer> context;
|
||||
|
||||
static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
|
||||
};
|
||||
|
||||
ErrorOr<String> base64_url_uint_encode(::Crypto::UnsignedBigInteger);
|
||||
WebIDL::ExceptionOr<ByteBuffer> base64_url_bytes_decode(JS::Realm&, String const& base64_url_string);
|
||||
WebIDL::ExceptionOr<::Crypto::UnsignedBigInteger> base64_url_uint_decode(JS::Realm&, String const& base64_url_string);
|
||||
|
|
|
@ -1181,11 +1181,11 @@ SupportedAlgorithmsMap const& supported_algorithms()
|
|||
define_an_algorithm<ED25519>("exportKey"_string, "Ed25519"_string);
|
||||
|
||||
// https://wicg.github.io/webcrypto-secure-curves/#ed448-registration
|
||||
// FIXME: define_an_algorithm<ED448, Ed448Params>("sign"_string, "Ed448"_string);
|
||||
// FIXME: define_an_algorithm<ED448, Ed448Params>("verify"_string, "Ed448"_string);
|
||||
// FIXME: define_an_algorithm<ED448>("generateKey"_string, "Ed448"_string);
|
||||
// FIXME: define_an_algorithm<ED448>("importKey"_string, "Ed448"_string);
|
||||
// FIXME: define_an_algorithm<ED448>("exportKey"_string, "Ed448"_string);
|
||||
define_an_algorithm<ED448, Ed448Params>("sign"_string, "Ed448"_string);
|
||||
define_an_algorithm<ED448, Ed448Params>("verify"_string, "Ed448"_string);
|
||||
define_an_algorithm<ED448>("generateKey"_string, "Ed448"_string);
|
||||
define_an_algorithm<ED448>("importKey"_string, "Ed448"_string);
|
||||
define_an_algorithm<ED448>("exportKey"_string, "Ed448"_string);
|
||||
|
||||
return internal_object;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,391 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 386 tests
|
||||
|
||||
386 Pass
|
||||
Pass Bad algorithm: generateKey(AES, false, [decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, true, [decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, RED, [decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, 7, [decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, false, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, true, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, RED, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, 7, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, false, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, true, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, RED, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, 7, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, false, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, true, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, RED, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, 7, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey(AES, false, [sign])
|
||||
Pass Bad algorithm: generateKey(AES, true, [sign])
|
||||
Pass Bad algorithm: generateKey(AES, RED, [sign])
|
||||
Pass Bad algorithm: generateKey(AES, 7, [sign])
|
||||
Pass Bad algorithm: generateKey(AES, false, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey(AES, true, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey(AES, RED, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey(AES, 7, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey(AES, false, [deriveBits])
|
||||
Pass Bad algorithm: generateKey(AES, true, [deriveBits])
|
||||
Pass Bad algorithm: generateKey(AES, RED, [deriveBits])
|
||||
Pass Bad algorithm: generateKey(AES, 7, [deriveBits])
|
||||
Pass Bad algorithm: generateKey(AES, false, [])
|
||||
Pass Bad algorithm: generateKey(AES, true, [])
|
||||
Pass Bad algorithm: generateKey(AES, RED, [])
|
||||
Pass Bad algorithm: generateKey(AES, 7, [])
|
||||
Pass Bad algorithm: generateKey(AES, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey(AES, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey(AES, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey(AES, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: AES}, false, [decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, true, [decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, RED, [decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, 7, [decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, false, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, true, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, RED, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, 7, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, false, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, true, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, RED, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, 7, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, false, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, true, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, RED, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, 7, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: AES}, false, [sign])
|
||||
Pass Bad algorithm: generateKey({name: AES}, true, [sign])
|
||||
Pass Bad algorithm: generateKey({name: AES}, RED, [sign])
|
||||
Pass Bad algorithm: generateKey({name: AES}, 7, [sign])
|
||||
Pass Bad algorithm: generateKey({name: AES}, false, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({name: AES}, true, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({name: AES}, RED, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({name: AES}, 7, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({name: AES}, false, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: AES}, true, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: AES}, RED, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: AES}, 7, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: AES}, false, [])
|
||||
Pass Bad algorithm: generateKey({name: AES}, true, [])
|
||||
Pass Bad algorithm: generateKey({name: AES}, RED, [])
|
||||
Pass Bad algorithm: generateKey({name: AES}, 7, [])
|
||||
Pass Bad algorithm: generateKey({name: AES}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: AES}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: AES}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: AES}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CMAC}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({length: 128, name: AES-CFB}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: MD5, name: HMAC}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA-256, modulusLength: 2048, name: RSA, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({hash: SHA, modulusLength: 2048, name: RSA-PSS, publicExponent: {0: 1, 1: 0, 2: 1}}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [deriveBits, sign, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [deriveBits, decrypt])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [sign])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [sign])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [sign])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [sign])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [deriveBits, sign])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad algorithm: generateKey({name: EC, namedCurve: P521}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Empty algorithm: generateKey({}, false, [decrypt])
|
||||
Pass Empty algorithm: generateKey({}, true, [decrypt])
|
||||
Pass Empty algorithm: generateKey({}, RED, [decrypt])
|
||||
Pass Empty algorithm: generateKey({}, 7, [decrypt])
|
||||
Pass Empty algorithm: generateKey({}, false, [sign, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, true, [sign, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, RED, [sign, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, 7, [sign, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, false, [deriveBits, sign, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, true, [deriveBits, sign, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, RED, [deriveBits, sign, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, 7, [deriveBits, sign, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, false, [deriveBits, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, true, [deriveBits, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, RED, [deriveBits, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, 7, [deriveBits, decrypt])
|
||||
Pass Empty algorithm: generateKey({}, false, [sign])
|
||||
Pass Empty algorithm: generateKey({}, true, [sign])
|
||||
Pass Empty algorithm: generateKey({}, RED, [sign])
|
||||
Pass Empty algorithm: generateKey({}, 7, [sign])
|
||||
Pass Empty algorithm: generateKey({}, false, [deriveBits, sign])
|
||||
Pass Empty algorithm: generateKey({}, true, [deriveBits, sign])
|
||||
Pass Empty algorithm: generateKey({}, RED, [deriveBits, sign])
|
||||
Pass Empty algorithm: generateKey({}, 7, [deriveBits, sign])
|
||||
Pass Empty algorithm: generateKey({}, false, [deriveBits])
|
||||
Pass Empty algorithm: generateKey({}, true, [deriveBits])
|
||||
Pass Empty algorithm: generateKey({}, RED, [deriveBits])
|
||||
Pass Empty algorithm: generateKey({}, 7, [deriveBits])
|
||||
Pass Empty algorithm: generateKey({}, false, [])
|
||||
Pass Empty algorithm: generateKey({}, true, [])
|
||||
Pass Empty algorithm: generateKey({}, RED, [])
|
||||
Pass Empty algorithm: generateKey({}, 7, [])
|
||||
Pass Empty algorithm: generateKey({}, false, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Empty algorithm: generateKey({}, true, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Empty algorithm: generateKey({}, RED, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Empty algorithm: generateKey({}, 7, [decrypt, sign, deriveBits, decrypt, sign, deriveBits])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [encrypt])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, encrypt])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [verify, sign, encrypt])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, verify, sign, sign, verify, encrypt])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [decrypt])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, decrypt])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [verify, sign, decrypt])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, verify, sign, sign, verify, decrypt])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [wrapKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, wrapKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [verify, sign, wrapKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, verify, sign, sign, verify, wrapKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [unwrapKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, unwrapKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [verify, sign, unwrapKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, verify, sign, sign, verify, unwrapKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [deriveKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, deriveKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [verify, sign, deriveKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, verify, sign, sign, verify, deriveKey])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [deriveBits])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, deriveBits])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [verify, sign, deriveBits])
|
||||
Pass Bad usages: generateKey({name: Ed448}, true, [sign, verify, sign, sign, verify, deriveBits])
|
||||
Pass Empty usages: generateKey({name: Ed448}, false, [])
|
||||
Pass Empty usages: generateKey({name: Ed448}, true, [])
|
|
@ -0,0 +1,23 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 18 tests
|
||||
|
||||
18 Pass
|
||||
Pass Success: generateKey({name: ED448}, false, [sign])
|
||||
Pass Success: generateKey({name: ED448}, true, [sign])
|
||||
Pass Success: generateKey({name: ED448}, false, [verify, sign])
|
||||
Pass Success: generateKey({name: ED448}, true, [verify, sign])
|
||||
Pass Success: generateKey({name: ED448}, false, [sign, verify, sign, sign, verify])
|
||||
Pass Success: generateKey({name: ED448}, true, [sign, verify, sign, sign, verify])
|
||||
Pass Success: generateKey({name: ed448}, false, [sign])
|
||||
Pass Success: generateKey({name: ed448}, true, [sign])
|
||||
Pass Success: generateKey({name: ed448}, false, [verify, sign])
|
||||
Pass Success: generateKey({name: ed448}, true, [verify, sign])
|
||||
Pass Success: generateKey({name: ed448}, false, [sign, verify, sign, sign, verify])
|
||||
Pass Success: generateKey({name: ed448}, true, [sign, verify, sign, sign, verify])
|
||||
Pass Success: generateKey({name: Ed448}, false, [sign])
|
||||
Pass Success: generateKey({name: Ed448}, true, [sign])
|
||||
Pass Success: generateKey({name: Ed448}, false, [verify, sign])
|
||||
Pass Success: generateKey({name: Ed448}, true, [verify, sign])
|
||||
Pass Success: generateKey({name: Ed448}, false, [sign, verify, sign, sign, verify])
|
||||
Pass Success: generateKey({name: Ed448}, true, [sign, verify, sign, sign, verify])
|
|
@ -0,0 +1,18 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 13 tests
|
||||
|
||||
13 Pass
|
||||
Pass EdDSA Ed448 verification
|
||||
Pass EdDSA Ed448 verification with altered signature after call
|
||||
Pass EdDSA Ed448 with altered data after call
|
||||
Pass EdDSA Ed448 using privateKey to verify
|
||||
Pass EdDSA Ed448 using publicKey to sign
|
||||
Pass EdDSA Ed448 no verify usage
|
||||
Pass EdDSA Ed448 round trip
|
||||
Pass EdDSA Ed448 signing with wrong algorithm name
|
||||
Pass EdDSA Ed448 verifying with wrong algorithm name
|
||||
Pass EdDSA Ed448 verification failure due to altered signature
|
||||
Pass EdDSA Ed448 verification failure due to shortened signature
|
||||
Pass EdDSA Ed448 verification failure due to altered data
|
||||
Pass Sign and verify using generated Ed448 keys.
|
|
@ -1,8 +1,8 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 281 tests
|
||||
Found 309 tests
|
||||
|
||||
281 Pass
|
||||
309 Pass
|
||||
Pass setup
|
||||
Pass Can wrap and unwrap RSA-OAEP public key keys using spki and RSA-OAEP
|
||||
Pass Can wrap and unwrap RSA-OAEP public key keys using jwk and RSA-OAEP
|
||||
|
@ -27,6 +27,13 @@ Pass Can wrap and unwrap Ed25519 private key keys as non-extractable using pkcs8
|
|||
Pass Can wrap and unwrap Ed25519 private key keys using jwk and RSA-OAEP
|
||||
Pass Can wrap and unwrap Ed25519 private key keys as non-extractable using jwk and RSA-OAEP
|
||||
Pass Can unwrap Ed25519 private key non-extractable keys using jwk and RSA-OAEP
|
||||
Pass Can wrap and unwrap Ed448 public key keys using spki and RSA-OAEP
|
||||
Pass Can wrap and unwrap Ed448 public key keys using jwk and RSA-OAEP
|
||||
Pass Can wrap and unwrap Ed448 private key keys using pkcs8 and RSA-OAEP
|
||||
Pass Can wrap and unwrap Ed448 private key keys as non-extractable using pkcs8 and RSA-OAEP
|
||||
Pass Can wrap and unwrap Ed448 private key keys using jwk and RSA-OAEP
|
||||
Pass Can wrap and unwrap Ed448 private key keys as non-extractable using jwk and RSA-OAEP
|
||||
Pass Can unwrap Ed448 private key non-extractable keys using jwk and RSA-OAEP
|
||||
Pass Can wrap and unwrap X25519 public key keys using spki and RSA-OAEP
|
||||
Pass Can wrap and unwrap X25519 public key keys using jwk and RSA-OAEP
|
||||
Pass Can wrap and unwrap X25519 private key keys using pkcs8 and RSA-OAEP
|
||||
|
@ -94,6 +101,13 @@ Pass Can wrap and unwrap Ed25519 private key keys as non-extractable using pkcs8
|
|||
Pass Can wrap and unwrap Ed25519 private key keys using jwk and AES-CTR
|
||||
Pass Can wrap and unwrap Ed25519 private key keys as non-extractable using jwk and AES-CTR
|
||||
Pass Can unwrap Ed25519 private key non-extractable keys using jwk and AES-CTR
|
||||
Pass Can wrap and unwrap Ed448 public key keys using spki and AES-CTR
|
||||
Pass Can wrap and unwrap Ed448 public key keys using jwk and AES-CTR
|
||||
Pass Can wrap and unwrap Ed448 private key keys using pkcs8 and AES-CTR
|
||||
Pass Can wrap and unwrap Ed448 private key keys as non-extractable using pkcs8 and AES-CTR
|
||||
Pass Can wrap and unwrap Ed448 private key keys using jwk and AES-CTR
|
||||
Pass Can wrap and unwrap Ed448 private key keys as non-extractable using jwk and AES-CTR
|
||||
Pass Can unwrap Ed448 private key non-extractable keys using jwk and AES-CTR
|
||||
Pass Can wrap and unwrap X25519 public key keys using spki and AES-CTR
|
||||
Pass Can wrap and unwrap X25519 public key keys using jwk and AES-CTR
|
||||
Pass Can wrap and unwrap X25519 private key keys using pkcs8 and AES-CTR
|
||||
|
@ -161,6 +175,13 @@ Pass Can wrap and unwrap Ed25519 private key keys as non-extractable using pkcs8
|
|||
Pass Can wrap and unwrap Ed25519 private key keys using jwk and AES-CBC
|
||||
Pass Can wrap and unwrap Ed25519 private key keys as non-extractable using jwk and AES-CBC
|
||||
Pass Can unwrap Ed25519 private key non-extractable keys using jwk and AES-CBC
|
||||
Pass Can wrap and unwrap Ed448 public key keys using spki and AES-CBC
|
||||
Pass Can wrap and unwrap Ed448 public key keys using jwk and AES-CBC
|
||||
Pass Can wrap and unwrap Ed448 private key keys using pkcs8 and AES-CBC
|
||||
Pass Can wrap and unwrap Ed448 private key keys as non-extractable using pkcs8 and AES-CBC
|
||||
Pass Can wrap and unwrap Ed448 private key keys using jwk and AES-CBC
|
||||
Pass Can wrap and unwrap Ed448 private key keys as non-extractable using jwk and AES-CBC
|
||||
Pass Can unwrap Ed448 private key non-extractable keys using jwk and AES-CBC
|
||||
Pass Can wrap and unwrap X25519 public key keys using spki and AES-CBC
|
||||
Pass Can wrap and unwrap X25519 public key keys using jwk and AES-CBC
|
||||
Pass Can wrap and unwrap X25519 private key keys using pkcs8 and AES-CBC
|
||||
|
@ -228,6 +249,13 @@ Pass Can wrap and unwrap Ed25519 private key keys as non-extractable using pkcs8
|
|||
Pass Can wrap and unwrap Ed25519 private key keys using jwk and AES-GCM
|
||||
Pass Can wrap and unwrap Ed25519 private key keys as non-extractable using jwk and AES-GCM
|
||||
Pass Can unwrap Ed25519 private key non-extractable keys using jwk and AES-GCM
|
||||
Pass Can wrap and unwrap Ed448 public key keys using spki and AES-GCM
|
||||
Pass Can wrap and unwrap Ed448 public key keys using jwk and AES-GCM
|
||||
Pass Can wrap and unwrap Ed448 private key keys using pkcs8 and AES-GCM
|
||||
Pass Can wrap and unwrap Ed448 private key keys as non-extractable using pkcs8 and AES-GCM
|
||||
Pass Can wrap and unwrap Ed448 private key keys using jwk and AES-GCM
|
||||
Pass Can wrap and unwrap Ed448 private key keys as non-extractable using jwk and AES-GCM
|
||||
Pass Can unwrap Ed448 private key non-extractable keys using jwk and AES-GCM
|
||||
Pass Can wrap and unwrap X25519 public key keys using spki and AES-GCM
|
||||
Pass Can wrap and unwrap X25519 public key keys using jwk and AES-GCM
|
||||
Pass Can wrap and unwrap X25519 private key keys using pkcs8 and AES-GCM
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>WebCryptoAPI: generateKey() for Failures</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="../util/helpers.js"></script>
|
||||
<script src="failures.js"></script>
|
||||
<div id=log></div>
|
||||
<script src="../../WebCryptoAPI/generateKey/failures_Ed448.https.any.js"></script>
|
|
@ -0,0 +1,5 @@
|
|||
// META: title=WebCryptoAPI: generateKey() for Failures
|
||||
// META: timeout=long
|
||||
// META: script=../util/helpers.js
|
||||
// META: script=failures.js
|
||||
run_test(["Ed448"]);
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>WebCryptoAPI: generateKey() Successful Calls</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="../util/helpers.js"></script>
|
||||
<script src="../../common/subset-tests.js"></script>
|
||||
<script src="successes.js"></script>
|
||||
<div id=log></div>
|
||||
<script src="../../WebCryptoAPI/generateKey/successes_Ed448.https.any.js"></script>
|
|
@ -0,0 +1,6 @@
|
|||
// META: title=WebCryptoAPI: generateKey() Successful Calls
|
||||
// META: timeout=long
|
||||
// META: script=../util/helpers.js
|
||||
// META: script=/common/subset-tests.js
|
||||
// META: script=successes.js
|
||||
run_test(["Ed448"]);
|
|
@ -0,0 +1,233 @@
|
|||
|
||||
function run_test(algorithmName) {
|
||||
var subtle = self.crypto.subtle; // Change to test prefixed implementations
|
||||
|
||||
// Source file [algorithm_name]_vectors.js provides the getTestVectors method
|
||||
// for the algorithm that drives these tests.
|
||||
var testVectors = getTestVectors(algorithmName);
|
||||
|
||||
testVectors.forEach(function(vector) {
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
|
||||
// Test verification first, because signing tests rely on that working
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
isVerified = await subtle.verify(algorithm, key, vector.signature, vector.data)
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_true(isVerified, "Signature verified");
|
||||
}, vector.name + " verification");
|
||||
|
||||
// Test verification with an altered buffer after call
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
var signature = copyBuffer(vector.signature);
|
||||
[isVerified] = await Promise.all([
|
||||
subtle.verify(algorithm, key, signature, vector.data),
|
||||
signature[0] = 255 - signature[0]
|
||||
]);
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_true(isVerified, "Signature verified");
|
||||
}, vector.name + " verification with altered signature after call");
|
||||
|
||||
// Check for successful verification even if data is altered after call.
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
var data = copyBuffer(vector.data);
|
||||
[isVerified] = await Promise.all([
|
||||
subtle.verify(algorithm, key, vector.signature, data),
|
||||
data[0] = 255 - data[0]
|
||||
]);
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_true(isVerified, "Signature verified");
|
||||
}, vector.name + " with altered data after call");
|
||||
|
||||
// Check for failures due to using privateKey to verify.
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("pkcs8", vector.privateKeyBuffer, algorithm, false, ["sign"]);
|
||||
isVerified = await subtle.verify(algorithm, key, vector.signature, vector.data)
|
||||
assert_unreached("Should have thrown error for using privateKey to verify in " + vector.name);
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError)
|
||||
throw err;
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'");
|
||||
};
|
||||
assert_false(isVerified, "Signature verified");
|
||||
}, vector.name + " using privateKey to verify");
|
||||
|
||||
// Check for failures due to using publicKey to sign.
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
let signature = await subtle.sign(algorithm, key, vector.data);
|
||||
assert_unreached("Should have thrown error for using publicKey to sign in " + vector.name);
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError)
|
||||
throw err;
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'");
|
||||
};
|
||||
}, vector.name + " using publicKey to sign");
|
||||
|
||||
// Check for failures due to no "verify" usage.
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let key;
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, []);
|
||||
isVerified = await subtle.verify(algorithm, key, vector.signature, vector.data)
|
||||
assert_unreached("Should have thrown error for no verify usage in " + vector.name);
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError)
|
||||
throw err;
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_equals(err.name, "InvalidAccessError", "Should throw InvalidAccessError instead of '" + err.message + "'");
|
||||
};
|
||||
assert_false(isVerified, "Signature verified");
|
||||
}, vector.name + " no verify usage");
|
||||
|
||||
// Check for successful signing and verification.
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(async() => {
|
||||
let isVerified = false;
|
||||
let privateKey, publicKey;
|
||||
let signature;
|
||||
try {
|
||||
privateKey = await subtle.importKey("pkcs8", vector.privateKeyBuffer, algorithm, false, ["sign"]);
|
||||
publicKey = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
signature = await subtle.sign(algorithm, privateKey, vector.data);
|
||||
isVerified = await subtle.verify(algorithm, publicKey, vector.signature, vector.data)
|
||||
} catch (err) {
|
||||
assert_false(publicKey === undefined || privateKey === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_false(signature === undefined, "sign error for test " + vector.name + ": '" + err.message + "'");
|
||||
assert_unreached("verify error for test " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_true(isVerified, "Round trip verification works");
|
||||
}, vector.name + " round trip");
|
||||
|
||||
// Test signing with the wrong algorithm
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(async() => {
|
||||
let wrongKey;
|
||||
try {
|
||||
wrongKey = await subtle.generateKey({name: "HMAC", hash: "SHA-1"}, false, ["sign", "verify"])
|
||||
let signature = await subtle.sign(algorithm, wrongKey, vector.data);
|
||||
assert_unreached("Signing should not have succeeded for " + vector.name);
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError)
|
||||
throw err;
|
||||
assert_false(wrongKey === undefined, "Generate wrong key for test " + vector.name + " failed: '" + err.message + "'");
|
||||
assert_equals(err.name, "InvalidAccessError", "Should have thrown InvalidAccessError instead of '" + err.message + "'");
|
||||
};
|
||||
}, vector.name + " signing with wrong algorithm name");
|
||||
|
||||
// Test verification with the wrong algorithm
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(async() => {
|
||||
let wrongKey;
|
||||
try {
|
||||
wrongKey = await subtle.generateKey({name: "HMAC", hash: "SHA-1"}, false, ["sign", "verify"])
|
||||
let isVerified = await subtle.verify(algorithm, wrongKey, vector.signature, vector.data)
|
||||
assert_unreached("Verifying should not have succeeded for " + vector.name);
|
||||
} catch (err) {
|
||||
if (err instanceof AssertionError)
|
||||
throw err;
|
||||
assert_false(wrongKey === undefined, "Generate wrong key for test " + vector.name + " failed: '" + err.message + "'");
|
||||
assert_equals(err.name, "InvalidAccessError", "Should have thrown InvalidAccessError instead of '" + err.message + "'");
|
||||
};
|
||||
}, vector.name + " verifying with wrong algorithm name");
|
||||
|
||||
// Test verification fails with wrong signature
|
||||
var algorithm = {name: vector.algorithmName};
|
||||
promise_test(async() => {
|
||||
let key;
|
||||
let isVerified = true;
|
||||
var signature = copyBuffer(vector.signature);
|
||||
signature[0] = 255 - signature[0];
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
isVerified = await subtle.verify(algorithm, key, signature, vector.data)
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_false(isVerified, "Signature verified");
|
||||
}, vector.name + " verification failure due to altered signature");
|
||||
|
||||
// Test verification fails with short (odd length) signature
|
||||
promise_test(async() => {
|
||||
let key;
|
||||
let isVerified = true;
|
||||
var signature = vector.signature.slice(1); // Skip the first byte
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
isVerified = await subtle.verify(algorithm, key, signature, vector.data)
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_false(isVerified, "Signature verified");
|
||||
}, vector.name + " verification failure due to shortened signature");
|
||||
|
||||
// Test verification fails with wrong data
|
||||
promise_test(async() => {
|
||||
let key;
|
||||
let isVerified = true;
|
||||
var data = copyBuffer(vector.data);
|
||||
data[0] = 255 - data[0];
|
||||
try {
|
||||
key = await subtle.importKey("spki", vector.publicKeyBuffer, algorithm, false, ["verify"]);
|
||||
isVerified = await subtle.verify(algorithm, key, vector.signature, data)
|
||||
} catch (err) {
|
||||
assert_false(key === undefined, "importKey failed for " + vector.name + ". Message: ''" + err.message + "''");
|
||||
assert_unreached("Verification should not throw error " + vector.name + ": " + err.message + "'");
|
||||
};
|
||||
assert_false(isVerified, "Signature verified");
|
||||
}, vector.name + " verification failure due to altered data");
|
||||
|
||||
// Test that generated keys are valid for signing and verifying.
|
||||
promise_test(async() => {
|
||||
let key = await subtle.generateKey(algorithm, false, ["sign", "verify"]);
|
||||
let signature = await subtle.sign(algorithm, key.privateKey, vector.data);
|
||||
let isVerified = await subtle.verify(algorithm, key.publicKey, signature, vector.data);
|
||||
assert_true(isVerified, "Verificaton failed.");
|
||||
}, "Sign and verify using generated " + vector.algorithmName + " keys.");
|
||||
});
|
||||
|
||||
// Returns a copy of the sourceBuffer it is sent.
|
||||
function copyBuffer(sourceBuffer) {
|
||||
var source = new Uint8Array(sourceBuffer);
|
||||
var copy = new Uint8Array(sourceBuffer.byteLength)
|
||||
|
||||
for (var i=0; i<source.byteLength; i++) {
|
||||
copy[i] = source[i];
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>WebCryptoAPI: sign() and verify() Using EdDSA</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.js"></script>
|
||||
<div id=log></div>
|
||||
<script src="../../WebCryptoAPI/sign_verify/eddsa_curve448.https.any.js"></script>
|
|
@ -0,0 +1,6 @@
|
|||
// META: title=WebCryptoAPI: sign() and verify() Using EdDSA
|
||||
// META: script=eddsa_vectors.js
|
||||
// META: script=eddsa.js
|
||||
// META: timeout=long
|
||||
|
||||
run_test("Ed448");
|
|
@ -0,0 +1,197 @@
|
|||
// eddsa_vectors.js
|
||||
|
||||
// Data for testing Ed25519 and Ed448.
|
||||
|
||||
// The following function returns an array of test vectors
|
||||
// for the subtleCrypto sign method.
|
||||
//
|
||||
// Each test vector has the following fields:
|
||||
// name - a unique name for this vector
|
||||
// publicKeyBuffer - an arrayBuffer with the key data
|
||||
// publicKeyFormat - "spki" "jwk"
|
||||
// publicKey - a CryptoKey object for the keyBuffer. INITIALLY null! You must fill this in first to use it!
|
||||
// privateKeyBuffer - an arrayBuffer with the key data
|
||||
// privateKeyFormat - "pkcs8" or "jwk"
|
||||
// privateKey - a CryptoKey object for the keyBuffer. INITIALLY null! You must fill this in first to use it!
|
||||
// algorithmName - the name of the AlgorithmIdentifier parameter to provide to sign
|
||||
// data - the text to sign
|
||||
// signature - the expected signature
|
||||
function getTestVectors(algorithmName) {
|
||||
var pkcs8 = {
|
||||
"Ed25519": new Uint8Array([48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32, 243, 200, 244, 196, 141, 248, 120, 20, 110, 140, 211, 191, 109, 244, 229, 14, 56, 155, 167, 7, 78, 21, 194, 53, 45, 205, 93, 48, 141, 76, 168, 31]),
|
||||
"Ed448": new Uint8Array([48, 71, 2, 1, 0, 48, 5, 6, 3, 43, 101, 113, 4, 59, 4, 57, 14, 255, 3, 69, 140, 40, 224, 23, 156, 82, 29, 227, 18, 201, 105, 183, 131, 67, 72, 236, 171, 153, 26, 96, 227, 178, 233, 167, 158, 76, 217, 228, 128, 239, 41, 23, 18, 210, 200, 61, 4, 114, 114, 213, 201, 244, 40, 102, 79, 105, 109, 38, 112, 69, 143, 29, 46]),
|
||||
};
|
||||
|
||||
var spki = {
|
||||
"Ed25519": new Uint8Array([48, 42, 48, 5, 6, 3, 43, 101, 112, 3, 33, 0, 216, 225, 137, 99, 216, 9, 212, 135, 217, 84, 154, 204, 174, 198, 116, 46, 126, 235, 162, 77, 138, 13, 59, 20, 183, 227, 202, 234, 6, 137, 61, 204]),
|
||||
"Ed448": new Uint8Array([48, 67, 48, 5, 6, 3, 43, 101, 113, 3, 58, 0, 171, 75, 184, 133, 253, 125, 44, 90, 242, 78, 131, 113, 12, 255, 160, 199, 74, 87, 226, 116, 128, 29, 178, 5, 123, 11, 220, 94, 160, 50, 182, 254, 107, 199, 139, 128, 69, 54, 90, 235, 38, 232, 110, 31, 20, 253, 52, 157, 7, 196, 132, 149, 245, 164, 106, 90, 128]),
|
||||
};
|
||||
|
||||
// data
|
||||
var data = new Uint8Array([43, 126, 208, 188, 119, 149, 105, 74, 180, 172, 211, 89, 3, 254, 140, 215, 216, 15, 106, 28, 134, 136, 166, 195, 65, 68, 9, 69, 117, 20, 161, 69, 120, 85, 187, 178, 25, 227, 10, 27, 238, 168, 254, 134, 144, 130, 217, 159, 200, 40, 47, 144, 80, 208, 36, 229, 158, 175, 7, 48, 186, 157, 183, 10]);
|
||||
|
||||
// For verification tests.
|
||||
var signatures = {
|
||||
"Ed25519": new Uint8Array([61, 144, 222, 94, 87, 67, 223, 194, 130, 37, 191, 173, 179, 65, 177, 22, 203, 248, 163, 241, 206, 237, 191, 74, 220, 53, 14, 245, 211, 71, 24, 67, 164, 24, 97, 77, 203, 110, 97, 72, 98, 97, 76, 247, 175, 20, 150, 249, 52, 11, 60, 132, 78, 164, 220, 234, 177, 211, 209, 85, 235, 126, 204, 0]),
|
||||
"Ed448": new Uint8Array([118, 137, 126, 140, 80, 172, 107, 17, 50, 115, 92, 9, 197, 95, 80, 108, 1, 73, 210, 103, 124, 117, 102, 79, 139, 193, 11, 130, 111, 189, 157, 240, 160, 60, 217, 134, 188, 232, 51, 158, 100, 199, 209, 114, 14, 169, 54, 23, 132, 220, 115, 131, 119, 101, 172, 41, 128, 192, 218, 192, 129, 74, 139, 193, 135, 209, 201, 201, 7, 197, 220, 192, 121, 86, 248, 91, 112, 147, 15, 228, 45, 231, 100, 23, 114, 23, 203, 45, 82, 186, 183, 193, 222, 190, 12, 168, 156, 206, 203, 205, 99, 247, 2, 90, 42, 90, 87, 43, 157, 35, 176, 100, 47, 0]),
|
||||
}
|
||||
|
||||
var vectors = [];
|
||||
{
|
||||
var vector = {
|
||||
name: "EdDSA " + algorithmName,
|
||||
publicKeyBuffer: spki[algorithmName],
|
||||
publicKeyFormat: "spki",
|
||||
publicKey: null,
|
||||
privateKeyBuffer: pkcs8[algorithmName],
|
||||
privateKeyFormat: "pkcs8",
|
||||
privateKey: null,
|
||||
algorithmName: algorithmName,
|
||||
data: data,
|
||||
signature: signatures[algorithmName]
|
||||
};
|
||||
|
||||
vectors.push(vector);
|
||||
}
|
||||
return vectors;
|
||||
}
|
||||
|
||||
// https://eprint.iacr.org/2020/1244.pdf#table.caption.3
|
||||
var kSmallOrderPoints = [
|
||||
// Canonical serializations
|
||||
[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], // #0 - Order 1
|
||||
[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], // #1 - Order 2
|
||||
[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], // #2 - 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, 0x00], // #3 - Order 4
|
||||
[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, 0x7A], // #4 - Order 8
|
||||
[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], // #5 - Order 8
|
||||
[0x26, 0xE8, 0x95, 0x8F, 0xC2, 0xB2, 0x27, 0xB0, 0x45, 0xC3, 0xF4, 0x89, 0xF2, 0xEF, 0x98, 0xF0, 0xD5, 0xDF, 0xAC, 0x05, 0xD3, 0xC6, 0x33, 0x39, 0xB1, 0x38, 0x02, 0x88, 0x6D, 0x53, 0xFC, 0x05], // #6 - Order 8
|
||||
[0x26, 0xE8, 0x95, 0x8F, 0xC2, 0xB2, 0x27, 0xB0, 0x45, 0xC3, 0xF4, 0x89, 0xF2, 0xEF, 0x98, 0xF0, 0xD5, 0xDF, 0xAC, 0x05, 0xD3, 0xC6, 0x33, 0x39, 0xB1, 0x38, 0x02, 0x88, 0x6D, 0x53, 0xFC, 0x85], // #7 - Order 8
|
||||
|
||||
// Non-canonical serializatons
|
||||
[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, 0x80], // #8 - Order 1
|
||||
[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], // #9 - Order 2
|
||||
[0xEE, 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], // #10 - Order 1
|
||||
[0xEE, 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], // #11 - Order 1
|
||||
[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], // #12 - Order 4
|
||||
[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, 0x7F], // #13 - Order 4
|
||||
];
|
||||
|
||||
|
||||
var pubKeys = [
|
||||
[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], // kSmallOrderPoints #5
|
||||
[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], // highest 32 bytes of case "1" signature
|
||||
[0xcd, 0xb2, 0x67, 0xce, 0x40, 0xc5, 0xcd, 0x45, 0x30, 0x6f, 0xa5, 0xd2, 0xf2, 0x97, 0x31, 0x45, 0x93, 0x87, 0xdb, 0xf9, 0xeb, 0x93, 0x3b, 0x7b, 0xd5, 0xae, 0xd9, 0xa7, 0x65, 0xb8, 0x8d, 0x4d],
|
||||
[0x44, 0x2a, 0xad, 0x9f, 0x08, 0x9a, 0xd9, 0xe1, 0x46, 0x47, 0xb1, 0xef, 0x90, 0x99, 0xa1, 0xff, 0x47, 0x98, 0xd7, 0x85, 0x89, 0xe6, 0x6f, 0x28, 0xec, 0xa6, 0x9c, 0x11, 0xf5, 0x82, 0xa6, 0x23],
|
||||
[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], // kSmallOrderPoints #9
|
||||
[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], // kSmallOrderPoints #1
|
||||
]
|
||||
|
||||
// https://eprint.iacr.org/2020/1244.pdf
|
||||
// signature = (R, S); public key A, h = SHA512(R||A||M )
|
||||
// 8(SB) = 8R + 8(hA) => (1)
|
||||
// SB = R + hA => (2)
|
||||
var kSmallOrderTestCases = {
|
||||
"Ed25519": [
|
||||
{
|
||||
id: "0", // S = 0 | A's order = small | R's order = small | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0x8c, 0x93, 0x25, 0x5d, 0x71, 0xdc, 0xab, 0x10, 0xe8, 0xf3, 0x79, 0xc2, 0x62, 0x00, 0xf3, 0xc7, 0xbd, 0x5f, 0x09, 0xd9, 0xbc, 0x30, 0x68, 0xd3, 0xef, 0x4e, 0xde, 0xb4, 0x85, 0x30, 0x22, 0xb6]),
|
||||
keyData : Uint8Array.from(pubKeys[0]),
|
||||
signature : Uint8Array.from([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, 0x7a, 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]),
|
||||
verified: false, // small-order signature's R fail in the verification.
|
||||
},
|
||||
{
|
||||
id: "1", // 0 < S < L | A's order = small | R's order = mixed | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0x9b, 0xd9, 0xf4, 0x4f, 0x4d, 0xcc, 0x75, 0xbd, 0x53, 0x1b, 0x56, 0xb2, 0xcd, 0x28, 0x0b, 0x0b, 0xb3, 0x8f, 0xc1, 0xcd, 0x6d, 0x12, 0x30, 0xe1, 0x48, 0x61, 0xd8, 0x61, 0xde, 0x09, 0x2e, 0x79]),
|
||||
keyData : Uint8Array.from(pubKeys[0]),
|
||||
signature : Uint8Array.from([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, 0xa5, 0xbb, 0x70, 0x47, 0x86, 0xbe, 0x79, 0xfc, 0x47, 0x6f, 0x91, 0xd3, 0xf3, 0xf8, 0x9b, 0x03, 0x98, 0x4d, 0x80, 0x68, 0xdc, 0xf1, 0xbb, 0x7d, 0xfc, 0x66, 0x37, 0xb4, 0x54, 0x50, 0xac, 0x04]),
|
||||
verified: false, // small-order key's data fail in the verification.
|
||||
},
|
||||
{
|
||||
id: "2", // 0 < S < L | A's order = mixed | R's order = small | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0xae, 0xbf, 0x3f, 0x26, 0x01, 0xa0, 0xc8, 0xc5, 0xd3, 0x9c, 0xc7, 0xd8, 0x91, 0x16, 0x42, 0xf7, 0x40, 0xb7, 0x81, 0x68, 0x21, 0x8d, 0xa8, 0x47, 0x17, 0x72, 0xb3, 0x5f, 0x9d, 0x35, 0xb9, 0xab]),
|
||||
keyData : Uint8Array.from(pubKeys[1]),
|
||||
signature : Uint8Array.from([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, 0x8c, 0x4b, 0xd4, 0x5a, 0xec, 0xac, 0xa5, 0xb2, 0x4f, 0xb9, 0x7b, 0xc1, 0x0a, 0xc2, 0x7a, 0xc8, 0x75, 0x1a, 0x7d, 0xfe, 0x1b, 0xaf, 0xf8, 0xb9, 0x53, 0xec, 0x9f, 0x58, 0x33, 0xca, 0x26, 0x0e]),
|
||||
verified: false, // small-order signature's R fail in the verification.
|
||||
},
|
||||
{
|
||||
id: "3", // 0 < S < L | A's order = mixed | R's order = mixed | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0x9b, 0xd9, 0xf4, 0x4f, 0x4d, 0xcc, 0x75, 0xbd, 0x53, 0x1b, 0x56, 0xb2, 0xcd, 0x28, 0x0b, 0x0b, 0xb3, 0x8f, 0xc1, 0xcd, 0x6d, 0x12, 0x30, 0xe1, 0x48, 0x61, 0xd8, 0x61, 0xde, 0x09, 0x2e, 0x79]),
|
||||
keyData : Uint8Array.from(pubKeys[2]),
|
||||
signature : Uint8Array.from([0x90, 0x46, 0xa6, 0x47, 0x50, 0x44, 0x49, 0x38, 0xde, 0x19, 0xf2, 0x27, 0xbb, 0x80, 0x48, 0x5e, 0x92, 0xb8, 0x3f, 0xdb, 0x4b, 0x65, 0x06, 0xc1, 0x60, 0x48, 0x4c, 0x01, 0x6c, 0xc1, 0x85, 0x2f, 0x87, 0x90, 0x9e, 0x14, 0x42, 0x8a, 0x7a, 0x1d, 0x62, 0xe9, 0xf2, 0x2f, 0x3d, 0x3a, 0xd7, 0x80, 0x2d, 0xb0, 0x2e, 0xb2, 0xe6, 0x88, 0xb6, 0xc5, 0x2f, 0xcd, 0x66, 0x48, 0xa9, 0x8b, 0xd0, 0x09]),
|
||||
verified: true, // mixed-order points are not checked.
|
||||
},
|
||||
{
|
||||
id: "4", // 0 < S < L | A's order = mixed | R's order = mixed | (1) = pass | (2) = fail
|
||||
message : Uint8Array.from([0xe4, 0x7d, 0x62, 0xc6, 0x3f, 0x83, 0x0d, 0xc7, 0xa6, 0x85, 0x1a, 0x0b, 0x1f, 0x33, 0xae, 0x4b, 0xb2, 0xf5, 0x07, 0xfb, 0x6c, 0xff, 0xec, 0x40, 0x11, 0xea, 0xcc, 0xd5, 0x5b, 0x53, 0xf5, 0x6c]),
|
||||
keyData : Uint8Array.from(pubKeys[2]),
|
||||
signature : Uint8Array.from([0x16, 0x0a, 0x1c, 0xb0, 0xdc, 0x9c, 0x02, 0x58, 0xcd, 0x0a, 0x7d, 0x23, 0xe9, 0x4d, 0x8f, 0xa8, 0x78, 0xbc, 0xb1, 0x92, 0x5f, 0x2c, 0x64, 0x24, 0x6b, 0x2d, 0xee, 0x17, 0x96, 0xbe, 0xd5, 0x12, 0x5e, 0xc6, 0xbc, 0x98, 0x2a, 0x26, 0x9b, 0x72, 0x3e, 0x06, 0x68, 0xe5, 0x40, 0x91, 0x1a, 0x9a, 0x6a, 0x58, 0x92, 0x1d, 0x69, 0x25, 0xe4, 0x34, 0xab, 0x10, 0xaa, 0x79, 0x40, 0x55, 0x1a, 0x09]),
|
||||
verified: false, // expect a cofactorless verification algorithm.
|
||||
},
|
||||
{
|
||||
id: "5", // 0 < S < L | A's order = mixed | R's order = L | (1) = pass | (2) = fail
|
||||
message : Uint8Array.from([0xe4, 0x7d, 0x62, 0xc6, 0x3f, 0x83, 0x0d, 0xc7, 0xa6, 0x85, 0x1a, 0x0b, 0x1f, 0x33, 0xae, 0x4b, 0xb2, 0xf5, 0x07, 0xfb, 0x6c, 0xff, 0xec, 0x40, 0x11, 0xea, 0xcc, 0xd5, 0x5b, 0x53, 0xf5, 0x6c]),
|
||||
keyData : Uint8Array.from(pubKeys[2]),
|
||||
signature : Uint8Array.from([0x21, 0x12, 0x2a, 0x84, 0xe0, 0xb5, 0xfc, 0xa4, 0x05, 0x2f, 0x5b, 0x12, 0x35, 0xc8, 0x0a, 0x53, 0x78, 0x78, 0xb3, 0x8f, 0x31, 0x42, 0x35, 0x6b, 0x2c, 0x23, 0x84, 0xeb, 0xad, 0x46, 0x68, 0xb7, 0xe4, 0x0b, 0xc8, 0x36, 0xda, 0xc0, 0xf7, 0x10, 0x76, 0xf9, 0xab, 0xe3, 0xa5, 0x3f, 0x9c, 0x03, 0xc1, 0xce, 0xee, 0xdd, 0xb6, 0x58, 0xd0, 0x03, 0x04, 0x94, 0xac, 0xe5, 0x86, 0x68, 0x74, 0x05]),
|
||||
verified: false, // expect a cofactorless verification algorithm.
|
||||
},
|
||||
{
|
||||
id: "6", // S > L | A's order = L | R's order = L | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0x85, 0xe2, 0x41, 0xa0, 0x7d, 0x14, 0x8b, 0x41, 0xe4, 0x7d, 0x62, 0xc6, 0x3f, 0x83, 0x0d, 0xc7, 0xa6, 0x85, 0x1a, 0x0b, 0x1f, 0x33, 0xae, 0x4b, 0xb2, 0xf5, 0x07, 0xfb, 0x6c, 0xff, 0xec, 0x40]),
|
||||
keyData : Uint8Array.from(pubKeys[3]),
|
||||
signature : Uint8Array.from([0xe9, 0x6f, 0x66, 0xbe, 0x97, 0x6d, 0x82, 0xe6, 0x01, 0x50, 0xba, 0xec, 0xff, 0x99, 0x06, 0x68, 0x4a, 0xeb, 0xb1, 0xef, 0x18, 0x1f, 0x67, 0xa7, 0x18, 0x9a, 0xc7, 0x8e, 0xa2, 0x3b, 0x6c, 0x0e, 0x54, 0x7f, 0x76, 0x90, 0xa0, 0xe2, 0xdd, 0xcd, 0x04, 0xd8, 0x7d, 0xbc, 0x34, 0x90, 0xdc, 0x19, 0xb3, 0xb3, 0x05, 0x2f, 0x7f, 0xf0, 0x53, 0x8c, 0xb6, 0x8a, 0xfb, 0x36, 0x9b, 0xa3, 0xa5, 0x14]),
|
||||
verified: false, // S out of bounds
|
||||
},
|
||||
{
|
||||
id: "7", // S >> L | A's order = L | R's order = L | (1) = pass | (2) = pass
|
||||
message : Uint8Array.from([0x85, 0xe2, 0x41, 0xa0, 0x7d, 0x14, 0x8b, 0x41, 0xe4, 0x7d, 0x62, 0xc6, 0x3f, 0x83, 0x0d, 0xc7, 0xa6, 0x85, 0x1a, 0x0b, 0x1f, 0x33, 0xae, 0x4b, 0xb2, 0xf5, 0x07, 0xfb, 0x6c, 0xff, 0xec, 0x40]),
|
||||
keyData : Uint8Array.from(pubKeys[3]),
|
||||
signature : Uint8Array.from([0x8c, 0xe5, 0xb9, 0x6c, 0x8f, 0x26, 0xd0, 0xab, 0x6c, 0x47, 0x95, 0x8c, 0x9e, 0x68, 0xb9, 0x37, 0x10, 0x4c, 0xd3, 0x6e, 0x13, 0xc3, 0x35, 0x66, 0xac, 0xd2, 0xfe, 0x8d, 0x38, 0xaa, 0x19, 0x42, 0x7e, 0x71, 0xf9, 0x8a, 0x47, 0x34, 0xe7, 0x4f, 0x2f, 0x13, 0xf0, 0x6f, 0x97, 0xc2, 0x0d, 0x58, 0xcc, 0x3f, 0x54, 0xb8, 0xbd, 0x0d, 0x27, 0x2f, 0x42, 0xb6, 0x95, 0xdd, 0x7e, 0x89, 0xa8, 0xc2, 0x02]),
|
||||
verified: false, // S out of bounds
|
||||
},
|
||||
{
|
||||
id: "8", // 0 < S < L | A's order = mixed | R's order = small (non-canonical) | (1) = ? | (2) = ? Implementations that reduce A before hashing will accept #8 and accept #9, and viceversa
|
||||
message : Uint8Array.from([0x9b, 0xed, 0xc2, 0x67, 0x42, 0x37, 0x25, 0xd4, 0x73, 0x88, 0x86, 0x31, 0xeb, 0xf4, 0x59, 0x88, 0xba, 0xd3, 0xdb, 0x83, 0x85, 0x1e, 0xe8, 0x5c, 0x85, 0xe2, 0x41, 0xa0, 0x7d, 0x14, 0x8b, 0x41]),
|
||||
keyData : Uint8Array.from(pubKeys[1]),
|
||||
signature : Uint8Array.from([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, 0x03, 0xbe, 0x96, 0x78, 0xac, 0x10, 0x2e, 0xdc, 0xd9, 0x2b, 0x02, 0x10, 0xbb, 0x34, 0xd7, 0x42, 0x8d, 0x12, 0xff, 0xc5, 0xdf, 0x5f, 0x37, 0xe3, 0x59, 0x94, 0x12, 0x66, 0xa4, 0xe3, 0x5f, 0x0f]),
|
||||
verified: false, // non-canonical point should fail in the verificaton (RFC8032)
|
||||
},
|
||||
{
|
||||
id: "9", // 0 < S < L | A's order = mixed | R's order = small (non-canonical) | (1) = ? | (2) = ?
|
||||
message : Uint8Array.from([0x9b, 0xed, 0xc2, 0x67, 0x42, 0x37, 0x25, 0xd4, 0x73, 0x88, 0x86, 0x31, 0xeb, 0xf4, 0x59, 0x88, 0xba, 0xd3, 0xdb, 0x83, 0x85, 0x1e, 0xe8, 0x5c, 0x85, 0xe2, 0x41, 0xa0, 0x7d, 0x14, 0x8b, 0x41]),
|
||||
keyData : Uint8Array.from(pubKeys[1]),
|
||||
signature : Uint8Array.from([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, 0xca, 0x8c, 0x5b, 0x64, 0xcd, 0x20, 0x89, 0x82, 0xaa, 0x38, 0xd4, 0x93, 0x66, 0x21, 0xa4, 0x77, 0x5a, 0xa2, 0x33, 0xaa, 0x05, 0x05, 0x71, 0x1d, 0x8f, 0xdc, 0xfd, 0xaa, 0x94, 0x3d, 0x49, 0x08]),
|
||||
verified: false, // non-canonical point should fail in the verificaton (RFC8032)
|
||||
},
|
||||
{
|
||||
id: "10", // 0 < S < L | A's order = small (non-canonical) | R's order = mixed | (1) = ? | (2) = ? Implementations that reduce A before hashing will accept #10 and accept #11, and viceversa
|
||||
message : Uint8Array.from([0xe9, 0x6b, 0x70, 0x21, 0xeb, 0x39, 0xc1, 0xa1, 0x63, 0xb6, 0xda, 0x4e, 0x30, 0x93, 0xdc, 0xd3, 0xf2, 0x13, 0x87, 0xda, 0x4c, 0xc4, 0x57, 0x2b, 0xe5, 0x88, 0xfa, 0xfa, 0xe2, 0x3c, 0x15, 0x5b]),
|
||||
keyData : Uint8Array.from(pubKeys[4]),
|
||||
signature : Uint8Array.from([0xa9, 0xd5, 0x52, 0x60, 0xf7, 0x65, 0x26, 0x1e, 0xb9, 0xb8, 0x4e, 0x10, 0x6f, 0x66, 0x5e, 0x00, 0xb8, 0x67, 0x28, 0x7a, 0x76, 0x19, 0x90, 0xd7, 0x13, 0x59, 0x63, 0xee, 0x0a, 0x7d, 0x59, 0xdc, 0xa5, 0xbb, 0x70, 0x47, 0x86, 0xbe, 0x79, 0xfc, 0x47, 0x6f, 0x91, 0xd3, 0xf3, 0xf8, 0x9b, 0x03, 0x98, 0x4d, 0x80, 0x68, 0xdc, 0xf1, 0xbb, 0x7d, 0xfc, 0x66, 0x37, 0xb4, 0x54, 0x50, 0xac, 0x04]),
|
||||
verified: false, // non-canonical point should fail in the verificaton (RFC8032)
|
||||
},
|
||||
{
|
||||
id: "11", // 0 < S < L | A's order = small (non-canonical) | R's order = mixed | (1) = ? | (2) = ? Implementations that reduce A before hashing will accept #10 and accept #11, and viceversa
|
||||
message : Uint8Array.from([0x39, 0xa5, 0x91, 0xf5, 0x32, 0x1b, 0xbe, 0x07, 0xfd, 0x5a, 0x23, 0xdc, 0x2f, 0x39, 0xd0, 0x25, 0xd7, 0x45, 0x26, 0x61, 0x57, 0x46, 0x72, 0x7c, 0xee, 0xfd, 0x6e, 0x82, 0xae, 0x65, 0xc0, 0x6f]),
|
||||
keyData : Uint8Array.from(pubKeys[4]),
|
||||
signature : Uint8Array.from([0xa9, 0xd5, 0x52, 0x60, 0xf7, 0x65, 0x26, 0x1e, 0xb9, 0xb8, 0x4e, 0x10, 0x6f, 0x66, 0x5e, 0x00, 0xb8, 0x67, 0x28, 0x7a, 0x76, 0x19, 0x90, 0xd7, 0x13, 0x59, 0x63, 0xee, 0x0a, 0x7d, 0x59, 0xdc, 0xa5, 0xbb, 0x70, 0x47, 0x86, 0xbe, 0x79, 0xfc, 0x47, 0x6f, 0x91, 0xd3, 0xf3, 0xf8, 0x9b, 0x03, 0x98, 0x4d, 0x80, 0x68, 0xdc, 0xf1, 0xbb, 0x7d, 0xfc, 0x66, 0x37, 0xb4, 0x54, 0x50, 0xac, 0x04]),
|
||||
verified: false, // non-canonical point should fail in the verificaton (RFC8032)
|
||||
},
|
||||
// https://eprint.iacr.org/2020/1244.pdf#section.A.2
|
||||
// cases breaking non-repudiation
|
||||
{
|
||||
id: "12", // 0 < S < L | A's order = small | R's order = mixed | (1) = ? | (2) = ?
|
||||
message : Uint8Array.from([0x53, 0x65, 0x6e, 0x64, 0x20, 0x31, 0x30, 0x30, 0x20, 0x55, 0x53, 0x44, 0x20, 0x74, 0x6f, 0x20, 0x41, 0x6c, 0x69, 0x63, 0x65]),
|
||||
keyData : Uint8Array.from(pubKeys[5]),
|
||||
signature : Uint8Array.from([0xa9, 0xd5, 0x52, 0x60, 0xf7, 0x65, 0x26, 0x1e, 0xb9, 0xb8, 0x4e, 0x10, 0x6f, 0x66, 0x5e, 0x00, 0xb8, 0x67, 0x28, 0x7a, 0x76, 0x19, 0x90, 0xd7, 0x13, 0x59, 0x63, 0xee, 0x0a, 0x7d, 0x59, 0xdc, 0xa5, 0xbb, 0x70, 0x47, 0x86, 0xbe, 0x79, 0xfc, 0x47, 0x6f, 0x91, 0xd3, 0xf3, 0xf8, 0x9b, 0x03, 0x98, 0x4d, 0x80, 0x68, 0xdc, 0xf1, 0xbb, 0x7d, 0xfc, 0x66, 0x37, 0xb4, 0x54, 0x50, 0xac, 0x04]),
|
||||
verified: false,
|
||||
},
|
||||
{
|
||||
id: "13", // 0 < S < L | A's order = small | R's order = mixed | (1) = ? | (2) = ?
|
||||
message : Uint8Array.from([0x53, 0x65, 0x6e, 0x64, 0x20, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x55, 0x53, 0x44, 0x20, 0x74, 0x6f, 0x20, 0x41, 0x6c, 0x69, 0x63, 0x65]),
|
||||
keyData : Uint8Array.from(pubKeys[5]),
|
||||
signature : Uint8Array.from([0xa9, 0xd5, 0x52, 0x60, 0xf7, 0x65, 0x26, 0x1e, 0xb9, 0xb8, 0x4e, 0x10, 0x6f, 0x66, 0x5e, 0x00, 0xb8, 0x67, 0x28, 0x7a, 0x76, 0x19, 0x90, 0xd7, 0x13, 0x59, 0x63, 0xee, 0x0a, 0x7d, 0x59, 0xdc, 0xa5, 0xbb, 0x70, 0x47, 0x86, 0xbe, 0x79, 0xfc, 0x47, 0x6f, 0x91, 0xd3, 0xf3, 0xf8, 0x9b, 0x03, 0x98, 0x4d, 0x80, 0x68, 0xdc, 0xf1, 0xbb, 0x7d, 0xfc, 0x66, 0x37, 0xb4, 0x54, 0x50, 0xac, 0x04]),
|
||||
verified: false,
|
||||
}
|
||||
]
|
||||
};
|
Loading…
Reference in a new issue