@@ -23,6 +23,7 @@ import org.bouncycastle.crypto.signers.ECDSASigner
2323import org.bouncycastle.crypto.signers.HMacDSAKCalculator
2424import org.bouncycastle.crypto.util.PrivateKeyFactory
2525import org.bouncycastle.crypto.util.PublicKeyFactory
26+ import org.bouncycastle.math.ec.ECPoint
2627import org.bouncycastle.util.BigIntegers
2728import java.math.BigInteger
2829
@@ -34,9 +35,7 @@ internal fun ecdsaP384Sign(m: ByteArray, sk: ByteArray, enforceLowS: Boolean = f
3435 if (m.isEmpty()) {
3536 throw ByteArrayLengthException (" m" , 0 , 1 , false )
3637 }
37- if (sk.size !=
38- ECDSA_P384_SECRETKEYBYTES
39- ) {
38+ if (sk.size != ECDSA_P384_SECRETKEYBYTES ) {
4039 throw ByteArrayLengthException (" sk" , sk.size, ECDSA_P384_SECRETKEYBYTES )
4140 }
4241
@@ -59,9 +58,20 @@ internal fun ecdsaP384Sign(m: ByteArray, sk: ByteArray, enforceLowS: Boolean = f
5958
6059 val components = signer.generateSignature(hash)
6160 val r = components[0 ]
62- var s = components[1 ]
63- if (enforceLowS && s > params.n shr 1 ) {
64- s = params.n - s
61+ val s = components[1 ]
62+
63+ return ecdsaFormatSignature(r, s, params.n, enforceLowS)
64+ }
65+
66+ internal fun ecdsaFormatSignature (
67+ r : BigInteger ,
68+ s : BigInteger ,
69+ n : BigInteger ,
70+ enforceLowS : Boolean = false
71+ ): ByteArray {
72+ var s = s
73+ if (enforceLowS && s > n shr 1 ) {
74+ s = n - s
6575 }
6676
6777 return BigIntegers .asUnsignedByteArray(ECDSA_P384_BYTES / 2 , r) +
@@ -120,31 +130,29 @@ internal fun p384SkToPk(sk: ByteArray): ByteArray {
120130 return q.getEncoded(true )
121131}
122132
123- internal fun p384VerifyPk (pk : ByteArray ) {
133+ internal fun p384VerifyPk (pk : ByteArray ): ECPoint {
124134 if (pk.size != ECDSA_P384_PUBLICKEYBYTES ) {
125135 throw ByteArrayLengthException (" pk" , pk.size, ECDSA_P384_PUBLICKEYBYTES )
126136 }
127137 if (pk[0 ] != 0x02 .toByte() && pk[0 ] != 0x03 .toByte()) {
128138 throw KeyV3Exception (" must use point compression" )
129139 }
130140
131- try {
132- val params = CustomNamedCurves .getByOID(SECObjectIdentifiers .secp384r1)
133- val q = try {
134- params.curve.decodePoint(pk)
135- } catch (ex: IllegalArgumentException ) {
136- throw KeyV3Exception (" decode point" , ex)
137- }
141+ val params = CustomNamedCurves .getByOID(SECObjectIdentifiers .secp384r1)
142+ val q = try {
143+ params.curve.decodePoint(pk)
144+ } catch (ex: IllegalArgumentException ) {
145+ throw KeyV3Exception (" decode point" , ex)
146+ }
138147
139- if (q.isInfinity) {
140- throw KeyV3Exception (" Point at infinity" )
141- }
142- if (! q.isValid) {
143- throw KeyV3Exception (" Point not on curve" )
144- }
145- } catch (e: IllegalArgumentException ) {
146- throw KeyV3Exception (e.message ? : " " , e)
148+ if (q.isInfinity) {
149+ throw KeyV3Exception (" Point at infinity" )
147150 }
151+ if (! q.isValid) {
152+ throw KeyV3Exception (" Point not on curve" )
153+ }
154+
155+ return q
148156}
149157
150158internal fun p384EncodeSkPkcs8 (sk : ByteArray ): ByteArray {
@@ -170,20 +178,24 @@ internal fun p384EncodeSkPkcs8(sk: ByteArray): ByteArray {
170178}
171179
172180internal fun p384DecodeSkPkcs8 (der : ByteArray ): ByteArray {
173- val params = PrivateKeyFactory .createKey(der) as ? ECPrivateKeyParameters
174- ? : throw KeyV3Exception (" Private key is not on secp384r1" )
175- val domain = params.parameters
176- val expected = CustomNamedCurves .getByOID(SECObjectIdentifiers .secp384r1)
181+ try {
182+ val params = PrivateKeyFactory .createKey(der) as ? ECPrivateKeyParameters
183+ ? : throw KeyV3Exception (" Private key is not on secp384r1" )
184+ val domain = params.parameters
185+ val expected = CustomNamedCurves .getByOID(SECObjectIdentifiers .secp384r1)
177186
178- if (domain.curve != expected.curve || domain.g != expected.g || domain.n != expected.n || domain.h != expected.h) {
179- throw KeyV3Exception (" Private key is not on secp384r1" )
180- }
187+ if (domain.curve != expected.curve || domain.g != expected.g || domain.n != expected.n || domain.h != expected.h) {
188+ throw KeyV3Exception (" Private key is not on secp384r1" )
189+ }
181190
182- if (params.d.signum() <= 0 || params.d >= domain.n) {
183- throw KeyV3Exception (" Invalid private key" )
184- }
191+ if (params.d.signum() <= 0 || params.d >= domain.n) {
192+ throw KeyV3Exception (" Invalid private key" )
193+ }
185194
186- return BigIntegers .asUnsignedByteArray(ECDSA_P384_SECRETKEYBYTES , params.d)
195+ return BigIntegers .asUnsignedByteArray(ECDSA_P384_SECRETKEYBYTES , params.d)
196+ } catch (ex: Throwable ) {
197+ throw KeyV3Exception (" invalid private key" , ex)
198+ }
187199}
188200
189201internal fun p384EncodeSkSec1 (sk : ByteArray ): ByteArray {
@@ -203,70 +215,62 @@ internal fun p384EncodeSkSec1(sk: ByteArray): ByteArray {
203215}
204216
205217internal fun p384DecodeSkSec1 (der : ByteArray ): ByteArray {
206- val key = ECPrivateKey .getInstance(ASN1Primitive .fromByteArray(der))
207- val curveParams = CustomNamedCurves .getByOID(SECObjectIdentifiers .secp384r1)
218+ try {
219+ val key = ECPrivateKey .getInstance(ASN1Primitive .fromByteArray(der))
220+ ? : throw KeyV3Exception (" Invalid private key" )
221+ val curveParams = CustomNamedCurves .getByOID(SECObjectIdentifiers .secp384r1)
222+
223+ key.parametersObject?.let { params ->
224+ when (params) {
225+ is ASN1ObjectIdentifier -> {
226+ if (params != SECObjectIdentifiers .secp384r1) {
227+ throw KeyV3Exception (" SEC1 key not on secp384r1" )
228+ }
229+ }
208230
209- key.parametersObject?.let { params ->
210- when (params) {
211- is ASN1ObjectIdentifier -> {
212- if (params != SECObjectIdentifiers .secp384r1) {
213- throw KeyV3Exception (" SEC1 key not on secp384r1" )
231+ else -> {
232+ throw KeyV3Exception (" Unsupported curve parameters" )
214233 }
215234 }
235+ } ? : throw KeyV3Exception (" SEC1 key must include curve parameters" )
216236
217- else -> {
218- throw KeyV3Exception ( " Unsupported curve parameters " )
219- }
237+ val d = key.key
238+ if (d.signum() <= 0 || d >= curveParams.n) {
239+ throw KeyV3Exception ( " Invalid P-384 private key " )
220240 }
221- } ? : throw KeyV3Exception (" SEC1 key must include curve parameters" )
222241
223- val d = key.key
224- if (d.signum() <= 0 || d >= curveParams.n ) {
225- throw KeyV3Exception (" Invalid P-384 private key" )
242+ return BigIntegers .asUnsignedByteArray( ECDSA_P384_SECRETKEYBYTES , d)
243+ } catch (ex : Throwable ) {
244+ throw KeyV3Exception (" Invalid private key" , ex )
226245 }
227-
228- return BigIntegers .asUnsignedByteArray(ECDSA_P384_SECRETKEYBYTES , d)
229246}
230247
231248internal fun p384EncodePkSpki (pk : ByteArray ): ByteArray {
232- val params = CustomNamedCurves .getByOID(SECObjectIdentifiers .secp384r1)
233- val point = try {
234- params.curve.decodePoint(pk)
235- } catch (ex: IllegalArgumentException ) {
236- throw KeyV3Exception (" decode point" , ex)
237- }
238-
239- if (point.isInfinity) {
240- throw KeyV3Exception (" Point at infinity" )
241- }
242- if (! point.isValid) {
243- throw KeyV3Exception (" Point not on curve" )
244- }
249+ val q = p384VerifyPk(pk)
245250
246251 return SubjectPublicKeyInfo (
247252 AlgorithmIdentifier (X9ObjectIdentifiers .id_ecPublicKey, SECObjectIdentifiers .secp384r1),
248- point .getEncoded(true ),
253+ q .getEncoded(true ),
249254 ).encoded
250255}
251256
252257internal fun p384DecodePkSpki (der : ByteArray ): ByteArray {
253- val params = PublicKeyFactory .createKey(der) as ? ECPublicKeyParameters
254- ? : throw KeyV3Exception (" Public key is not on secp384r1" )
255- val domain = params.parameters
256- val expected = CustomNamedCurves .getByOID(SECObjectIdentifiers .secp384r1)
258+ try {
259+ val params = PublicKeyFactory .createKey(der) as ? ECPublicKeyParameters
260+ ? : throw KeyV3Exception (" Public key is not on secp384r1" )
261+ val domain = params.parameters
262+ val expected = CustomNamedCurves .getByOID(SECObjectIdentifiers .secp384r1)
257263
258- if (domain.curve != expected.curve || domain.g != expected.g || domain.n != expected.n || domain.h != expected.h) {
259- throw KeyV3Exception (" Public key is not on secp384r1" )
260- }
264+ if (domain.curve!= expected.curve || domain.g!= expected.g || domain.n!= expected.n || domain.h!= expected.h) {
265+ throw KeyV3Exception (" Public key is not on secp384r1" )
266+ }
261267
262- if ( params.q.isInfinity) {
263- throw KeyV3Exception ( " Point at infinity " )
264- }
265- if ( ! params.q.isValid ) {
266- throw KeyV3Exception (" Point not on curve " )
268+ return params.q.getEncoded( true ). also {
269+ p384VerifyPk(it )
270+ }
271+ } catch (ex : Throwable ) {
272+ throw KeyV3Exception (" invalid public key " , ex )
267273 }
268-
269- return params.q.getEncoded(true )
270274}
271275
272276internal fun p384Generate (): Pair <ByteArray , ByteArray > {
0 commit comments