Skip to content

Commit 73b241a

Browse files
committed
tmp
# Conflicts: # Libraries/LibWeb/Crypto/CryptoBindings.h
1 parent 3a9a8e3 commit 73b241a

6 files changed

Lines changed: 140 additions & 4 deletions

File tree

Libraries/LibCrypto/PK/EC.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class ECPublicKey {
3636
{
3737
}
3838

39+
UnsignedBigInteger const& x() const { return m_x; }
40+
UnsignedBigInteger const& y() const { return m_y; }
3941
size_t scalar_size() const { return m_scalar_size; }
4042

4143
ErrorOr<ByteBuffer> x_bytes() const

Libraries/LibWeb/Crypto/CryptoBindings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ JS::ThrowCompletionOr<JsonWebKey> JsonWebKey::parse(JS::Realm& realm, ReadonlyBy
8787

8888
#undef JWK_PARSE_STRING_PROPERTY
8989

90-
JS::ThrowCompletionOr<GC::Ref<JS::Object>> JsonWebKey::to_object(JS::Realm& realm)
90+
JS::ThrowCompletionOr<GC::Ref<JS::Object>> JsonWebKey::to_object(JS::Realm& realm) const
9191
{
9292
auto& vm = realm.vm();
9393
auto object = JS::Object::create(realm, realm.intrinsics().object_prototype());

Libraries/LibWeb/Crypto/CryptoBindings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ struct JsonWebKey {
4848
Optional<String> pub;
4949
Optional<String> priv;
5050

51-
JS::ThrowCompletionOr<GC::Ref<JS::Object>> to_object(JS::Realm&);
51+
JS::ThrowCompletionOr<GC::Ref<JS::Object>> to_object(JS::Realm&) const;
5252

5353
static JS::ThrowCompletionOr<JsonWebKey> parse(JS::Realm& realm, ReadonlyBytes data);
5454
};

Libraries/LibWeb/Crypto/CryptoKey.cpp

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ JS_DEFINE_NATIVE_FUNCTION(CryptoKeyPair::private_key_getter)
137137
return TRY(Bindings::throw_dom_exception_if_needed(vm, [&] { return impl->private_key(); }));
138138
}
139139

140+
// https://w3c.github.io/webcrypto/#cryptokey-interface-serializable
140141
WebIDL::ExceptionOr<void> CryptoKey::serialization_steps(HTML::TransferDataEncoder& serialized, bool for_storage, HTML::SerializationMemory& memory)
141142
{
142143
auto& vm = this->vm();
@@ -155,11 +156,48 @@ WebIDL::ExceptionOr<void> CryptoKey::serialization_steps(HTML::TransferDataEncod
155156
auto serialized_usages = TRY(HTML::structured_serialize_internal(vm, m_usages, for_storage, memory));
156157
serialized.append(move(serialized_usages));
157158

158-
// FIXME: 5. Set serialized.[[Handle]] to the [[handle]] internal slot of value.
159+
// 5. Set serialized.[[Handle]] to the [[handle]] internal slot of value.
160+
TRY(m_key_data.visit(
161+
[&](ByteBuffer const& data) -> WebIDL::ExceptionOr<void> {
162+
TRY(HTML::serialize_string(vm, serialized, "bytes"_string));
163+
TRY(HTML::serialize_bytes(vm, serialized, data));
164+
return {};
165+
},
166+
[&](Bindings::JsonWebKey const& jwk) -> WebIDL::ExceptionOr<void> {
167+
TRY(HTML::serialize_string(vm, serialized, "jwk"_string));
168+
auto serialized_jwk = TRY(HTML::structured_serialize_internal(vm, TRY(jwk.to_object(realm())), for_storage, memory));
169+
serialized.extend(move(serialized_jwk));
170+
return {};
171+
},
172+
[&](::Crypto::PK::RSAPublicKey const& public_key) -> WebIDL::ExceptionOr<void> {
173+
TRY(HTML::serialize_string(vm, serialized, "rsa-pub"_string));
174+
auto bytes = TRY_OR_THROW_OOM(vm, public_key.export_as_der());
175+
TRY(HTML::serialize_bytes(vm, serialized, bytes));
176+
return {};
177+
},
178+
[&](::Crypto::PK::RSAPrivateKey const& private_key) -> WebIDL::ExceptionOr<void> {
179+
TRY(HTML::serialize_string(vm, serialized, "rsa-priv"_string));
180+
auto bytes = TRY_OR_THROW_OOM(vm, private_key.export_as_der());
181+
TRY(HTML::serialize_bytes(vm, serialized, bytes));
182+
return {};
183+
},
184+
[&](::Crypto::PK::ECPublicKey const& public_key) -> WebIDL::ExceptionOr<void> {
185+
TRY(HTML::serialize_string(vm, serialized, "ec-pub"_string));
186+
auto bytes = TRY_OR_THROW_OOM(vm, public_key.to_uncompressed());
187+
TRY(HTML::serialize_bytes(vm, serialized, bytes));
188+
return {};
189+
},
190+
[&](::Crypto::PK::ECPrivateKey const& private_key) -> WebIDL::ExceptionOr<void> {
191+
TRY(HTML::serialize_string(vm, serialized, "ec-priv"_string));
192+
auto bytes = TRY_OR_THROW_OOM(vm, private_key.export_as_der());
193+
TRY(HTML::serialize_bytes(vm, serialized, bytes));
194+
return {};
195+
}));
159196

160197
return {};
161198
}
162199

200+
// https://w3c.github.io/webcrypto/#cryptokey-interface-serializable
163201
WebIDL::ExceptionOr<void> CryptoKey::deserialization_steps(HTML::TransferDataDecoder& serialized, HTML::DeserializationMemory& memory)
164202
{
165203
auto& vm = this->vm();
@@ -179,7 +217,31 @@ WebIDL::ExceptionOr<void> CryptoKey::deserialization_steps(HTML::TransferDataDec
179217
deserialized = TRY(HTML::structured_deserialize_internal(vm, serialized, realm, memory));
180218
m_usages = deserialized.as_object();
181219

182-
// FIXME: 5. Initialize the [[handle]] internal slot of value to serialized.[[Handle]].
220+
// 5. Initialize the [[handle]] internal slot of value to serialized.[[Handle]].
221+
auto deserialized_key_data_type = TRY(HTML::deserialize_string(vm, serialized, position));
222+
if (deserialized_key_data_type == "bytes") {
223+
m_key_data = TRY(HTML::deserialize_bytes(vm, serialized, position));
224+
} else if (deserialized_key_data_type == "jwk") {
225+
VERIFY_NOT_REACHED();
226+
} else if (deserialized_key_data_type == "rsa-pub") {
227+
auto bytes = TRY(HTML::deserialize_bytes(vm, serialized, position));
228+
auto key_pair = MUST(::Crypto::PK::RSA::parse_rsa_key(bytes, false, {}));
229+
m_key_data = key_pair.public_key;
230+
} else if (deserialized_key_data_type == "rsa-priv") {
231+
auto bytes = TRY(HTML::deserialize_bytes(vm, serialized, position));
232+
auto key_pair = MUST(::Crypto::PK::RSA::parse_rsa_key(bytes, true, {}));
233+
m_key_data = key_pair.private_key;
234+
} else if (deserialized_key_data_type == "ec-pub") {
235+
auto bytes = TRY(HTML::deserialize_bytes(vm, serialized, position));
236+
auto key_pair = MUST(::Crypto::PK::EC::parse_ec_key(bytes, false, {}));
237+
m_key_data = key_pair.public_key;
238+
} else if (deserialized_key_data_type == "ec-priv") {
239+
auto bytes = TRY(HTML::deserialize_bytes(vm, serialized, position));
240+
auto key_pair = MUST(::Crypto::PK::EC::parse_ec_key(bytes, true, {}));
241+
m_key_data = key_pair.private_key;
242+
} else {
243+
VERIFY_NOT_REACHED();
244+
}
183245

184246
return {};
185247
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
AES-GCM kty: true
2+
AES-GCM key_ops: false
3+
AES-GCM alg: false
4+
AES-GCM ext: true
5+
AES-GCM k: false
6+
Caught error while running async test: OperationError: unclear key size
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<!DOCTYPE html>
2+
<script src="../include.js"></script>
3+
<script>
4+
async function prepareDatabase() {
5+
const req = window.indexedDB.open("TestDatabase");
6+
7+
return new Promise((resolve, reject) => {
8+
req.onerror = () => {
9+
reject(req.error);
10+
};
11+
req.onupgradeneeded = () => {
12+
req.result.createObjectStore("TestObjectStore");
13+
};
14+
req.onsuccess = () => {
15+
resolve(req.result);
16+
};
17+
})
18+
}
19+
20+
async function awaitRequest(request) {
21+
return new Promise((resolve, reject) => {
22+
request.onerror = () => {
23+
reject(request.error);
24+
};
25+
request.onsuccess = () => {
26+
resolve(request.result);
27+
};
28+
});
29+
}
30+
31+
asyncTest(async (done) => {
32+
for (const [algo, usages] of [
33+
[{name: "AES-GCM", length: 256}, ["encrypt", "decrypt"]],
34+
[{name: "AES-CBC", length: 256}, ["encrypt", "decrypt"]],
35+
[{name: "AES-KW", length: 256}, ["wrapKey", "unwrapKey"]],
36+
[{name: "HMAC", hash: {name: "SHA-256"}}, ["sign", "verify"]],
37+
[{name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-256"}}, ["sign", "verify"]],
38+
[{name: "ECDSA", namedCurve: "P-256"}, ["sign", "verify"]],
39+
[{name: "Ed25519"}, ["sign", "verify"]],
40+
]) {
41+
const originalKey = await crypto.subtle.generateKey(algo, true, usages);
42+
43+
const db = await prepareDatabase()
44+
45+
const tx = db.transaction("TestObjectStore", "readwrite");
46+
const store = tx.objectStore("TestObjectStore");
47+
await awaitRequest(store.put(originalKey, "testKey"));
48+
49+
const serializedKey = await awaitRequest(store.get("testKey"));
50+
51+
const originalKeyJwk = await crypto.subtle.exportKey("jwk", originalKey);
52+
53+
try {
54+
const serializedKeyJwk = await crypto.subtle.exportKey("jwk", serializedKey);
55+
56+
for (const key of Object.keys(originalKeyJwk)) {
57+
println(`${algo.name} ${key}: ${originalKeyJwk[key] === serializedKeyJwk[key]}`);
58+
}
59+
} catch (e) {
60+
println(`${algo.name}: ${e}`);
61+
}
62+
}
63+
64+
done();
65+
});
66+
</script>

0 commit comments

Comments
 (0)