Skip to content

Commit 9afa965

Browse files
committed
Honor requested key usages in RSA generateKey
- msrcryptoRsa.generateKeyPair previously ignored the caller's requested usages (the usages: null || ... was a dead no-op) and forced a fixed pair, unlike AES/ECDH/ECDSA and RSA importKey which preserve p.usages. - It now filters the requested usages into the half each applies to: verify/sign for RSASSA-PKCS1-v1_5 and RSA-PSS; encrypt/wrapKey (public) and decrypt/unwrapKey (private) for RSA-OAEP/RSAES. Defaults to all valid usages when none are requested. - Fixes generating an RSA-OAEP key with ["wrapKey","unwrapKey"] producing a key that could not be used with subtle.wrapKey (rejected InvalidAccessError).
1 parent 1e9eabf commit 9afa965

2 files changed

Lines changed: 27 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- `SubtleCrypto.generateKey` for RSA algorithms now honors the requested key
13+
usages (routing each usage to the public or private key it applies to)
14+
instead of forcing a fixed pair. Generating an `RSA-OAEP` key with
15+
`["wrapKey", "unwrapKey"]` now yields keys usable with `wrapKey`/`unwrapKey`.
16+
17+
### Removed
18+
19+
- Dead, unreachable `wrapKey.js` module (legacy JWE-style key wrapping that was
20+
never dispatched) and its orphaned JWK byte-serializer helper. The public
21+
`wrapKey`/`unwrapKey` continue to work via the standard
22+
export-then-encrypt / decrypt-then-import path.
23+
1024
## [1.7.0] - 2026-06-25
1125

1226
### Added

src/rsa.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -463,14 +463,23 @@ if (typeof operations !== "undefined") {
463463
var algName = p.algorithm.name;
464464
var rsaKeyType = algName.slice(algName.indexOf("-") + 1).toUpperCase();
465465

466+
// The usages valid for each half of the key pair for this algorithm.
466467
var publicUsage, privateUsage;
467468

468469
if (algName === "RSASSA-PKCS1-V1_5" || algName === "RSA-PSS") {
469470
publicUsage = ["verify"];
470471
privateUsage = ["sign"];
471472
} else { // OAEP, RSAES
472-
publicUsage = ["encrypt"];
473-
privateUsage = ["decrypt"];
473+
publicUsage = ["encrypt", "wrapKey"];
474+
privateUsage = ["decrypt", "unwrapKey"];
475+
}
476+
477+
// Honor the caller's requested usages (like the other algorithms do),
478+
// routing each requested usage to the key half it applies to. When no
479+
// usages are requested, default to all usages valid for the algorithm.
480+
if (p.usages) {
481+
publicUsage = publicUsage.filter(function(usage) { return p.usages.indexOf(usage) >= 0; });
482+
privateUsage = privateUsage.filter(function(usage) { return p.usages.indexOf(usage) >= 0; });
474483
}
475484

476485
return {
@@ -481,7 +490,7 @@ if (typeof operations !== "undefined") {
481490
keyHandle: {
482491
algorithm: p.algorithm,
483492
extractable: p.extractable,
484-
usages: null || publicUsage,
493+
usages: publicUsage,
485494
type: "public"
486495
}
487496
},
@@ -490,7 +499,7 @@ if (typeof operations !== "undefined") {
490499
keyHandle: {
491500
algorithm: p.algorithm,
492501
extractable: p.extractable,
493-
usages: null || privateUsage,
502+
usages: privateUsage,
494503
type: "private"
495504
}
496505
}

0 commit comments

Comments
 (0)