package primitives import ( "cwtch.im/tapir/primitives/core" "github.com/bwesterb/go-ristretto" ) // DLProof Encapsulates a Discrete Log / Schnorr Proof // Note that these parameters are read-only. type DLProof struct { V, A ristretto.Point R ristretto.Scalar } // DiscreteLogProof - Proof of Knowledge of Exponent // Given V = xG // Peggy: z := choose randomly from Zq // A := zG // c := H(transcript(G,V,A)) mod q // r := (z + cx) mod q // // Sends A,r,V to Vicky func DiscreteLogProof(x ristretto.Scalar, v ristretto.Point, transcript *core.Transcript) (proof DLProof) { transcript.AddToTranscript("G", new(ristretto.Point).SetBase().Bytes()) // We bind the proof to our public V proof.V = v transcript.AddToTranscript("V", proof.V.Bytes()) // Generate a random z // A := zG z := new(ristretto.Scalar).Rand() proof.A = *new(ristretto.Point).ScalarMultBase(z) transcript.AddToTranscript("A", proof.A.Bytes()) // Derive Challenge c := transcript.CommitToTranscriptScalar("c") // r := (z + cx) mod p cx := new(ristretto.Scalar).Mul(c, &x) proof.R = *new(ristretto.Scalar).Add(z, cx) return } // VerifyDiscreteLogProof validates a given Schnorr Proof // Vicky gets A,r,V from Peggy // Vicky computes c := H(transcript(G,V,A)) mod q // Vicky checks rG := A + cV // rG ?= zG + cV // (z+cx)G ?= zG + cV // ?= zG + cxG // Thus demonstrating that Peggy knows the discrete log to V func VerifyDiscreteLogProof(proof DLProof, transcript *core.Transcript) bool { transcript.AddToTranscript("G", new(ristretto.Point).SetBase().Bytes()) transcript.AddToTranscript("V", proof.V.Bytes()) transcript.AddToTranscript("A", proof.A.Bytes()) c := transcript.CommitToTranscriptScalar("c") // Compute left hand side lhs := new(ristretto.Point).ScalarMultBase(&proof.R) // Compute right hand side cV := new(ristretto.Point).ScalarMult(&proof.V, c) rhs := new(ristretto.Point).Add(&proof.A, cV) // Result of verification: lhs ?= rhs return lhs.Equals(rhs) }