---
bip: 374
title: "Discrete Log Equality Proofs"
status: Draft
type: Specification
layer: "Applications"
authors: ["Andrew Toth","Ruben Somsen","Sebastian Falbesoner"]
assigned: 2024-12-26
last_modified: 2026-08-19
topics: ["wallets"]
license: "BSD-2-Clause"
url: https://bipexplorer.com/bip/374
source: https://github.com/bitcoin/bips/blob/master/bip-0374.mediawiki
---

# BIP 374: Discrete Log Equality Proofs

> **In plain English:** Standardizes a short cryptographic proof that someone used the same secret key in two related calculations, without revealing the key itself. This is useful, for example, to prove that a shared secret was computed honestly, which helps protocols like Silent Payments work safely with hardware wallets and multiple signers.

## Introduction

### Abstract

This document proposes a standard for 64-byte zero-knowledge _discrete logarithm equality proofs_ (DLEQ proofs) over an elliptic curve. For given elliptic curve points _A_, _B_, _C_, _G_, and a scalar _a_ known only to the prover where _A = a⋅G_ and _C = a⋅B_, the prover proves knowledge of _a_ without revealing anything about _a_. This can, for instance, be useful in ECDH: if _A_ and _B_ are ECDH public keys, and _C_ is their ECDH shared secret computed as _C = a⋅B_, the proof establishes that the same secret key _a_ is used for generating both _A_ and _C_ without revealing _a_.

### Copyright

This document is licensed under the 2-clause BSD license.

### Motivation

