Module: BSV::Primitives::Schnorr

Defined in:
lib/bsv/primitives/schnorr.rb

Overview

BRC-94 Schnorr zero-knowledge proof protocol.

Provides generation and verification of Schnorr proofs for verifiable revelation of ECDH shared secrets. Given two public keys A and B and a shared secret S = a*B (where a is A’s private key), the prover can demonstrate knowledge of the discrete log relationship without revealing the private key.

See Also:

Defined Under Namespace

Classes: Proof

Class Method Summary collapse

Class Method Details

.generate_proof(private_key, public_key_a, public_key_b, shared_secret) ⇒ Proof

Generate a Schnorr proof of knowledge of a shared secret.

Proves that the prover knows the private key a such that shared_secret = a * public_key_b, without revealing a.

Parameters:

  • private_key (PrivateKey)

    the prover’s private key (a)

  • public_key_a (PublicKey)

    the prover’s public key (A = a*G)

  • public_key_b (PublicKey)

    the counterparty’s public key (B)

  • shared_secret (PublicKey)

    the ECDH shared secret (S = a*B)

Returns:

  • (Proof)

    the Schnorr proof



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/bsv/primitives/schnorr.rb', line 73

def generate_proof(private_key, public_key_a, public_key_b, shared_secret)
  nonce = PrivateKey.generate
  r_pub = nonce.public_key
  s_prime = PublicKey.new(Curve.multiply_point(public_key_b.point, nonce.bn))

  e = compute_challenge(public_key_a, public_key_b, shared_secret, s_prime, r_pub)

  z = (nonce.bn + (e * private_key.bn)) % Curve::N

  Proof.new(r_pub, s_prime, z)
end

.verify_proof(public_key_a, public_key_b, shared_secret, proof) ⇒ Boolean

Verify a Schnorr proof of knowledge of a shared secret.

Checks the two verification equations:

  1. z*G == R + e*A

  2. z*B == S’ + e*S

Parameters:

  • public_key_a (PublicKey)

    the prover’s public key

  • public_key_b (PublicKey)

    the counterparty’s public key

  • shared_secret (PublicKey)

    the claimed shared secret

  • proof (Proof)

    the Schnorr proof to verify

Returns:

  • (Boolean)

    true if the proof is valid



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/bsv/primitives/schnorr.rb', line 96

def verify_proof(public_key_a, public_key_b, shared_secret, proof)
  e = compute_challenge(public_key_a, public_key_b, shared_secret, proof.s_prime, proof.r)

  # Equation 1: z·G == R + e·A
  z_g = Curve.multiply_generator(proof.z)
  e_a = Curve.multiply_point(public_key_a.point, e)
  r_plus_ea = Curve.add_points(proof.r.point, e_a)

  return false unless points_equal?(z_g, r_plus_ea)

  # Equation 2: z·B == S' + e·S
  z_b = Curve.multiply_point(public_key_b.point, proof.z)
  e_s = Curve.multiply_point(shared_secret.point, e)
  sp_plus_es = Curve.add_points(proof.s_prime.point, e_s)

  points_equal?(z_b, sp_plus_es)
end