Does anybody know an efficient mechanism to prove the possession of a digital signature (e.g. RSA) on a certain attribute (message) in zero-knowledge? That is, without revealing the actual signature (against tracking, for privacy) prove that you have one? Thanks a lot in advance!
-
It would be trivial if you could generate the signature in question. Is this your scenario? – rath May 05 '14 at 13:05
-
My scenario is that the attribute is signed by another party. That is, I can not generate the signature. Instead, I'd like to prove I have this signature without revealing it. This should happen in such a way that two different proof session are unlinkable to each other. – OnTarget May 05 '14 at 13:22
-
If both of you possess the signature you could ask for a nonce and reply with the hash of the nonce and the signature. I take it only one party has the signature? – rath May 05 '14 at 13:29
-
2Are you familiar with the concept of multi-show (unlinkable) anonymous credentials? They are built upon re-randomizable signature schemes which have the properties you require and are used in exactly the way you want it. Well known candidates are CL credentials Strong RSA or Pairing based or built upon the pairing based BBS signature scheme. – DrLecter May 05 '14 at 13:36
-
Thanks for your comments, guys. With respect to your comment, @DrLecter, I'm familiar with the concept of Camenish-Lysyanskaya one-show credentials based on CL-signatures. A caveat is, however, they can be used only with the specific CL-signatures and are rather complex. It would be nice to have something similar for conventional group signatures, e.g. RSA- or DSA-alike. (In this case, obtaining a signature does not have to be fully anonymous against an issuer). Any ideas? – OnTarget May 05 '14 at 14:43
-
@user13397 CL signatures as well as BBS signatures allow to built multi-show and not only one-show credentials. What do you exactly mean by "not fully anonymous against the issuer"? Is your assumption that issuer and verifier are distinct and do not communicate to identify a user? – DrLecter May 05 '14 at 15:04
-
1I meant, the requirement of user anonymity (with respect to user-side secrets) against the issuer during the issuance of the credential. Verifier and Issuer are parts of one system in my case, so they do communicate with each other. With respect to "one-show" I really meant "multi-show and unlinkable". Since both CL and BBS are fairly complex, I would like to know if there is any high-level description of such systems (e.g. a lecture, etc.). For example, both of them essentially use a public reference parameter with certain trapdoor built in (to issuer credentials)..... And so on. Thanks! – OnTarget May 05 '14 at 17:31
-
One could do this with BLS signatures. $:$ One could even use that to show possession of signatures for at least $m$ out of a list of $n$ messages. $;;;;$ – May 05 '14 at 19:12
-
@OnTarget Why would you consider CL credentials one-show? Direct Anonymous Attestation admits multiple show. For reference: IACR preprint 2004/205. – Vadym Fedyukovych May 10 '15 at 14:07
3 Answers
Guillou and Quisquater (link) present a zero-knowledge proof of an RSA signature. Basically, the scheme is as follows:
Public knowledge: RSA modulus $n$, public RSA exponent $v$, preimage $X$.
Secret knowledge for prover: $A$, such that $A^v = X \mod n$.
$$ \begin{matrix} \mathcal{P} & & \mathcal{V} \\ r \xleftarrow{\$} \mathbb{Z}_n^* \phantom{\mod n} & & \\ T \leftarrow r^v \mod n & & \\ & \xrightarrow{\quad{}T\quad{}} & \\ & & d \xleftarrow{\$} \{0,1,\ldots,v-1\} \\ & \xleftarrow{d} & \\ t \leftarrow A^dr \mod n & & \\ & \xrightarrow{\quad{}t\quad} & \\ & & t^v \stackrel{?}{=} X^{d}T \mod n \end{matrix} $$
In this diagram, $\leftarrow$ denotes assignment of a value to a variable and $\xleftarrow{\$}$ denotes uniformly random selection from a finite set.

