Skip to content

Commit

Permalink
Merge pull request #412 from ScorexFoundation/distributed-sigs
Browse files Browse the repository at this point in the history
Distributed signatures (spam and ergo tests passed)
  • Loading branch information
aslesarenko authored Aug 11, 2020
2 parents 0905651 + 8d6865a commit 6fc2491
Show file tree
Hide file tree
Showing 23 changed files with 1,042 additions and 298 deletions.
2 changes: 1 addition & 1 deletion sigmastate/src/main/scala/sigmastate/SigSerializer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ object SigSerializer {
def traverseNode(node: UncheckedSigmaTree,
acc: Array[Byte],
writeChallenge: Boolean = true): Array[Byte] = {
val parentChal = (if (writeChallenge) node.challenge else Array.emptyByteArray)
val parentChal = if (writeChallenge) node.challenge else Array.emptyByteArray
node match {
case dl: UncheckedSchnorr =>
acc ++
Expand Down
5 changes: 4 additions & 1 deletion sigmastate/src/main/scala/sigmastate/UnprovenTree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import com.google.common.primitives.Shorts
import gf2t.GF2_192_Poly
import sigmastate.basics.DLogProtocol.{FirstDLogProverMessage, ProveDlog}
import sigmastate.basics.VerifierMessage.Challenge
import sigmastate.Values.{SigmaBoolean, SigmaPropConstant}
import sigmastate.basics.{FirstDiffieHellmanTupleProverMessage, FirstProverMessage, ProveDHTuple, SigmaProtocol}
import sigmastate.serialization.ErgoTreeSerializer
import sigmastate.Values.{ErgoTree, SigmaBoolean, SigmaPropConstant}
import sigmastate.basics.{FirstDiffieHellmanTupleProverMessage, FirstProverMessage, ProveDHTuple}
import sigmastate.serialization.ErgoTreeSerializer.DefaultSerializer
Expand All @@ -24,7 +27,7 @@ trait ProofTree extends Product

trait ProofTreeLeaf extends ProofTree {
val proposition: SigmaBoolean
val commitmentOpt: Option[FirstProverMessage[_]]
val commitmentOpt: Option[FirstProverMessage]
}

trait ProofTreeConjecture extends ProofTree {
Expand Down
2 changes: 1 addition & 1 deletion sigmastate/src/main/scala/sigmastate/Values.scala
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ object Values {
case FalseProp.opCode => FalseProp
case TrueProp.opCode => TrueProp
case ProveDlogCode => dlogSerializer.parse(r)
case ProveDHTupleCode => dhtSerializer.parse(r)
case ProveDiffieHellmanTupleCode => dhtSerializer.parse(r)
case AndCode =>
val n = r.getUShort()
val children = new Array[SigmaBoolean](n)
Expand Down
61 changes: 8 additions & 53 deletions sigmastate/src/main/scala/sigmastate/basics/BcDlogGroup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,13 @@ abstract class BcDlogGroup[ElemType <: ECPoint](val x9params: X9ECParameters) ex
override lazy val identity: ElemType = curve.getInfinity.asInstanceOf[ElemType]


def createPoint(x: BigInteger, y: BigInteger): ElemType = curve.createPoint(x, y).asInstanceOf[ElemType]


/**
* Creates ECPoint.Fp with infinity values
* Create point from its affine coordinates
* @param x - X coordinate
* @param y - Y coordinate
* @return
*/
lazy val getInfinity: ElemType = curve.getInfinity.asInstanceOf[ElemType]
def createPoint(x: BigInteger, y: BigInteger): ElemType = curve.createPoint(x, y).asInstanceOf[ElemType]


/**
Expand All @@ -182,7 +182,7 @@ abstract class BcDlogGroup[ElemType <: ECPoint](val x9params: X9ECParameters) ex
* @return the inverse element of the given GroupElement
* @throws IllegalArgumentException
**/
override def getInverse(groupElement: ElemType): ElemType =
override def inverseOf(groupElement: ElemType): ElemType =
groupElement.negate().asInstanceOf[ElemType]

/**
Expand Down Expand Up @@ -413,54 +413,9 @@ abstract class BcDlogGroup[ElemType <: ECPoint](val x9params: X9ECParameters) ex
}
}

object SecP384R1 extends BcDlogGroup[SecP384R1Point](CustomNamedCurves.getByName("secp384r1")) with App {
val elems = 5000
val base = generator
val exps = (1 to elems).map { _ =>
val one = BigInteger.ONE
val qMinusOne = x9params.getN.subtract(one)
// choose a random number x in Zq*
BigIntegers.createRandomInRange(one, qMinusOne, secureRandom)
}.toArray

println(exps.map(e => exponentiateWithPreComputedValues(base, e) == exponentiate(base, e)).forall(_ == true))

var t0 = System.currentTimeMillis()
exps.foreach(exp => exponentiate(base, exp))
println(System.currentTimeMillis() - t0)
object SecP384R1 extends BcDlogGroup[SecP384R1Point](CustomNamedCurves.getByName("secp384r1"))


t0 = System.currentTimeMillis()
exps.foreach(exp => exponentiateWithPreComputedValues(base, exp))
println(System.currentTimeMillis() - t0)
}

object SecP521R1 extends BcDlogGroup[SecP521R1Point](CustomNamedCurves.getByName("secp521r1")) with App {
val elems = 1000
val bases = (1 to elems).map(_ => createRandomGenerator()).toArray
val exps = (1 to elems).map { _ =>
val one = BigInteger.ONE
val qMinusOne = x9params.getN.subtract(one)
// choose a random number x in Zq*
BigIntegers.createRandomInRange(one, qMinusOne, secureRandom)
}.toArray

var t0 = System.currentTimeMillis()
val naive = computeNaive(bases, exps)
println(System.currentTimeMillis() - t0)

t0 = System.currentTimeMillis()
val ll = computeLL(bases, exps)
println(System.currentTimeMillis() - t0)

println(naive.normalize().getAffineXCoord)
println(naive.normalize().getAffineYCoord)

println(ll.normalize().getAffineXCoord)
println(ll.normalize().getAffineYCoord)

println(naive == ll)
}
object SecP521R1 extends BcDlogGroup[SecP521R1Point](CustomNamedCurves.getByName("secp521r1"))

object Curve25519 extends BcDlogGroup[Curve25519Point](CustomNamedCurves.getByName("curve25519"))

Expand Down
19 changes: 12 additions & 7 deletions sigmastate/src/main/scala/sigmastate/basics/DLogProtocol.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import java.math.BigInteger
import org.bouncycastle.util.BigIntegers
import sigmastate.Values._
import Value.PropositionCode
import scorex.util.encode.Base16
import sigmastate._
import sigmastate.eval._
import sigmastate.basics.VerifierMessage.Challenge
Expand All @@ -23,7 +24,8 @@ object DLogProtocol {

/** Construct a new SigmaBoolean value representing public key of discrete logarithm signature protocol. */
case class ProveDlog(value: EcPointType)
extends SigmaProofOfKnowledgeTree[DLogSigmaProtocol, DLogProverInput] {
extends SigmaProofOfKnowledgeLeaf[DLogSigmaProtocol, DLogProverInput] {

override val opCode: OpCode = OpCodes.ProveDlogCode
lazy val h: EcPointType = value
lazy val pkBytes: Array[Byte] = GroupElementSerializer.toBytes(h)
Expand Down Expand Up @@ -64,14 +66,17 @@ object DLogProtocol {
}
}

case class FirstDLogProverMessage(ecData: EcPointType) extends FirstProverMessage[DLogSigmaProtocol] {
case class FirstDLogProverMessage(ecData: EcPointType) extends FirstProverMessage {
override type SP = DLogSigmaProtocol
override def bytes: Array[Byte] = {
GroupElementSerializer.toBytes(ecData)
}

override def toString: Idn = s"FirstDLogProverMessage(${Base16.encode(bytes)})"
}

case class SecondDLogProverMessage(z: BigInt) extends SecondProverMessage[DLogSigmaProtocol] {
override def bytes: Array[Byte] = z.toByteArray
case class SecondDLogProverMessage(z: BigInt) extends SecondProverMessage {
override type SP = DLogSigmaProtocol
}

class DLogInteractiveProver(override val publicInput: ProveDlog, override val privateInputOpt: Option[DLogProverInput])
Expand All @@ -83,7 +88,7 @@ object DLogProtocol {
assert(privateInputOpt.isDefined, "Secret is not known")
assert(rOpt.isEmpty, "Already generated r")

val (r, fm) = DLogInteractiveProver.firstMessage(publicInput)
val (r, fm) = DLogInteractiveProver.firstMessage()
rOpt = Some(r)
fm
}
Expand All @@ -110,7 +115,7 @@ object DLogProtocol {
object DLogInteractiveProver {
import CryptoConstants.secureRandom

def firstMessage(publicInput: ProveDlog): (BigInteger, FirstDLogProverMessage) = {
def firstMessage(): (BigInteger, FirstDLogProverMessage) = {
import CryptoConstants.dlogGroup

val qMinusOne = dlogGroup.order.subtract(BigInteger.ONE)
Expand Down Expand Up @@ -164,7 +169,7 @@ object DLogProtocol {

dlogGroup.multiplyGroupElements(
dlogGroup.exponentiate(g, secondMessage.z.underlying()),
dlogGroup.getInverse(dlogGroup.exponentiate(h, new BigInteger(1, challenge))))
dlogGroup.inverseOf(dlogGroup.exponentiate(h, new BigInteger(1, challenge))))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ case class DiffieHellmanTupleProverInput(w: BigInteger, commonInput: ProveDHTupl
}

object DiffieHellmanTupleProverInput {

import sigmastate.interpreter.CryptoConstants.dlogGroup

def random(): DiffieHellmanTupleProverInput = {
Expand All @@ -43,24 +44,28 @@ object DiffieHellmanTupleProverInput {

//a = g^r, b = h^r
case class FirstDiffieHellmanTupleProverMessage(a: CryptoConstants.EcPointType, b: CryptoConstants.EcPointType)
extends FirstProverMessage[DiffieHellmanTupleProtocol] {
extends FirstProverMessage {

override type SP = DiffieHellmanTupleProtocol

override def bytes: Array[Byte] = {
GroupElementSerializer.toBytes(a) ++ GroupElementSerializer.toBytes(b)
}
}

//z = r + ew mod q
case class SecondDiffieHellmanTupleProverMessage(z: BigInteger)
extends SecondProverMessage[DiffieHellmanTupleProtocol] {
override def bytes: Array[PropositionCode] = ???
case class SecondDiffieHellmanTupleProverMessage(z: BigInteger) extends SecondProverMessage {

override type SP = DiffieHellmanTupleProtocol

}

/** Construct a new SigmaProp value representing public key of Diffie Hellman signature protocol.
* Common input: (g,h,u,v)*/
* Common input: (g,h,u,v) */
case class ProveDHTuple(gv: EcPointType, hv: EcPointType, uv: EcPointType, vv: EcPointType)
extends SigmaProtocolCommonInput[DiffieHellmanTupleProtocol]
with SigmaProofOfKnowledgeTree[DiffieHellmanTupleProtocol, DiffieHellmanTupleProverInput] {
override val opCode: OpCode = OpCodes.ProveDHTupleCode
with SigmaProofOfKnowledgeLeaf[DiffieHellmanTupleProtocol, DiffieHellmanTupleProverInput] {
override val opCode: OpCode = OpCodes.ProveDiffieHellmanTupleCode
lazy val g = gv
lazy val h = hv
lazy val u = uv
Expand Down Expand Up @@ -115,6 +120,7 @@ class DiffieHellmanTupleInteractiveProver(override val publicInput: ProveDHTuple
}

object DiffieHellmanTupleInteractiveProver {

import sigmastate.interpreter.CryptoConstants.dlogGroup

def firstMessage(publicInput: ProveDHTuple): (BigInteger, FirstDiffieHellmanTupleProverMessage) = {
Expand All @@ -136,7 +142,7 @@ object DiffieHellmanTupleInteractiveProver {
}

def simulate(publicInput: ProveDHTuple, challenge: Challenge):
(FirstDiffieHellmanTupleProverMessage, SecondDiffieHellmanTupleProverMessage) = {
(FirstDiffieHellmanTupleProverMessage, SecondDiffieHellmanTupleProverMessage) = {

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

Expand Down Expand Up @@ -187,8 +193,8 @@ object DiffieHellmanTupleInteractiveProver {
val uToE = dlogGroup.exponentiate(u, e)
val vToE = dlogGroup.exponentiate(v, e)

val a = dlogGroup.multiplyGroupElements(gToZ, dlogGroup.getInverse(uToE))
val b = dlogGroup.multiplyGroupElements(hToZ, dlogGroup.getInverse(vToE))
val a = dlogGroup.multiplyGroupElements(gToZ, dlogGroup.inverseOf(uToE))
val b = dlogGroup.multiplyGroupElements(hToZ, dlogGroup.inverseOf(vToE))
a -> b
}
}
18 changes: 1 addition & 17 deletions sigmastate/src/main/scala/sigmastate/basics/DlogGroup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,6 @@ import org.bouncycastle.math.ec.ECPoint
* In cryptography, we are interested in groups for which the discrete logarithm problem
* (Dlog for short) is assumed to be hard. The most known groups of that kind are some Elliptic curve groups.
*
* Another issue pertaining elliptic curves is the need to find a suitable mapping that will convert an arbitrary
* message (that is some binary string) to an element of the group and vice-versa.
*
* Only a subset of the messages can be effectively mapped to a group element in such a way that there is a one-to-one
* injection that converts the string to a group element and vice-versa.
*
* On the other hand, any group element can be mapped to some string.
*
* In this case, the operation is not invertible. This functionality is implemented by the functions:
* - {@code encodeByteArrayToGroupElement(binaryString: Array[Byte]): ElemType}
* - {@code decodeGroupElementToByteArray(element: ElemType) : Array[Byte]}
* - {@code mapAnyGroupElementToByteArray(element: ElemType): Array[Byte]}
*
* The first two work as a pair and decodeGroupElementToByteArray is the inverse of encodeByteArrayToGroupElement,
* whereas the last one works alone and does not have an inverse.
*
* @tparam ElemType is concrete type
*/
trait DlogGroup[ElemType <: ECPoint] {
Expand Down Expand Up @@ -73,7 +57,7 @@ trait DlogGroup[ElemType <: ECPoint] {
* @return the inverse element of the given GroupElement
* @throws IllegalArgumentException
**/
def getInverse(groupElement: ElemType): ElemType
def inverseOf(groupElement: ElemType): ElemType

/**
* Raises the base GroupElement to the exponent. The result is another GroupElement.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.security.SecureRandom

import sigmastate.basics.VerifierMessage.Challenge
import sigmastate.interpreter.CryptoConstants
import sigmastate.{SigmaProofOfKnowledgeTree, UncheckedTree}
import sigmastate.{SigmaProofOfKnowledgeLeaf, UncheckedTree}
import supertagged.TaggedType

import scala.concurrent.Future
Expand All @@ -23,7 +23,6 @@ import scala.concurrent.Future


trait TranscriptMessage {
def bytes: Array[Byte]
}

/** The message sent by a prover to its associated verifier as part of a sigma protocol interaction. */
Expand All @@ -39,17 +38,23 @@ object VerifierMessage {
}

/** First message from the prover (message `a` of `SigmaProtocol`)*/
trait FirstProverMessage[SP <: SigmaProtocol[SP]] extends ProverMessage
trait FirstProverMessage extends ProverMessage {
type SP <: SigmaProtocol[SP]

def bytes: Array[Byte]
}

/** Second message from the prover (message `z` of `SigmaProtocol`)*/
trait SecondProverMessage[SP <: SigmaProtocol[SP]] extends ProverMessage
trait SecondProverMessage extends ProverMessage {
type SP <: SigmaProtocol[SP]
}

/** Abstract template for sigma protocols.
* For details see the following book
* [1] Efficient Secure Two-Party Protocols - Techniques and Constructions, p.150)*/
trait SigmaProtocol[SP <: SigmaProtocol[SP]] {
type A <: FirstProverMessage[SP]
type Z <: SecondProverMessage[SP]
type A <: FirstProverMessage
type Z <: SecondProverMessage
}


Expand Down Expand Up @@ -96,7 +101,7 @@ trait ZeroKnowledgeProofOfKnowledge[SP <: SigmaProtocol[SP]]

trait NonInteractiveProver[SP <: SigmaProtocol[SP],
PI <: SigmaProtocolPrivateInput[SP, CI],
CI <: SigmaProofOfKnowledgeTree[SP, PI],
CI <: SigmaProofOfKnowledgeLeaf[SP, PI],
P <: UncheckedTree]
extends Prover[SP, CI, PI] {

Expand Down
2 changes: 1 addition & 1 deletion sigmastate/src/main/scala/sigmastate/eval/Evaluation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ trait Evaluation extends RuntimeCosting { IR: IRContext =>
case SDBM.blake2b256(_, _) => CalcBlake2b256Code
case SDBM.sha256(_, _) => CalcSha256Code
case SDBM.proveDlog(_, _) => ProveDlogCode
case SDBM.proveDHTuple(_, _, _, _, _) => ProveDHTupleCode
case SDBM.proveDHTuple(_, _, _, _, _) => ProveDiffieHellmanTupleCode
case SDBM.sigmaProp(_, _) => BoolToSigmaPropCode
case SDBM.decodePoint(_, _) => DecodePointCode
case SDBM.xorOf(_, _) => XorOfCode
Expand Down
Loading

0 comments on commit 6fc2491

Please sign in to comment.