Skip to content

Commit

Permalink
Merge pull request #42 from decentralized-identity/tl/split-draft
Browse files Browse the repository at this point in the history
Split out blind sign functionality into a seperate draft
  • Loading branch information
tplooker authored Feb 1, 2022
2 parents 38f9001 + 8e6742c commit 2be9472
Show file tree
Hide file tree
Showing 2 changed files with 301 additions and 223 deletions.
224 changes: 1 addition & 223 deletions draft-bbs-signatures.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,7 @@ BBS is a form of short group digital signature scheme that supports multi-messag

A digital signature scheme is a fundamental cryptographic primitive that is used to provide data integrity and verifiable authenticity in various protocols. The core premise of digital signature technology is built upon asymmetric cryptography where-by the possessor of a private key is able to sign a payload (often revered to as the signer), where anyone in possession of the corresponding public key matching that of the private key is able to verify the signature.

However traditional digital signatures are limited to fixed mode of signing and verifying, that is the entire payload that was signed by a signer must be known by the verifier in-order to validate the digital signature.

This document describes the BBS signature scheme. (FIXME: THE BBS signature scheme? Or A BBS signature schemes? Also: BBS citation needed/informative reference).
The scheme feature important properties that allow the scheme to be used in applications where privacy and data minimization techniques are desired and/or required:

1. Signatures can be created blinded or un-blinded.

2. Traditional signature schemes require the entire signature and message to be disclosed during verification. BBS allows a fast and small zero-knowledge signature proof of knowledge to be created from the signature and the public key. This allows the signature holder to selectively reveal any number of signed messages to another entity (none, all, or any number in between).
However traditional signature schemes require the entire signature and message to be disclosed during verification. BBS allows a fast and small zero-knowledge signature proof of knowledge to be created from the signature and the public key. This allows the signature holder to selectively reveal any number of signed messages to another entity (none, all, or any number in between).