- 1,450
- 9
- 10
-
1Nice, but here you require that signer and verifier are distinct entities and do not communicate, because any verifier must not know the factorization of $n$ (and in a previous comment the OP wrote "Verifier and Issuer are parts of one system in my case, so they do communicate with each other."). But this could be solved by requiring the issuer issue a blind signature (anyways, one would then still not achieve unlinkability of showings when conducting several proofs - the OP wants multi-show unlinkability - under the assumption that issuer and verifier collude). – DrLecter May 06 '14 at 11:33
-
Thanks, @Alan, for an interesting link. The only problem in this case is that even if verifiers and the issuer do not collude, the verification sessions are traceable, since for each verification the prover has to deliver his "identity" which is used to check the proof (in my previous terms, to "bootstrap" verification). I guess that was one of the motivations to resort to more complex CL-like signatures. Any ideas on how to make Guillou and Quisquater method "multi-show" in a privacy-preserving sense (let's assume at first that verifiers and the issuer do no collude)? – OnTarget May 06 '14 at 13:49
-
2You can use Ferguson's randomized blind signature protocol (http://oai.cwi.nl/oai/asset/5290/05290D.pdf) for issuing the credentials. (You want the protocol from figure 1, in which the bank signs a jointly generated and perfectly blinded random value.) – Alan May 06 '14 at 14:17
-
How about a "small patch": simply randomizing the reference parameter $X$ on each session? Then, on each verification, additionally generate $s \in_{R} Z_{n}^{*}$ and deliver $X_{r}=X^{s}$ (instead of $X$) along with T as well as $K=s^{v}$. Then compute $t$ as $t \leftarrow A^{ds}rs$. To verify, compare $t^{v} \overset{?}{=} X_{r}^{d} TK$. What do you think, guys? – OnTarget May 06 '14 at 14:25
-
In addition to releasing $X$, the prover must also release another preimage of $X$. For example, $x$ such that $X = \mathsf{H}(x)$ where $\mathsf{H}$ is a suitable one-way hash function. Otherwise, the prover can generate any value-signature combination $(X,A)$ by first selecting $A \xleftarrow{$} \mathbb{Z}_n^*$ and then calculating $X \leftarrow A^v \mod n$. The patch you proposed for enabling multi-use unlinkability fails because you need to release $x$ too. – Alan May 06 '14 at 15:07
-
... in other words, there is essentially no way to transform the Guillou-Quisquater method in order to obtain the multi-use unlinkability property? – OnTarget May 06 '14 at 16:28
-
I wouldn't say that ... In my last comment I referred to $\mathsf{H}$ as a hash function, but any one-way function will do -- even if they are defined in the ring of integers modulo $n$. But if you were to follow this approach, your zero-knowledge proof would have to prove three things: first, that a signature $A$ on $X$ is known; second, that a preimage of $X$ is known; and third, that these $X$'s are the same value. I'm not sure yet how to do it, but I will post another answer if I find a way. And I do expect it to draw from the Guillou-Quisquater protocol. – Alan May 06 '14 at 16:35
-
Thanks, @AlanSz! I am also going to explore the opportunities, so to speak, and I'll post the update on this issue soon. – OnTarget May 06 '14 at 16:52
-
Towards the multi-show patch: what if prior to obtaining a signature on $X$, a prover commits to its value: $X \leftarrow g^{y}$. Then the following things have to be appended to the patch I proposed above: (1) send $Y \leftarrow ys$ along with $T, X_{r}, k$ (2) after the verification step, additionally check if $g^{ysd} \overset{?}{=} X_{r}^{d}$. The generator $g$ (as well as the corresponding modulo $p$ for $Z_{p}^{*}$, etc.) should be chosen appropriately (without going into details in this sketch). Do you think such a commitment scheme based on the DL assumption would work for multi-show? – OnTarget May 07 '14 at 14:02
-
So if I understand correctly, you are proving knowledge of a secret tuple $(y, X, A)$ that satisfies $X = g^y \mod p$ and $X = A^v \mod n$? You would also have to prove that the $X$ from the first equation is equal to the $X$ from the second, which I think is pretty much impossible unless the modulus is the same: $p = n$. But in this case, you are proving $X = g^y = A^v \mod n$ and the credential $(y, X, A)$ is trivial to generate (hint: choose $y$ to be a multiple of $v$). Using a DLOG commitment scheme might work, but I'm not sure yet. – Alan May 08 '14 at 08:44
-
More fundamentally: what is wrong with issuing the same credential $(X,A)$ to all parties? Then, different showings are guaranteed to be unlinkable and adversaries that merely observe spendings still can't convincingly prove knowledge of a credential because $A$ remains secret. – Alan May 08 '14 at 08:48
-
About the $(y, X, A)$ credential: do you think the scheme with DL-commitment to $y$ still allows a prover to cheat and generate a signature himself? With respect to $y$ being a multiple of $v$: could you please clarify the choice? (sorry, if this kind of a question seems to quite silly...) Concerning the issuance of the same credential $(X,A)$ to all parties there two issues: $\textit(1)$ local verifier revocation would then would not be possible without additional techniques and $\textit(2)$ should the secret $(X,A)$ get leaked for some reason, all other credentials must be re-issued anew. – OnTarget May 08 '14 at 09:01
-
1Generating the credential: $z \xleftarrow{$} {0,1,\ldots,2^{|n|}-1}; y \leftarrow zv; X \leftarrow g^y \mod n; A \leftarrow g^z \mod n$. Since $y$ is necessarily kept secret, the verifier cannot tell it is a multiple of $v$. – Alan May 08 '14 at 11:15
-
(1) Local verifier revocation. This is a tricky design goal. If credential-spending leaks no Shannon information, then the credential cannot be blacklisted. If it can be blacklisted, then at most you can get computational anonymity (i.e. the verifier/bank would have to solve hard problems). I assume this is OK then? – Alan May 08 '14 at 11:20
-
Thanks a lot for pointing out the issue with $y$ being multiple of $v$. Now to make this work, an additional proof of $y$ not being a multiple of $v$ is needed :) Maybe you could provide a hint on which direction I should be working on to make the protocol multi-show and at the same time prevent cheating? About your last comment on local verifier revocation: computational anonymity is OK in this case (as a trade-off for the opportunity for to perform revocation). – OnTarget May 08 '14 at 15:20
-
What could be done to additionally prove that $y$ is not a multiple of $v$ is either to prove that $y$ is prime (in ZK) or alternatively, it could be proven that $y \mod{v} \neq 0$ – OnTarget May 08 '14 at 18:33
-
I'm not sure how to prove either that $y$ is not a multiple of $v$ or to prove $y \neq 0 \mod v$, but I'm sure you can find an efficient zero knowledge proof for one of these relations. But the more crucial question is this: given such a proof protocol, how do you link this proof with the credential-spending so as to indicate that the same $y$ is being used? I'm afraid I do not have an answer. – Alan May 10 '14 at 14:22
-
I see what you mean. I think you it should be possible but then the whole solution effectively transforms to the one reminiscent of CL-signatures or alike... – OnTarget May 13 '14 at 07:08
-
Where does the requirement that $d$ in a GQ signature be less than $v$ come from? What happens if I choose a $d$ greater than $v$? – Ethan Heilman Aug 31 '23 at 18:39
-
Choosing $d=2v$, would let the prover break soundness, but how likely are you too choose an unsafe $d$ is say $d$ is a randomly chosen 256 bit number? – Ethan Heilman Aug 31 '23 at 21:24
For many signature schemes based on zero knowledge proofs of discrete log knowledge, (EG:Schnorr signature, ECDSA) it is possible to perform an interactive proof that a signature exists without revealing the signature. This proof is interactive only, and a dishonest verifier cannot turn it into a non-interactive proof.
A Schnorr signature for a public key Y=xG
(x
is secret key) is a tuple (e,s)
such that for an R
R=eY+sG
, e=H(R,m)
. Where H is a cryptographic hash.
It is verified by computing R=eY+sG
from the (e,s)
signature tuple, then checking that e=H(R,m)
holds.
Suppose Alice has a signature on a string m
and wishes to prove that a signature (e,s)
exists to Bob. Alice first sends everything but the s
scalar.
- A-->B:
(m,R)
- Bob: compute
e=H(R,m)
,S=R-e*Y
Bob can, with R
and m
compute the point S
in the equation for the valid signature but not the discrete log s
of that point. If Bob could do that he could sign things.
Alice does know the scalar s
and can prove this by using it as a key during a Diffie-Hellman key exchange. DH acting as an interactive only proof.
- Bob: generate ephemeral public key
Y_b=b*G
- B-->A:
Y_b
- Alice: compute
K=Y_b*s
, - A-->B:
H(K,context)
- Bob: compute
K=b*S
, verifyH(K,context)=(received_value)
Alice has proven knowledge of the scalar s
in the signature (e,s)
tuple without revealing it to Bob. DH key exchange shouldn't reveal anything about s
especially with that hash in there to destroy any algebraic structure.
Note that there are a lot of extra back and forth steps in the protocol above. If Bob has a known public key, Alice can just send Bob (e,H(K,context),context,m)
or (R,H(K,context),context,m)
, with Bob computing S
and verifying H(K,context)
. Bob can provide an ephemeral challenge key as a first step if there's no such widely known key.
Sending K
directly may be fine, although it makes Alice into a "multiply by s
oracle". The context helps if using Bob's public key since Eve the eavesdropper who listens in on the exchange doesn't learn K and so can't compute the hash value for a different (proverID,verifierID,time)
context, preventing replay attacks.
The following python code uses the NACL library to generate signatures. Additionally the ECPy library is used to implement EC calculations concisely. You can use NACL._sodium.(whatever) but that's a lot more verbose. AFAIK this should just work securely assuming you have an ED25519 signature. Vanilla Schnorr signatures require slight changes to a few sections.
The following graphical overview of the ED25519 signature system is useful for understanding the code below.
from nacl.signing import SigningKey
import json
gov_sk=SigningKey(b"1"*32)
gov_pk=gov_sk.verify_key.encode()
alice_ID={"info":json.dumps(
{"name":"Alice Liddell",
"DOB":"1970-01-01",
"occupation":"cryptographer"}).encode("utf8")}
alice_ID["sig"]=gov_sk.sign(alice_ID["info"])[:64]
from ecpy.curves import Curve
cv = Curve.get_curve('Ed25519')
import hashlib
def decodeint(s):
return sum(256*i b for i,b in enumerate(bytearray(s)))
def encodeint(y,n):
return bytes(bytearray((y>>i*8)&255 for i in range(n)))
def sha512(m):return hashlib.sha512(m).digest()
def h_int(m):return decodeint(sha512(m))
def verify(sig,pk,m):
#verify an ed25519 signature
assert len(sig)==64
R = cv.decode_point(sig[0:32])
A = cv.decode_point(pk)
s = decodeint(sig[32:])
h = h_int(cv.encode_point(R) + pk + m)
return cv.generators == R+Ah
#check the signature
if verify(alice_ID["sig"],gov_pk,alice_ID["info"]):
print("Alice verified she has a valid signature")
def get_sk_scalar(sk):
return cv.decode_scalar_25519(sha512(sk.encode())[:32])
def make_proof(sig,challenge_key,m,context=b""):
R=sig[0:32]
PKc = cv.decode_point(challenge_key)
s = decodeint(sig[32:])
K = cv.encode_point(s * PKc)
H = sha512(K+context)[:32]
proof = R+H+encodeint(len(context), 2)+context+m
return proof
def check_proof(proof,challenge_sk,pk):
#unpack
def get(n,i=[0]):
data=proof[i[0]:i[0]+n] if n>=0 else proof[i[0]:];i[0]+=len(data)
if len(data)<n:raise ValueError("not enough data")
return data
R = cv.decode_point(get(32))
H = get(32)
context=get(decodeint(get(2)))
m = get(-1)#remainder
#calculate S from signature equation
A = cv.decode_point(pk)
h = h_int(cv.encode_point(R) + pk + m)
S = R+A*h
#check the DH shared key sha512 was correctly calculated
K=cv.encode_point( S * get_sk_scalar(challenge_sk))
H_target=sha512(K+context)[:32]
if H_target!=H:
raise Exception("verification failed")
return context,m
#bob has a known key or generates an ephemeral challenge key for the protocol.
bob_sk=SigningKey((b"bob"*100)[:32])
bob_pk=bob_sk.verify_key.encode()
print("Bob --> Alice: challenge key:",repr(bob_pk))
#Alice makes a proof
proof=make_proof(sig=alice_ID["sig"], challenge_key=bob_pk, m=alice_ID["info"],
context=json.dumps({"prover":"Alice","verifier":"Bob","date":"2023-01-01T01:02:59Z"}).encode())
print("Alice --> Bob: proof:",repr(proof))
#bob can verify it
result=check_proof(proof, bob_sk, gov_pk)
print("Bob knows the following was signed:",result[1])
print("with protocol context:",result[0])
This should work for signatures based on discrete log problems. Schnorr makes the transformation clean. ECDSA is messier. Alice can prove knowledge of dlog(R)
in base (H(m)*G+r*Q_A)
(IE:factor inverse(S) out of the right side of the R=(H(m)/s)*G+(r/s)*Q_A
equation. Bob chooses an ephemeral key with (H(m)*G+r*Q_A)
as the generator and they do DH as above. There are also ways to use trapdoor one way functions to do non-interactive zero knowledge proofs that can either be generated legitimately or forged by using the trapdoor (Bob's secret key) to mess with the output of the random oracle. The resulting proof will convince Bob (and only Bob) that the signature exists.

- 1,741
- 9
- 13
One-Way Aggregate Signatures (OWAS) (also called composite signatures) can be used to do this. They are based on BLS signatures. I will skip the notation except mention that they are based on bilinear pairings. The above links will give the details.
Let $H$ be a hash function and $x_1$ be the private key. The public key is $y_1=g^{x_1}$. For any message $m_1$, the signature is $\sigma_1={h_1}^{x_1}$, where $h_1 = H(m_1)$. To verify the signature, test that: $\hat{e}(\sigma_1, g) \stackrel{?}{=} \hat{e}(h_1, y_1)$ holds.
Let $x_2$ be another private key. The public key is $y_2=g^{x_2}$. As before, for any message $m_2$, the signature is $\sigma_2={h_2}^{x_2}$, where $h_2 = H(m_2)$. To verify the signature, test that: $\hat{e}(\sigma_2, g) \stackrel{?}{=} \hat{e}(h_2, y_2)$ holds.
We can also combine $\sigma_1, \sigma_2$ into an aggregate signature $\sigma$ as follows: $\sigma=\sigma_{1}\cdot \sigma_{2}$. To verify, we check that: $$\hat{e}(\sigma, g) \stackrel{?}{=} \hat{e}(h_1, y_1)\cdot\hat{e}(h_2, y_2)$$
The signatures satisfy the standard security as shown in the Aggregate Signatures Paper. That is, assuming that the Diffie-Hellman problem is hard, presentation of $\sigma$ proves that $y_1$ signed $m_1$ and $y_2$ signed $m_2$ (even if the original signatures are not provided).
The security of OWAS relies on the fact that given just $\sigma$, it is hard to compute either $\sigma_1$ or $\sigma_2$ (as hard as solving Diffle-Hellman problem). In fact, for two combined signatures, the resulting signature is a zero-knowledge proof of knowledge of each individual signature. This can be shown as follows:
Suppose I can control the output of the hash function (i.e., we are using the "random oracle model"), then instead of doing it the correct way as described above, given $(g, h_1, y_1)$, I can compute a fake tuple $(\sigma, h_2, y_2)$ such that the last verification equation above holds. First generate random $a, b$. The compute:
$$y_2=g^a y_1$$ $$h_2=\frac{g^b}{h_1}$$ $$\sigma=\frac{{y_1}^b\cdot g^{ab}}{{h_1}^a}$$
It can be checked that the above values satisfy the aggregate signature verification equation. Yet, I did this without knowing $\sigma_1$. Hence this is zero-knowledge.