diff --git a/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-sign.txt b/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-sign.txt index dd749e8d8ea..984528d61d5 100644 --- a/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-sign.txt +++ b/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-sign.txt @@ -1 +1 @@ -Signed OK ... [13 bytes total] (Hello friends) +Signed OK diff --git a/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-sign.html b/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-sign.html index 94ed5b3adba..83442d84a0e 100644 --- a/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-sign.html +++ b/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-sign.html @@ -3,29 +3,25 @@ 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); - 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 ); - const data_view = String.fromCharCode.apply(null, new Uint8Array(signature)); - - println(`Signed OK ... [${signature.byteLength} bytes total] (${data_view})`); + println(`Signed OK`); done(); }); diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index 3f2cd6298b8..2e96c5d1a79 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -1278,4 +1278,38 @@ WebIDL::ExceptionOr, JS::NonnullGCPtr, JS::NonnullGCPtr> { CryptoKeyPair::create(m_realm, public_key, private_key) }; } +WebIDL::ExceptionOr> ED25519::sign([[maybe_unused]] AlgorithmParams const& params, JS::NonnullGCPtr key, ByteBuffer const& message) +{ + auto& realm = m_realm; + auto& vm = realm.vm(); + + // 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"_fly_string); + + // 2. Perform the Ed25519 signing process, as specified in [RFC8032], Section 5.1.6, + // with message as M, using the Ed25519 private key associated with key. + auto private_key = key->handle().visit( + [](ByteBuffer data) -> ByteBuffer { + return data; + }, + [](auto) -> ByteBuffer { VERIFY_NOT_REACHED(); }); + + ::Crypto::Curves::Ed25519 curve; + auto maybe_public_key = curve.generate_public_key(private_key); + if (maybe_public_key.is_error()) + return WebIDL::OperationError::create(realm, "Failed to generate public key"_fly_string); + auto public_key = maybe_public_key.release_value(); + + auto maybe_signature = curve.sign(public_key, private_key, message); + if (maybe_signature.is_error()) + return WebIDL::OperationError::create(realm, "Failed to sign message"_fly_string); + auto signature = maybe_signature.release_value(); + + // 3. Return a new ArrayBuffer associated with the relevant global object of this [HTML], + // and containing the bytes of the signature resulting from performing the Ed25519 signing process. + auto result = TRY_OR_THROW_OOM(vm, ByteBuffer::copy(signature)); + return JS::ArrayBuffer::create(realm, move(result)); +} + } diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h index 3955c83da70..5f920288339 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.h @@ -266,6 +266,7 @@ private: class ED25519 : public AlgorithmMethods { public: + virtual WebIDL::ExceptionOr> sign(AlgorithmParams const&, JS::NonnullGCPtr, 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 bf9f2f230c9..e19b16c7792 100644 --- a/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp +++ b/Userland/Libraries/LibWeb/Crypto/SubtleCrypto.cpp @@ -645,6 +645,7 @@ SupportedAlgorithmsMap supported_algorithms() define_an_algorithm("generateKey"_string, "ECDSA"_string); // https://wicg.github.io/webcrypto-secure-curves/#ed25519 + define_an_algorithm("sign"_string, "Ed25519"_string); define_an_algorithm("generateKey"_string, "Ed25519"_string); return internal_object;