mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-21 10:32:51 +00:00
LibWeb: Implement the exportKey algorithm for Ed25519
This commit is contained in:
parent
4d25369f29
commit
ed7b1caba2
Notes:
github-actions[bot]
2024-11-24 22:29:36 +00:00
Author: https://github.com/awesomekling
Commit: ed7b1caba2
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2555
Reviewed-by: https://github.com/alimpfard ✅
Reviewed-by: https://github.com/gmta ✅
Reviewed-by: https://github.com/stelar7
4 changed files with 115 additions and 9 deletions
|
@ -2950,6 +2950,111 @@ WebIDL::ExceptionOr<GC::Ref<CryptoKey>> ED25519::import_key(
|
|||
return GC::Ref { *key };
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<GC::Ref<JS::Object>> ED25519::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-Ed25519 OID defined in [RFC8410].
|
||||
// * Set the subjectPublicKey field to keyData.
|
||||
auto ed25519_oid = TLS::ed25519_oid;
|
||||
auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_subject_public_key_info(key_data, ed25519_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-Ed25519 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 Ed25519 private key represented by the [[handle]] internal slot of key
|
||||
|
||||
auto ed25519_oid = TLS::ed25519_oid;
|
||||
auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_private_key_info(key_data, ed25519_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 "Ed25519".
|
||||
jwk.crv = "Ed25519"_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));
|
||||
} 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::Ed25519 curve;
|
||||
auto public_key = TRY_OR_THROW_OOM(vm, curve.generate_public_key(key_data));
|
||||
jwk.x = TRY_OR_THROW_OOM(vm, encode_base64url(key_data));
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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 Ed25519 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);
|
||||
}
|
||||
|
||||
WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> ED25519::sign([[maybe_unused]] AlgorithmParams const& params, GC::Ref<CryptoKey> key, ByteBuffer const& message)
|
||||
{
|
||||
auto& realm = *m_realm;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue