Advertisement
Guest User

Blurgh

a guest
May 25th, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 3.26 KB | None | 0 0
  1. @Nullable
  2.     public static byte[] recoverPubBytesFromSignature(int recId, ECDSASignature sig, byte[] messageHash) {
  3.         check(recId >= 0, "recId must be positive");
  4.         check(sig.r.signum() >= 0, "r must be positive");
  5.         check(sig.s.signum() >= 0, "s must be positive");
  6.         check(messageHash != null, "messageHash must not be null");
  7.         // 1.0 For j from 0 to h   (h == recId here and the loop is outside this function)
  8.         //   1.1 Let x = r + jn
  9.         BigInteger n = CURVE.getN();  // Curve order.
  10.         BigInteger i = BigInteger.valueOf((long) recId / 2);
  11.         BigInteger x = sig.r.add(i.multiply(n));
  12.         //   1.2. Convert the integer x to an octet string X of length mlen using the conversion routine
  13.         //        specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉.
  14.         //   1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R using the
  15.         //        conversion routine specified in Section 2.3.4. If this conversion routine outputs “invalid”, then
  16.         //        do another iteration of Step 1.
  17.         //
  18.         // More concisely, what these points mean is to use X as a compressed public key.
  19.         ECCurve.Fp curve = (ECCurve.Fp) CURVE.getCurve();
  20.         BigInteger prime = curve.getQ();  // Bouncy Castle is not consistent about the letter it uses for the prime.
  21.         if (x.compareTo(prime) >= 0) {
  22.             // Cannot have point co-ordinates larger than this as everything takes place modulo Q.
  23.             return null;
  24.         }
  25.         // Compressed keys require you to know an extra bit of data about the y-coord as there are two possibilities.
  26.         // So it's encoded in the recId.
  27.         ECPoint R = decompressKey(x, (recId & 1) == 1);
  28.         //   1.4. If nR != point at infinity, then do another iteration of Step 1 (callers responsibility).
  29.         if (!R.multiply(n).isInfinity())
  30.             return null;
  31.         //   1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification.
  32.         BigInteger e = new BigInteger(1, messageHash);
  33.         //   1.6. For k from 1 to 2 do the following.   (loop is outside this function via iterating recId)
  34.         //   1.6.1. Compute a candidate public key as:
  35.         //               Q = mi(r) * (sR - eG)
  36.         //
  37.         // Where mi(x) is the modular multiplicative inverse. We transform this into the following:
  38.         //               Q = (mi(r) * s ** R) + (mi(r) * -e ** G)
  39.         // Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). In the above equation
  40.         // ** is point multiplication and + is point addition (the EC group operator).
  41.         //
  42.         // We can find the additive inverse by subtracting e from zero then taking the mod. For example the additive
  43.         // inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod 11 = 8.
  44.         BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n);
  45.         BigInteger rInv = sig.r.modInverse(n);
  46.         BigInteger srInv = rInv.multiply(sig.s).mod(n);
  47.         BigInteger eInvrInv = rInv.multiply(eInv).mod(n);
  48.         ECPoint.Fp q = (ECPoint.Fp) ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, R, srInv);
  49.         return q.getEncoded(/* compressed */ false);
  50.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement