List of usage examples for org.bouncycastle.math.ec ECPoint multiply
public ECPoint multiply(BigInteger k)
ECPoint
by the given number. From source file:l2fheBased.ZeroKnowledgeProofs.Zkp.java
License:Apache License
public Zkp(PublicParameters params, BigInteger eta1, BigInteger eta2, BigInteger eta3, SecureRandom rand, ECPoint c, ECPoint r, L1Ciphertext w1FHE, L1Ciphertext w2FHE, L1Ciphertext w3FHE, BigInteger w1, BigInteger w2, BigInteger w3, BigInteger randomness1, BigInteger randomness2, BigInteger randomness3) { this.w1 = w1; this.w2 = w2; this.w3 = w3; BigInteger N = params.paillierPubKey.getNS(); BigInteger q = BitcoinParams.q; BigInteger nSquared = params.paillierPubKey.getNSPlusOne(); BigInteger nTilde = params.nTilde; BigInteger h1 = params.h1;/*from w w w . j a v a2 s . co m*/ BigInteger h2 = params.h2; BigInteger g = params.paillierPubKey.getNPlusOne(); BigInteger alpha1 = randomFromZn(q.pow(3), rand); BigInteger alpha2 = randomFromZn(q.pow(3), rand); BigInteger alpha3 = randomFromZn(q.pow(7), rand); BigInteger beta1 = randomFromZnStar(N, rand); BigInteger beta2 = randomFromZnStar(N, rand); BigInteger beta3 = randomFromZnStar(N, rand); BigInteger gamma1 = randomFromZn(q.pow(3).multiply(nTilde), rand); BigInteger gamma2 = randomFromZn(q.pow(3).multiply(nTilde), rand); BigInteger gamma3 = randomFromZn(q.pow(7).multiply(nTilde), rand); BigInteger rho1 = randomFromZn(q.multiply(nTilde), rand); BigInteger rho2 = randomFromZn(q.multiply(nTilde), rand); BigInteger rho3 = randomFromZn(q.pow(5).multiply(nTilde), rand); z1 = modPowInsecure(h1, eta1, nTilde).multiply(modPowInsecure(h2, rho1, nTilde)).mod(nTilde); z2 = modPowInsecure(h1, eta2, nTilde).multiply(modPowInsecure(h2, rho2, nTilde)).mod(nTilde); z3 = modPowInsecure(h1, eta3, nTilde).multiply(modPowInsecure(h2, rho3, nTilde)).mod(nTilde); u1 = c.multiply(alpha1); u2 = modPowInsecure(g, alpha1, nSquared).multiply(modPowInsecure(beta1, N, nSquared)).mod(nSquared); u3 = modPowInsecure(g, alpha2, nSquared).multiply(modPowInsecure(beta2, N, nSquared)).mod(nSquared); u4 = modPowInsecure(g, alpha3, nSquared).multiply(modPowInsecure(beta3, N, nSquared)).mod(nSquared); v1 = modPowInsecure(h1, alpha1, nTilde).multiply(modPowInsecure(h2, gamma1, nTilde)).mod(nTilde); v2 = modPowInsecure(h1, alpha2, nTilde).multiply(modPowInsecure(h2, gamma2, nTilde)).mod(nTilde); v3 = modPowInsecure(h1, alpha3, nTilde).multiply(modPowInsecure(h2, gamma3, nTilde)).mod(nTilde); byte[] digest = sha256Hash(getBytes(c), getBytes(r), getBytes(w1FHE.a), getBytes(w1FHE.beta), getBytes(w2FHE.a), getBytes(w2FHE.beta), getBytes(w3FHE.a), getBytes(w3FHE.beta), getBytes(z1), getBytes(u1), getBytes(u2), getBytes(u3), getBytes(u4), getBytes(v1), getBytes(v2), getBytes(v3)); if (digest == null) { throw new AssertionError(); } e = new BigInteger(1, digest); s1 = e.multiply(eta1).add(alpha1); t1 = modPowInsecure(randomness1, e, N).multiply(beta1).mod(N); t2 = modPowInsecure(randomness2, e, N).multiply(beta2).mod(N); t3 = modPowInsecure(randomness3, e, N).multiply(beta3).mod(N); s3 = e.multiply(rho1).add(gamma1); s4 = e.multiply(eta2).add(alpha2); s5 = e.multiply(rho2).add(gamma2); s6 = e.multiply(eta3).add(alpha3); s7 = e.multiply(rho3).add(gamma3); }
From source file:l2fheBased.ZeroKnowledgeProofs.Zkp.java
License:Apache License
public boolean verify(final PublicParameters params, ECDomainParameters CURVE, final ECPoint r, final L1Ciphertext w1FHE, final L1Ciphertext w2FHE, final L1Ciphertext w3FHE) { final ECPoint c = params.getG(CURVE); final BigInteger h1 = params.h1; final BigInteger h2 = params.h2; final BigInteger N = params.paillierPubKey.getNS(); final BigInteger nTilde = params.nTilde; final BigInteger nSquared = params.paillierPubKey.getNSPlusOne(); final PaillierKey key = params.paillierPubKey.getPublicKey(); final BigInteger gamma = N.add(BigInteger.ONE); ExecutorService executor = Executors.newCachedThreadPool(); int numTests = 11; List<Callable<Boolean>> tests = new ArrayList<Callable<Boolean>>(11); // Callable<BigInteger> w1t = new Callable<BigInteger>() { // @Override//from w ww .j av a2s . com // public BigInteger call() { // return w1.toPaillierCiphertext(key); // } // }; // // Callable<BigInteger> w2t = new Callable<BigInteger>() { // @Override // public BigInteger call() { // return w2.toPaillierCiphertext(key); // } // }; // // Callable<BigInteger> w3t = new Callable<BigInteger>() { // @Override // public BigInteger call() { // return w3.toPaillierCiphertext(key); // } // }; // // final Future<BigInteger> w1val = executor.submit(w1t); // final Future<BigInteger> w2val = executor.submit(w2t); // final Future<BigInteger> w3val = executor.submit(w3t); tests.add(new Callable<Boolean>() { @Override public Boolean call() { return w1.equals(w1FHE.toPaillierCiphertext(key)); } }); tests.add(new Callable<Boolean>() { @Override public Boolean call() { return w2.equals(w2FHE.toPaillierCiphertext(key)); } }); tests.add(new Callable<Boolean>() { @Override public Boolean call() { return w3.equals(w3FHE.toPaillierCiphertext(key)); } }); tests.add(new Callable<Boolean>() { @Override public Boolean call() { return u1.equals(c.multiply(s1).add(r.multiply(e.negate()))); } }); tests.add(new Callable<Boolean>() { @Override public Boolean call() { return u2.equals(modPowInsecure(gamma, s1, nSquared).multiply(modPowInsecure(t1, N, nSquared)) .multiply(w1.modPow(e.negate(), nSquared)).mod(nSquared)); } }); tests.add(new Callable<Boolean>() { @Override public Boolean call() { return u3.equals(modPowInsecure(gamma, s4, nSquared).multiply(modPowInsecure(t2, N, nSquared)) .multiply(w2.modPow(e.negate(), nSquared)).mod(nSquared)); } }); tests.add(new Callable<Boolean>() { @Override public Boolean call() { return u4.equals(modPowInsecure(gamma, s6, nSquared).multiply(modPowInsecure(t3, N, nSquared)) .multiply(w3.modPow(e.negate(), nSquared)).mod(nSquared)); } }); tests.add(new Callable<Boolean>() { @Override public Boolean call() { return v1.equals(modPowInsecure(h1, s1, nTilde).multiply(modPowInsecure(h2, s3, nTilde)) .multiply(z1.modPow(e.negate(), nTilde)).mod(nTilde)); } }); tests.add(new Callable<Boolean>() { @Override public Boolean call() { return v2.equals(modPowInsecure(h1, s4, nTilde).multiply(modPowInsecure(h2, s5, nTilde)) .multiply(z2.modPow(e.negate(), nTilde)).mod(nTilde)); } }); tests.add(new Callable<Boolean>() { @Override public Boolean call() { return v3.equals(modPowInsecure(h1, s6, nTilde).multiply(modPowInsecure(h2, s7, nTilde)) .multiply(z3.modPow(e.negate(), nTilde)).mod(nTilde)); } }); tests.add(new Callable<Boolean>() { @Override public Boolean call() { byte[] digestRecovered = null; digestRecovered = sha256Hash(getBytes(c), getBytes(r), getBytes(w1FHE.a), getBytes(w1FHE.beta), getBytes(w2FHE.a), getBytes(w2FHE.beta), getBytes(w3FHE.a), getBytes(w3FHE.beta), getBytes(z1), getBytes(u1), getBytes(u2), getBytes(u3), getBytes(u4), getBytes(v1), getBytes(v2), getBytes(v3)); if (digestRecovered == null) { return false; } BigInteger eRecovered = new BigInteger(1, digestRecovered); return eRecovered.equals(e); } }); List<Future<Boolean>> futures = new ArrayList<Future<Boolean>>(numTests); for (Callable<Boolean> test : tests) { futures.add(executor.submit(test)); } for (Future<Boolean> future : futures) { try { if (!future.get().booleanValue()) { return false; } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } } executor.shutdown(); return true; // if (!u1.equals(c.multiply(s1).add(r.multiply(e.negate())))) { // return false; // } // // if (!u2.equals(gamma.modPow(s1, nSquared) // .multiply(t1.modPow(N, nSquared)) // .multiply(w1.modPow(e.negate(), nSquared)).mod(nSquared))) { // return false; // } // // if (!u3.equals(gamma.modPow(s4, nSquared) // .multiply(t2.modPow(N, nSquared)) // .multiply(w2.modPow(e.negate(), nSquared)).mod(nSquared))) { // return false; // } // // if (!u4.equals(gamma.modPow(s6, nSquared) // .multiply(t3.modPow(N, nSquared)) // .multiply(w3.modPow(e.negate(), nSquared)).mod(nSquared))) { // return false; // } // // if (!v1.equals(h1.modPow(s1, nTilde).multiply(h2.modPow(s3, nTilde)) // .multiply(z1.modPow(e.negate(), nTilde)).mod(nTilde))) { // return false; // } // // if (!v2.equals(h1.modPow(s4, nTilde).multiply(h2.modPow(s5, nTilde)) // .multiply(z2.modPow(e.negate(), nTilde)).mod(nTilde))) { // return false; // } // // if (!v3.equals(h1.modPow(s6, nTilde).multiply(h2.modPow(s7, nTilde)) // .multiply(z3.modPow(e.negate(), nTilde)).mod(nTilde))) { // return false; // } // // byte[] digestRecovered = sha256Hash(getBytes(c), getBytes(r), // getBytes(w1), getBytes(w2), getBytes(w3), getBytes(z1), // getBytes(u1), getBytes(u2), getBytes(u3), getBytes(u4), // getBytes(v1), getBytes(v2), getBytes(v3)); // // if (digestRecovered == null) { // return false; // } // // BigInteger eRecovered = new BigInteger(1, digestRecovered); // // if (!eRecovered.equals(e)) { // return false; // } // return true; }
From source file:libeac.tests.CPACECoreTest.java
License:Open Source License
public void testCalcX() throws Exception { m_pace.calcKPassword(m_szPw);/*from www . java2 s . c o m*/ m_pace.decryptNonce(DatatypeConverter.parseHexBinary("4dd3ea7e1d014d9f6c66940d4125496b")); IECPoint X = m_pace.calcX(); byte[] byaRnd = m_pace.getRand(); VMPCRandomGenerator rndGen = new VMPCRandomGenerator(); rndGen.nextBytes(byaRnd); X9ECParameters params = TeleTrusTNamedCurves.getByName("brainpoolp256r1"); ECCurve.Fp curve = (ECCurve.Fp) params.getCurve(); ECPoint base = params.getG(); ECPoint.Fp Xbc = (ECPoint.Fp) base.multiply(new BigInteger(1, byaRnd)); assertTrue(Arrays.equals(Xbc.getEncoded(), X.getEncoded())); }
From source file:org.cryptoworkshop.ximix.common.crypto.ECDecryptionProof.java
License:Apache License
/** * Return true if the decryption verifies * * @param pubKey public key corresponding to private value used. * @param c the point representing the cipher text * @param pTxt the point representing the plain text * @return true if plain text matches proof, false otherwise. *//*from w w w .ja v a 2 s. co m*/ public boolean isVerified(ECPublicKeyParameters pubKey, ECPoint c, ECPoint pTxt) { ECPoint g = pubKey.getParameters().getG(); BigInteger challenge = computeChallenge(a, b, c, pTxt, g, pubKey.getQ()); return g.multiply(this.getR()).normalize() .equals(this.getA().add(pubKey.getQ().multiply(challenge)).normalize()) // correct public key check && c.multiply(this.getR()).normalize() .equals(this.getB().add(pTxt.multiply(challenge)).normalize()); // correct decryption check }
From source file:org.cryptoworkshop.ximix.common.crypto.threshold.ECCommittedSecretShare.java
License:Apache License
/** * Return true if the share value is revealed by the commitment we carry, false otherwise. * * @param shareNumber the number of this share. * @param domainParams the domain parameters of the curve we expect to be on. * @param hValue the value of h used to commit against. * @return true if share is revealed by commitment, false otherwise. *//*from www. j av a 2s. c o m*/ public boolean isRevealed(int shareNumber, ECDomainParameters domainParams, ECPoint hValue) { return getCommitment(shareNumber).equals(domainParams.getG().multiply(share).add(hValue.multiply(witness))); }
From source file:org.ethereum.crypto.ECKey.java
License:Open Source 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>//ww w .j a va 2 s . c o m * * <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 the R and S components of the signature, wrapped. * @param messageHash Hash of the data that was signed. * @param compressed Whether or not the original pubkey was compressed. * @return An ECKey containing only the public part, or null if recovery wasn't possible. */ @Nullable public static ECKey recoverFromSignature(int recId, ECDSASignature sig, byte[] messageHash, boolean compressed) { check(recId >= 0, "recId must be positive"); check(sig.r.signum() >= 0, "r must be positive"); check(sig.s.signum() >= 0, "s must be positive"); check(messageHash != null, "messageHash must not be null"); // 1.0 For j from 0 to h (h == recId here and the loop is outside this function) // 1.1 Let x = r + jn BigInteger n = CURVE.getN(); // Curve order. BigInteger i = BigInteger.valueOf((long) recId / 2); BigInteger x = sig.r.add(i.multiply(n)); // 1.2. 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. // 1.3. 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 of Step 1. // // More concisely, what these points mean is to use X as a compressed public key. ECCurve.Fp curve = (ECCurve.Fp) CURVE.getCurve(); BigInteger prime = curve.getQ(); // Bouncy Castle is not consistent about the letter it uses for the prime. if (x.compareTo(prime) >= 0) { // Cannot have point co-ordinates larger than this as everything takes place modulo Q. return null; } // Compressed keys require you to know an extra bit of data about the y-coord as there are two possibilities. // So it's encoded in the recId. ECPoint r = decompressKey(x, (recId & 1) == 1); // 1.4. If nR != point at infinity, then do another iteration of Step 1 (callers responsibility). if (!r.multiply(n).isInfinity()) { return null; } // 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification. BigInteger e = new BigInteger(1, messageHash); // 1.6. For k from 1 to 2 do the following. (loop is outside this function via iterating recId) // 1.6.1. 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.r.modInverse(n); BigInteger srInv = rInv.multiply(sig.s).mod(n); BigInteger eInvrInv = rInv.multiply(eInv).mod(n); ECPoint.Fp q = (ECPoint.Fp) ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, r, srInv); return ECKey.fromPublicOnly(q.getEncoded(compressed)); }
From source file:org.kframework.backend.java.builtins.crypto.ECDSARecover.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>/*w w w. j a v a2 s .com*/ * * <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 the R and S components of the signature, wrapped. * @param messageHash Hash of the data that was signed. * @param compressed Whether or not the original pubkey was compressed. * @return An ECKey containing only the public part, or null if recovery wasn't possible. */ @Nullable public static ECDSARecover recoverFromSignature(int recId, ECDSASignature sig, byte[] messageHash, boolean compressed) { check(recId >= 0, "recId must be positive"); check(sig.r.signum() >= 0, "r must be positive"); check(sig.s.signum() >= 0, "s must be positive"); check(messageHash != null, "messageHash must not be null"); // 1.0 For j from 0 to h (h == recId here and the loop is outside this function) // 1.1 Let x = r + jn BigInteger n = CURVE.getN(); // Curve order. BigInteger i = BigInteger.valueOf((long) recId / 2); BigInteger x = sig.r.add(i.multiply(n)); // 1.2. 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. // 1.3. 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 of Step 1. // // More concisely, what these points mean is to use X as a compressed public key. ECCurve.Fp curve = (ECCurve.Fp) CURVE.getCurve(); BigInteger prime = curve.getQ(); // Bouncy Castle is not consistent about the letter it uses for the prime. if (x.compareTo(prime) >= 0) { // Cannot have point co-ordinates larger than this as everything takes place modulo Q. return null; } // Compressed keys require you to know an extra bit of data about the y-coord as there are two possibilities. // So it's encoded in the recId. ECPoint R = decompressKey(x, (recId & 1) == 1); // 1.4. If nR != point at infinity, then do another iteration of Step 1 (callers responsibility). if (!R.multiply(n).isInfinity()) return null; // 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification. BigInteger e = new BigInteger(1, messageHash); // 1.6. For k from 1 to 2 do the following. (loop is outside this function via iterating recId) // 1.6.1. 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.r.modInverse(n); BigInteger srInv = rInv.multiply(sig.s).mod(n); BigInteger eInvrInv = rInv.multiply(eInv).mod(n); ECPoint.Fp q = (ECPoint.Fp) ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, R, srInv); return ECDSARecover.fromPublicOnly(q.getEncoded(compressed)); }
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 *//* ww w . j ava 2s. c o m*/ 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.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 *//*from w w w . ja v a 2s .c o m*/ 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)); }
From source file:service.ACService.java
License:Open Source License
static private ECPoint[] constructPublicAttributeKeys(BigInteger[] private_key, ECPoint fixed_point) { ECPoint[] public_key = new ECPoint[private_key.length]; for (int i = 0; i < private_key.length; i++) { public_key[i] = fixed_point.multiply(private_key[i]); }/*from ww w . j av a2 s. co m*/ return public_key; }