All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sigmastate.crypto.DiffieHellmanTupleProtocol.scala Maven / Gradle / Ivy

The newest version!
package sigmastate.crypto

import sigma.crypto.{BigIntegers, CryptoConstants, EcPointType}
import sigma.data.ProveDHTuple
import sigma.serialization.GroupElementSerializer
import sigmastate.crypto.VerifierMessage.Challenge

import java.math.BigInteger


case class DiffieHellmanTupleProverInput(w: BigInteger, commonInput: ProveDHTuple)
  extends SigmaProtocolPrivateInput[ProveDHTuple] {

  override lazy val publicImage: ProveDHTuple = commonInput
}

object DiffieHellmanTupleProverInput {

  import CryptoConstants.dlogGroup

  def random(): DiffieHellmanTupleProverInput = {
    val g = dlogGroup.generator
    val h = dlogGroup.createRandomGenerator()

    val qMinusOne = dlogGroup.order.subtract(BigInteger.ONE)
    val w = BigIntegers.createRandomInRange(BigInteger.ZERO, qMinusOne, dlogGroup.secureRandom)
    val u = dlogGroup.exponentiate(g, w)
    val v = dlogGroup.exponentiate(h, w)
    val ci = ProveDHTuple(g, h, u, v)
    DiffieHellmanTupleProverInput(w, ci)
  }
}

/** First message of Diffie Hellman tuple sigma protocol.
  * @param a commitment to secret randomness `a = g^r`, where `g` is default generator of the group
  * @param b commitment to secret randomness `b = h^r`, where `h` is another random generator of the group
  * @see createRandomGenerator in [[CryptoConstants.dlogGroup]]
  */
case class FirstDHTupleProverMessage(a: EcPointType, b: EcPointType)
  extends FirstProverMessage {
  override def bytes: Array[Byte] = {
    GroupElementSerializer.toBytes(a) ++ GroupElementSerializer.toBytes(b)
  }
}

/** Represents a response for challenge in Diffie Hellman tuple sigma protocol.
  * @param z responce to the challenge computed as `(r + ew) mod q`, where
  *          `r` is the prover's randomness,
  *          `e` challenge from the verifier (also computed by the prover in non-interactive case),
  *          `w` is the prover's secret.
  *          `q` is the group order
  */
case class SecondDHTupleProverMessage(z: BigInteger) extends SecondProverMessage

object DiffieHellmanTupleProver extends SigmaProtocolProver {

  import CryptoConstants.dlogGroup

  /** Create a commitment to randomness r and a first message of sigma protocol. */
  def firstMessage(publicInput: ProveDHTuple): (BigInteger, FirstDHTupleProverMessage) = {
    val qMinusOne = dlogGroup.order.subtract(BigInteger.ONE)
    val r = BigIntegers.createRandomInRange(BigInteger.ZERO, qMinusOne, dlogGroup.secureRandom)
    val a = dlogGroup.exponentiate(publicInput.g, r)
    val b = dlogGroup.exponentiate(publicInput.h, r)
    r -> FirstDHTupleProverMessage(a, b)
  }

  /** Creates second message of sigma protocol, which is a response for the challenge from the verifier.
    *
    * @param privateInput private input of the prover (secret)
    * @param rnd          random number generated by the prover (secret random number used to
    *                     compute commitment)
    * @param challenge    challenge from the verifier (also computed by the prover in non-interactive case)
    * @return second message from the prover
    */
  def secondMessage(privateInput: DiffieHellmanTupleProverInput,
                    rnd: BigInteger,
                    challenge: Challenge): SecondDHTupleProverMessage = {
    val z = responseToChallenge(privateInput, rnd, challenge)
    SecondDHTupleProverMessage(z)
  }

  /** Simulates messages of the sigma protocol which are indistinquishable from generated
    * by the real prover. */
  def simulate(publicInput: ProveDHTuple, challenge: Challenge): (FirstDHTupleProverMessage, SecondDHTupleProverMessage) = {

    val qMinusOne = dlogGroup.order.subtract(BigInteger.ONE)

    //SAMPLE a random z <- Zq, this will be the simulated response to the challenge
    val z = BigIntegers.createRandomInRange(BigInteger.ZERO, qMinusOne, dlogGroup.secureRandom)

    // COMPUTE a = g^z*u^(-e) and b = h^z*v^{-e}  (where -e here means -e mod q)
    // in real prover we compute commitments from random number and them compute response to the challenge,
    // but here we do in opposite direction, use random response and compute commitments from it
    val e: BigInteger = new BigInteger(1, challenge.toArray)
    val minusE = dlogGroup.order.subtract(e)
    val hToZ = dlogGroup.exponentiate(publicInput.h, z)
    val gToZ = dlogGroup.exponentiate(publicInput.g, z)
    val uToMinusE = dlogGroup.exponentiate(publicInput.u, minusE)
    val vToMinusE = dlogGroup.exponentiate(publicInput.v, minusE)
    val a = dlogGroup.multiplyGroupElements(gToZ, uToMinusE)
    val b = dlogGroup.multiplyGroupElements(hToZ, vToMinusE)
    FirstDHTupleProverMessage(a, b) -> SecondDHTupleProverMessage(z)
  }

  /**
    * The function computes initial prover's commitment to randomness
    * ("a" message of the sigma-protocol, which in this case has two parts "a" and "b")
    * based on the verifier's challenge ("e")
    * and prover's response ("z")
    *
    * g^z = a*u^e, h^z = b*v^e  => a = g^z/u^e, b = h^z/v^e
    *
    * @param proposition proposition "I know DH tuple"
    * @param challenge  challenge from verifier
    * @param secondMessage  prover's response to the challenge
    * @return
    */
  def computeCommitment(proposition: ProveDHTuple,
                        challenge: Challenge,
                        secondMessage: SecondDHTupleProverMessage): (EcPointType, EcPointType) = {

    val g = proposition.g
    val h = proposition.h
    val u = proposition.u
    val v = proposition.v

    val z = secondMessage.z

    val e = new BigInteger(1, challenge.toArray)

    val gToZ = dlogGroup.exponentiate(g, z)
    val hToZ = dlogGroup.exponentiate(h, z)

    val uToE = dlogGroup.exponentiate(u, e)
    val vToE = dlogGroup.exponentiate(v, e)

    val a = dlogGroup.multiplyGroupElements(gToZ, dlogGroup.inverseOf(uToE))
    val b = dlogGroup.multiplyGroupElements(hToZ, dlogGroup.inverseOf(vToE))
    a -> b
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy