Skip to content

Conversation

@hkleungai
Copy link

@hkleungai hkleungai commented Jun 23, 2025

Opening this PR in favor of this comment from @Renegade334 in my another PR in DT repo.

Since https://nodejs.org/api/webcrypto.html#cryptokeyusages lists the usages in its own table, and it is closely aligned to the MDN reference in https://developer.mozilla.org/docs/Web/API/SubtleCrypto/generateKey, I believe it is possible to raise such change to @types/web as well.

Potentially we can do this to other methods in the key-usages table, but let's see how reviewers think about this change, then we may perform the refactoring incrementally in subsequent PRs.

Fallback signature is also updated, in favor of matching richer shape of possible Algorithm object.

@github-actions
Copy link
Contributor

Thanks for the PR!

This section of the codebase is owned by @saschanaz - if they write a comment saying "LGTM" then it will be merged.

Comment on lines 1797 to 1808
"typeParameters": [
{
"name": "T",
"extends": "{ name: string }"
}
],
"param": [
{
"name": "algorithm",
"overrideType": "string | T"
}
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary generic?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this generic is needed, or else the fallback signature will fail to capture poosibly-work algorithm object with extra attibutes other than name.

See https://tsplay.dev/N5oDdW.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No-one's raised any issues with AlgorithmIdentifier; this seems an arbitrary modification.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See https://tsplay.dev/Ndp9MN, in which the method call is taken from types/node/test/globals-non-dom.ts in DefinitelyTyped.

Without the use of generic, mismatched algorithm and keyUsages[] params would yield a confusing error, saying the code is violating the wrong overload.

But with the generic, such mismatch will pass and give Promise<CryptoKeyPair | CryptoKey>. It may not be the best way to typecheck, but I think this generic could help prevent certain possible breaking change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand – the whole point of this PR is that it breaks in this case?

The example provided is a mismatch with the accepted usages of the new HmacKeyGenParams signature, and is genuinely incorrect usage that would error at runtime. If we're going to provide a route for the new keyUsages constraints to be ignored anyway, then there's surely there's no real advantage to these changes?

(We can always modify that test – I suspect that the selection of keyUsages there was entirely arbitrary.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are right. I have repushed the PR to remove the generics.

@hkleungai hkleungai force-pushed the crypto-factorize-subtle.generateKey branch from 0dc3d22 to a6b6305 Compare July 4, 2025 08:40
@saschanaz
Copy link
Collaborator

Ok, enough procrastinating to review this...

I think this PR is incorrectly based on Node.js docs while it should be based on Web Cryptography spec. Node.js had some freedom to add more algorithms than Web Cryptography has.

Would be nice if this can be limited to what's listed in the spec.

Copy link
Contributor

@Bashamega Bashamega left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this quickly and added links to the relevant specs. It might be useful to also include those links as comments in the JSONC file for future reference.

I added one question as well, and left a comment about something that doesn’t appear to be covered by the spec.

I’m not familiar with cryptography, so I’d prefer not to make further changes until @saschanaz has reviewed and approved these updates.

Note: It would be preferable to migrate this to KDL now, since we’ll need to do so eventually. If you’re interested in handling the migration, you can refer to the WebGL KDL file for syntax guidance:
https://github.com/microsoft/TypeScript-DOM-lib-generator/blob/main/inputfiles/patches/webgl.kdl

The SubtleCrypto migration should be largely similar to the WebGL one.

"generateKey(algorithm: \"Ed25519\" | { name: \"Ed25519\" }, extractable: boolean, keyUsages: ReadonlyArray<\"sign\" | \"verify\">): Promise<CryptoKeyPair>",
"generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKeyPair>",
"generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>"
"generateKey(algorithm: RsaHashedKeyGenParams & { name: \"RSA-OAEP\" }, extractable: boolean, keyUsages: readonly (\"encrypt\" | \"decrypt\" | \"wrapKey\" | \"unwrapKey\")[]): Promise<CryptoKeyPair>",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKeyPair>",
"generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>"
"generateKey(algorithm: RsaHashedKeyGenParams & { name: \"RSA-OAEP\" }, extractable: boolean, keyUsages: readonly (\"encrypt\" | \"decrypt\" | \"wrapKey\" | \"unwrapKey\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: (RsaHashedKeyGenParams & { name: \"RSA-PSS\" | \"RSASSA-PKCS1-v1_5\" }) | EcKeyGenParams | \"Ed25519\" | { name: \"Ed25519\" } | \"Ed448\" | { name: \"Ed448\" }, extractable: boolean, keyUsages: readonly (\"sign\" | \"verify\")[]): Promise<CryptoKeyPair>",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>"
"generateKey(algorithm: RsaHashedKeyGenParams & { name: \"RSA-OAEP\" }, extractable: boolean, keyUsages: readonly (\"encrypt\" | \"decrypt\" | \"wrapKey\" | \"unwrapKey\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: (RsaHashedKeyGenParams & { name: \"RSA-PSS\" | \"RSASSA-PKCS1-v1_5\" }) | EcKeyGenParams | \"Ed25519\" | { name: \"Ed25519\" } | \"Ed448\" | { name: \"Ed448\" }, extractable: boolean, keyUsages: readonly (\"sign\" | \"verify\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: \"X25519\" | { name: \"X25519\" } | \"X448\" | { name: \"X448\" }, extractable: boolean, keyUsages: readonly (\"deriveKey\" | \"deriveBits\")[]): Promise<CryptoKeyPair>",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>"
"generateKey(algorithm: RsaHashedKeyGenParams & { name: \"RSA-OAEP\" }, extractable: boolean, keyUsages: readonly (\"encrypt\" | \"decrypt\" | \"wrapKey\" | \"unwrapKey\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: (RsaHashedKeyGenParams & { name: \"RSA-PSS\" | \"RSASSA-PKCS1-v1_5\" }) | EcKeyGenParams | \"Ed25519\" | { name: \"Ed25519\" } | \"Ed448\" | { name: \"Ed448\" }, extractable: boolean, keyUsages: readonly (\"sign\" | \"verify\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: \"X25519\" | { name: \"X25519\" } | \"X448\" | { name: \"X448\" }, extractable: boolean, keyUsages: readonly (\"deriveKey\" | \"deriveBits\")[]): Promise<CryptoKeyPair>",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"generateKey(algorithm: \"X25519\" | { name: \"X25519\" } | \"X448\" | { name: \"X448\" }, extractable: boolean, keyUsages: readonly (\"deriveKey\" | \"deriveBits\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: \"X25519\" | { name: \"X25519\" }, extractable: boolean, keyUsages: readonly (\"deriveKey\" | \"deriveBits\")[]): Promise<CryptoKeyPair>",

There is no mention of X448 in the specs

"generateKey(algorithm: RsaHashedKeyGenParams & { name: \"RSA-OAEP\" }, extractable: boolean, keyUsages: readonly (\"encrypt\" | \"decrypt\" | \"wrapKey\" | \"unwrapKey\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: (RsaHashedKeyGenParams & { name: \"RSA-PSS\" | \"RSASSA-PKCS1-v1_5\" }) | EcKeyGenParams | \"Ed25519\" | { name: \"Ed25519\" } | \"Ed448\" | { name: \"Ed448\" }, extractable: boolean, keyUsages: readonly (\"sign\" | \"verify\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: \"X25519\" | { name: \"X25519\" } | \"X448\" | { name: \"X448\" }, extractable: boolean, keyUsages: readonly (\"deriveKey\" | \"deriveBits\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: AesKeyGenParams & { name: \"AES-CBC\" | \"AES-CTR\" | \"AES-GCM\" }, extractable: boolean, keyUsages: readonly (\"encrypt\" | \"decrypt\" | \"wrapKey\" | \"unwrapKey\")[]): Promise<CryptoKey>",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"generateKey(algorithm: (RsaHashedKeyGenParams & { name: \"RSA-PSS\" | \"RSASSA-PKCS1-v1_5\" }) | EcKeyGenParams | \"Ed25519\" | { name: \"Ed25519\" } | \"Ed448\" | { name: \"Ed448\" }, extractable: boolean, keyUsages: readonly (\"sign\" | \"verify\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: \"X25519\" | { name: \"X25519\" } | \"X448\" | { name: \"X448\" }, extractable: boolean, keyUsages: readonly (\"deriveKey\" | \"deriveBits\")[]): Promise<CryptoKeyPair>",
"generateKey(algorithm: AesKeyGenParams & { name: \"AES-CBC\" | \"AES-CTR\" | \"AES-GCM\" }, extractable: boolean, keyUsages: readonly (\"encrypt\" | \"decrypt\" | \"wrapKey\" | \"unwrapKey\")[]): Promise<CryptoKey>",
"generateKey(algorithm: AesKeyGenParams & { name: \"AES-KW\" }, extractable: boolean, keyUsages: readonly (\"wrapKey\" | \"unwrapKey\")[]): Promise<CryptoKey>",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generateKey(algorithm: (RsaHashedKeyGenParams & { name: "RSA-PSS" | "RSASSA-PKCS1-v1_5" }) | EcKeyGenParams | "Ed25519" | { name: "Ed25519" } | "Ed448" | { name: "Ed448" }, extractable: boolean, keyUsages: readonly ("sign" | "verify")[]): Promise<CryptoKeyPair>;
generateKey(algorithm: "X25519" | { name: "X25519" } | "X448" | { name: "X448" }, extractable: boolean, keyUsages: readonly ("deriveKey" | "deriveBits")[]): Promise<CryptoKeyPair>;
generateKey(algorithm: AesKeyGenParams & { name: "AES-CBC" | "AES-CTR" | "AES-GCM" }, extractable: boolean, keyUsages: readonly ("encrypt" | "decrypt" | "wrapKey" | "unwrapKey")[]): Promise<CryptoKey>;
generateKey(algorithm: AesKeyGenParams & { name: "AES-KW" }, extractable: boolean, keyUsages: readonly ("wrapKey" | "unwrapKey")[]): Promise<CryptoKey>;
Copy link
Contributor

@Bashamega Bashamega Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate? How is it not a type?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, this is correct.

@hkleungai
Copy link
Author

Thank you for your feedback.

It has been a while since I worked on this PR... I will need some time (maybe over the weekend) to digest the comments and the latest dev on this repo first. :)

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.

4 participants