List of usage examples for org.bouncycastle.math.ec.custom.sec SecP256K1Curve getQ
public BigInteger getQ()
From source file:org.ScripterRon.BitcoinCore.ECKey.java
License:Apache License
/** * <p>Given the components of a signature and a selector value, recover and return the public key * that generated the signature according to the algorithm in SEC1v2 section 4.1.6.</p> * * <p>The recID is an index from 0 to 3 which indicates which of the 4 possible keys is the correct one. * Because the key recovery operation yields multiple potential keys, the correct key must either be * stored alongside the signature, or you must be willing to try each recId in turn until you find one * that outputs the key you are expecting.</p> * * <p>If this method returns null, it means recovery was not possible and recID should be iterated.</p> * * <p>Given the above two points, a correct usage of this method is inside a for loop from 0 to 3, and if the * output is null OR a key that is not the one you expect, you try again with the next recID.</p> * * @param recID Which possible key to recover. * @param sig R and S components of the signature * @param e The double SHA-256 hash of the original message * @param compressed Whether or not the original public key was compressed * @return An ECKey containing only the public part, or null if recovery wasn't possible *//*from w w w . j a va 2 s. c om*/ private static ECKey recoverFromSignature(int recID, ECDSASignature sig, BigInteger e, boolean compressed) { BigInteger n = ecParams.getN(); BigInteger i = BigInteger.valueOf((long) recID / 2); BigInteger x = sig.getR().add(i.multiply(n)); // // Convert the integer x to an octet string X of length mlen using the conversion routine // specified in Section 2.3.7, where mlen = (log2 p)/8 or mlen = m/8. // Convert the octet string (16 set binary digits)||X to an elliptic curve point R using the // conversion routine specified in Section 2.3.4. If this conversion routine outputs 'invalid', then // do another iteration. // // More concisely, what these points mean is to use X as a compressed public key. // SecP256K1Curve curve = (SecP256K1Curve) ecParams.getCurve(); BigInteger prime = curve.getQ(); if (x.compareTo(prime) >= 0) { return null; } // // Compressed keys require you to know an extra bit of data about the y-coordinate as // there are two possibilities. So it's encoded in the recID. // ECPoint R = decompressKey(x, (recID & 1) == 1); if (!R.multiply(n).isInfinity()) return null; // // For k from 1 to 2 do the following. (loop is outside this function via iterating recId) // Compute a candidate public key as: // Q = mi(r) * (sR - eG) // // Where mi(x) is the modular multiplicative inverse. We transform this into the following: // Q = (mi(r) * s ** R) + (mi(r) * -e ** G) // Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). // In the above equation, ** is point multiplication and + is point addition (the EC group operator). // // We can find the additive inverse by subtracting e from zero then taking the mod. For example the additive // inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod 11 = 8. // BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n); BigInteger rInv = sig.getR().modInverse(n); BigInteger srInv = rInv.multiply(sig.getS()).mod(n); BigInteger eInvrInv = rInv.multiply(eInv).mod(n); ECPoint q = ECAlgorithms.sumOfTwoMultiplies(ecParams.getG(), eInvrInv, R, srInv); return new ECKey(q.getEncoded(compressed)); }
From source file:org.ScripterRon.BitcoinCore.ECKey.java
License:Apache License
/** * Decompress a compressed public key (x coordinate and low-bit of y-coordinate). * * @param xBN X-coordinate * @param yBit Sign of Y-coordinate * @return Uncompressed public key *//*from w w w . java 2 s . co m*/ private static ECPoint decompressKey(BigInteger xBN, boolean yBit) { SecP256K1Curve curve = (SecP256K1Curve) ecParams.getCurve(); ECFieldElement x = curve.fromBigInteger(xBN); ECFieldElement alpha = x.multiply(x.square().add(curve.getA())).add(curve.getB()); ECFieldElement beta = alpha.sqrt(); if (beta == null) throw new IllegalArgumentException("Invalid point compression"); ECPoint ecPoint; BigInteger nBeta = beta.toBigInteger(); if (nBeta.testBit(0) == yBit) { ecPoint = curve.createPoint(x.toBigInteger(), nBeta); } else { ECFieldElement y = curve.fromBigInteger(curve.getQ().subtract(nBeta)); ecPoint = curve.createPoint(x.toBigInteger(), y.toBigInteger()); } return ecPoint; }
From source file:org.toporin.bitcoincore.ECKey.java
License:Apache License
/** * <p>Given the components of a signature and a selector value, recover and return the public key * that generated the signature according to the algorithm in SEC1v2 section 4.1.6.</p> * * <p>The recID is an index from 0 to 3 which indicates which of the 4 possible keys is the correct one. * Because the key recovery operation yields multiple potential keys, the correct key must either be * stored alongside the signature, or you must be willing to try each recId in turn until you find one * that outputs the key you are expecting.</p> * * <p>If this method returns null, it means recovery was not possible and recID should be iterated.</p> * * <p>Given the above two points, a correct usage of this method is inside a for loop from 0 to 3, and if the * output is null OR a key that is not the one you expect, you try again with the next recID.</p> * * @param recID Which possible key to recover. * @param sig R and S components of the signature * @param e The double SHA-256 hash of the original message * @param compressed Whether or not the original public key was compressed * @return An ECKey containing only the public part, or null if recovery wasn't possible *//*ww w . ja va 2s .c om*/ protected static ECKey recoverFromSignature(int recID, ECDSASignature sig, BigInteger e, boolean compressed) { BigInteger n = ecParams.getN(); BigInteger i = BigInteger.valueOf((long) recID / 2); BigInteger x = sig.getR().add(i.multiply(n)); // // Convert the integer x to an octet string X of length mlen using the conversion routine // specified in Section 2.3.7, where mlen = (log2 p)/8 or mlen = m/8. // Convert the octet string (16 set binary digits)||X to an elliptic curve point R using the // conversion routine specified in Section 2.3.4. If this conversion routine outputs 'invalid', then // do another iteration. // // More concisely, what these points mean is to use X as a compressed public key. // SecP256K1Curve curve = (SecP256K1Curve) ecParams.getCurve(); BigInteger prime = curve.getQ(); if (x.compareTo(prime) >= 0) { return null; } // // Compressed keys require you to know an extra bit of data about the y-coordinate as // there are two possibilities. So it's encoded in the recID. // ECPoint R = decompressKey(x, (recID & 1) == 1); if (!R.multiply(n).isInfinity()) return null; // // For k from 1 to 2 do the following. (loop is outside this function via iterating recId) // Compute a candidate public key as: // Q = mi(r) * (sR - eG) // // Where mi(x) is the modular multiplicative inverse. We transform this into the following: // Q = (mi(r) * s ** R) + (mi(r) * -e ** G) // Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). // In the above equation, ** is point multiplication and + is point addition (the EC group operator). // // We can find the additive inverse by subtracting e from zero then taking the mod. For example the additive // inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod 11 = 8. // BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n); BigInteger rInv = sig.getR().modInverse(n); BigInteger srInv = rInv.multiply(sig.getS()).mod(n); BigInteger eInvrInv = rInv.multiply(eInv).mod(n); ECPoint q = ECAlgorithms.sumOfTwoMultiplies(ecParams.getG(), eInvrInv, R, srInv); return new ECKey(q.getEncoded(compressed)); }