@@ -9,6 +9,8 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters
99import org .bouncycastle .crypto .signers .{ECDSASigner , HMacDSAKCalculator }
1010import org .bouncycastle .math .ec .{ECCurve , ECPoint }
1111
12+ import scala .util .Try
13+
1214object ECDSASignature {
1315
1416 val SLength = 32
@@ -107,26 +109,28 @@ object ECDSASignature {
107109 chainId : Option [Byte ],
108110 messageHash : Array [Byte ]
109111 ): 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
127131 } else None
128- } else None
129- }
132+ }
133+ }.toOption.flatten
130134 }
131135
132136 private def constructPoint (xCoordinate : BigInt , recId : Int ): ECPoint = {
0 commit comments