/* * Copyright 2014 Christopher Mann * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.uni_bonn.bit; import org.bitcoinj.core.ECKey; import de.uni_bonn.bit.wallet_protocol.*; import org.spongycastle.math.ec.ECPoint; import org.spongycastle.pqc.math.linearalgebra.IntegerFunctions; import java.math.BigInteger; import java.util.concurrent.ForkJoinTask; /** * This class implements the phone's part of the two-party ECDSA signature protocol. The phone takes the side of Bob * in the protocol. This class does not return any result. (The resulting ECDSA signature is returned by the * {@link de.uni_bonn.bit.DesktopSigner}). */ public class PhoneSigner { static final BigInteger nEC = ECKey.CURVE.getN(); PaillierKeyPair pkpDesktop; PaillierKeyPair pkpPhone; BCParameters desktopBCParameters; BCParameters phoneBCParameters; BigInteger privateKey; ECPoint otherPublicKey; MultiThreadingHelper multiThreadingHelper; private BigInteger alphaDesktop; private BigInteger beta; private BigInteger kPhone; private ECPoint RPhone; protected States state; public PhoneSigner(ECKey privateKey, ECKey otherPublicKey, PaillierKeyPair pkpDesktop, PaillierKeyPair pkpPhone, BCParameters desktopBCParameters, BCParameters phoneBCParameters) { this.pkpDesktop = pkpDesktop; this.pkpPhone = pkpPhone; this.desktopBCParameters = desktopBCParameters; this.phoneBCParameters = phoneBCParameters; this.privateKey = BitcoinECMathHelper.convertPrivKeyToBigInt(privateKey); this.otherPublicKey = BitcoinECMathHelper.convertPubKeyToPoint(otherPublicKey); this.multiThreadingHelper = new MultiThreadingHelper(); this.state = States.GenerateEphemeralValueShare; } public EphemeralValueShare generateEphemeralValueShare(SignatureParts signatureParts){ if(! state.equals(States.GenerateEphemeralValueShare)) throw new ProtocolException("Operation not allowed in this protocol state."); alphaDesktop = signatureParts.getAlphaDesktop(); beta = signatureParts.getBeta(); kPhone = IntegerFunctions.randomize(nEC); RPhone = ECKey.CURVE.getG().multiply(kPhone).normalize(); state = States.ComputeEncryptedSignature; return new EphemeralValueShare(RPhone); } public EncryptedSignatureWithProof computeEncryptedSignature(EphemeralPublicValueWithProof message, byte[] hash){ if(! state.equals(States.ComputeEncryptedSignature)) throw new ProtocolException("Operation not allowed in this protocol state."); ECPoint R = message.getR(); // We first check that R is associated with the correct curve and then we check that it is on the associated curve. if(! (R.getCurve().equals(ECKey.CURVE.getCurve()) && R.isValid())){ throw new ProtocolException("The point R provided by the desktop is invalid"); } ECPoint QPhone = ECKey.CURVE.getG().multiply(privateKey).normalize(); BigInteger zPhone = kPhone.modInverse(nEC); BigInteger r = R.normalize().getAffineXCoord().toBigInteger().mod(nEC); BigInteger hm = new BigInteger(1, hash); BigInteger randomizer = IntegerFunctions.randomize(nEC.pow(5)); BigInteger r3 = pkpDesktop.generateRandomizer(); BigInteger nsquaredDesktop = pkpDesktop.getN().pow(2); ForkJoinTask<BigInteger> sigma = multiThreadingHelper.PowMult(alphaDesktop, zPhone.multiply(hm), beta, zPhone.multiply(privateKey).mod(nEC).multiply(r), pkpDesktop.getG(), nEC.multiply(randomizer), r3, pkpDesktop.getN(), nsquaredDesktop); BigInteger r4 = pkpPhone.generateRandomizer(); BigInteger nsquaredPhone = pkpPhone.getN().pow(2); ForkJoinTask<BigInteger> alphaPhone = multiThreadingHelper.PowMult(pkpPhone.getG(), zPhone, r4, pkpPhone.getN(), nsquaredPhone); ForkJoinTask<BigInteger> c1 = multiThreadingHelper.PowMult(alphaDesktop, hm, nsquaredDesktop); ForkJoinTask<BigInteger> c2 = multiThreadingHelper.PowMult(beta, r, nsquaredDesktop); message.getProof().verify(alphaDesktop, beta, ECKey.CURVE.getG(), message.getR(), otherPublicKey, RPhone, pkpDesktop, desktopBCParameters, multiThreadingHelper); ZKProofPhone proof = ZKProofPhone.generateProof(zPhone, privateKey.multiply(zPhone).mod(nEC), randomizer, r3, r4, RPhone, QPhone, ECKey.CURVE.getG(), c1.join(), c2.join(), sigma.join(), alphaPhone.join(), pkpDesktop, pkpPhone, phoneBCParameters, multiThreadingHelper); state = States.Finished; return new EncryptedSignatureWithProof(sigma.join(), alphaPhone.join(), proof); } protected enum States{ GenerateEphemeralValueShare, ComputeEncryptedSignature, Finished } }