Skip to content

X25519 CryptoKeys stored in IndexedDB are read back as null - #77415

Open
calamity5677 wants to merge 1 commit into
WebKit:mainfrom
calamity5677:eng/X25519-CryptoKey-stored-in-IndexedDB-returns-null
Open

calamity5677 wants to merge 1 commit into
WebKit:mainfrom
calamity5677:eng/X25519-CryptoKey-stored-in-IndexedDB-returns-null

Conversation

@calamity5677

@calamity5677 calamity5677 commented Oct 18, 2026 •

Copy link
Copy Markdown

1a3c1ce

X25519 CryptoKeys stored in IndexedDB are read back as null
https://bugs.webkit.org/show_bug.cgi?id=312279
rdar://175258859

Reviewed by NOBODY (OOPS!).

X25519 keys could not be round-tripped through structured cloning (and so
IndexedDB) at all. CryptoKeyOKP::isValidOKPAlgorithm() only accepted Ed25519,
so deserializing any X25519 key failed and IndexedDB returned null.

Fixing that exposed a second problem: the serialized OKP key does not record
the key type, and deserialization inferred it with CryptoKeyOKP::importRaw(),
which treats a key as private only if its usages contain "sign". This works
for Ed25519, but an X25519 private key (usages "deriveBits"/"deriveKey") would
come back as a public key holding the private key material.

Accept X25519 in isValidOKPAlgorithm(), and infer the key type per curve when
deserializing an OKP key: Ed25519 keys are private if they can sign, and X25519
keys are private if they can derive. Private keys can never have empty usages
and X25519 public keys always have empty usages, so this is unambiguous and
keeps the serialization format unchanged, including for X25519 keys that were
already written to IndexedDB. Also reject serialized OKP keys whose algorithm
and curve do not match, and fail deserialization instead of crashing on a null
key if the OKP key cannot be created.

Tests: crypto/subtle/ed25519-indexeddb.html
       crypto/subtle/x25519-indexeddb.html

* LayoutTests/crypto/subtle/ed25519-indexeddb-expected.txt: Added.
* LayoutTests/crypto/subtle/ed25519-indexeddb.html: Added.
* LayoutTests/crypto/subtle/x25519-indexeddb-expected.txt: Added.
* LayoutTests/crypto/subtle/x25519-indexeddb.html: Added.
* LayoutTests/platform/win/TestExpectations:
* Source/WebCore/bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneDeserializer::readOKPKey):
* Source/WebCore/crypto/keys/CryptoKeyOKP.cpp:
(WebCore::CryptoKeyOKP::isValidOKPAlgorithm):

1a3c1ce

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 win
✅ 🧪 bindings ✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 ✅ 🧪 win-tests
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 api-wpe
✅ 🧪 ios-wk2-wpt ⏳ 🧪 api-mac-debug
loading 🧪 api-ios ✅ 🧪 mac-wk2 ✅ 🛠 gtk3-gcc
✅ 🛠 ios-safer-cpp ✅ 🧪 mac-AS-debug-wk2 ✅ 🛠 gtk
✅ 🛠 vision ✅ 🧪 mac-wk2-stress ✅ 🧪 gtk-wk2
✅ 🛠 vision-sim ⏳ 🧪 mac-intel-wk2 ✅ 🧪 api-gtk
✅ 🧪 vision-wk2 ✅ 🛠 mac-safer-cpp   🛠 playstation
✅ 🛠 tv ✅ 🧪 mac-site-isolation
✅ 🛠 tv-sim
✅ 🛠 watch
✅ 🛠 watch-sim

https://bugs.webkit.org/show_bug.cgi?id=312279
rdar://175258859

Reviewed by NOBODY (OOPS!).

X25519 keys could not be round-tripped through structured cloning (and so
IndexedDB) at all. CryptoKeyOKP::isValidOKPAlgorithm() only accepted Ed25519,
so deserializing any X25519 key failed and IndexedDB returned null.

Fixing that exposed a second problem: the serialized OKP key does not record
the key type, and deserialization inferred it with CryptoKeyOKP::importRaw(),
which treats a key as private only if its usages contain "sign". This works
for Ed25519, but an X25519 private key (usages "deriveBits"/"deriveKey") would
come back as a public key holding the private key material.

Accept X25519 in isValidOKPAlgorithm(), and infer the key type per curve when
deserializing an OKP key: Ed25519 keys are private if they can sign, and X25519
keys are private if they can derive. Private keys can never have empty usages
and X25519 public keys always have empty usages, so this is unambiguous and
keeps the serialization format unchanged, including for X25519 keys that were
already written to IndexedDB. Also reject serialized OKP keys whose algorithm
and curve do not match, and fail deserialization instead of crashing on a null
key if the OKP key cannot be created.

Tests: crypto/subtle/ed25519-indexeddb.html
       crypto/subtle/x25519-indexeddb.html

* LayoutTests/crypto/subtle/ed25519-indexeddb-expected.txt: Added.
* LayoutTests/crypto/subtle/ed25519-indexeddb.html: Added.
* LayoutTests/crypto/subtle/x25519-indexeddb-expected.txt: Added.
* LayoutTests/crypto/subtle/x25519-indexeddb.html: Added.
* LayoutTests/platform/win/TestExpectations:
* Source/WebCore/bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneDeserializer::readOKPKey):
* Source/WebCore/crypto/keys/CryptoKeyOKP.cpp:
(WebCore::CryptoKeyOKP::isValidOKPAlgorithm):
@calamity5677
calamity5677 requested a review from cdumez as a code owner October 18, 2026 00:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants