@@ -16,17 +16,17 @@ import java.math.*
1616import java.security.interfaces.*
1717import java.security.spec.*
1818
19- internal sealed class JdkEc <PublicK : EC .PublicKey , PrivateK : EC .PrivateKey , KP : EC .KeyPair <PublicK , PrivateK >>(
19+ internal sealed class JdkEc <PublicK : EC .PublicKey , PrivateK : EC .PrivateKey < PublicK > , KP : EC .KeyPair <PublicK , PrivateK >>(
2020 protected val state : JdkCryptographyState ,
2121) : EC<PublicK, PrivateK, KP> {
22+ protected abstract val wrapPublicKey: (JPublicKey ) -> PublicK
23+ protected abstract val wrapPrivateKey: (JPrivateKey , PublicK ? ) -> PrivateK
24+ protected abstract val wrapKeyPair: (PublicK , PrivateK ) -> KP
25+
2226 private fun algorithmParameters (spec : AlgorithmParameterSpec ): JAlgorithmParameters {
2327 return state.algorithmParameters(" EC" ).also { it.init (spec) }
2428 }
2529
26- protected abstract fun JPublicKey.convert (): PublicK
27- protected abstract fun JPrivateKey.convert (): PrivateK
28- protected abstract fun JKeyPair.convert (): KP
29-
3030 final override fun publicKeyDecoder (curve : EC .Curve ): KeyDecoder <EC .PublicKey .Format , PublicK > {
3131 return EcPublicKeyDecoder (algorithmParameters(ECGenParameterSpec (curve.jdkName)).curveName())
3232 }
@@ -54,19 +54,30 @@ internal sealed class JdkEc<PublicK : EC.PublicKey, PrivateK : EC.PrivateKey, KP
5454 initialize(keyGenParameters, state.secureRandom)
5555 }
5656
57- override fun JKeyPair.convert (): KP = with (this @JdkEc) { convert() }
57+ override fun JKeyPair.convert (): KP {
58+ val publicKey = wrapPublicKey(public)
59+ val privateKey = wrapPrivateKey(private, publicKey)
60+ return wrapKeyPair(publicKey, privateKey)
61+ }
5862 }
5963
6064 private inner class EcPublicKeyDecoder (
6165 private val curveName : String ,
6266 ) : JdkPublicKeyDecoder<EC.PublicKey.Format, PublicK>(state, " EC" ) {
67+
68+ fun fromPrivateKey (privateKey : ECPrivateKey ): PublicK = decode(
69+ BouncyCastleBridge .derivePublicKey(privateKey, curveName) ? : error(
70+ " Getting public key from private key for EC is not supported in JDK without BouncyCastle APIs"
71+ )
72+ )
73+
6374 override fun JPublicKey.convert (): PublicK {
6475 check(this is ECPublicKey )
6576
6677 val keyCurve = algorithmParameters(params).curveName()
6778 check(curveName == keyCurve) { " Key curve $keyCurve is not equal to expected curve $curveName " }
6879
69- return with (this @JdkEc) { convert() }
80+ return wrapPublicKey (this )
7081 }
7182
7283 override fun decodeFromByteArrayBlocking (format : EC .PublicKey .Format , bytes : ByteArray ): PublicK = when (format) {
@@ -98,7 +109,7 @@ internal sealed class JdkEc<PublicK : EC.PublicKey, PrivateK : EC.PrivateKey, KP
98109 val keyCurve = algorithmParameters(params).curveName()
99110 check(curveName == keyCurve) { " Key curve $keyCurve is not equal to expected curve $curveName " }
100111
101- return with (this @JdkEc) { convert() }
112+ return wrapPrivateKey (this , null )
102113 }
103114
104115 override fun decodeFromByteArrayBlocking (format : EC .PrivateKey .Format , bytes : ByteArray ): PrivateK = when (format) {
@@ -116,7 +127,7 @@ internal sealed class JdkEc<PublicK : EC.PublicKey, PrivateK : EC.PrivateKey, KP
116127 }
117128
118129 protected abstract class BaseEcPublicKey (
119- private val key : JPublicKey ,
130+ val key : JPublicKey ,
120131 ) : EC.PublicKey, JdkEncodableKey<EC.PublicKey.Format>(key) {
121132 final override fun encodeToByteArrayBlocking (format : EC .PublicKey .Format ): ByteArray = when (format) {
122133 EC .PublicKey .Format .JWK -> error(" $format is not supported" )
@@ -150,9 +161,19 @@ internal sealed class JdkEc<PublicK : EC.PublicKey, PrivateK : EC.PrivateKey, KP
150161
151162 }
152163
153- protected abstract class BaseEcPrivateKey (
154- private val key : JPrivateKey ,
155- ) : EC.PrivateKey, JdkEncodableKey<EC.PrivateKey.Format>(key) {
164+ protected abstract inner class BaseEcPrivateKey (
165+ val key : JPrivateKey ,
166+ private var publicKey : PublicK ? ,
167+ ) : EC.PrivateKey<PublicK>, JdkEncodableKey<EC.PrivateKey.Format>(key) {
168+ override fun getPublicKeyBlocking (): PublicK {
169+ if (publicKey == null ) {
170+ key as ECPrivateKey
171+ val curveName = algorithmParameters(key.params).curveName()
172+ publicKey = EcPublicKeyDecoder (curveName).fromPrivateKey(key)
173+ }
174+ return publicKey!!
175+ }
176+
156177 final override fun encodeToByteArrayBlocking (format : EC .PrivateKey .Format ): ByteArray = when (format) {
157178 EC .PrivateKey .Format .JWK -> error(" $format is not supported" )
158179 EC .PrivateKey .Format .DER -> encodeToDer()
0 commit comments