[BIP352](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#specification) requires senders to compute output scripts using ECDH shared secrets from the same secret keys used to sign the inputs. Generating an incorrect signature will produce an invalid transaction that will be rejected by consensus. An incorrectly generated output script can still be consensus-valid, meaning funds may be lost if it gets broadcast. By producing a DLEQ proof for the generated ECDH shared secrets, the signing entity can prove to other entities that the output scripts have been generated correctly without revealing the private keys.

## Specification

All conventions and notations are used as defined in [BIP327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki#notation).

### Description

The basic proof generation uses a random scalar _k_, the secret _a_, and the point being proven _C = a⋅B_.

-   Let _R1 = k⋅G_.

-   Let _R2 = k⋅B_.

-   Let _e = hash(R1 || R2)_.

-   Let _s = (k + e⋅a)_.

Providing only _C_, _e_ and _s_ as a proof does not reveal _a_ or _k_.

Verifying the proof involves recreating _R1_ and _R2_ with only _e_ and _s_ as follows:

-   Let _R1 = s⋅G - e⋅A_.

-   Let _R2 = s⋅B - e⋅C_.

This can be verified by substituting _s = (k + e⋅a)_:

-   _s⋅G - e⋅A = (k + e⋅a)⋅G - e⋅A = k⋅G + e⋅(a⋅G) - e⋅A = k⋅G + e⋅A - e⋅A = k⋅G_.

-   _s⋅B - e⋅C = (k + e⋅a)⋅B - e⋅C = k⋅B + e⋅(a⋅B) - e⋅C = k⋅B + e⋅C - e⋅C = k⋅B_.

Thus verifying _e = hash(R1 || R2)_ proves the discrete logarithm equivalency of _A_ and _C_.

### DLEQ Proof Generation

The following generates a proof that the result of _a⋅B_ and the result of _a⋅G_ are both generated from the same scalar _a_ without having to reveal _a_.

Input:

-   The secret key _a_: a 256-bit unsigned integer

-   The public key _B_: a point on the curve

-   Auxiliary random data _r_: a 32-byte array[1]

-   The generator point _G_: a point on the curve[2]

-   An optional message _m_: a 32-byte array[3]

The algorithm _GenerateProof(a, B, r, G, m)_ is defined as:

-   Fail if _a = 0_ or _a ≥ n_.

-   Fail if _is\_infinite(B)_.

-   Let _A = a⋅G_.

-   Let _C = a⋅B_.

-   Let _t_ be the byte-wise xor of _bytes(32, a)_ and _hashBIP0374/aux(r)_.

-   Let _m' = m if m is provided, otherwise an empty byte array_.

-   Let _rand = hashBIP0374/nonce(t || cbytes(A) || cbytes(C) || m')_.[4]

-   Let _k = int(rand) mod n_.

-   Fail if _k = 0_.

-   Let _R1 = k⋅G_.

-   Let _R2 = k⋅B_.

-   Let _e = int(hashBIP0374/challenge(cbytes(A) || cbytes(B) || cbytes(C) || cbytes(G) || cbytes(R1) || cbytes(R2) || m')) mod n_.

-   Let _s = (k + e⋅a) mod n_.

-   Let _proof = bytes(32, e) || bytes(32, s)_.

-   If _VerifyProof(A, B, C, proof, G, m)_ (see below) returns failure, abort.

-   Return the proof _proof_.

### DLEQ Proof Verification

The following verifies the proof generated in the previous section. If the following algorithm succeeds, the points _A_ and _C_ were both generated from the same scalar. The former from multiplying by _G_, and the latter from multiplying by _B_.

Input:

-   The public key of the secret key used in the proof generation _A_: a point on the curve

-   The public key used in the proof generation _B_: a point on the curve

-   The result of multiplying the secret and public keys used in the proof generation _C_: a point on the curve

-   A proof _proof_: a 64-byte array

-   The generator point used in the proof generation _G_: a point on the curve[5]

-   An optional message _m_: a 32-byte array[6]

The algorithm _VerifyProof(A, B, C, proof, G, m)_ is defined as:

-   Fail if any of _is\_infinite(A)_, _is\_infinite(B)_, _is\_infinite(C)_, _is\_infinite(G)_

-   Let _e = int(proof\[0:32\])_; fail if _e ≥ n_.

-   Let _s = int(proof\[32:64\])_; fail if _s ≥ n_.

-   Let _R1 = s⋅G - e⋅A_.

-   Fail if _is\_infinite(R1)_.

-   Let _R2 = s⋅B - e⋅C_.

-   Fail if _is\_infinite(R2)_.

-   Let _m' = m if m is provided, otherwise an empty byte array_.

-   Fail if _e ≠ int(hashBIP0374/challenge(cbytes(A) || cbytes(B) || cbytes(C) || cbytes(G) || cbytes(R1) || cbytes(R2) || m')) mod n_.

-   Return success iff no failure occurred before reaching this point.

## Backwards Compatibility

This proposal is compatible with all older clients.

## Test Vectors and Reference Code

A reference python implementation is included [here](https://github.com/bitcoin/bips/blob/master/bip-0374/reference.py). It uses a vendored copy of the [secp256k1lab](https://github.com/secp256k1lab/secp256k1lab/) library at version 1.0.0 (commit [44dc4bd893b8f03e621585e3bf255253e0e0fbfb](https://github.com/secp256k1lab/secp256k1lab/commit/44dc4bd893b8f03e621585e3bf255253e0e0fbfb)).

Test vectors can be generated by running `./bip-0374/gen_test_vectors.py` which will produce a CSV file of random test vectors for both generating and verifying proofs. These can be run against the reference implementation with `./bip-0374/run_test_vectors.py`.

## Changelog

-   0.3.0 (2026-08-19):
    -   Treat the challenge _e_ as a scalar (reduced modulo the curve order) and reject proofs with _e ≥ n_
-   0.2.0 (2025-02-27):
    -   Add the message to the rand computation
-   0.1.0 (2024-12-26):
    -   Initial version

## Footnotes

1.  **Why include auxiliary random data?** The auxiliary random data should be set to fresh randomness for each proof. The same rationale and recommendations from [BIP340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki#default-signing) should be applied. 
2.  **Why include the generator point G as an input?** While all other BIPs have used the generator point from secp256k1, passing it as an input here lets this algorithm be used for other curves. 
3.  **Why include a message as an input?** This could be useful for protocols that want to authorize on a compound statement, not just knowledge of a scalar. This allows the protocol to combine knowledge of the scalar and the statement. 
4.  **Why include the message in the rand computation?** Not including the message in the rand computation could leak _a_ if two proofs were constructed for the same _a_, _B_, and _G_ but a different message _m_ and an all-zero _r_. 
5.  **Why include the generator point G as an input?** While all other BIPs have used the generator point from Secp256k1, passing it as an input here lets this algorithm be used for other curves. 
6.  **Why include a message as an input?** This could be useful for protocols that want to authorize on a compound statement, not just knowledge of a scalar. This allows the protocol to combine knowledge of the scalar and the statement. 

## Acknowledgements

Thanks to josibake, Tim Ruffing, benma, stratospher, waxwing, Yuval Kogman and all others who participated in discussions on this topic.
