diff --git a/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-verify.txt b/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-verify.txt index ef7110fd5bd..90cd1ea4ce7 100644 --- a/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-verify.txt +++ b/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-verify.txt @@ -1,2 +1 @@ -FIXME: This will fail as we dont support ECDSA sign() -FAIL: Verification not ok +Verified OK diff --git a/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-verify.html b/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-verify.html index d870c20172c..a1bf43ebd83 100644 --- a/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-verify.html +++ b/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-verify.html @@ -3,37 +3,31 @@ asyncTest(async done => { const encoder = new TextEncoder(); const message = "Hello friends"; - const encoded_message = encoder.encode(message); + const encodedMessage = encoder.encode(message); - const key_algorithm = { - name: "ECDSA", - namedCurve: "P-384", + const keyAlgorithm = { + name: "Ed25519", }; const extractable = true; const usages = ["sign", "verify"]; - const key = await window.crypto.subtle.generateKey(key_algorithm, extractable, usages); + const key = await window.crypto.subtle.generateKey(keyAlgorithm, extractable, usages); - console.log(key.publicKey); - - const signature_algorithm = { - name: "ECDSA", - hash: { name: "SHA-384" }, + const signatureAlgorithm = { + name: "Ed25519", }; const signature = await window.crypto.subtle.sign( - signature_algorithm, + signatureAlgorithm, key.privateKey, - encoded_message + encodedMessage ); let result = await window.crypto.subtle.verify( - signature_algorithm, + signatureAlgorithm, key.publicKey, signature, - encoded_message + encodedMessage ); - println(`FIXME: This will fail as we dont support ECDSA sign()`); - if (result) { println(`Verified OK`); } else { diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index 2e96c5d1a79..276788e4f36 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -1312,4 +1312,34 @@ WebIDL::ExceptionOr> ED25519::sign([[maybe_unu return JS::ArrayBuffer::create(realm, move(result)); } +WebIDL::ExceptionOr ED25519::verify([[maybe_unused]] AlgorithmParams const& params, JS::NonnullGCPtr 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"_fly_string); + + // NOTE: this is checked by ED25519::verify() + // 2. If the key data of key represents an invalid point or a small-order element on the Elliptic Curve of Ed25519, return false. + // 3. 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 Ed25519, return false. + + // 4. Perform the Ed25519 verification steps, as specified in [RFC8032], Section 5.1.7, + // using the cofactorless (unbatched) equation, [S]B = R + [k]A', on the signature, + // with message as M, using the Ed25519 public key associated with key. + + auto public_key = key->handle().visit( + [](ByteBuffer data) -> ByteBuffer { + return data; + }, + [](auto) -> ByteBuffer { VERIFY_NOT_REACHED(); }); + + // 9. Let result be a boolean with the value true if the signature is valid and the value false otherwise. + ::Crypto::Curves::Ed25519 curve; + auto result = curve.verify(public_key, signature, message); + + // 10. Return result. + return JS::Value(result); +} + } diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h index 5f920288339..2ceef18009a 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h @@ -267,6 +267,8 @@ private: class ED25519 : public AlgorithmMethods { public: virtual WebIDL::ExceptionOr> sign(AlgorithmParams const&, JS::NonnullGCPtr, ByteBuffer const&) override; + virtual WebIDL::ExceptionOr verify(AlgorithmParams const&, JS::NonnullGCPtr, ByteBuffer const&, ByteBuffer const&) override; + virtual WebIDL::ExceptionOr, JS::NonnullGCPtr>> generate_key(AlgorithmParams const&, bool, Vector const&) override; static NonnullOwnPtr create(JS::Realm& realm) { return adopt_own(*new ED25519(realm)); } diff --git a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp index e19b16c7792..7f2cf0dd6e6 100644 --- a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp +++ b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp @@ -646,6 +646,7 @@ SupportedAlgorithmsMap supported_algorithms() // https://wicg.github.io/webcrypto-secure-curves/#ed25519 define_an_algorithm("sign"_string, "Ed25519"_string); + define_an_algorithm("verify"_string, "Ed25519"_string); define_an_algorithm("generateKey"_string, "Ed25519"_string); return internal_object;