sigmastate.crypto.DLogProtocol.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sigma-state_2.12 Show documentation
Show all versions of sigma-state_2.12 Show documentation
Interpreter of a Sigma-State language
The newest version!
package sigmastate.crypto
import scorex.util.encode.Base16
import sigma.crypto.{BigIntegers, EcPointType}
import sigma.data.ProveDlog
import sigma.serialization.GroupElementSerializer
import sigma.crypto.CryptoConstants.dlogGroup
import sigmastate.crypto.VerifierMessage.Challenge
import java.math.BigInteger
/** Implementation of sigma protocol steps using discrete logarithm problem in EC group. */
object DLogProtocol {
/** Secret key of discrete logarithm signature protocol.
* @param w secret number in [0, q-1]
* where q - an order of DLog group.
*/
case class DLogProverInput(w: BigInteger)
extends SigmaProtocolPrivateInput[ProveDlog] {
import sigma.crypto.CryptoConstants.dlogGroup
override lazy val publicImage: ProveDlog = {
val g = dlogGroup.generator
ProveDlog(dlogGroup.exponentiate(g, w))
}
}
object DLogProverInput {
import sigma.crypto.CryptoConstants.dlogGroup
/** Create random secret in a range 0..q-1, where q - an order of DLog group. */
def random(): DLogProverInput = {
val qMinusOne = dlogGroup.order.subtract(BigInteger.ONE)
val w = BigIntegers.createRandomInRange(BigInteger.ZERO, qMinusOne, dlogGroup.secureRandom)
DLogProverInput(w)
}
}
/** First message of dlog-based sigma protocol.
* @param ecData commitment to randomness ecData = G^r, where
* G - generator of EC group,
* r - random number known only to prover from [0, q-1] range,
* where q - order of EC group.
*/
case class FirstDLogProverMessage(ecData: EcPointType) extends FirstProverMessage {
override def bytes: Array[Byte] = {
GroupElementSerializer.toBytes(ecData)
}
override def toString = s"FirstDLogProverMessage(${Base16.encode(bytes)})"
}
/** Second message of dlog-based sigma protocol.
* @param z response to the challenge from the verifier
* @see responseToChallenge()
*/
case class SecondDLogProverMessage(z: BigInt) extends SecondProverMessage
/** Prover operations of dlog-based sigma protocol. */
object DLogProver extends SigmaProtocolProver {
import sigma.crypto.CryptoConstants.secureRandom
/** Generate a first prover message with a commitment to a secret random number. */
def firstMessage(): (BigInteger, FirstDLogProverMessage) = {
import sigma.crypto.CryptoConstants.dlogGroup
val qMinusOne = dlogGroup.order.subtract(BigInteger.ONE) // q - 1
val r = BigIntegers.createRandomInRange(BigInteger.ZERO, qMinusOne, secureRandom) // r <- [0, q-1]
val a = dlogGroup.exponentiate(dlogGroup.generator, r) // g^r
r -> FirstDLogProverMessage(a)
}
/** Creates a second message of sigma protocol by computing
* `z = rnd + challenge * privateInput.w mod q`, where q - order of EC group.
*
* @param privateInput secret known only to prover from [0, q-1] range,
* @param rnd random number generated by the prover (secret random number used to
* compute commitment)
* @param challenge from the verifier (also computed by the prover in non-interactive case)
*/
def secondMessage(privateInput: DLogProverInput, rnd: BigInteger, challenge: Challenge): SecondDLogProverMessage = {
val z = responseToChallenge(privateInput, rnd, challenge)
SecondDLogProverMessage(z)
}
/** Simulation of sigma protocol. */
def simulate(publicInput: ProveDlog, challenge: Challenge): (FirstDLogProverMessage, SecondDLogProverMessage) = {
val qMinusOne = dlogGroup.order.subtract(BigInteger.ONE)
//SAMPLE a random z <- Zq
val z = BigIntegers.createRandomInRange(BigInteger.ZERO, qMinusOne, secureRandom)
//COMPUTE a = g^z*h^(-e) (where -e here means -e mod q)
val e: BigInteger = new BigInteger(1, challenge.toArray)
val minusE = dlogGroup.order.subtract(e)
val hToE = dlogGroup.exponentiate(publicInput.value, minusE)
val gToZ = dlogGroup.exponentiate(dlogGroup.generator, z)
val a = dlogGroup.multiplyGroupElements(gToZ, hToE)
FirstDLogProverMessage(a) -> SecondDLogProverMessage(z)
}
/**
* The function computes initial prover's commitment to randomness
* ("a" message of the sigma-protocol) based on the verifier's challenge ("e")
* and prover's response ("z")
*
* g^z = a*h^e => a = g^z/h^e
*
* @param proposition proposition being proved
* @param challenge challenge from verifier
* @param secondMessage prover's response to the challenge
* @return
*/
def computeCommitment(proposition: ProveDlog,
challenge: Challenge,
secondMessage: SecondDLogProverMessage): EcPointType = {
val g = dlogGroup.generator
val h = proposition.value
// COMPUTE a = g^z / h^e
dlogGroup.multiplyGroupElements(
dlogGroup.exponentiate(g, secondMessage.z.underlying()),
dlogGroup.inverseOf(dlogGroup.exponentiate(h, new BigInteger(1, challenge.toArray))))
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy