@@ -134,6 +134,11 @@ <h2>Introduction</h2>
134134 < a href ="#dfn-SubtleCrypto-method-decapsulateKey "> `SubtleCrypto.decapsulateKey`</ a > and
135135 < a href ="#dfn-SubtleCrypto-method-decapsulateBits "> `SubtleCrypto.decapsulateBits`</ a > .
136136 </ p >
137+ < p >
138+ Additionally, this proposal also introduces the < a href ="#dfn-SubtleCrypto-method-getPublicKey "> `SubtleCrypto.getPublicKey`</ a > function,
139+ which provides a convenient way to derive a public key from an asymmetric private key,
140+ eliminating the need to store both the public and private key separately when only the private key is needed.
141+ </ p >
137142 < p >
138143 Finally, this proposal aims to make feature detection easier,
139144 by adding a < a href ="#dfn-SubtleCrypto-method-supports "> `SubtleCrypto.supports`</ a > function,
@@ -187,6 +192,11 @@ <h2>Partial SubtleCrypto interface</h2>
187192 BufferSource ciphertext
188193 );
189194
195+ Promise<CryptoKey> getPublicKey(
196+ CryptoKey key,
197+ sequence<KeyUsage> keyUsages
198+ );
199+
190200 static boolean supports(DOMString operation,
191201 AlgorithmIdentifier algorithm,
192202 optional unsigned long? length = null);
@@ -720,6 +730,128 @@ <h4>The decapsulateBits method</h4>
720730 </ li >
721731 </ ol >
722732 </ section >
733+
734+ < section id ="SubtleCrypto-method-getPublicKey ">
735+ < h4 > The getPublicKey method</ h4 >
736+ < p >
737+ The < dfn id ="dfn-SubtleCrypto-method-getPublicKey " data-dfn-for =SubtleCrypto data-lt ="getPublicKey "> getPublicKey(|key|, |usages|)</ dfn >
738+ method returns the public key corresponding to a given private key.
739+ It behaves as follows:
740+ </ p >
741+ < ol >
742+ < li >
743+ < p >
744+ Let |key| and |usages| be the `key` and `keyUsages` parameters passed to the
745+ {{SubtleCrypto/getPublicKey()}} method,
746+ respectively.
747+ </ p >
748+ </ li >
749+ < li >
750+ < p >
751+ Let |algorithm| be the < a data-cite ="webcrypto#dfn-CryptoKey-slot-algorithm "> `[[algorithm]]`</ a > internal slot of |key|.
752+ </ p >
753+ </ li >
754+ < li >
755+ < p >
756+ If the cryptographic algorithm identified by |algorithm|
757+ does not support deriving a public key from a private key,
758+ then return a Promise rejected with a {{NotSupportedError}}.
759+ </ p >
760+ </ li >
761+ < li >
762+ < p >
763+ Let |realm| be the [= relevant realm =] of [= this =].
764+ </ p >
765+ </ li >
766+ < li >
767+ < p >
768+ Let |promise| be a new Promise.
769+ </ p >
770+ </ li >
771+ < li >
772+ < p >
773+ Return |promise| and perform the remaining steps [= in parallel =].
774+ </ p >
775+ </ li >
776+ < li >
777+ < p >
778+ If the following steps or referenced procedures say to
779+ [= exception/throw =] an error,
780+ [= queue a global task =] on the < a data-cite ="webcrypto#dfn-crypto-task-source "> crypto task source</ a > ,
781+ given |realm|'s global object,
782+ to reject |promise| with the returned error;
783+ and then < a data-cite ="webcrypto#terminate-the-algorithm "> terminate the algorithm</ a > .
784+ </ p >
785+ </ li >
786+ < li >
787+ < p >
788+ If the < a data-cite ="webcrypto#dfn-CryptoKey-slot-type "> `[[type]]`</ a > internal slot of
789+ |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
790+ </ p >
791+ </ li >
792+ < li >
793+ < p >
794+ If |usages| contains an entry which is not supported for a public key
795+ by the algorithm identified by |algorithm|,
796+ then [= exception/throw =] a {{SyntaxError}}.
797+ </ p >
798+ </ li >
799+ < li >
800+ < p >
801+ Let |publicKey| be a new {{CryptoKey}} representing the public key corresponding to
802+ the private key represented by the < a data-cite ="webcrypto#dfn-CryptoKey-slot-handle "> `[[handle]]`</ a >
803+ internal slot of |key|.
804+ </ p >
805+ </ li >
806+ < li >
807+ < p >
808+ If an error occurred, then [= exception/throw =] a {{OperationError}}.
809+ </ p >
810+ </ li >
811+ < li >
812+ < p >
813+ Set the < a data-cite ="webcrypto#dfn-CryptoKey-slot-type "> `[[type]]`</ a > internal slot of
814+ |publicKey| to {{KeyType/"public"}}.
815+ </ p >
816+ </ li >
817+ < li >
818+ < p >
819+ Set the < a data-cite ="webcrypto#dfn-CryptoKey-slot-algorithm "> `[[algorithm]]`</ a > internal
820+ slot of |publicKey| to |publicKeyAlgorithm|.
821+ </ p >
822+ </ li >
823+ < li >
824+ < p >
825+ Set the < a data-cite ="webcrypto#dfn-CryptoKey-slot-extractable "> `[[extractable]]`</ a > internal
826+ slot of |publicKey| to true.
827+ </ p >
828+ </ li >
829+ < li >
830+ < p >
831+ Set the < a data-cite ="webcrypto#dfn-CryptoKey-slot-usages "> `[[usages]]`</ a > internal slot of
832+ |publicKey| to |usages|.
833+ </ p >
834+ </ li >
835+ < li >
836+ < p >
837+ [= Queue a global task =] on the < a data-cite ="webcrypto#dfn-crypto-task-source "> crypto task source</ a > ,
838+ given |realm|'s global object, to perform the remaining steps.
839+ </ p >
840+ </ li >
841+ < li >
842+ < p >
843+ Let |result| be the result of converting |publicKey| to an ECMAScript Object in |realm|, as defined by [[WebIDL]].
844+ </ p >
845+ </ li >
846+ < li >
847+ < p >
848+ Resolve |promise| with
849+ |result|.
850+ </ p >
851+ </ li >
852+ </ ol >
853+ </ section >
854+
723855 < section id ="SubtleCrypto-method-supports ">
724856 < h4 > The supports method</ h4 >
725857 < p >
@@ -737,7 +869,7 @@ <h4>The supports method</h4>
737869 "`digest`", "`generateKey`", "`deriveKey`", "`deriveBits`",
738870 "`importKey`", "`exportKey`", "`wrapKey`", "`unwrapKey`",
739871 "`encapsulateKey`", "`encapsulateBits`",
740- "`decapsulateKey`" or "`decapsulateBits `",
872+ "`decapsulateKey`", "`decapsulateBits`" or "`getPublicKey `",
741873 return false.
742874 </ p >
743875 </ li >
@@ -766,7 +898,7 @@ <h4>The supports method</h4>
766898 "`digest`", "`generateKey`", "`deriveKey`", "`deriveBits`",
767899 "`importKey`", "`exportKey`", "`wrapKey`", "`unwrapKey`",
768900 "`encapsulateKey`", "`encapsulateBits`",
769- "`decapsulateKey`" or "`decapsulateBits `",
901+ "`decapsulateKey`", "`decapsulateBits`" or "`getPublicKey `",
770902 return false.
771903 </ p >
772904 </ li >
@@ -868,6 +1000,39 @@ <h3>Checking support for an algorithm</h3>
8681000 If |op| is "`decapsulateKey`" or "`decapsulateBits`", set |op| to "`decapsulate`".
8691001 </ p >
8701002 </ li >
1003+ < li >
1004+ < dl class ="switch ">
1005+ < dt > If |op| is "`getPublicKey`":</ dt >
1006+ < dd >
1007+ < ol >
1008+ < li >
1009+ < p >
1010+ Let |normalizedAlgorithm| be the result of
1011+ < a data-cite ="webcrypto#dfn-normalize-an-algorithm "> normalizing an algorithm</ a > , with
1012+ `alg` set to |alg| and `op` set to "`exportKey`".
1013+ </ p >
1014+ </ li >
1015+ < li >
1016+ < p >
1017+ If an error occurred, return false.
1018+ </ p >
1019+ </ li >
1020+ < li >
1021+ < p >
1022+ If the cryptographic algorithm identified by |normalizedAlgorithm|
1023+ does not support deriving a public key from a private key,
1024+ then return false.
1025+ </ p >
1026+ </ li >
1027+ < li >
1028+ < p >
1029+ Otherwise, return true.
1030+ </ p >
1031+ </ li >
1032+ </ ol >
1033+ </ dd >
1034+ </ dl >
1035+ </ li >
8711036 < li >
8721037 < p >
8731038 Let |normalizedAlgorithm| be the result of
0 commit comments