@@ -9,6 +9,8 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters
9
9
import org .bouncycastle .crypto .signers .{ECDSASigner , HMacDSAKCalculator }
10
10
import org .bouncycastle .math .ec .{ECCurve , ECPoint }
11
11
12
+ import scala .util .Try
13
+
12
14
object ECDSASignature {
13
15
14
16
val SLength = 32
@@ -107,26 +109,28 @@ object ECDSASignature {
107
109
chainId : Option [Byte ],
108
110
messageHash : Array [Byte ]
109
111
): Option [Array [Byte ]] = {
110
- val order = curve.getCurve.getOrder
111
- // ignore case when x = r + order because it is negligibly improbable
112
- // says: https://github.com/paritytech/rust-secp256k1/blob/f998f9a8c18227af200f0f7fdadf8a6560d391ff/depend/secp256k1/src/ecdsa_impl.h#L282
113
- val xCoordinate = r
114
- val curveFp = curve.getCurve.asInstanceOf [ECCurve .Fp ]
115
- val prime = curveFp.getQ
116
-
117
- getRecoveredPointSign(recId, chainId).flatMap { recovery =>
118
- if (xCoordinate.compareTo(prime) < 0 ) {
119
- val R = constructPoint(xCoordinate, recovery)
120
- if (R .multiply(order).isInfinity) {
121
- val e = BigInt (1 , messageHash)
122
- val rInv = r.modInverse(order)
123
- // Q = r^(-1)(sR - eG)
124
- val q = R .multiply(s.bigInteger).subtract(curve.getG.multiply(e.bigInteger)).multiply(rInv.bigInteger)
125
- // byte 0 of encoded ECC point indicates that it is uncompressed point, it is part of bouncycastle encoding
126
- Some (q.getEncoded(false ).tail)
112
+ Try {
113
+ val order = curve.getCurve.getOrder
114
+ // ignore case when x = r + order because it is negligibly improbable
115
+ // says: https://github.com/paritytech/rust-secp256k1/blob/f998f9a8c18227af200f0f7fdadf8a6560d391ff/depend/secp256k1/src/ecdsa_impl.h#L282
116
+ val xCoordinate = r
117
+ val curveFp = curve.getCurve.asInstanceOf [ECCurve .Fp ]
118
+ val prime = curveFp.getQ
119
+
120
+ getRecoveredPointSign(recId, chainId).flatMap { recovery =>
121
+ if (xCoordinate.compareTo(prime) < 0 ) {
122
+ val R = constructPoint(xCoordinate, recovery)
123
+ if (R .multiply(order).isInfinity) {
124
+ val e = BigInt (1 , messageHash)
125
+ val rInv = r.modInverse(order)
126
+ // Q = r^(-1)(sR - eG)
127
+ val q = R .multiply(s.bigInteger).subtract(curve.getG.multiply(e.bigInteger)).multiply(rInv.bigInteger)
128
+ // byte 0 of encoded ECC point indicates that it is uncompressed point, it is part of bouncycastle encoding
129
+ Some (q.getEncoded(false ).tail)
130
+ } else None
127
131
} else None
128
- } else None
129
- }
132
+ }
133
+ }.toOption.flatten
130
134
}
131
135
132
136
private def constructPoint (xCoordinate : BigInt , recId : Int ): ECPoint = {
0 commit comments