A recent emerging use case applies signature schemes in [verifiable credentials](https://www.w3.org/TR/vc-data-model/). One problem with
using simple signature schemes like ECDSA or ED25519 is that a holder must disclose the entire signed message and signature for verification. Circuit based logic can be applied to verify these in zero-knowledge like SNARKS or Bulletproofs with R1CS but tend to be complicated. BBS on the other hand adds, to verifiable credentials or any other application, the ability to do very efficient zero-knowledge proofs. A holder gains the ability to choose which claims to reveal to a relying party without the need for any additional complicated logic. (FIXME: Informative references missing)
Expand All @@ -78,12 +71,6 @@ SK
PK
: The public key for the signature scheme.

U
: The set of messages that are blinded from the signer during a blind signing.

K
: The set of messages that are known to the signer during a blind signing.

L
: The total number of messages that the signature scheme can sign.

Expand All @@ -105,12 +92,6 @@ h0
signature
: The digital signature output.

s'
: The signature blinding factor held by the signature recipient.

blind\_signature
: The blind digital signature output.

commitment
: A pedersen commitment composed of 1 or more messages.

Expand Down Expand Up @@ -168,7 +149,6 @@ point\_to\_octets\_min(P) -> ostr
point\_to\_octets\_norm(P) -> ostr
: returns the canonical representation of the point P as an octet string in uncompressed form. This operation is also known as serialization. (FIXME: This either requires a normative wire format or a reference to the normative wire format)


octets\_to\_point(ostr) -> P
: returns the point P corresponding to the canonical representation ostr, or INVALID if ostr is not a valid output of point\_to\_octets. This operation is also known as deserialization. Consumes either compressed or uncompressed ostr.

Expand Down Expand Up @@ -373,184 +353,6 @@ Procedure:

8. return C1 == C2

## PreBlindSign

The PreBlindSign algorithm allows a holder of a signature to blind messages that when signed, are unknown to the signer.

The algorithm returns a generated blinding factor that is used to un-blind the signature from the signer, and a pedersen commitment from a vector of messages and the domain parameters h and h0.

```
(s', commitment) = PreBlindSign((msg[1],...,msg[U]), CGIdxs)
```

Inputs:

- msg\[1\],...,msg\[U\], octet strings of the messages to be blinded.
- CGIdxs, vector of unsigned integers. Indices of the generators from the domain parameter h, used for the messages to be blinded.

Outputs:

- s', octet string.
- commitment, octet string

Procedure:

1. (i1,...,iU) = CGIdxs

2. s' = H(PRF(8 \* ceil(log2(r)))) mod r

3. if subgroup\_check(h0) is INVALID abort

4. if (subgroup\_check(h\[i1\]) && ... && subgroup\_check(h\[iU\])) is INVALID abort

5. commitment = h0 \* s' + h\[i1\] \* msg\[1\] + ... + Ch\[iU\] \* msg\[U\]

6. return s', commitment

## BlindSign

BlindSign generates a blind signature from a commitment received from a holder, known messages, a secret key, the domain parameter h0 and generators from the domain parameter h. The signer also validates the commitment using the proof of knowledge of committed messages received from the holder and checks that the generators used in the commitment are not also used for the known messages.

```
blind_signature = BlindSign(commitment, (msg[1],...msg[K]), SK, GIdxs, CGIdxs, nizk, nonce)
```

Inputs:

- commitment, octet string receive from the holder in output form PreBlindSign.
- nizk, octet string received from the holder in output from BlindMessagesProofGen.
- msg\[1\],...,msg\[K\], octet strings.
- SK, a secret key output from KeyGen.
- GIdxs, vector of unsigned integers. Indices of the generators from the domain parameter h, used for the known messages.
- CGIdxs, vector of unsigned integers. Indices of the generators from the domain parameter h, used for the commited messages.
- nonce, octet string, suplied to the holder by the signer to be used with BlindMessagesProofGen.

Outputs:

- blind\_signature, octet string

Procedure:

1. (j1, ..., jK) = GIdxs

2. e = H(PRF(8 \* ceil(log2(r)))) mod r

3. s'' = H(PRF(8 \* ceil(log2(r)))) mod r

4. if BlindMessagesProofVerify(commitment, nizk, CGIdxs, nonce) is INVALID abort

5. if GIdxs intersection with CGIdxs is not empty abort

6. b = commitment + h0 \* s'' + h\[j1\] \* msg\[1\] + ... + h\[jK\] \* msg\[K\]

7. A = b \* (1 / (SK + e))

8. blind\_signature = (A, e, s'')

9. return blind\_signature

## UnblindSign

UnblindSign computes the unblinded signature given a blind signature and the holder's blinding factor. It is advised to verify the signature after un-blinding.

```
signature = UnblindSign(blind_signature, s')
```

Inputs:

- s', octet string in output form from PreBlindSign
- blind\_signature, octet string in output form from BlindSign

Outputs:

- signature, octet string

Procedure:

1. (A, e, s'') = blind\_signature

2. if subgroup\_check(A) is INVALID abort

3. if (subgroup\_check(blind\_signature)) is INVALID abort

4. s = s' + s''

5. signature = (A, e, s)

6. return signature

## BlindMessagesProofGen

BlindMessagesProofGen creates a proof of committed messages zero-knowledge proof. The proof should be verified before a signer computes a blind signature. The proof is created from a nonce given to the holder from the signer, a vector of messages, a blinding factor output from PreBlindSign, the domain parameter h0 and generators from the domain parameter h.

```
nizk = BlindMessagesProofGen(commitment, s', (msg[1],...,msg[U]), CGIdxs, nonce)
```

Inputs:

- commitment, octet string as output from PreBlindSign
- s', octet string as output from PreBlindSign
- msg\[1\],...,msg\[U\], octet strings of the blinded messages.
- CGIdxs, vector of unsigned integers. Indices of the generators from the domain parameter h, used for the commited messages.
- nonce, octet string.

Outputs:

- nizk, octet string

Procedure:

1. (i1,...,iU) = CGIdxs

2. r\~ = \[U\]

3. s\~ = H(PRF(8 \* ceil(log2(r)))) mod r

4. for i in 1 to U: r\~\[i\] = H(PRF(8 \* ceil(log2(r)))) mod r

5. U~ = h0 \* s\~ + h\[i1\] \* r\~\[1\] + ... + h\[iU\] \* r\~\[U\]

6. c = H(commitment || U\~ || nonce)

7. s^ = s\~ + c \* s'

8. for i in 1 to U: r^\[i\] = r\~\[i\] + c \* msg\[i\]

9. nizk = ( c, s^, r^)

## BlindMessagesProofVerify

BlindMessagesProofVerify checks whether a proof of committed messages zero-knowledge proof is valid.

```
result = BlindMessagesProofVerify(commitment, nizk, CGIdxs, nonce)
```

Inputs:

- commitment, octet string in output form from PreBlindSign
- nizk, octet string in output form from BlindMessagesProofGen
- CGIdxs, vector of unsigned integers. Indices of the generators from the domain parameter h, used for the commited messages.
- nonce, octet string

Outputs:

- result, either VALID or INVALID.

Procedure:

1. (i1,...,iU) = CGIdxs

2. ( c, s^, r^ ) = nizk

3. U^ = commitment \* -c + h0 \* s^ + h\[i1\] \* r^\[1\] + ... + h\[iU\] \* r^\[U\]

4. c\_v = H(U || U^ || nonce)

5. return c == c\_v

## SpkGen

A signature proof of knowledge generating algorithm that creates a zero-knowledge proof of knowledge of a signature while selectively disclosing messages from a signature given a vector of messages, a vector of indices of the revealed messages, the signer's public key, and a presentation message.
Expand Down Expand Up @@ -772,30 +574,6 @@ This document does not make any requests of IANA.

# Appendix

## Blind Sign Flow Example

The example below illustrates the creation of a blind signature. Let the Signer have a public key PK = (w, h0, h[1],...,h[L]) where (h[1],...,h[L]) generators. The end result will be a signature to the messages (m[1],...,m[K]) (K less than L). The messages (m[1],...,m[U]) (U less than K), will be committed by the Client using the first U generators from the Signers PK (i.e., h[1],,,,h[U]). The messages (m[U+1],...,m[K]) will be known to the Signer and will be signed using the generators (h[U+1],...,h[K]) from their PK.

~~~ ascii-art
+--------+ +--------+
| | <-(1)------- nonce ---------- | |
| | | |
| Client | --(2)- Commitment, nizk, U -> | Signer |
| | | |
| | <-(3)--- Blind Signature ---- | |
+--------+ +--------+
~~~

1. The Signer and the Client will agree on a nonce to be used by the BlindMessagesProofGen and BlindMessagesProofVerify functions.

2. The Client will use the PreBlindSign function to calculate a Pedersen commitment for the messages (m[1],...,m[U]), using the generators (h[1],...,h[U]). Then they will create a proof of knowledge (nizk) for that commitment using BlindMessagesProofGen. The Signer will receive the commitment, the proof of knowledge (nizk) and the number of committed messages (U).

3. Before sending the blinded signature to the Client the Signer must execute the following steps,
- Validate the proof of knowledge of the commitment using BlindMessagesProofVerify, on input the commitment, nizk, the nonce (from step 1) and the U first generators from their PK. Then check that the intersection between the generators used by the Client for the commitment, and the generators (h[U+1],...,h[K]), used by the Signer for the known messages, is indeed empty.
- Create the blind signature using the BlindSign function. Note that the blinded signature is not a valid BBS signature.

After the Client receives the blind signature they will use the UnblindSign function to unblinded it, getting a valid BBS signature on the messages (m[1],...,m[K]).

## Usecases

### Non-correlating Security Token
Expand Down
Loading

0 comments on commit 2be9472

Please sign in to comment.