From 64eb8cf098b138c7ca752c96fb1e9b3d063ab847 Mon Sep 17 00:00:00 2001 From: Vasilis Kalos Date: Tue, 4 Jul 2023 21:36:06 +0300 Subject: [PATCH 1/5] put the challenge at the end --- draft-irtf-cfrg-bbs-signatures.md | 14 +++++++------- .../bls12-381-sha-256/proof/proof001.json | 2 +- .../bls12-381-sha-256/proof/proof002.json | 2 +- .../bls12-381-sha-256/proof/proof003.json | 2 +- .../bls12-381-sha-256/proof/proof004.json | 2 +- .../bls12-381-sha-256/proof/proof005.json | 2 +- .../bls12-381-sha-256/proof/proof006.json | 4 ++-- .../bls12-381-sha-256/proof/proof007.json | 2 +- .../bls12-381-sha-256/proof/proof008.json | 2 +- .../bls12-381-sha-256/proof/proof009.json | 2 +- .../bls12-381-sha-256/proof/proof010.json | 2 +- .../bls12-381-sha-256/proof/proof011.json | 2 +- .../bls12-381-sha-256/proof/proof012.json | 2 +- .../bls12-381-sha-256/proof/proof013.json | 2 +- .../bls12-381-sha-256/proof/proof014.json | 2 +- .../bls12-381-sha-256/proof/proof015.json | 2 +- .../bls12-381-sha-256/signature/signature009.json | 10 +++++----- .../bls12-381-shake-256/proof/proof001.json | 2 +- .../bls12-381-shake-256/proof/proof002.json | 2 +- .../bls12-381-shake-256/proof/proof003.json | 2 +- .../bls12-381-shake-256/proof/proof004.json | 2 +- .../bls12-381-shake-256/proof/proof005.json | 2 +- .../bls12-381-shake-256/proof/proof006.json | 4 ++-- .../bls12-381-shake-256/proof/proof007.json | 2 +- .../bls12-381-shake-256/proof/proof008.json | 2 +- .../bls12-381-shake-256/proof/proof009.json | 2 +- .../bls12-381-shake-256/proof/proof010.json | 2 +- .../bls12-381-shake-256/proof/proof011.json | 2 +- .../bls12-381-shake-256/proof/proof012.json | 2 +- .../bls12-381-shake-256/proof/proof013.json | 2 +- .../bls12-381-shake-256/proof/proof014.json | 2 +- .../bls12-381-shake-256/proof/proof015.json | 2 +- .../signature/signature009.json | 14 +++++++------- 33 files changed, 51 insertions(+), 51 deletions(-) diff --git a/draft-irtf-cfrg-bbs-signatures.md b/draft-irtf-cfrg-bbs-signatures.md index 80a1b07a..861203f9 100644 --- a/draft-irtf-cfrg-bbs-signatures.md +++ b/draft-irtf-cfrg-bbs-signatures.md @@ -549,7 +549,7 @@ Procedure: 13. r2^ = r2 + r4 * c (mod r) 14. r3^ = r3 + e * r4 * c (mod r) 15. for j in (j1, ..., jU): m^_j = m~_j + msg_j * c (mod r) -16. proof = (Abar, Bbar, c, r2^, r3^, (m^_j1, ..., m^_jU)) +16. proof = (Abar, Bbar, r2^, r3^, (m^_j1, ..., m^_jU), c) 17. return proof_to_octets(proof) ``` @@ -606,7 +606,7 @@ Deserialization: 1. proof_result = octets_to_proof(proof) 2. if proof_result is INVALID, return INVALID -3. (Abar, Bbar, c, r2^, r3^, commitments) = proof_result +3. (Abar, Bbar, r2^, r3^, commitments, c) = proof_result 4. W = octets_to_pubkey(PK) 5. if W is INVALID, return INVALID 6. U = length(commitments) @@ -1129,8 +1129,8 @@ Outputs: Procedure: -1. (Abar, Bbar, c, r2^, r3^, (m^_1, ..., m^_U)) = proof -2. return serialize((Abar, Bbar, c, r2^, r3^, m^_1, ..., m^_U)) +1. (Abar, Bbar, r2^, r3^, (m^_1, ..., m^_U), c) = proof +2. return serialize((Abar, Bbar, r2^, r3^, m^_1, ..., m^_U), c) ``` ### Octets to Proof @@ -1179,7 +1179,7 @@ Procedure: 7. if A_i is INVALID or Identity_G1, return INVALID 8. index += octet_point_length -// Scalars (i.e., (c, r2^, r3^, (m^_j1, ..., m^_jU)) in +// Scalars (i.e., (r2^, r3^, (m^_j1, ..., m^_jU), c) in // ProofGen) de-serialization. 9. j = 0 10. while index < length(proof_octets): @@ -1191,8 +1191,8 @@ Procedure: 16. if index != length(proof_octets), return INVALID 17. msg_commitments = () -18. If j > 3, set msg_commitments = (s_3, ..., s_(j-1)) -19. return (A_0, A_1, s_0, s_1, s_2, msg_commitments) +18. If j > 3, set msg_commitments = (s_2, ..., s_(j-2)) +19. return (A_0, A_1, s_0, s_1, msg_commitments, s_(j-1)) ``` ### Octets to Public Key diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof001.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof001.json index c0118bda..9657b2eb 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof001.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof001.json @@ -6,7 +6,7 @@ "revealedMessages": { "0": "9872ad089e452c7b6e283dfac2a80d58e8d0ff71cc4d5e310a1debdda4a45f02" }, - "proof": "8e9bc91d68151e4b105ec0d46ca95fe1526672bed27b26541a648ec990b3b11b8905e671fb981f1b9cd1ed64167a7ba18b7697d9bd6f3cac02f75551f2db95bf2707e3790c10d815346a96198327cc7048f220bdc7d6fc5ec41c6d9f89d607ff6e5d45c7116e54ebbb28aaf71154ee7126ec5592ae6cc373e3477d45a0a409585277a3f99826146887ac6f7cb39acd837e987e2db04d07383062edd741c83eb439c52e4ae9fce2b1a882f2df186eec8c9451a2e2fc5cf494146918c587a12e75", + "proof": "8e9bc91d68151e4b105ec0d46ca95fe1526672bed27b26541a648ec990b3b11b8905e671fb981f1b9cd1ed64167a7ba18b7697d9bd6f3cac02f75551f2db95bf2707e3790c10d815346a96198327cc7048f220bdc7d6fc5ec41c6d9f89d607ff6ef2eef19447b3e34a14660eedb8b4f6189f202a4fef22e60dd23041e2761a9f18701019b520ed3ccf07a298e349222ab059e7ebd84c65e3a2127ec42f5f357c27d5601b2193b697a576fd9bd896c25a75004f6604a98707741916769c49175f", "result": { "valid": true } diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof002.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof002.json index 586a246c..1e80785c 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof002.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof002.json @@ -15,7 +15,7 @@ "8": "96012096", "9": "" }, - "proof": "89910f223320044fe6342b8dabfeac786f35cc98bb64c95ecb39348281d5a8c84e975581b5f37ec45c8bc4cda486d5e2a20e007d0dd0fba77f846dfe3458fc01ff94a49c058550684638e1b88b61e8d69a1453652477af005d42cdb2d57e86b071951a701909a2fcadf08304f7d17495e03c07ea5854cd18c969063eced31c42345ccb154cefbf42eca0f0dcfd3d2370d56c247955f0b0ea6fd97bfd29cbe9755e902bf83ecf5949a9a4b4351814e5b2a7ebe74da74ec7c61ac4975a085cefb6", + "proof": "89910f223320044fe6342b8dabfeac786f35cc98bb64c95ecb39348281d5a8c84e975581b5f37ec45c8bc4cda486d5e2a20e007d0dd0fba77f846dfe3458fc01ff94a49c058550684638e1b88b61e8d69a1453652477af005d42cdb2d57e86b03a2cf88bc0bac5a3d12a1c0717b9ea8d42ecdb746f522edfc15910574b289faa0438d6516504a7a66ce180b2271101d87519cad823f03f266f66649b388e680a58a6e7ae4982ae797890d5d0b574fa73a7ae7023d4dd9f8a9b3a11f208256d7c", "result": { "valid": true } diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof003.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof003.json index 3614e287..0eb1aa2c 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof003.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof003.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd32b2f1e0cf27a7c1bd17c09963d32ff3e05bcf547e91828e52738624618791ab", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f21767c467fdd882eb038492a390ee5d0c0f72f50f2ac5cedb705fc465f7bc093b", "result": { "valid": true } diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof004.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof004.json index ce51e695..a2b41890 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof004.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof004.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd32b2f1e0cf27a7c1bd17c09963d32ff3e05bcf547e91828e52738624618791ab", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f21767c467fdd882eb038492a390ee5d0c0f72f50f2ac5cedb705fc465f7bc093b", "result": { "valid": false, "reason": "different presentation header" diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof005.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof005.json index 1754c583..ed88fe57 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof005.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof005.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd32b2f1e0cf27a7c1bd17c09963d32ff3e05bcf547e91828e52738624618791ab", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f21767c467fdd882eb038492a390ee5d0c0f72f50f2ac5cedb705fc465f7bc093b", "result": { "valid": false, "reason": "wrong public key" diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof006.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof006.json index 50f36005..d377f77f 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof006.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof006.json @@ -4,12 +4,12 @@ "header": "11223344556677889900aabbccddeeff", "presentationHeader": "bed231d880675ed101ead304512e043ade9958dd0241ea70b4b3957fba941501", "revealedMessages": { - "0": "569a1a67abb8a307385c898f3b9abef43c06d5ea803460572ff621e5a584edaab2f1caa982a1b23490a3f2d1d7921500e018648911718c6bb70d3c59391a9c85e837cec76dd8dbe82aba4ff87b0f93e8b1ca8ff5a4144fa49e4731fcc3a8efa2b77df26b", + "0": "429f239d9576fa31684988c429e4f397ca8fa68c1af826bdd878e2d770a5e60923d5760cbf91d7a859e2d8960712624656443e0abaf2ec3225ac078fcea63cbe66d1f1d8cc172829147aeeac18ba5953709fda6803ce93c715800212036a53422a5a3b70", "2": "7372e9daa5ed31e6cd5c825eac1b855e84476a1d94932aa348e07b73", "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd32b2f1e0cf27a7c1bd17c09963d32ff3e05bcf547e91828e52738624618791ab", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f21767c467fdd882eb038492a390ee5d0c0f72f50f2ac5cedb705fc465f7bc093b", "result": { "valid": false, "reason": "modified messages" diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof007.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof007.json index 0ab4f715..60bd236e 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof007.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof007.json @@ -10,7 +10,7 @@ "6": "d183ddc6e2665aa4e2f088af", "9": "" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd32b2f1e0cf27a7c1bd17c09963d32ff3e05bcf547e91828e52738624618791ab", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f21767c467fdd882eb038492a390ee5d0c0f72f50f2ac5cedb705fc465f7bc093b", "result": { "valid": false, "reason": "extra message un-revealed in proof" diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof008.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof008.json index b4b45518..c85a91ac 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof008.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof008.json @@ -10,7 +10,7 @@ "6": "d183ddc6e2665aa4e2f088af", "9": "96012096" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd32b2f1e0cf27a7c1bd17c09963d32ff3e05bcf547e91828e52738624618791ab", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f21767c467fdd882eb038492a390ee5d0c0f72f50f2ac5cedb705fc465f7bc093b", "result": { "valid": false, "reason": "extra message invalid message un-revealed in proof" diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof009.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof009.json index d0139c16..18260739 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof009.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof009.json @@ -8,7 +8,7 @@ "2": "7372e9daa5ed31e6cd5c825eac1b855e84476a1d94932aa348e07b73", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd32b2f1e0cf27a7c1bd17c09963d32ff3e05bcf547e91828e52738624618791ab", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f21767c467fdd882eb038492a390ee5d0c0f72f50f2ac5cedb705fc465f7bc093b", "result": { "valid": false, "reason": "missing message revealed in proof" diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof010.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof010.json index b0847d7f..4f974829 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof010.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof010.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "7372e9daa5ed31e6cd5c825eac1b855e84476a1d94932aa348e07b73" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd32b2f1e0cf27a7c1bd17c09963d32ff3e05bcf547e91828e52738624618791ab", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f21767c467fdd882eb038492a390ee5d0c0f72f50f2ac5cedb705fc465f7bc093b", "result": { "valid": false, "reason": "re-ordered messages" diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof011.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof011.json index 353a968e..8d582b3a 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof011.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof011.json @@ -10,7 +10,7 @@ "6": "d183ddc6e2665aa4e2f088af", "9": "" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd32b2f1e0cf27a7c1bd17c09963d32ff3e05bcf547e91828e52738624618791ab", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f21767c467fdd882eb038492a390ee5d0c0f72f50f2ac5cedb705fc465f7bc093b", "result": { "valid": false, "reason": "extra valid message, modified total message count" diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof012.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof012.json index db64128e..c7c3b056 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof012.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof012.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f2", "result": { "valid": false, "reason": "truncated proof, one less undisclosed message" diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof013.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof013.json index 39bd14ff..1de54107 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof013.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof013.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd335141e3727ea61ede2644833a1153c11e79737b75afd2b94729d00be2e5faa5ab47e0deff12c70e1be2bab6c1a663fc28f8aa37ae7c1f8494b72dd8ad430da4561c64e9e11c2f4283e8e25282d4a5c9d72d2d856a0b3141668c9304467f403d9a06448d69c21da1822d9a857e66fcbf6bb2884e0aaa4e2e78295d63c1304968230ac5f09570f76affa7eaed15709a8fa361aeccda9cfb50c8fed9844f1fab9645033f7d923b46d193107cb8b7064e4f21c536a6528635d5b78dc721b1ca7f296918fd8430f8d647aecb7d1ed7d123dc8514027bdcb093340797e4d72cc35f9c111c06100844d2498bdc1106847e373143267a325d10ebca86fb71fbc066fa41dd32b2f1e0cf27a7c1bd17c09963d32ff3e05bcf547e91828e52738624618791ab", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd33111a4b4fc79a2201d18b5cc63fab1252def0d4f020129c7e022f56f505aa977a7240da430bc60a2d4d17897b42228054a2fb4f780fb710268ebea24c9fb0e15e2ac415b99a232b13bfd215af3fb35f5518953eaccc200555eaa69ae434eb623f0a83bb57a8a8e70ba37761ffaeb756d9115c1177ce929f04be23b5636120c7ac0a73546f177a3c3be2d233b3253f31c3468260723c1afa2d0febd38161e16ed0147369bda8b05ec3f6183239c6ecb9fb54b0989160e8cdf8b9f0cf4a46a2150232d96c466fad2d60ff067492c52cc6af1d16e62364ed6d3dc19feaf1fcf9c12750301c2de6541c0edce5ede7425f75e01fd94a7e6137ebf23460bf3f1afec9f21767c467fdd882eb038492a390ee5d0c0f72f50f2ac5cedb705fc465f7bc093b", "result": { "valid": false, "reason": "different header" diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof014.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof014.json index bc523f8e..5a5618cd 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof014.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof014.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "89cefce40c3dc7adcc8bcd07d92767d0f0397d0e120511b58b8403b531fa573987003fd235bdfe6fb5e9da937774c7799397bc951cd4030a78f8dae7820bfa150a243d74c3aa34daf6299dc0baaf7796705e952e2c8ac7d37c69e91db85012d61feae653bf35cb79213536826d131a852e4795aa72b16bbe73aff710af01ff78548fb02b4d14c7c2713c24fe2acea76976920ba656cb69aa9de69a3ee87772bd3b75f1bc3c56b14a36863200442910d801d75b70c3c892d029d2063c5b0b4cbf6c4ebad57ac623632340798d2fd18436a497fdfa822089bd6e12ed2344486a3d231b39ac4fdf401133b532c4205752b1850ba86f465a69c5b72074a85983b6f543926341f308d85457ba1463aff6b39cf68b4bf358750792f7cc06e35508e7af53f3bc44f7c44a4807acae5345ceb232be759d9f591fcfd59c1155a8dc2d0ba511e59e15761839275d0a1d758214d85fd57dcafcd3d816a0347ae0b4c74faec305f2ddb353081edf9e15a0b07050aee59cb48f5c5968d6b7f2eeec64ffbd33a4", + "proof": "89cefce40c3dc7adcc8bcd07d92767d0f0397d0e120511b58b8403b531fa573987003fd235bdfe6fb5e9da937774c7799397bc951cd4030a78f8dae7820bfa150a243d74c3aa34daf6299dc0baaf7796705e952e2c8ac7d37c69e91db85012d61f3387f096a022361972d6afd2c095eeb4adc95f72cfb739539f27f1917c7cc80fba233fd9eef52196cc31183d7c4168e6b87a66b249225398c31e2950e3e24420d3af3eeee3308933a343310cf822287dc95b86eb5716e8ff23cc52c980d41218bdaeff521a242e5330daee27a1a499ac1a20b0c39477cebf4936d0ec2b95e0384b80bba24febc527b0b640481df2125b58f85708590838ee32789ce1c755a6150ce6bf0650bff3dfff61eae16e88916f9869d75c7884554ea517f8dec320c011d211b1ec05073238d7949fe6d9ff6f729c475bbfc5a21c6fa6d35df92f79d43c3f78bcd3cb4c6e6de2ac27108316bd8d751fb445c5f6b4e6e104b227362efe3f5f2904b6100e01b6cf94d9d6c5501fbbfd2e5e57c2dcb1cf117c41eedcda57", "result": { "valid": true } diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof015.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof015.json index 45dd8a05..12ca326f 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof015.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/proof/proof015.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd3311a891c8be705c21f464e7fcdf2e13abc518af70e5978a6c6a0511d0b60c47db06b9f2b257e35509c284786c65647b00448fda42a85831c303df6582b474f821455e75744ca90f9d93a546c4711ffa2abffeca76c215399493b6fa194ccf98ab2f7f22ad61d01550e9e4aca0afef0258a77ad26d0f1406c525d508bd2fd21bda103863fc03397ed98bb410b446cf4478c2240b1e7240753af099f35180bcb5ce6bd59f3ceb0e647b24d7a7da6cb009ae752505f48196f8978466e1ff79850e813c5ad085869817c0a906c4ab37a8a81c4c8d6ed1033c488c32c6f751295879273a5454bd28e4f24015567b03a0ea9ac88aaafd50a72d664a87c1e6268bf25e644ecd9879b59e62beffb2ab0e6a7b51fab571c5b07990103029ad6280b81e29c2", + "proof": "812a204f66c9084feed7383894d910f2c17399b3c4b4bed05660921de8539f5042318c356609496a6ca0a26626661be78ca723b7182ccd314924b93a3997654fcd77e29e3847dc881f422a751017705173ec094d2997221e134710d4fff1bd332fd2f270e96b6b8de89b2fff1294dcd5bd0e1eb314b199f7fb7f5702839f409e167c6a78eb3a57a08a7996330f83ac167d51c57f4ebabea87ad8e08b4b3875926d9d2427df59abd2e2befe32774b03668a5080c54412f81c4cbf47571b15a35c4f93bd38805c3224ca6c4d2f387c28288e8fffb0ab0c43cdb860f31c739b3091192268789d3da05b97d277ab91699a209c97e9057a6cf66c9d4d311ea09c680d4aa2485bfdbaa7ee954a2e0b4f6ea542eda44a1adf2b19f63332b9de00f46c533f1c696bc8b4aea5cc56b0cf12ecdba434b36324d754eabf1734e6c3301f300435797edcb007eae6ef75bc5d5500a1ce74ba8f4e0c5c8836f42371c2c469265909585f44695f088ea39bda2317224f47208c7f77570deae84efea007c14f18ef", "result": { "valid": true } diff --git a/tooling/fixtures/fixture_data/bls12-381-sha-256/signature/signature009.json b/tooling/fixtures/fixture_data/bls12-381-sha-256/signature/signature009.json index e09fab10..804cf86d 100644 --- a/tooling/fixtures/fixture_data/bls12-381-sha-256/signature/signature009.json +++ b/tooling/fixtures/fixture_data/bls12-381-sha-256/signature/signature009.json @@ -6,16 +6,16 @@ }, "header": "11223344556677889900aabbccddeeff", "messages": [ + "77fe97eb97a1ebe2e81e4e3597a3ee740a66e9ef2412472c", + "7372e9daa5ed31e6cd5c825eac1b855e84476a1d94932aa348e07b73", "c344136d9ab02da4dd5908bbba913ae6f58c2cc844b802a6f811f5fb075f9b80", "496694774c5604ab1b2544eababcf0f53278ff50", - "ac55fb33a75909ed", - "515ae153e22aae04ad16f759e07237b4", "9872ad089e452c7b6e283dfac2a80d58e8d0ff71cc4d5e310a1debdda4a45f02", "96012096", + "ac55fb33a75909ed", + "d183ddc6e2665aa4e2f088af", "", - "7372e9daa5ed31e6cd5c825eac1b855e84476a1d94932aa348e07b73", - "77fe97eb97a1ebe2e81e4e3597a3ee740a66e9ef2412472c", - "d183ddc6e2665aa4e2f088af" + "515ae153e22aae04ad16f759e07237b4" ], "signature": "895cd9c0ccb9aca4de913218655346d718711472f2bf1f3e68916de106a0d93cf2f47200819b45920bbda541db2d91480665df253fedab2843055bdc02535d83baddbbb2803ec3808e074f71f199751e", "result": { diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof001.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof001.json index 441a0fb4..6c516ed4 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof001.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof001.json @@ -6,7 +6,7 @@ "revealedMessages": { "0": "9872ad089e452c7b6e283dfac2a80d58e8d0ff71cc4d5e310a1debdda4a45f02" }, - "proof": "85c250f9a52faeb883ad9598aed05d31fe5861478d9f33b8de2deed1d92de5c0b0ef34458e6cf8bad8caa0724fd3d3ca854abee98db3384e81a406d976643e239df0a924576eaf8f4eec2885e9c688af7a52e4a752bef2c6f07d0a45611db3790816b68b68b37d619f9fdac6ed8b21eb491ae587c9b12797ace60872f8788de1704a4d79fdd62c0c8d4320928f2df69fde902a0815affa8c0416218a7620af326bb1017d9a912d0e09057474865807a254005a3bf1587523aa4503bec70c57af", + "proof": "85c250f9a52faeb883ad9598aed05d31fe5861478d9f33b8de2deed1d92de5c0b0ef34458e6cf8bad8caa0724fd3d3ca854abee98db3384e81a406d976643e239df0a924576eaf8f4eec2885e9c688af7a52e4a752bef2c6f07d0a45611db3795d83d9cd71dfe8a62e3ad992e6327413baaea14c1de798c8929f9c6b1524bab54d0494dd5354d5a0770b79d2911bb6591ce293e03a0d083bb81fc5bed8a44ff67386c0c33ddaaebf7d046849428fc6cf4d08815fa39c94144c79ac50e86a0f5d", "result": { "valid": true } diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof002.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof002.json index 5f6fd231..226a4cfc 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof002.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof002.json @@ -15,7 +15,7 @@ "8": "96012096", "9": "" }, - "proof": "94dfa4e26276f0ccf319b0ade65317e0bac41867aaebc73c7edc38673776cc6321dadd721920f5bd33f14be6dd101ec0b48f82f7ce8a8eb1d7cba2b93b66206bb7c3b5340e358be39380c7a9f17083fa1bcdf9c4e5ba5927edfd01519189b7b3264388b676eb64195ddb11db197d10d7d9af9177d82288a6b048561b187e08290055038ff000dc92c6206d3f7fedd448c7bc7107f9703959b3f4345a20a5aef346d185684c5216c276f8e0f50d0fd426229dfd8f0f474ae83015f32d080e12f1", + "proof": "94dfa4e26276f0ccf319b0ade65317e0bac41867aaebc73c7edc38673776cc6321dadd721920f5bd33f14be6dd101ec0b48f82f7ce8a8eb1d7cba2b93b66206bb7c3b5340e358be39380c7a9f17083fa1bcdf9c4e5ba5927edfd01519189b7b33fa2b5bbb5baf963598694e9f9c0c12e7aee29395e61a16129b43edaef245d5732bbc6e2e626ce241b8fdc60aea5532f829ace9ed443a679b3e6ffd712ce67681537982406ba09ff6a1c6dee258fd22b3f9aa1f28e19a83bbd1141f24171f380", "result": { "valid": true } diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof003.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof003.json index add4f449..ad287fa7 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof003.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof003.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278278e180c964ba3183afa27b31967d9a029b2ba81ae73fa8ba6cf770e62d7a851", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a5253f079b3ede1b244a809807ae2088deff841b93d0bca442e346b33d6b8aff8961", "result": { "valid": true } diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof004.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof004.json index f030a1dd..5b2c0335 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof004.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof004.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278278e180c964ba3183afa27b31967d9a029b2ba81ae73fa8ba6cf770e62d7a851", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a5253f079b3ede1b244a809807ae2088deff841b93d0bca442e346b33d6b8aff8961", "result": { "valid": false, "reason": "different presentation header" diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof005.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof005.json index 3f5dc84a..cfed6692 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof005.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof005.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278278e180c964ba3183afa27b31967d9a029b2ba81ae73fa8ba6cf770e62d7a851", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a5253f079b3ede1b244a809807ae2088deff841b93d0bca442e346b33d6b8aff8961", "result": { "valid": false, "reason": "wrong public key" diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof006.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof006.json index 802cb1a4..2162c696 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof006.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof006.json @@ -4,12 +4,12 @@ "header": "11223344556677889900aabbccddeeff", "presentationHeader": "bed231d880675ed101ead304512e043ade9958dd0241ea70b4b3957fba941501", "revealedMessages": { - "0": "806823e386f8b1e5c6ec2f5ecb68a9ba1cd8e125ae41926048785cb828b1dfa24269e3d5c835e089f2f8943d1f577add4424574a5d4c1e9d21ed9145512ca2bd80fcf64ed2dc991bece09379f64a7ed2c492a8100f61a35031e3624bfb6461920f53f8b0", + "0": "e9c7e4ebdfc3e9c945a020acf5332049dc1459a2fedcf936b4a2c3a1d5d7d4e61c620c724973056ed2ff67c772b5deabe227ba43f4e334bcaa0a61d4da28e15f4ce2e9f67200a21201f5d03df048e5f7091fbec360c2464249caa069ebedc3670439ff64", "2": "7372e9daa5ed31e6cd5c825eac1b855e84476a1d94932aa348e07b73", "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278278e180c964ba3183afa27b31967d9a029b2ba81ae73fa8ba6cf770e62d7a851", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a5253f079b3ede1b244a809807ae2088deff841b93d0bca442e346b33d6b8aff8961", "result": { "valid": false, "reason": "modified messages" diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof007.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof007.json index 73942fa8..9e7cc4ae 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof007.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof007.json @@ -10,7 +10,7 @@ "6": "d183ddc6e2665aa4e2f088af", "9": "" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278278e180c964ba3183afa27b31967d9a029b2ba81ae73fa8ba6cf770e62d7a851", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a5253f079b3ede1b244a809807ae2088deff841b93d0bca442e346b33d6b8aff8961", "result": { "valid": false, "reason": "extra message un-revealed in proof" diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof008.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof008.json index 34a8d626..9fc6872e 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof008.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof008.json @@ -10,7 +10,7 @@ "6": "d183ddc6e2665aa4e2f088af", "9": "96012096" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278278e180c964ba3183afa27b31967d9a029b2ba81ae73fa8ba6cf770e62d7a851", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a5253f079b3ede1b244a809807ae2088deff841b93d0bca442e346b33d6b8aff8961", "result": { "valid": false, "reason": "extra message invalid message un-revealed in proof" diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof009.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof009.json index e717c7dd..801cd41b 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof009.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof009.json @@ -8,7 +8,7 @@ "2": "7372e9daa5ed31e6cd5c825eac1b855e84476a1d94932aa348e07b73", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278278e180c964ba3183afa27b31967d9a029b2ba81ae73fa8ba6cf770e62d7a851", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a5253f079b3ede1b244a809807ae2088deff841b93d0bca442e346b33d6b8aff8961", "result": { "valid": false, "reason": "missing message revealed in proof" diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof010.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof010.json index 4db7f887..e95f5209 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof010.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof010.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "7372e9daa5ed31e6cd5c825eac1b855e84476a1d94932aa348e07b73" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278278e180c964ba3183afa27b31967d9a029b2ba81ae73fa8ba6cf770e62d7a851", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a5253f079b3ede1b244a809807ae2088deff841b93d0bca442e346b33d6b8aff8961", "result": { "valid": false, "reason": "re-ordered messages" diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof011.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof011.json index 5d70ef64..e472d4d2 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof011.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof011.json @@ -10,7 +10,7 @@ "6": "d183ddc6e2665aa4e2f088af", "9": "" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278278e180c964ba3183afa27b31967d9a029b2ba81ae73fa8ba6cf770e62d7a851", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a5253f079b3ede1b244a809807ae2088deff841b93d0bca442e346b33d6b8aff8961", "result": { "valid": false, "reason": "extra valid message, modified total message count" diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof012.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof012.json index 0dfbdf7f..d6338a8a 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof012.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof012.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a525", "result": { "valid": false, "reason": "truncated proof, one less undisclosed message" diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof013.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof013.json index e94d96fe..2f44c042 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof013.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof013.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a012168ebeab535cd5de65d83fea10f72b14410c0d764f5debc698681a6ea68a1be043cedcd6e155f5339744778600750e6edb72a8288a152924d61816f5201e7532c2c43579e68cb77ee013f226602d9117ce88990ba19887a7c4f5ee6f9c155854784e64ce87b8062df65c8c5fa186f283e2e85e6ecc216a7c65bb8d6c5ac3f654e6c72af242e66b470aae1b24d975b0b668f0132555523007df48667c6b5ae704abac451a726041dca91028e6493bd5a25cb6115f0a10105be75148e5c212894338698044676654797cadaaa26c5d8e02141e265a39a203af7bb939c7315592f12b75561302a57a5f3bc59fa7d9593183b8b0e5ec52e226fcb82a3b6db750278278e180c964ba3183afa27b31967d9a029b2ba81ae73fa8ba6cf770e62d7a851", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a0128d65da028243bdab954c1d6b4f3874ccafe69bb0900c0b8528d56dd9bd1d78b0c328022210ff9fe95276f79d23278956a0898d974932bd90e6c79f7e970de6b637c7e6326540699080d39bd076a50095e031e980e68068e3e34a982ff4678c656db3c3b49df591ade6db848d7c2ddadf7e7d1db858848a948f858f7fd59068c6b816607e5abd4f039bf2d1904fd7f89a1917023a1fc4862dbe8848041da2e36271d76ad8b5e357ea3fd71ebc3617427a064256febf122773528023e4df1d25900dc1ab19a563587c74a82495c59115263c51dcea106baa5f7f82c0b50e7756370f0470cb4630d2a188309f28e1e0582c47a9ec76f864363835812984432a5253f079b3ede1b244a809807ae2088deff841b93d0bca442e346b33d6b8aff8961", "result": { "valid": false, "reason": "different header" diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof014.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof014.json index bbbcd265..9fcf7362 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof014.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof014.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "ae46046037ed58bfa5771c603895b26b42748a3071a1dc9f8a272a4bc030bc3cda7cfa8686a6dc8382d728ad96e8d8ceb6ad6b76b99242514e520c43dd7d1a0728ce709d977c4dd200874e4acffa5b4cc0cbbd37c00d979d8688c636770cc8b403d98c010cac16c017bc4219d6163c425ba1b1127b715472fff1b93098842c286bb102d55ba9b3469d250181305d1ab3341c9e1ac704696f6e634f2d462ab327026e2f7cbcd470cc85673508a86555f3870bdf70a77e96d324ba04afa3491f273abb603dccddf6a9190a7f74bdc70faf6c7883e7bc391ab5ff15735d65a1175c354459ee06bb41b3edfcf850fab1de2c15c185f4eaabbc5d65de2a3849c6d54136be694126b70d71a3765c61f71643f9c6508e682bf297e0b8a66fec607151cc717535af4a2d8d1dd41235e7a290096b0a60aed54fb60e0bd05428611481bcb934c77fbb3c4fbb1f5e0fbba4f3dca1a18f1974b80eac8d17eab39257e4dc7092573d087e8557da2647b74d601153e489dfea04fa4c4108f6d86ecfd2df06b6fb", + "proof": "ae46046037ed58bfa5771c603895b26b42748a3071a1dc9f8a272a4bc030bc3cda7cfa8686a6dc8382d728ad96e8d8ceb6ad6b76b99242514e520c43dd7d1a0728ce709d977c4dd200874e4acffa5b4cc0cbbd37c00d979d8688c636770cc8b428ea9f05ed60cd85fdbd4c2fd73092e8bfc167c244d6e285ace1deade4fe8ce74fe2993a041e84004fe7d3dd170db765f7811a91043c4e75e9231804d577bfa533ec7a44bb6e49eb85089d8df1dc1acfb00ea0c7bdce5609595099e3cf7559c1715df6ec6982c5d9fffd317955ec3387a9055de28691e399b5af14722ae044a506d622e0e6ff0de8d1e4d4f3e9e5fdb01c4dbab02826ac38cb40eb80afe7b9d661dc27c94b146fedea19353b70310714932674c1f4bc1edc2c17605749e0bbb60a77ac62a606d31081ff5a52e1485be257b2c0afa4b676438b0eaa0bd483c66828bc66032b91fbe8a309408e595e085a1b55e2dd12789e6f522ef5682ac46deb628e03e4eb0303af7162f36a119313c3396fe6bca6082238fe396e8c08e607c4", "result": { "valid": true } diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof015.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof015.json index 1dcc3a41..09f3eeae 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof015.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/proof/proof015.json @@ -9,7 +9,7 @@ "4": "496694774c5604ab1b2544eababcf0f53278ff50", "6": "d183ddc6e2665aa4e2f088af" }, - "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a015530b74ffff8ec6e75503faef5debdff1a7a7bf6c995af7a269dec99cd2b50643c475ed7c2e9a803cbb0bb28df0a40bc58b7142488dca96dd47b63442d9d8c3f38cbc79c461a5cd4edcc85706592149f38b6dca720a831de28a20be1e175873858509b86b55f67aaaaa3f0554d959016e1add297971cb2a92e79f547832d2d733bc49b3343dc8455d9098f3aa85914a65e2112bd623d9a9ae0f3a32aaf1a26b96fc0e25d993393006aa0a43b346f3d95f451d0ef32606b3a5cb63ea165784ee4334214e996e4fa64ddebc199c921c641ecbb8d8519b36b305c7c6c330c8776760920f2d429da881b32e4389b991d26bc17c8098214bbae7030beef81b2f759390f4fc9e50297fc50dad9784e593351bf47174fc442a76e04a4684cdf4f0d4c55", + "proof": "ac0424b2a984c55d0061aa61df105f2c882d393494f3f4205d1e73f93c9c76b30664baeb3dc87f23fbf4035fb0a8e76b851dd39cecce8843e747ccf540f0850a30e1317f8897a56c2d85bfc1e0b4dba1b0e0322d89aad4feb8b21c414a384a015238f4643b9d075bc6638ec42d0e285f73c6ca9830be2a5bb48955ddb094751026493147def3cfe2a37bbd89a4536bdff6548d891d5206ac6b69c22c6fa8624512caeb80c56dbd79b7a4c8050bc9e782232f9594087561b10d7f4b0bef708458096637a34962399e918d5adb496faf7c38ded94fe79c3bfdc53c81f0dcb0da3f1bed0dbfdb6f0310d71d50a63b265e1992dd7d12315bf11da69a8897d8e33be36f116d58eff998f80e23ad0aad544e93615a5f10f169a3aed7c4d6266191a21412f4f4d8eb5096a05243b809c4c53a8d237817dfa15a403d8943b968d1216c753fb988fbcfe9280232c25cac1570873a66d3f4a7e713fb19723f5b99338f053f08fae9f905b10e0526451968e25569e3779f642a4d2b6bcc1e00be28e2711d1a", "result": { "valid": true } diff --git a/tooling/fixtures/fixture_data/bls12-381-shake-256/signature/signature009.json b/tooling/fixtures/fixture_data/bls12-381-shake-256/signature/signature009.json index c2ca3e48..e0b2a0f8 100644 --- a/tooling/fixtures/fixture_data/bls12-381-shake-256/signature/signature009.json +++ b/tooling/fixtures/fixture_data/bls12-381-shake-256/signature/signature009.json @@ -6,16 +6,16 @@ }, "header": "11223344556677889900aabbccddeeff", "messages": [ - "ac55fb33a75909ed", - "", + "c344136d9ab02da4dd5908bbba913ae6f58c2cc844b802a6f811f5fb075f9b80", "d183ddc6e2665aa4e2f088af", + "496694774c5604ab1b2544eababcf0f53278ff50", + "", + "9872ad089e452c7b6e283dfac2a80d58e8d0ff71cc4d5e310a1debdda4a45f02", "77fe97eb97a1ebe2e81e4e3597a3ee740a66e9ef2412472c", + "7372e9daa5ed31e6cd5c825eac1b855e84476a1d94932aa348e07b73", "96012096", - "9872ad089e452c7b6e283dfac2a80d58e8d0ff71cc4d5e310a1debdda4a45f02", - "496694774c5604ab1b2544eababcf0f53278ff50", - "515ae153e22aae04ad16f759e07237b4", - "c344136d9ab02da4dd5908bbba913ae6f58c2cc844b802a6f811f5fb075f9b80", - "7372e9daa5ed31e6cd5c825eac1b855e84476a1d94932aa348e07b73" + "ac55fb33a75909ed", + "515ae153e22aae04ad16f759e07237b4" ], "signature": "97a296c83ed3626fe254d26021c5e9a087b580f1e8bc91bb51efb04420bfdaca215fe376a0bc12440bcc52224fb33c696cca9239b9f28dcddb7bd850aae9cd1a9c3e9f3639953fe789dbba53b8f0dd6f", "result": { From 26a253b383cec6c5c24050cc6d946b3bb33c491e Mon Sep 17 00:00:00 2001 From: Vasilis Kalos Date: Thu, 6 Jul 2023 13:34:02 +0300 Subject: [PATCH 2/5] switch r3 with r2 --- .vscode/settings.json | 10 + draft-blind-bbs-signatures.html | 1557 ++++++++++ draft-irtf-cfrg-bbs-signatures.html | 4444 +++++++++++++++++++++++++++ draft-irtf-cfrg-bbs-signatures.md | 8 +- 4 files changed, 6015 insertions(+), 4 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 draft-blind-bbs-signatures.html create mode 100644 draft-irtf-cfrg-bbs-signatures.html diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..f5953e87 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "cSpell.words": [ + "cfrg", + "ciphersuite", + "HKDF", + "irtf", + "octs", + "Shamir" + ] +} \ No newline at end of file diff --git a/draft-blind-bbs-signatures.html b/draft-blind-bbs-signatures.html new file mode 100644 index 00000000..9b5375e9 --- /dev/null +++ b/draft-blind-bbs-signatures.html @@ -0,0 +1,1557 @@ + + + + + + +Blind Signatures extension of the BBS Signature Scheme + + + + + + + + + + + + + + + + + + + + + + + + +
Blind Signatures extension of the BBS SiJanuary 2023
Lodder, et al.Informational[Page]
+
+
+
+
Workgroup:
+
none
+
Published:
+
+ +
+
Authors:
+
+
+
M. Lodder
+
CryptID
+
+
+
T. Looker
+
Mattr
+
+
+
A. Whitehead
+
+
+
+
+

Blind Signatures extension of the BBS Signature Scheme

+
+

Abstract

+

This document defines an extension to the BBS Signature scheme, a form of short group digital signature scheme that supports multi-message signing that produces a single output digital signature. To enable blind signing capabilities which in the most general sense provide the ability for a signer to blindly sign a set of messages.

+
+
+

+Discussion Venues +

+

This note is to be removed before publishing as an RFC.

+

Source for this draft and an issue tracker can be found at + https://github.com/decentralized-identity/bbs-signature.

+
+
+
+

+Table of Contents +

+ +
+
+
+
+

+1. Introduction +

+

// TODO

+
+
+

+1.1. Terminology +

+

All terminology defined by [BBS-DRAFT] is applicable to this draft

+

The following further terminology is defined by this document:

+
+
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. +
+
+
s'
+
The signature blinding factor held by the signature recipient. +
+
+
blind_signature
+
The blind digital signature output. +
+
+
+
+
+
+
+

+1.2. Notation +

+

Terms specific to pairing-friendly elliptic curves that are relevant to this document are restated in [BBS-DRAFT], originally defined in [I-D.irtf-cfrg-pairing-friendly-curves]

+
+
+
+
+
+
+

+2. Conventions +

+

The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, +SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL, when they appear in this +document, are to be interpreted as described in [RFC2119].

+
+
+
+
+

+3. Overview +

+

//TODO

+
+
+
+
+

+4. Example Flow +

+

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.

+
+
+--------+                               +--------+
+|        | <-(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. +
  3. +

    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).

    +
  4. +
  5. +

    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]).

    +
  6. +
+
+
+
+
+

+5. Operations +

+
+
+

+5.1. 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' = HASH(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
+
+
+
+
+
+
+

+5.2. 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 = HASH(PRF(8 \* ceil(log2(r)))) mod r
+
+3. s'' = HASH(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 + P1 + 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
+
+
+
+
+
+
+

+5.3. 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
+
+
+
+
+
+
+

+5.4. 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\~ = HASH(PRF(8 \* ceil(log2(r)))) mod r
+
+4. for i in 1 to U: r\~\[i\] = HASH(PRF(8 \* ceil(log2(r)))) mod r
+
+5. U~ = h0 \* s\~ + h\[i1\] \* r\~\[1\] + ... + h\[iU\] \* r\~\[U\]
+
+6. c = HASH(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^)
+
+
+
+
+
+
+

+5.5. 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 = HASH(U || U^ || nonce)
+
+5. return c == c\_v
+
+
+
+
+
+
+
+
+

+6. Security Considerations +

+

Implementers should consider the security considerations of [BBS-DRAFT] when implementing this work.

+
+
+
+
+

+7. IANA Considerations +

+

This document does not make any requests of IANA.

+
+
+
+

+8. Normative References +

+
+
[I-D.irtf-cfrg-pairing-friendly-curves]
+
+Sakemi, Y., Kobayashi, T., Saito, T., and R. S. Wahby, "Pairing-Friendly Curves", Work in Progress, Internet-Draft, draft-irtf-cfrg-pairing-friendly-curves-11, , <https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.txt>.
+
+
[RFC2119]
+
+Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
+
+
+
+
+

+9. Informative References +

+
+
[BBS-DRAFT]
+
+Lodder, M., Looker, T., Whitehead, A., and V. Kalos, "The BBS Signature Scheme", <https://identity.foundation/bbs-signature/draft-irtf-cfrg-bbs-signatures.html>.
+
+
+
+
+
+

+Appendix A. Appendix +

+
+
+

+A.1. Test Vectors +

+

//TODO

+
+
+
+
+
+
+

+Authors' Addresses +

+
+
Mike Lodder
+
CryptID
+ +
+
+
Tobias Looker
+
Mattr
+ +
+
+
Andrew Whitehead
+ +
+
+
+ + + diff --git a/draft-irtf-cfrg-bbs-signatures.html b/draft-irtf-cfrg-bbs-signatures.html new file mode 100644 index 00000000..6cbaa469 --- /dev/null +++ b/draft-irtf-cfrg-bbs-signatures.html @@ -0,0 +1,4444 @@ + + + + + + +The BBS Signature Scheme + + + + + + + + + + + + + + + + + + + + + + + + + +
Internet-DraftThe BBS Signature SchemeJuly 2023
Looker, et al.Expires 5 January 2024[Page]
+
+
+
+
Workgroup:
+
CFRG
+
Internet-Draft:
+
draft-irtf-cfrg-bbs-signatures-latest
+
Published:
+
+ +
+
Intended Status:
+
Informational
+
Expires:
+
+
Authors:
+
+
+
T. Looker
+
MATTR
+
+
+
V. Kalos
+
MATTR
+
+
+
A. Whitehead
+
Portage
+
+
+
M. Lodder
+
CryptID
+
+
+
+
+

The BBS Signature Scheme

+
+

Abstract

+

BBS is a digital signature scheme categorized as a form of short group signature that supports several unique properties. Notably, the scheme supports signing multiple messages whilst producing a single output digital signature. Through this capability, the possessor of a signature is able to generate proofs that selectively disclose subsets of the originally signed set of messages, whilst preserving the verifiable authenticity and integrity of the messages. Furthermore, these proofs are said to be zero-knowledge in nature as they do not reveal the underlying signature; instead, what they reveal is a proof of knowledge of the undisclosed signature.

+
+
+

+Discussion Venues +

+

This note is to be removed before publishing as an RFC.

+

Source for this draft and an issue tracker can be found at + https://github.com/decentralized-identity/bbs-signature.

+
+
+
+

+Status of This Memo +

+

+ This Internet-Draft is submitted in full conformance with the + provisions of BCP 78 and BCP 79.

+

+ Internet-Drafts are working documents of the Internet Engineering Task + Force (IETF). Note that other groups may also distribute working + documents as Internet-Drafts. The list of current Internet-Drafts is + at https://datatracker.ietf.org/drafts/current/.

+

+ Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as "work in progress."

+

+ This Internet-Draft will expire on 5 January 2024.

+
+
+ +
+
+

+Table of Contents +

+ +
+
+
+
+

+1. Introduction +

+

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 message, where anyone in possession of the corresponding public key matching that of the private key is able to verify the signature.

+

The name BBS is derived from the authors of the original academic work of Dan Boneh, Xavier Boyen, and Hovav Shacham, where the scheme was first described.

+

Beyond the core properties of a digital signature scheme, BBS signatures provide multiple additional unique properties, three key ones are:

+

Selective Disclosure - The scheme allows a signer to sign multiple messages and produce a single -constant size- output signature. A holder/prover then possessing the messages and the signature can generate a proof whereby they can choose which messages to disclose, while revealing no-information about the undisclosed messages. The proof itself guarantees the integrity and authenticity of the disclosed messages (e.g. that they were originally signed by the signer).

+

Unlinkable Proofs - The proofs generated by the scheme are known as zero-knowledge, proofs-of-knowledge of the signature, meaning a verifying party in receipt of a proof is unable to determine which signature was used to generate the proof, removing a common source of correlation. In general, each proof generated is indistinguishable from random even for two proofs generated from the same signature.

+

Proof of Possession - The proofs generated by the scheme prove to a verifier that the party who generated the proof (holder/prover) was in possession of a signature without revealing it. The scheme also supports binding a presentation header to the generated proof. The presentation header can include arbitrary information such as a cryptographic nonce, an audience/domain identifier and or time based validity information.

+

Refer to the Appendix B for an elaboration on situations where these properties are useful

+

Below is a basic diagram describing the main entities involved in the scheme

+
+
+
  (1) sign                                      (3) ProofGen
+   +-----                                         +-----
+   |    |                                         |    |
+   |    |                                         |    |
+   |   \ /                                        |   \ /
++----------+                                   +-----------+
+|          |                                   |           |
+|          |                                   |           |
+|          |                                   |           |
+|  Signer  |---(2)* Send signature + msgs----->|  Holder/  |
+|          |                                   |  Prover   |
+|          |                                   |           |
+|          |                                   |           |
++----------+                                   +-----------+
+                                                     |
+                                                     |
+                                                     |
+                                      (4)* Send proof + disclosed msgs
+                                                     |
+                                                     |
+                                                    \ /
+                                               +-----------+
+                                               |           |
+                                               |           |
+                                               |           |
+                                               | Verifier  |
+                                               |           |
+                                               |           |
+                                               |           |
+                                               +-----------+
+                                                  |   / \
+                                                  |    |
+                                                  |    |
+                                                  +-----
+                                             (5) ProofVerify
+
+
+
+
+
Figure 1: +Basic diagram capturing the main entities involved in using the scheme +
+

Note The protocols implied by the items annotated by an asterisk are out of scope for this specification

+
+
+

+1.1. Terminology +

+

The following terminology is used throughout this document:

+
+
SK
+
The secret key for the signature scheme. +
+
+
PK
+
The public key for the signature scheme. +
+
+
L
+
The total number of signed messages. +
+
+
R
+
The number of message indexes that are disclosed (revealed) in a proof-of-knowledge of a signature. +
+
+
U
+
The number of message indexes that are undisclosed in a proof-of-knowledge of a signature. +
+
+
msg
+
An input message to be signed by the signature scheme. +
+
+
generator
+
A valid point on the selected subgroup of the curve being used that is employed to commit a value. +
+
+
scalar
+
An integer between 0 and r-1, where r is the prime order of the selected groups, defined by each ciphersuite (see also Notation). +
+
+
signature
+
The digital signature output. +
+
+
nonce
+
A cryptographic nonce +
+
+
presentation_header (ph)
+
A payload generated and bound to the context of a specific spk. +
+
+
nizk
+
A non-interactive zero-knowledge proof from the Fiat-Shamir heuristic. +
+
+
dst
+
The domain separation tag. +
+
+
I2OSP
+
An operation that transforms a non-negative integer into an octet string, defined in Section 4 of [RFC8017]. Note, the output of this operation is in big-endian order. +
+
+
OS2IP
+
An operation that transforms a octet string into an non-negative integer, defined in Section 4 of [RFC8017]. Note, the input of this operation must be in big-endian order. +
+
+
+
+
+
+
+

+1.2. Notation +

+

The following notation and primitives are used:

+
+
a || b
+
Denotes the concatenation of octet strings a and b. +
+
+
I \ J
+
For sets I and J, denotes the difference of the two sets i.e., all the elements of I that do not appear in J, in the same order as they were in I. +
+
+
X[a..b]
+
Denotes a slice of the array X containing all elements from and including the value at index a until and including the value at index b. Note when this syntax is applied to an octet string, each element in the array X is assumed to be a single byte. +
+
+
range(a, b)
+
For integers a and b, with a <= b, denotes the ascending ordered list of all integers between a and b inclusive (i.e., the integers "i" such that a <= i <= b). +
+
+
length(input)
+
Takes as input either an array or an octet string. If the input is an array, returns the number of elements of the array. If the input is an octet string, returns the number of bytes of the inputted octet string. +
+
+
+

Terms specific to pairing-friendly elliptic curves that are relevant to this document are restated below, originally defined in [I-D.irtf-cfrg-pairing-friendly-curves]

+
+
E1, E2
+
elliptic curve groups defined over finite fields. This document assumes that E1 has a more compact representation than E2, i.e., because E1 is defined over a smaller field than E2. +
+
+
G1, G2
+
subgroups of E1 and E2 (respectively) having prime order r. +
+
+
GT
+
a subgroup, of prime order r, of the multiplicative group of a field extension. +
+
+
e
+
G1 x G2 -> GT: a non-degenerate bilinear map. +
+
+
r
+
The prime order of the G1 and G2 subgroups. +
+
+
P1, P2
+
points on G1 and G2 respectively. For a pairing-friendly curve, this document denotes operations in E1 and E2 in additive notation, i.e., P + Q denotes point addition and x * P denotes scalar multiplication. Operations in GT are written in multiplicative notation, i.e., a * b is field multiplication. +
+
+
Identity_G1, Identity_G2, Identity_GT
+
The identity element for the G1, G2, and GT subgroups respectively. +
+
+
hash_to_curve_g1(ostr, dst) -> P
+
A cryptographic hash function that takes an arbitrary octet string as input and returns a point in G1, using the hash_to_curve operation defined in [I-D.irtf-cfrg-hash-to-curve] and the inputted dst as the domain separation tag for that operation (more specifically, the inputted dst will become the DST parameter for the hash_to_field operation, called by hash_to_curve). +
+
+
point_to_octets_g1(P) -> ostr, point_to_octets_g2(P) -> ostr
+
returns the canonical representation of the point P for the respective subgroup as an octet string. This operation is also known as serialization. +
+
+
octets_to_point_g1(ostr) -> P, octets_to_point_g2(ostr) -> P
+
returns the point P for the respective subgroup corresponding to the canonical representation ostr, or INVALID if ostr is not a valid output of the respective point_to_octets_g* function. This operation is also known as deserialization. +
+
+
subgroup_check(P) -> VALID or INVALID
+
returns VALID when the point P is an element of the subgroup of order r, and INVALID otherwise. This function can always be implemented by checking that r * P is equal to the identity element. In some cases, faster checks may also exist, e.g., [Bowe19]. +
+
+
+
+
+
+
+

+1.3. Document Organization +

+

This document is organized as follows:

+
    +
  • +

    Scheme Definition defines the core operations and parameters for the BBS signature scheme.

    +
  • +
  • +

    Utility Operations defines utilities used by the BBS signature scheme.

    +
  • +
  • +

    Security Considerations describes a set of security considerations associated to the signature scheme.

    +
  • +
  • +

    Ciphersuites defines the format of a ciphersuite, alongside a concrete ciphersuite based on the BLS12-381 curve.

    +
  • +
+
+
+
+
+
+
+

+2. Conventions +

+

The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, +SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL, when they appear in this +document, are to be interpreted as described in [RFC2119].

+
+
+
+
+

+3. Scheme Definition +

+

This section defines the BBS signature scheme, including the parameters required to define a concrete ciphersuite.

+
+
+

+3.1. Parameters +

+

The schemes operations defined in this section depend on the following parameters:

+
    +
  • +

    A pairing-friendly elliptic curve, plus associated functionality given in Section 1.2.

    +
  • +
  • +

    A hash-to-curve suite as defined in [I-D.irtf-cfrg-hash-to-curve], using the aforementioned pairing-friendly curve. This defines the hash_to_curve and expand_message operations, used by this document.

    +
  • +
  • +

    get_random(n): returns a random octet string with a length of n bytes, sampled uniformly at random using a cryptographically secure pseudo-random number generator (CSPRNG) or a pseudo random function. See [RFC4086] for recommendations and requirements on the generation of random numbers.

    +
  • +
+
+
+
+
+

+3.2. Considerations +

+
+
+

+3.2.1. Subgroup Selection +

+

In definition of this signature scheme there are two possible variations based upon the sub-group selection, namely where public keys are defined in G2 and signatures in G1 OR the opposite where public keys are defined in G1 and signatures in G2. Some pairing cryptography based digital signature schemes such as [I-D.irtf-cfrg-bls-signature] elect to allow for both variations, because they optimize for different things. However, in the case of this scheme, due to the operations involved in both signature and proof generation being computational in-efficient when performed in G2 and in the pursuit of simplicity, the scheme is limited to a construction where public keys are in G2 and signatures in G1.

+
+
+
+
+

+3.2.2. Messages +

+

Each of the core operations of the BBS signature scheme expect the inputted messages to be scalar values within a given range (specifically 1 and r-1, where r is the prime order of the G1 and G2 subgroups, defined by each ciphersuite, see Notation). There are multiple ways to transform a message from an octet string to a scalar value. This document defines the MapMessageToScalarAsHash operation, which hashes an octet string to a scalar (see Section 4.3.1). An application can use a different MapMessageToScalar operation, but it MUST be clearly and unambiguously defined, for all parties involved. Before using the core operations, all messages MUST be mapped to their respective scalars using the same operation. The defined Section 4.3.1 is the RECOMMENDED way of mapping octet strings to scalar values.

+
+
+
+
+

+3.2.3. Generators +

+

Throughout the operations of this signature scheme, each message that is signed is paired with a specific generator (point in G1). Specifically, if a generator H_1 is multiplied with msg_1 during signing, then H_1 MUST be multiplied with msg_1 in all other operations (signature verification, proof generation and proof verification).

+

Aside from the message generators, the scheme uses one additional generator Q_1 to sign the signature's domain, which binds both the signature and generated proofs to a specific context and cryptographically protects any potential application-specific information (for example, messages that must always be disclosed etc.).

+
+
+
+
+

+3.2.4. Serializing to Octets +

+

When serializing one or more values to produce an octet string, each element will be encoded using a specific operation determined by its type. More concretely,

+
    +
  • Points in G* will be serialized using the point_to_octets_g* implementation for a particular ciphersuite. +
  • +
  • Non-negative integers will be serialized using I2OSP with an output length of 8 bytes. +
  • +
  • Scalars will be serialized using I2OSP with a constant output length defined by a particular ciphersuite. +
  • +
+

We also use strings in double quotes to represent ASCII-encoded literals. For example "BBS" will be used to refer to the octet string, 010000100100001001010011.

+

Those rules will be used explicitly on every operation. See also Serialize.

+
+
+
+
+
+
+

+3.3. Key Generation Operations +

+
+
+

+3.3.1. Secret Key +

+

This operation generates a secret key (SK) deterministically from a secret octet string (key_material). This operation is the RECOMMENDED way of generating a secret key, but its use is not required for compatibility, and implementations MAY use a different key generation procedure. For security, such an alternative MUST output a secret key that is statistically close to uniformly random in the range from 1 to r-1. An example of an HKDF-based alternative is the KeyGen operation defined in Section 2.3 of [I-D.irtf-cfrg-bls-signature] (with an appropriate, BBS specific, salt value, like "BBS_SIG_KEYGENSALT").

+

For security, key_material MUST be random and infeasible to guess, e.g. generated by a trusted source of randomness and with enough entropy. See [RFC4086] for suggestions on generating randomness. key_material MUST be at least 32 bytes long, but it MAY be longer.

+

KeyGen takes an optional input, key_info. This parameter MAY be used to derive distinct keys from the same key material.

+

Because KeyGen is deterministic, implementations MAY choose either to store the resulting SK or to store key_material and key_info and call KeyGen to derive SK when necessary.

+
+
SK = KeyGen(key_material, key_info, key_dst)
+
+Inputs:
+
+- key_material (REQUIRED), a secret octet string. See requirements
+                           above.
+- key_info (OPTIONAL), an octet string. Defaults to an empty string if
+                       not supplied.
+- key_dst (OPTIONAL), an octet string representing the domain separation tag.
+                      Defaults to the octet string ciphersuite_id || "KEYGEN_DST_"
+                      if not supplied.
+
+Outputs:
+
+- SK, a uniformly random integer such that 0 < SK < r.
+
+Procedure:
+
+1. if length(key_material) < 32, return INVALID
+2. if length(key_info) > 65535, return INVALID
+3. derive_input = key_material || I2OSP(length(key_info), 2) || key_info
+4. SK = hash_to_scalar(derive_input, key_dst)
+5. if SK is INVALID, return INVALID
+6. return SK
+
+
+
+
+
+
+

+3.3.2. Public Key +

+

This operation takes a secret key (SK) and outputs a corresponding public key (PK).

+
+
PK = SkToPk(SK)
+
+Inputs:
+
+- SK (REQUIRED), a secret integer such that 0 < SK < r.
+
+Outputs:
+
+- PK, a public key encoded as an octet string.
+
+Procedure:
+
+1. W = SK * P2
+2. return point_to_octets_g2(W)
+
+
+
+
+
+
+
+
+

+3.4. Core Operations +

+

The operations of this section make use of functions and sub-routines defined in Utility Operations. More specifically,

+
    +
  • + hash_to_scalar is defined in Section 4.4 +
  • +
  • + calculate_domain and calculate_challenge are defined in Section 4.5 and Section 4.6 correspondingly. +
  • +
  • + serialize, signature_to_octets, octets_to_signature, proof_to_octets, octets_to_proof and octets_to_pubkey are defined in Section 4.7 +
  • +
+

The following operations also make use of the create_generators operation defined in Section 4.2, to create generator points on G1 (see Messages and Generators). Note that the values of those points depends only on a cipheruite defined seed. As a result, the output of that operation can be cached to avoid unnecessary calls to the create_generators procedure. See Section 4.2 for more details.

+
+
+

+3.4.1. Signature Generation (Sign) +

+

This operation computes a deterministic signature from a secret key (SK) and optionally over a header and or a vector of messages (as scalar values, see Messages).

+
+
signature = Sign(SK, PK, header, messages)
+
+Inputs:
+
+- SK (REQUIRED), a non negative integer mod r outputted by the KeyGen
+                 operation.
+- PK (REQUIRED), an octet string of the form outputted by the SkToPk
+                 operation provided the above SK as input.
+- header (OPTIONAL), an octet string containing context and application
+                     specific information. If not supplied, it defaults
+                     to an empty string.
+- messages (OPTIONAL), a vector of scalars. If not supplied, it defaults
+                       to the empty array "()".
+
+Parameters:
+
+- P1, fixed point of G1, defined by the ciphersuite.
+- expand_message, the expand_message operation defined by the suite
+                  specified by the hash_to_curve_suite parameter.
+- octet_scalar_length, non-negative integer. The length of a scalar
+                       octet representation, defined by the ciphersuite.
+- create_generators, an operation that returns a number of generator
+                     points, defined by the ciphersuite.
+
+Definitions:
+
+- L, is the non-negative integer representing the number of messages to
+     be signed.
+
+Outputs:
+
+- signature, a signature encoded as an octet string.
+
+Deserialization:
+
+1. L = length(messages)
+2. (msg_1, ..., msg_L) = messages
+
+Procedure:
+
+1. (Q_1, H_1, ..., H_L) = create_generators(L+1, PK)
+2. domain = calculate_domain(PK, Q_1, (H_1, ..., H_L), header)
+3. if domain is INVALID, return INVALID
+4. e = hash_to_scalar(serialize((SK, domain, msg_1, ..., msg_L)))
+5. if e is INVALID, return INVALID
+6. B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L
+7. A = B * (1 / (SK + e))
+8. return signature_to_octets(A, e)
+
+
+

Note When computing step 12 of the above procedure there is an extremely small probability (around 2^(-r)) that the condition (SK + e) = 0 mod r will be met. How implementations evaluate the inverse of the scalar value 0 may vary, with some returning an error and others returning 0 as a result. If the returned value from the inverse operation 1/(SK + e) does evaluate to 0 the value of A will equal Identity_G1 thus an invalid signature. Implementations MAY elect to check (SK + e) = 0 mod r prior to step 9, and or A != Identity_G1 after step 9 to prevent the production of invalid signatures.

+
+
+
+
+

+3.4.2. Signature Verification (Verify) +

+

This operation checks that a signature is valid for a given header and vector of messages against a supplied public key (PK). The messages MUST be supplied in this operation in the same order they were supplied to Sign when creating the signature.

+
+
result = Verify(PK, signature, header, messages)
+
+Inputs:
+
+- PK (REQUIRED), an octet string of the form outputted by the SkToPk
+                 operation.
+- signature (REQUIRED), an octet string of the form outputted by the
+                        Sign operation.
+- header (OPTIONAL), an octet string containing context and application
+                     specific information. If not supplied, it defaults
+                     to an empty string.
+- messages (OPTIONAL), a vector of scalars. If not supplied, it defaults
+                       to the empty array "()".
+
+Parameters:
+
+- P1, fixed point of G1, defined by the ciphersuite.
+- create_generators, an operation that returns a number of generator
+                     points, defined by the ciphersuite.
+
+Definitions:
+
+- L, is the non-negative integer representing the number of signed
+     messages.
+
+Outputs:
+
+- result, either VALID or INVALID.
+
+Deserialization:
+
+1. signature_result = octets_to_signature(signature)
+2. if signature_result is INVALID, return INVALID
+3. (A, e) = signature_result
+4. W = octets_to_pubkey(PK)
+5. if W is INVALID, return INVALID
+6. L = length(messages)
+7. (msg_1, ..., msg_L) = messages
+
+Procedure:
+
+1. (Q_1, H_1, ..., H_L) = create_generators(L+1, PK)
+2. domain = calculate_domain(PK, Q_1, (H_1, ..., H_L), header)
+3. if domain is INVALID, return INVALID
+4. B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L
+5. if e(A, W + P2 * e) * e(B, -P2) != Identity_GT, return INVALID
+6. return VALID
+
+
+
+
+
+
+

+3.4.3. Proof Generation (ProofGen) +

+

This operation computes a zero-knowledge proof-of-knowledge of a signature, while optionally selectively disclosing from the original set of signed messages. The "prover" may also supply a presentation header, see Presentation header selection for more details.

+

The messages supplied in this operation MUST be in the same order as when supplied to Sign. To specify which of those messages will be disclosed, the prover can supply the list of indexes (disclosed_indexes) that the disclosed messages have in the array of signed messages. Each element in disclosed_indexes MUST be a non-negative integer, in the range from 1 to length(messages).

+

The operation calculates multiple random scalars using the calculate_random_scalars utility operation defined in Section 4.1. See also Section 5.10 for considerations and requirements on random scalars generation.

+

To allow for flexibility in implementations, although ProofGen defines a specific value for expand_len, applications may use any value larger than ceil((ceil(log2(r))+k)/8) (for example, for the BLS12-381-SHAKE-256 and BLS12-381-SHA-256 ciphersuites, an implementation can elect to use a value of 64, instead of 48, as to allow for certain optimizations).

+
+
proof = ProofGen(PK, signature, header, ph, messages, disclosed_indexes)
+
+Inputs:
+
+- PK (REQUIRED), an octet string of the form outputted by the SkToPk
+                 operation.
+- signature (REQUIRED), an octet string of the form outputted by the
+                        Sign operation.
+- header (OPTIONAL), an octet string containing context and application
+                     specific information. If not supplied, it defaults
+                     to an empty string.
+- ph (OPTIONAL), an octet string containing the presentation header. If not
+                 supplied, it defaults to an empty string.
+- messages (OPTIONAL), a vector of scalars. If not supplied, it defaults
+                       to the empty array "()".
+- disclosed_indexes (OPTIONAL), vector of unsigned integers in ascending
+                                order. Indexes of disclosed messages. If
+                                not supplied, it defaults to the empty
+                                array "()".
+
+Parameters:
+
+- P1, fixed point of G1, defined by the ciphersuite.
+- create_generators, an operation that returns a number of generator
+                     points, defined by the ciphersuite.
+
+Definitions:
+
+- L, is the non-negative integer representing the number of messages.
+- R, is the non-negative integer representing the number of disclosed
+     (revealed) messages.
+- U, is the non-negative integer representing the number of undisclosed
+     messages, i.e., U = L - R.
+
+Outputs:
+
+- proof, an octet string; or INVALID.
+
+Deserialization:
+
+1.  signature_result = octets_to_signature(signature)
+2.  if signature_result is INVALID, return INVALID
+3.  (A, e) = signature_result
+4.  L = length(messages)
+5.  R = length(disclosed_indexes)
+6.  U = L - R
+7.  (i1, ..., iR) = disclosed_indexes
+8.  (j1, ..., jU) = range(1, L) \ disclosed_indexes
+9.  (msg_1, ..., msg_L) = messages
+10. (msg_i1, ..., msg_iR) = (messages[i1], ..., messages[iR])
+11. (msg_j1, ..., msg_jU) = (messages[j1], ..., messages[jU])
+
+Procedure:
+
+1.  (Q_1, MsgGenerators) = create_generators(L+1, PK)
+2.  (H_1, ..., H_L) = MsgGenerators
+3.  (H_j1, ..., H_jU) = (MsgGenerators[j1], ..., MsgGenerators[jU])
+4.  domain = calculate_domain(PK, Q_1, (H_1, ..., H_L), header)
+5.  if domain is INVALID, return INVALID
+6.  random_scalars = calculate_random_scalars(3+U)
+7.  (r1, r2, r3, m~_j1, ..., m~_jU) = random_scalars
+8.  B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L
+9.  Abar = A * r1
+10. Bbar = B * r1 - Abar * e
+11. C = Bbar * r2 + Abar * r3 + H_j1 * m~_j1 + ... + H_jU * m~_jU
+12. c = calculate_challenge(Abar, Bbar, C, (i1, ..., iR),
+                            (msg_i1, ..., msg_iR), domain, ph)
+13. if c is INVALID, return INVALID
+14. r4 = - r1^-1 (mod r)
+15. r2^ = r2 + r4 * c (mod r)
+16. r3^ = r3 + e * r4 * c (mod r)
+17. for j in (j1, ..., jU): m^_j = m~_j + msg_j * c (mod r)
+18. proof = (Abar, Bbar, r2^, r3^, (m^_j1, ..., m^_jU), c)
+19. return proof_to_octets(proof)
+
+
+
+
+
+
+

+3.4.4. Proof Verification (ProofVerify) +

+

This operation checks that a proof is valid for a header, vector of disclosed messages (along side their index corresponding to their original position when signed) and presentation header against a public key (PK).

+

The operation accepts the list of messages the prover indicated to be disclosed. Those messages MUST be in the same order as when supplied to Sign (as a subset of the signed messages list). The operation also requires the total number of signed messages (L). Lastly, it also accepts the indexes that the disclosed messages had in the original array of messages supplied to Sign (i.e., the disclosed_indexes list supplied to ProofGen). Every element in this list MUST be a non-negative integer in the range from 1 to L, in ascending order.

+
+
result = ProofVerify(PK, proof, header, ph,
+                     disclosed_messages,
+                     disclosed_indexes)
+
+Inputs:
+
+- PK (REQUIRED), an octet string of the form outputted by the SkToPk
+                 operation.
+- proof (REQUIRED), an octet string of the form outputted by the
+                    ProofGen operation.
+- header (OPTIONAL), an optional octet string containing context and
+                     application specific information. If not supplied,
+                     it defaults to an empty string.
+- ph (OPTIONAL), an octet string containing the presentation header. If not
+                 supplied, it defaults to an empty string.
+- disclosed_messages (OPTIONAL), a vector of scalars. If not supplied,
+                                 it defaults to the empty array "()".
+- disclosed_indexes (OPTIONAL), vector of unsigned integers in ascending
+                                order. Indexes of disclosed messages. If
+                                not supplied, it defaults to the empty
+                                array "()".
+
+Parameters:
+
+- P1, fixed point of G1, defined by the ciphersuite.
+- create_generators, an operation that returns a number of generator
+                     points, defined by the ciphersuite.
+
+Definitions:
+
+- R, is the non-negative integer representing the number of disclosed
+     (revealed) messages.
+- U, is the non-negative integer representing the number of undisclosed
+     messages.
+- L, is the non-negative integer representing the number of total,
+     messages i.e., L = U + R.
+
+Outputs:
+
+- result, either VALID or INVALID.
+
+Deserialization:
+
+1.  proof_result = octets_to_proof(proof)
+2.  if proof_result is INVALID, return INVALID
+3.  (Abar, Bbar, r2^, r3^, commitments, c) = proof_result
+4.  W = octets_to_pubkey(PK)
+5.  if W is INVALID, return INVALID
+6.  U = length(commitments)
+7.  R = length(disclosed_indexes)
+8.  L = R + U
+9.  (i1, ..., iR) = disclosed_indexes
+10. (j1, ..., jU) = range(1, L) \ disclosed_indexes
+11. (msg_i1, ..., msg_iR) = disclosed_messages
+12. (m^_j1, ...., m^_jU) = commitments
+
+Preconditions:
+
+1. for i in (i1, ..., iR), if i < 1 or i > L, return INVALID
+2. if length(disclosed_messages) != R, return INVALID
+
+Procedure:
+
+1.  (Q_1, MsgGenerators) = create_generators(L+1, PK)
+2.  (H_1, ..., H_L) = MsgGenerators
+3.  (H_i1, ..., H_iR) = (MsgGenerators[i1], ..., MsgGenerators[iR])
+4.  (H_j1, ..., H_jU) = (MsgGenerators[j1], ..., MsgGenerators[jU])
+
+5.  domain = calculate_domain(PK, Q_1, (H_1, ..., H_L), header)
+6.  if domain is INVALID, return INVALID
+7.  D = P1 + Q_1 * domain + H_i1 * msg_i1 + ... + H_iR * msg_iR
+8.  C = Bbar * r2^ + Abar * r3^ + H_j1 * m^_j1 + ... + H_jU * m^_jU + D * c
+9.  cv = calculate_challenge(Abar, Bbar, C, (i1, ..., iR),
+                             (msg_i1, ..., msg_iR), domain, ph)
+10. if cv is INVALID, return INVALID
+11. if c != cv, return INVALID
+12. if e(Abar, W) * e(Bbar, -P2) != Identity_GT, return INVALID
+13. return VALID
+
+
+
+
+
+
+
+
+
+
+

+4. Utility Operations +

+
+
+

+4.1. Random Scalars +

+

This operation returns the requested number of pseudo-random scalars, using the get_random operation (see Parameters). The operation makes multiple calls to get_random. It is REQUIRED that each call will be independent from each other, as to ensure independence of the returned pseudo-random scalars.

+

The required length of the get_random output is defined as expand_len. Each value returned by the get_random function is reduced modulo the group order r. To avoid biased results when creating the random scalars, the output of get_random MUST be at least (ceil(log2(r))+k bytes long, where k is the targeted security level specified by the ciphersuite (see Section 5 in [I-D.irtf-cfrg-hash-to-curve] for more details). ProofGen defines expand_len = ceil((ceil(log2(r))+k)/8). For both the BLS12-381-SHAKE-256 and BLS12-381-SHA-256 ciphersuites, log2(r) = 255 and k = 128 resulting to expand_len = 48. See Section 5.10 for further security considerations and requirements around the generated randomness.

+

Note: The security of the proof generation algorithm (ProofGen) is highly dependant on the quality of the get_random function. Care must be taken to ensure that a cryptographically secure pseudo-random generator is chosen, and that its outputs are not leaked to an adversary. See also Section 5.10 for more details.

+
+
random_scalars = calculate_random_scalars(count)
+
+Inputs:
+
+- count (REQUIRED), non negative integer. The number of pseudo random
+                    scalars to return.
+
+Parameters:
+
+- get_random, a pseudo random function with extendable output, returning
+              uniformly distributed pseudo random bytes.
+- expand_len = ceil((ceil(log2(r))+k)/8), where r and k are defined by
+                                          the ciphersuite.
+
+Outputs:
+
+- random_scalars, a list of pseudo random scalars,
+
+Procedure:
+
+1. for i in (1, ..., count):
+2.     r_i = OS2IP(get_random(expand_len)) mod r
+3. return (r_1, r_2, ..., r_count)
+
+
+
+
+
+
+

+4.2. Generators Calculation +

+

A create_generators procedure defines how to create a set of randomly sampled points from the G1 subgroup, called the generators. Generators form a part of the public parameters used by the BBS Signature scheme to accomplish operations such as Sign, Verify, ProofGen and ProofVerify. A create_generators operation takes as input the following arguments,

+
    +
  • count (REQUIRED), a non-negative integer describing the number of generator points to create, which is determined in part by the number of signed messages. +
  • +
  • PK (OPTIONAL), a point of G2, representing the Signer's public key. +
  • +
+

As a result, the create_generators operation has the following signature,

+
+
(G_1, G_2, ..., G_count) = create_generators(count, PK)
+
+
+

Each procedure MUST define a unique CREATE_GENERATORS_ID to be used by the ciphersuite. This value MUST only contain ASCII encoded characters with codes between 0x21 and 0x7e (inclusive) and MUST end with an underscore (ASCII code: 0x5f), other than the last character the string MUST not contain any other underscores (ASCII code: 0x5f).

+
+
+

+4.2.1. Hash to Generators +

+

The hash_to_generators operation makes use of the primitives defined in [I-D.irtf-cfrg-hash-to-curve] (more specifically of hash_to_curve and expand_message) to hash a predefined seed to a set of generators. Those primitives are implicitly defined by the ciphersuite, through the choice of a hash-to-curve suite (see the hash_to_curve_suite parameter in Section 6.1).

+

NOTE: The hash_to_generators operation ignores the PK input, creating the same generators across different Signers and signatures. The final create_generators operation defined by the ciphersuites in Section 6, will be,

+
+
create_generators(count, PK) := hash_to_generator(count)
+
+
+

Since hash_to_generator creates constant points, as an optimization, implementations MAY cache its result for a specific count (which can be arbitrarily large, depending on the application). Care must be taken, to guarantee that the generators will be fetched from the cache in the same order they had when they where created (i.e., an application should not short or in any way rearrange the cached generators).

+
+
generators = hash_to_generators(count)
+
+Inputs:
+
+- count (REQUIRED), unsigned integer. Number of generators to create.
+
+Parameters:
+
+- hash_to_curve_g1, the hash_to_curve operation for the G1 subgroup,
+                    defined by the suite specified by the
+                    hash_to_curve_suite parameter of the ciphersuite.
+- expand_message, the expand_message operation defined by the suite
+                  specified by the hash_to_curve_suite parameter of the
+                  ciphersuite.
+- generator_seed, an octet string representing the seed from which the
+                  generators are created, defined by the ciphersuite.
+
+Definitions:
+
+- seed_dst, an octet string representing the domain separation tag:
+            ciphersuite_id || "SIG_GENERATOR_SEED_" where
+            ciphersuite_id is defined by the ciphersuite and
+            "SIG_GENERATOR_SEED_" is an ASCII string comprised of 19
+            bytes.
+- generator_dst, an octet string representing the domain separation tag:
+                 ciphersuite_id || "SIG_GENERATOR_DST_", where
+                 ciphersuite_id is defined by the ciphersuite and
+                 "SIG_GENERATOR_DST_" is an ASCII string comprised of
+                 18 bytes.
+- seed_len = ceil((ceil(log2(r)) + k)/8), where r and k are defined by
+                                          the ciphersuite.
+
+Outputs:
+
+- generators, an array of generators.
+
+Procedure:
+
+1.  v = expand_message(generator_seed, seed_dst, seed_len)
+2.  n = 1
+3.  for i in range(1, count):
+4.     v = expand_message(v || I2OSP(n, 4), seed_dst, seed_len)
+5.     n = n + 1
+6.     generator_i = Identity_G1
+7.     candidate = hash_to_curve_g1(v, generator_dst)
+8.     if candidate in (generator_1, ..., generator_i, P_1):
+9.        go back to step 4
+10.    generator_i = candidate
+11. return (generator_1, ..., generator_count)
+
+
+

The values n and v MAY also be cached in order to efficiently extend an existing list of cached generator points. The CREATE_GENERATORS_ID of the above operation is define as,

+
+
CREATE_GENERATORS_ID = "H2G_"
+
+
+
+
+
+
+

+4.2.2. Defining new ways to create generators +

+

When defining a new create_generators procedure, the most important property is that the returned points are pseudo-randomly chosen from the G1 group, given reasonable assumptions and cryptographic primitives. More specifically, the required properties are

+
    +
  • The returned points should be indistinguishable from count uniformly radom points of G1. This means that given only the points H_1, ..., H_i it should be infeasible to guess H_(i+1) (or any H_j with j > i), for any i between 1 and count. +
  • +
  • The returned points must be unique with very high probability, that would not lessen the targeted security level of the ciphersuite. Specifically, for a security level k, the probability of a collision should be at least 1/2^k. +
  • +
  • It should be infeasible to guess the discrete logarithm of the returned points, for any base, even with knowledge of the public parameters that were used to create those generators (like the generator_seed value in Hash to Generators). Note that pseudo randomness does not necessarily imply this property. For example, an implementation that repeatably hashes a public seed value to create exponents r_1, r_2, ..., r_count (where r_1 = hash(seed), r_2 = hash(r_1), ...) and then returns the points H_1 = P1 * r_1, H_2 = P_1 * r_2, ..., H_count = P_1 * r_count would be insecure (given knowledge of the seed), but given knowledge of only the points H_1, ..., H_count, the sequence would appear random. +
  • +
  • The returned points must be different from the Identity point of G1 as well as the constant point P1 defined by the ciphersuite. +
  • +
  • Must be constant time for a specific count value. +
  • +
  • MUST be deterministic. +
  • +
  • Must use proper domain separation for both the create_generators procedure, as well as all of the internally-called procedures. +
  • +
+
+
+
+
+
+
+

+4.3. Message to Scalar +

+

There are multiple ways in which messages can be mapped to their respective scalar values, which is their required form to be used with the Sign, Verify, ProofGen and ProofVerify operations.

+
+
+

+4.3.1. Message to Scalar as Hash +

+

This operation takes an input message and maps it to a scalar value via a cryptographic hash function for the given curve. The operation takes also as an optional input a domain separation tag (dst). If a dst is not supplied, its value MUST default to the octet string returned from ciphersuite_id || "MAP_MSG_TO_SCALAR_AS_HASH_", where ciphersuite_id is the ASCII string representing the unique ID of the ciphersuite "MAP_MSG_TO_SCALAR_AS_HASH_" is an ASCII string comprised of 26 bytes.

+
+
msg_scalar = MapMessageToScalarAsHash(msg, dst)
+
+Inputs:
+
+- msg (REQUIRED), an octet string.
+- dst (OPTIONAL), an octet string representing a domain separation tag.
+                  If not supplied, it default to the octet string
+                  ciphersuite_id || "MAP_MSG_TO_SCALAR_AS_HASH_" where
+                  ciphersuite_id is defined by the ciphersuite.
+
+Outputs:
+
+- msg_scalar, a scalar value.
+
+Procedure:
+
+1. if length(msg) > 2^64 - 1 or length(dst) > 255 return INVALID
+2. msg_scalar = hash_to_scalar(msg, dst)
+3. if msg_scalar is INVALID, return INVALID
+4. return msg_scalar
+
+
+
+
+
+
+
+
+

+4.4. Hash to Scalar +

+

This operation describes how to hash an arbitrary octet string to n scalar values in the multiplicative group of integers mod r (i.e., values in the range [1, r-1]). This procedure acts as a helper function, used internally in various places within the operations described in the spec. To hash a message to a scalar that would be passed as input to the Sign, Verify, ProofGen and ProofVerify functions, one must use MapMessageToScalarAsHash instead.

+

This operation makes use of expand_message defined in [I-D.irtf-cfrg-hash-to-curve], in a similar way used by the hash_to_field operation of Section 5 from the same document (with the additional checks for getting a scalar that is 0). If an implementer wants to use hash_to_field instead, they MUST use the multiplicative group of integers mod r (Fr), as the target group (F). Note however, that the hash_to_curve document, makes use of hash_to_field with the target group being the multiplicative group of integers mod p (Fp). For this reason, we don’ (U+2019)t directly use hash_to_field here, rather we define a similar operation (hash_to_scalar), making direct use of the expand_message function, that will be defined by the hash-to-curve suite used (i.e., either expand_message_xmd or expand_message_xof). If someone also has a hash_to_field implementation available, with the target group been Fr, they can use this instead (adding the check for a scalar been 0).

+

The operation takes as input an octet string representing the message to hash (msg), the number of the scalars to return (count) as well as an optional domain separation tag (dst). If a dst is not supplied, its value MUST default to the octet string returned from ciphersuit_id || "H2S_", where ciphersuite_id is the octet string representing the unique ID of the ciphersuite and "H2S_" is an ASCII string comprised of 4 bytes.

+

Note It is possible that the hash_to_scalar procedure will return an error, if the underlying expand_message operation aborts. See [I-D.irtf-cfrg-hash-to-curve], Section 5.3, for more details on the cases that expand_message will abort (note that the input term len_in_bytes of expand_message in the Hash-to-Curve document equals count * expand_len in our case).

+
+
hashed_scalar = hash_to_scalar(msg_octets, dst)
+
+Inputs:
+
+- msg_octets (REQUIRED), an octet string. The message to be hashed.
+- dst (OPTIONAL), an octet string representing a domain separation tag.
+                  If not supplied, it defaults to the octet string given
+                  by ciphersuite_id || "H2S_", where ciphersuite_id is
+                  defined by the ciphersuite.
+
+Parameters:
+
+- hash_to_curve_suite, the hash to curve suite id defined by the
+                       ciphersuite.
+- expand_message, the expand_message operation defined by the suite
+                  specified by the hash_to_curve_suite parameter.
+
+Definitions:
+
+- expand_len = ceil((ceil(log2(r))+k)/8), where r and k are defined by
+                                          the ciphersuite.
+
+Outputs:
+
+- hashed_scalar, a non-zero scalar mod r.
+
+Procedure:
+
+1.  counter = 0
+2.  hashed_scalar = 0
+3.  while hashed_scalar == 0:
+4.      if counter > 255, return INVALID
+5.      msg_prime = msg_octets || I2OSP(counter, 1)
+6.      uniform_bytes = expand_message(msg_prime, dst, expand_len)
+7.      if uniform_bytes is INVALID, return INVALID
+8.      hashed_scalar = OS2IP(uniform_bytes) mod r
+9.      counter = counter + 1
+10. return hashed_scalar
+
+
+
+
+
+
+

+4.5. Domain Calculation +

+

This operation calculates the domain value, a scalar representing the distillation of all essential contextual information for a signature. The same domain value must be calculated by all parties (the signer, the prover, and the verifier) for both the signature and proofs to be validated.

+

The input to the domain value includes an octet string called the header, chosen by the signer and meant to encode any information that is required to be revealed by the prover (such as an expiration date, or an identifier for the target audience). This is in contrast to the signed message values, which may be withheld during a proof.

+

When a signature is calculated, the domain value is combined with a specific generator point (Q_1, see Sign) to protect the integrity of the public parameters and the header.

+

This operation makes use of the serialize function, defined in Section 4.6.1.

+
+
domain = calculate_domain(PK, Q_1, H_Points, header)
+
+Inputs:
+
+- PK (REQUIRED), an octet string, representing the public key of the
+                 Signer of the form outputted by the SkToPk operation.
+- Q_1 (REQUIRED), point of G1 (the first point returned from
+                  create_generators).
+- H_Points (REQUIRED), array of points of G1.
+- header (OPTIONAL), an octet string. If not supplied, it must default to
+                     the empty octet string ("").
+
+Parameters:
+
+- ciphersuite_id, an octet string. The unique ID of the ciphersuite.
+
+Outputs:
+
+- domain, a scalar value or INVALID.
+
+Procedure:
+
+1.  L = length(H_Points)
+2.  if length(header) > 2^64 - 1 or L > 2^64 - 1, return INVALID
+3.  (H_1, ..., H_L) = H_Points
+4.  dom_array = (L, Q_1, H_1, ..., H_L)
+5.  dom_octs = serialize(dom_array) || ciphersuite_id
+6.  if dom_octs is INVALID, return INVALID
+7.  dom_input = PK || dom_octs || I2OSP(length(header), 8) || header
+8.  domain = hash_to_scalar(dom_input)
+9.  if domain is INVALID, return INVALID
+10. return domain
+
+
+

Note: If the header is not supplied in calculate_domain, it defaults to the empty octet string (""). This means that in the concatenation step of the above procedure (step 7), 8 bytes representing a length of 0 (i.e., 0x0000000000000000), will still need to be appended at the end, even though a header value is not provided.

+
+
+
+
+

+4.6. Challenge Calculation +

+

This operation calculates the challenge scalar value, used during ProofGen and ProofVerify, as part of the Fiat-Shamir heuristic, for making the proof protocol non-interactive (in a interactive sating, the challenge would be a random value supplied by the verifier).

+

This operation makes use of the serialize function, defined in Section 4.6.1.

+
+
challenge = calculate_challenge(Abar, Bbar, C, i_array,
+                                                  msg_array, domain, ph)
+
+Inputs:
+
+- (Abar, Bbar, C) (REQUIRED), points of G1, as calculated in
+                                    ProofGen.
+- i_array (REQUIRED), array of non-negative integers (the indexes of
+                      the disclosed messages).
+- msg_array (REQUIRED), array of scalars (the disclosed messages).
+- domain (REQUIRED), a scalar.
+- ph (OPTIONAL), an octet string. If not supplied, it must default to the
+                 empty octet string ("").
+
+Outputs:
+
+- challenge, a scalar or INVALID.
+
+Procedure:
+
+1.  R = length(i_array)
+2.  if R > 2^64 - 1 or R != length(msg_array), return INVALID
+3.  if length(ph) > 2^64 - 1, return INVALID
+4.  (i1, ..., iR) = i_array
+5.  (msg_i1, ..., msg_iR) = msg_array
+6.  c_array = (Abar, Bbar, C, R, i1, ..., iR,
+                                   msg_i1, ..., msg_iR, domain)
+7.  c_octs = serialize(c_array)
+8.  if c_octs is INVALID, return INVALID
+9.  c_input = c_octs || I2OSP(length(ph), 8) || ph
+10. challenge = hash_to_scalar(c_input)
+11. if challenge is INVALID, return INVALID
+12. return challenge
+
+
+

Note: Similarly to the header value in Domain Calculation, if the presentation header (ph) is not supplied in calculate_challenge, 8 bytes representing a length of 0 (i.e., 0x0000000000000000), must still be appended after the c_octs value, during the concatenation step of the above procedure (step 9).

+
+
+
+
+

+4.7. Serialization +

+
+
+

+4.7.1. Serialize +

+

This operation describes how to transform multiple elements of different types (i.e., elements that are not already in a octet string format) to a single octet string (see Section 3.2.4). The inputted elements can be points, scalars (see Terminology) or integers between 0 and 2^64-1. The resulting octet string will then either be used as an input to a hash function (i.e., in Sign, ProofGen etc.), or to serialize a signature or proof (see SignatureToOctets and ProofToOctets).

+
+
octets_result = serialize(input_array)
+
+Inputs:
+
+- input_array (REQUIRED), an array of elements to be serialized. Each
+                          element must be either a point of G1 or G2, a
+                          scalar, an ASCII string or an integer value
+                          between 0 and 2^64 - 1.
+
+Parameters:
+
+- octet_scalar_length, non-negative integer. The length of a scalar
+                       octet representation, defined by the ciphersuite.
+- r, the prime order of the subgroups G1 and G2, defined by the
+     ciphersuite.
+- point_to_octets_g*, operations that serialize a point of G1 or G2 to
+                      an octet string of fixed length, defined by the
+                      ciphersuite.
+
+Outputs:
+
+- octets_result, a scalar value or INVALID.
+
+Procedure:
+
+1.  let octets_result be an empty octet string.
+2.  for el in input_array:
+3.      if el is a point of G1: el_octs = point_to_octets_g1(el)
+4.      else if el is a point of G2: el_octs = point_to_octets_g2(el)
+5.      else if el is a scalar: el_octs = I2OSP(el, octet_scalar_length)
+6.      else if el is an integer between 0 and 2^64 - 1:
+7.          el_octs = I2OSP(el, 8)
+8.      else: return INVALID
+9.      octets_result = octets_result || el_octs
+10. return octets_result
+
+
+
+
+
+
+

+4.7.2. Signature to Octets +

+

This operation describes how to encode a signature to an octet string.

+

Note this operation deliberately does not perform the relevant checks on the inputs A and e +because its assumed these are done prior to its invocation, e.g as is the case with the Sign operation.

+
+
signature_octets = signature_to_octets(signature)
+
+Inputs:
+
+- signature (REQUIRED), a valid signature, in the form (A, e), where
+                        A is a point in G1 and e is a non-zero scalar mod r.
+
+Outputs:
+
+- signature_octets, an octet string or INVALID.
+
+Procedure:
+
+1. (A, e) = signature
+2. return serialize((A, e))
+
+
+
+
+
+
+

+4.7.3. Octets to Signature +

+

This operation describes how to decode an octet string, validate it and return the underlying components that make up the signature.

+
+
signature = octets_to_signature(signature_octets)
+
+Inputs:
+
+- signature_octets (REQUIRED), an octet string of the form output from
+                               signature_to_octets operation.
+
+Outputs:
+
+signature, a signature in the form (A, e), where A is a point in G1
+           and e is a non-zero scalar mod r.
+
+Procedure:
+
+1.  expected_len = octet_point_length + octet_scalar_length
+2.  if length(signature_octets) != expected_len, return INVALID
+3.  A_octets = signature_octets[0..(octet_point_length - 1)]
+4.  A = octets_to_point_g1(A_octets)
+5.  if A is INVALID, return INVALID
+6.  if A == Identity_G1, return INVALID
+7.  index = octet_point_length
+8.  end_index = index + octet_scalar_length - 1
+9.  e = OS2IP(signature_octets[index..end_index])
+10. if e = 0 OR e >= r, return INVALID
+11. return (A, e)
+
+
+
+
+
+
+

+4.7.4. Proof to Octets +

+

This operation describes how to encode a proof, as computed at step 25 in ProofGen, to an octet string. The input to the operation MUST be a valid proof.

+

The inputted proof value must consist of the following components, in that order:

+
    +
  1. Two (2) valid points of the G1 subgroup, different from the identity point of G1 (i.e., Abar, Bbar, in ProofGen) +
  2. +
  3. Three (3) integers representing scalars in the range of 1 to r-1 inclusive (i.e., c, r2^, r3^, in ProofGen). +
  4. +
  5. A number of integers representing scalars in the range of 1 to r-1 inclusive, corresponding to the undisclosed from the proof messages (i.e., m^_j1, ..., m^_jU, in ProofGen, where U the number of undisclosed messages). +
  6. +
+
+
proof_octets = proof_to_octets(proof)
+
+Inputs:
+
+- proof (REQUIRED), a BBS proof in the form calculated by ProofGen in
+                    step 27 (see above).
+
+Parameters:
+
+- octet_scalar_length (REQUIRED), non-negative integer. The length of
+                                  a scalar octet representation, defined
+                                  by the ciphersuite.
+
+Outputs:
+
+- proof_octets, an octet string or INVALID.
+
+Procedure:
+
+1. (Abar, Bbar, r2^, r3^, (m^_1, ..., m^_U), c) = proof
+2. return serialize((Abar, Bbar, r2^, r3^, m^_1, ..., m^_U), c)
+
+
+
+
+
+
+

+4.7.5. Octets to Proof +

+

This operation describes how to decode an octet string representing a proof, validate it and return the underlying components that make up the proof value.

+

The proof value outputted by this operation consists of the following components, in that order:

+
    +
  1. Two (2) valid points of the G1 subgroup, each of which must not equal the identity point. +
  2. +
  3. Three (3) integers representing scalars in the range of 1 to r-1 inclusive. +
  4. +
  5. A set of integers representing scalars in the range of 1 to r-1 inclusive, corresponding to the undisclosed from the proof message commitments. This set can be empty (i.e., "()"). +
  6. +
+
+
proof = octets_to_proof(proof_octets)
+
+Inputs:
+
+- proof_octets (REQUIRED), an octet string of the form outputted from the
+                           proof_to_octets operation.
+
+Parameters:
+
+- r (REQUIRED), non-negative integer. The prime order of the G1 and
+                G2 groups, defined by the ciphersuite.
+- octet_scalar_length (REQUIRED), non-negative integer. The length of
+                                  a scalar octet representation, defined
+                                  by the ciphersuite.
+- octet_point_length (REQUIRED), non-negative integer. The length of
+                                 a point in G1 octet representation,
+                                 defined by the ciphersuite.
+
+Outputs:
+
+- proof, a proof value in the form described above or INVALID
+
+Procedure:
+
+1.  proof_len_floor = 2 * octet_point_length + 3 * octet_scalar_length
+2.  if length(proof_octets) < proof_len_floor, return INVALID
+
+// Points (i.e., (Abar, Bbar) in ProofGen) de-serialization.
+3.  index = 0
+4.  for i in range(0, 1):
+5.      end_index = index + octet_point_length - 1
+6.      A_i = octets_to_point_g1(proof_octets[index..end_index])
+7.      if A_i is INVALID or Identity_G1, return INVALID
+8.      index += octet_point_length
+
+// Scalars (i.e., (r2^, r3^, (m^_j1, ..., m^_jU), c) in
+// ProofGen) de-serialization.
+9.  j = 0
+10. while index < length(proof_octets):
+11.     end_index = index + octet_scalar_length - 1
+12.     s_j = OS2IP(proof_octets[index..end_index])
+13.     if s_j = 0 or if s_j >= r, return INVALID
+14.     index += octet_scalar_length
+15.     j += 1
+
+16. if index != length(proof_octets), return INVALID
+17. msg_commitments = ()
+18. If j > 3, set msg_commitments = (s_2, ..., s_(j-2))
+19. return (A_0, A_1, s_0, s_1, msg_commitments, s_(j-1))
+
+
+
+
+
+
+

+4.7.6. Octets to Public Key +

+

This operation describes how to decode an octet string representing a public key, validates it and returns the corresponding point in G2. Steps 2 to 5 check if the public key is valid. As an optimization, implementations MAY cache the result of those steps, to avoid unnecessarily repeating validation for known public keys.

+
+
W = octets_to_pubkey(PK)
+
+Inputs:
+
+- PK, an octet string. A public key in the form outputted by the SkToPK
+      operation
+
+Outputs:
+
+- W, a valid point in G2 or INVALID
+
+Procedure:
+
+1. W = octets_to_point_g2(PK)
+2. If W is INVALID, return INVALID
+3. if subgroup_check(W) is INVALID, return INVALID
+4. If W == Identity_G2, return INVALID
+5. return W
+
+
+
+
+
+
+
+
+
+
+

+5. Security Considerations +

+
+
+

+5.1. Validating Public Keys +

+

It is RECOMENDED for any operation in Core Operations involving public keys, that they deserialize the public key first using the OctetsToPublicKey operation, even if they only require the octet-string representation of the public key. If the octets_to_pubkey procedure (see the OctetsToPublicKey section) returns INVALID, the calling operation should also return INVALID and abort. An example of where this recommendation applies is the Sign operation. An example of where an explicit invocation to the octets_to_pubkey operation is already defined and therefore required is the Verify operation.

+
+
+
+
+

+5.2. Point Deserialization +

+

This document makes use of octet_to_point_g* to parse octet strings to elliptic curve points (either in G1 or G2). It is assumed (even if not explicitly described) that the result of this operation will not be INVALID. If octet_to_point_g* returns INVALID, then the calling operation should immediately return INVALID as well and abort the operation. Note that the only place where the output is assumed to be VALID implicitly is in the EncodingForHash section.

+
+
+
+
+

+5.3. Skipping Membership Checks +

+

Some existing implementations skip the subgroup_check invocation in Verify, whose purpose is ensuring that the signature is an element of a prime-order subgroup. This check is REQUIRED of conforming implementations, for two reasons.

+
    +
  1. +

    For most pairing-friendly elliptic curves used in practice, the pairing operation e Section 1.2 is undefined when its input points are not in the prime-order subgroups of E1 and E2. The resulting behavior is unpredictable, and may enable forgeries.

    +
  2. +
  3. +

    Even if the pairing operation behaves properly on inputs that are outside the correct subgroups, skipping the subgroup check breaks the strong unforgeability property [ADR02].

    +
  4. +
+
+
+
+
+

+5.4. Side Channel Attacks +

+

Implementations of the signing algorithm SHOULD protect the secret key from side-channel attacks. One method for protecting against certain side-channel attacks is ensuring that the implementation executes exactly the same sequence of instructions and performs exactly the same memory accesses, for any value of the secret key. In other words, implementations on the underlying pairing-friendly elliptic curve SHOULD run in constant time.

+
+
+
+
+

+5.5. Randomness Considerations +

+

The IKM input to KeyGen MUST be infeasible to guess and MUST be kept secret. One possibility is to generate IKM from a trusted source of randomness. Guidelines on constructing such a source are outside the scope of this document.

+

Secret keys MAY be generated using other methods; in this case they MUST be infeasible to guess and MUST be indistinguishable from uniformly random modulo r.

+

BBS proofs are nondeterministic, meaning care must be taken against attacks arising from using bad randomness, for example, the nonce reuse attack on ECDSA [HDWH12]. It is RECOMMENDED that the presentation header used in this specification contain a nonce chosen at random from a trusted source of randomness, see the Section 5.6 for additional considerations.

+

When a trusted source of randomness is used, signatures and proofs are much harder to forge or break due to the use of multiple nonces.

+
+
+
+
+

+5.6. Presentation Header Selection +

+

The signature proofs of knowledge generated in this specification are created using a specified presentation header. A verifier-specified cryptographically random value (e.g., a nonce) featuring in the presentation header provides strong protections against replay attacks, and is RECOMMENDED in most use cases. In some settings, proofs can be generated in a non-interactive fashion, in which case verifiers MUST be able to verify the uniqueness of the presentation header values.

+
+
+
+
+

+5.7. Implementing hash_to_curve_g1 +

+

The security analysis models hash_to_curve_g1 as random oracles. It is crucial that these functions are implemented using a cryptographically secure hash function. For this purpose, implementations MUST meet the requirements of [I-D.irtf-cfrg-hash-to-curve].

+

In addition, ciphersuites MUST specify unique domain separation tags for hash_to_curve. Some guidance around defining this can be found in Section 6.

+
+
+
+
+

+5.8. Choice of Underlying Curve +

+

BBS signatures can be implemented on any pairing-friendly curve. However care MUST be taken when selecting one that is appropriate, this specification defines a ciphersuite for using the BLS12-381 curve in Section 6 which as a curve achieves around 117 bits of security according to a recent NCC ZCash cryptography review [ZCASH-REVIEW].

+
+
+
+
+

+5.9. ProofGen Security +

+

The proof, as returned by ProofGen, is a zero-knowledge proof-of-knowledge [CDL16]. This guarantees that no information will be revealed about the signature itself or the undisclosed messages, from the output of ProofGen. Note that the security proofs in [CDL16] work on type 3 pairing setting. This means that G1 should be different from G2 and with no efficient isomorphism between them.

+
+
+
+
+

+5.10. Randomness Requirements +

+

ProofGen is by its nature a randomized algorithm, requiring the generation of multiple uniformly distributed, pseudo random scalars. This makes ProofGen vulnerable to bad entropy in certain applications. As an example of such application, consider systems that need to monitor and potentially restrict outbound traffic, in order to minimize data leakage during a breach. In such cases, the attacker could manipulate couple of bits in the output of the get_random function to create an undetected chanel out of the system. Although the applicability of such attacks is limited for most of the targeted use cases of the BBS scheme, some applications may want to take measures towards mitigating them. To that end, it is RECOMMENDED to use a deterministic RNG (like a ChaCha20 based deterministic RNG), seeded with a unique, uniformly random, single seed [DRBG]. This will limit the amount of bits the attacker can manipulate (note that some randomness is always needed).

+

In any case, the randomness used in ProofGen MUST be unique in each call and MUST have a distribution that is indistinguishable from uniform. If the random scalars are re-used, are created from "bad randomness" (for example with a known relationship to each other) or are in any way predictable, an adversary will be able to unveil the undisclosed from the proof messages or the hidden signature value. Naturally, a cryptographically secure pseudorandom number generator or pseudo random function is REQUIRED to implement the get_random functionality. See also [RFC8937], for recommendations on generating good randomness in cases where the Prover has direct or in-direct access to a secret key.

+
+
+
+
+
+
+

+6. Ciphersuites +

+

This section defines the format for a BBS ciphersuite. It also gives concrete ciphersuites based on the BLS12-381 pairing-friendly elliptic curve [I-D.irtf-cfrg-pairing-friendly-curves].

+
+
+

+6.1. Ciphersuite Format +

+
+
+

+6.1.1. Ciphersuite ID +

+

The following section defines the format of the unique identifier for the ciphersuite denoted ciphersuite_id, which will be represented as an ASCII encoded octet string. The REQUIRED format for this string is

+
+
  "BBS_" || H2C_SUITE_ID || CG_ID || ADD_INFO
+
+
+
    +
  • +

    H2C_SUITE_ID is the suite ID of the hash-to-curve suite used to define the hash_to_curve function.

    +
  • +
  • +

    CG_ID is the ID of the create generators used, i.e., CREATE_GENERATORS_ID as defined in the Section 4.2 section.

    +
  • +
  • +

    ADD_INFO is an optional octet string indicating any additional information used to uniquely qualify the ciphersuite. When present this value MUST only contain ASCII encoded characters with codes between 0x21 and 0x7e (inclusive) and MUST end with an underscore (ASCII code: 0x5f), other than the last character the string MUST not contain any other underscores (ASCII code: 0x5f).

    +
  • +
+
+
+
+
+

+6.1.2. Additional Parameters +

+

The parameters that each ciphersuite needs to define are generally divided into three main categories; the basic parameters (a hash function etc.,), the serialization operations (point_to_octets_g1 etc.,) and the generator parameters. See below for more details.

+

Basic parameters:

+
    +
  • +

    hash: a cryptographic hash function.

    +
  • +
  • +

    octet_scalar_length: Number of bytes to represent a scalar value, in the multiplicative group of integers mod r, encoded as an octet string. It is RECOMMENDED this value be set to ceil(log2(r)/8).

    +
  • +
  • +

    octet_point_length: Number of bytes to represent a point encoded as an octet string outputted by the point_to_octets_g* function. It is RECOMMENDED that this value is set to ceil(log2(p)/8).

    +
  • +
  • +

    hash_to_curve_suite: The hash-to-curve ciphersuite id, in the form defined in [I-D.irtf-cfrg-hash-to-curve]. This defines the hash_to_curve_g1 (the hash_to_curve operation for the G1 subgroup, see the Notation section) and the expand_message (either expand_message_xmd or expand_message_xof) operations used in this document.

    +
  • +
  • +

    P1: A fixed point in the G1 subgroup.

    +
  • +
+

Serialization functions:

+
    +
  • +

    point_to_octets_g1: +a function that returns the canonical representation of the point P for the G1 subgroup as an octet string.

    +
  • +
  • +

    point_to_octets_g2: +a function that returns the canonical representation of the point P for the G2 subgroup as an octet string.

    +
  • +
  • +

    octets_to_point_g1: +a function that returns the point P in the subgroup G1 corresponding to the canonical representation ostr, or INVALID if ostr is not a valid output of point_to_octets_g1.

    +
  • +
  • +

    octets_to_point_g2: +a function that returns the point P in the subgroup G2 corresponding to the canonical representation ostr, or INVALID if ostr is not a valid output of point_to_octets_g2.

    +
  • +
+

Generator parameters:

+
    +
  • create_generators: the operation with which to create a set of generators. See Section 4.2. +
  • +
+
+
+
+
+
+
+

+6.2. BLS12-381 Ciphersuites +

+

The following two ciphersuites are based on the BLS12-381 elliptic curves defined in Section 4.2.1 of [I-D.irtf-cfrg-pairing-friendly-curves]. The targeted security level of both suites in bits is k = 128.

+

The first ciphersuite makes use of an extendable output function, and most specifically of SHAKE-256, as defined in Section 6.2 of [SHA3]. It also uses the hash-to-curve suite defined by this document in Appendix A.1, which also makes use of the SHAKE-256 function.

+

The second ciphersuite uses SHA-256, as defined in Section 6.2 of [SHA2] and the BLS12-381 G1 hash-to-curve suite defined in Section 8.8.1 of the [I-D.irtf-cfrg-hash-to-curve] document.

+

Note that these two ciphersuites differ only in the hash function (SHAKE-256 vs SHA-256) and in the hash-to-curve suites used. The hash-to-curve suites differ in the expand_message variant and underlying hash function. More concretely, the BLS12-381-SHAKE-256 ciphersuite makes use of expand_message_xof with SHAKE-256, while BLS12-381-SHA-256 makes use of expand_message_xmd with SHA-256. Curve parameters are common between the two ciphersuites.

+
+
+

+6.2.1. BLS12-381-SHAKE-256 +

+

Basic parameters:

+
    +
  • +

    ciphersuite_id: "BBS_BLS12381G1_XOF:SHAKE-256_SSWU_RO_H2G_"

    +
  • +
  • +

    hash: SHAKE-256 as defined in [SHA3].

    +
  • +
  • +

    octet_scalar_length: 32, based on the RECOMMENDED approach of ceil(log2(r)/8).

    +
  • +
  • +

    octet_point_length: 48, based on the RECOMMENDED approach of ceil(log2(p)/8).

    +
  • +
  • +

    hash_to_curve_suite: "BLS12381G1_XOF:SHAKE-256_SSWU_RO_" as defined in Appendix A.1 for the G1 subgroup.

    +
  • +
  • +

    P1: The G1 point returned from the hash_to_generators procedure (Section 4.2.1), with count = 1 and generator_seed = ciphersuite_id || "BP_MESSAGE_GENERATOR_SEED". More specifically,

    +
    +
    P1 = {{ $generatorFixtures.bls12-381-shake-256.generators.BP }}
    +
    +
    +
  • +
+

Serialization functions:

+ +

Generator parameters:

+
    +
  • +

    create_generators: the operation is using hash_to_generators as defined in Section 4.2.1, with generator_seed = ciphersuite_id || "MESSAGE_GENERATOR_SEED" and the expand_message and hash_to_curve_g1 defined by the hash_to_curve_suite,

    +
    +
    create_generators(count, PK) := hash_to_generators(count)
    +
    +
    +
  • +
+
+
+
+
+

+6.2.2. BLS12-381-SHA-256 +

+

Basic parameters:

+
    +
  • +

    Ciphersuite_ID: "BBS_BLS12381G1_XMD:SHA-256_SSWU_RO_H2G_"

    +
  • +
  • +

    hash: SHA-256 as defined in [SHA2].

    +
  • +
  • +

    octet_scalar_length: 32, based on the RECOMMENDED approach of ceil(log2(r)/8).

    +
  • +
  • +

    octet_point_length: 48, based on the RECOMMENDED approach of ceil(log2(p)/8).

    +
  • +
  • +

    hash_to_curve_suite: "BLS12381G1_XMD:SHA-256_SSWU_RO_" as defined in Section 8.8.1 of the [I-D.irtf-cfrg-hash-to-curve] for the G1 subgroup.

    +
  • +
  • +

    P1: The G1 point returned from the hash_to_generators procedure, with count = 1 and generator_seed = ciphersuite_id || "BP_MESSAGE_GENERATOR_SEED". More specifically,

    +
    +
    P1 = {{ $generatorFixtures.bls12-381-sha-256.generators.BP }}
    +
    +
    +
  • +
+

Serialization functions:

+ +

Generator parameters:

+
    +
  • +

    create_generators: the operation is using hash_to_generators as defined in Section 4.2.1, with generator_seed = ciphersuite_id || "MESSAGE_GENERATOR_SEED" and the expand_message and hash_to_curve_g1 defined by the hash_to_curve_suite,

    +
    +
    create_generators(count, PK) := hash_to_generators(count)
    +
    +
    +
  • +
+
+
+
+
+
+
+
+
+

+7. Test Vectors +

+

The following section details a basic set of test vectors that can be used to confirm an implementations correctness

+

NOTE All binary data below is represented as octet strings in big endian order, encoded in hexadecimal format.

+

NOTE These fixtures are a work in progress and subject to change.

+
+
+

+7.1. Mocked Random Scalars +

+

For the purpose of presenting fixtures for the ProofGen operation we describe here a way to mock the calculate_random_scalars operation (Random scalars computation), used by ProofGen to create all the necessary random scalars.

+

To that end, the seeded_random_scalars(SEED) operation is defined, which will deterministically calculate count random-looking scalars from a single SEED. The proof test vector will then define a SEED (as a nothing-up-my-sleeve value) and set

+
+
mocked_calculate_random_scalars(count) :=
+                             seeded_random_scalars(SEED, count)
+
+
+

The mocked_calculate_random_scalars operation will then be used in place of calculate_random_scalars during the ProofGen operation's procedure.

+

Note For the BLS12-381-SHA-256 ciphersuite if more than 170 mocked random scalars are required, the operation will return INVALID. Similarly, for the BLS12-381-SHAKE-256 ciphersuite, if more than 1365 mocked random scalars are required, the operation will return INVALID. For the purpose of describing ProofGen test vectors, those limits are inconsequential.

+
+
seeded_scalars = seeded_random_scalars(SEED, count)
+
+Inputs:
+
+- count (REQUIRED), non negative integer. The number of scalars to
+                    return.
+- SEED (REQUIRED), an octet string. The random seed from which to generate
+                   the scalars.
+
+Parameters:
+
+- expand_message, the expand_message operation defined by the
+                  ciphersuite.
+- expand_len = ceil((ceil(log2(r))+k)/8), where r and k are defined by
+                                          the ciphersuite.
+- dst = ciphersuite_id || "MOCK_RANDOM_SCALARS_DST_", where
+        ciphersuite_id is defined by the ciphersuite.
+
+Outputs:
+
+- mocked_random_scalars, a list of "count" pseudo random scalars
+
+Preconditions:
+
+1. if count * expand_len > 65535, return INVALID
+
+Procedure:
+
+1. out_len = expand_len * count
+2. v = expand_message(SEED, dst, out_len)
+3. if v is INVALID, return INVALID
+
+4. for i in (1, ..., count):
+5.     start_idx = (i-1) * expand_len
+6.     end_idx = i * expand_len - 1
+7.     r_i = OS2IP(v[start_idx..end_idx]) mod r
+8. return (r_1, ...., r_count)
+
+
+
+
+
+
+

+7.2. Messages +

+

The following messages are used by the test vectors of both ciphersuites (unless otherwise stated).

+
+
{{ $messages[0] }}
+
+{{ $messages[1] }}
+
+{{ $messages[2] }}
+
+{{ $messages[3] }}
+
+{{ $messages[4] }}
+
+{{ $messages[5] }}
+
+{{ $messages[6] }}
+
+{{ $messages[7] }}
+
+{{ $messages[8] }}
+
+{{ $messages[9] }}
+
+
+
+
+
+
+

+7.3. BLS12-381-SHAKE-256 Test Vectors +

+

Test vectors of the BLS12-381-SHAKE-256 ciphersuite. Further fixtures are available in additional BLS12-381-SHAKE-256 test vectors.

+
+
+

+7.3.1. Key Pair +

+

The following key pair will be used for the test vectors of the BLS12-381-SHAKE-256 ciphersuite.

+

Following the procedure defined in Section 3.3.1 with an input key_material value as follows

+
+
{{ $KeyPairFixtures.bls12-381-shake-256.keypair.keyMaterial }}
+
+
+

and the following key_info value

+
+
{{ $KeyPairFixtures.bls12-381-shake-256.keypair.keyInfo }}
+
+
+

Outputs the following SK value

+
+
{{ $KeyPairFixtures.bls12-381-shake-256.keypair.keyPair.secretKey }}
+
+
+

Following the procedure defined in Section 3.3.2 with an input SK value as above produces the following PK value

+
+
{{ $KeyPairFixtures.bls12-381-shake-256.keypair.keyPair.publicKey }}
+
+
+
+
+
+
+

+7.3.2. Map Messages to Scalars +

+

The messages in Section 7.2 must be mapped to scalars before passed to the Sign, Verify, ProofGen and ProofVerify operations. For the purpose of the test vectors presented in this document we are using the MapMessageToScalarAsHash operation to map each message to a scalar. For the BLS12-381-SHAKE-256 ciphersuite, on input each message in Section 7.2 and the following default dst

+
+
{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.dst }}
+
+
+

The output scalars, encoded to octets using I2OSP and represented in big endian order, are the following,

+
+
{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[0].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[1].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[2].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[3].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[4].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[5].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[6].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[7].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[8].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[9].scalar }}
+
+
+

Note that in both the following test vectors, as well as the additional BLS12-381-SHAKE-256 test vectors in Appendix C.1, when we are referring to a message that will be passed to one of the Sign, Verify, ProofGen or ProofVerify operations, we assume that it will first be mapped into one of the above scalars, using the MapMessageToScalarAsHash operation.

+
+
+
+
+

+7.3.3. Message Generators +

+

Following the procedure defined in Section 4.2 with an input count value of 11, for the BLS12-381-SHAKE-256 suite, outputs the following values (note that the first one corresponds to Q_1, while the next 10, to the message generators H_1, ..., H_10).

+
+
{{ $generatorFixtures.bls12-381-shake-256.generators.Q1 }}
+
+{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[0] }}
+
+{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[1] }}
+
+{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[2] }}
+
+{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[3] }}
+
+{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[4] }}
+
+{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[5] }}
+
+{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[6] }}
+
+{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[7] }}
+
+{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[8] }}
+
+{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[9] }}
+
+
+
+
+
+
+

+7.3.4. Signature Fixtures +

+
+
+
+7.3.4.1. Valid Single Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature001.header }}
+
+
+

And the following message (the first message defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature001.messages[0] }}
+
+
+

After it is mapped to the first scalar in Section 7.3.2, along with the SK value as defined in Section 7.3.1 as inputs into the Sign operations, yields the following output signature

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature001.signature }}
+
+
+
+
+
+
+
+7.3.4.2. Valid Multi-Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature004.header }}
+
+
+

And the messages defined in Section 7.2 (Note the ordering of the messages MUST be preserved), after they are mapped to the scalars in Section 7.3.2, along with the SK value as defined in Section 7.3.1 as inputs into the Sign operations, yields the following output signature

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature004.signature }}
+
+
+
+
+
+
+
+
+

+7.3.5. Proof Fixtures +

+

For the generation of the following fixtures the mocked_calculate_random_scalars defined in Mocked Random Scalars is used, in place of the calculate_random_scalars operation, with the following seed value (hex encoding of the ASCII-encoded 30 first digits of pi)

+
+
SEED = "332e313431353932363533353839373933323338343632363433333833323739"
+
+
+

Given the above seed the first 10 scalars returned by the mocked_calculate_random_scalars operation will be,

+
+
{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[0] }}
+{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[1] }}
+{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[2] }}
+{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[3] }}
+{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[4] }}
+{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[5] }}
+{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[6] }}
+{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[7] }}
+{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[8] }}
+{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[9] }}
+
+
+
+
+
+7.3.5.1. Valid Single Message Proof +
+

Using the header, message and signature used in Valid Single Message Signature to create a proof disclosing the message, with the following presentation header

+
+
{{ $proofFixtures.bls12-381-shake-256.proof001.presentationHeader }}
+
+
+

will result to the following proof value

+
+
{{ $proofFixtures.bls12-381-shake-256.proof001.proof }}
+
+
+
+
+
+
+
+7.3.5.2. Valid Multi-Message, All Messages Disclosed Proof +
+

Using the header, messages and signature used in Valid Multi Message Signature to create a proof disclosing all the messages, with the following presentation header

+
+
{{ $proofFixtures.bls12-381-shake-256.proof002.presentationHeader }}
+
+
+

will result to the following proof value

+
+
{{ $proofFixtures.bls12-381-shake-256.proof002.proof }}
+
+
+
+
+
+
+
+7.3.5.3. Valid Multi-Message, Half of Messages Disclosed Proof +
+

Using the same header, messages and signature as in Multi-Message, All Messages Disclosed Proof but this time with only every other messages disclosed (messages in index 0, 2, 4 and 6, in that order), with the following presentation header

+
+
{{ $proofFixtures.bls12-381-shake-256.proof003.presentationHeader }}
+
+
+

will result to the following proof value

+
+
{{ $proofFixtures.bls12-381-shake-256.proof003.proof }}
+
+
+
+
+
+
+
+
+
+
+

+7.4. BLS12381-SHA-256 Test Vectors +

+

Test vectors of the BLS12-381-SHA-256 ciphersuite. Further fixtures are available in additional BLS12-381-SHA-256 test vectors.

+
+
+

+7.4.1. Key Pair +

+

The following key pair will be used for the test vectors of the BLS12-381-SHA-256 ciphersuite.

+

Following the procedure defined in Section 3.3.1 with an input key_material value as follows

+
+
{{ $KeyPairFixtures.bls12-381-sha-256.keypair.keyMaterial }}
+
+
+

and the following key_info value

+
+
{{ $KeyPairFixtures.bls12-381-sha-256.keypair.keyInfo }}
+
+
+

Outputs the following SK value

+
+
{{ $KeyPairFixtures.bls12-381-sha-256.keypair.keyPair.secretKey }}
+
+
+

Following the procedure defined in Section 3.3.2 with an input SK value as above produces the following PK value

+
+
{{ $KeyPairFixtures.bls12-381-sha-256.keypair.keyPair.publicKey }}
+
+
+
+
+
+
+

+7.4.2. Map Messages to Scalars +

+

Similarly to how messages are mapped to scalars in BLS12381-SHAKE-256 Test Vectors, we are using the MapMessageToScalarAsHash operation to map each message to a scalar. For the BLS12-381-SHA-256 ciphersuite, on input each message in Section 7.2 and the following default dst

+
+
{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.dst }}
+
+
+

The output scalars, encoded to octets using I2OSP and represented in big endian order, are the following,

+
+
{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[0].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[1].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[2].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[3].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[4].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[5].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[6].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[7].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[8].scalar }}
+
+{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[9].scalar }}
+
+
+

Note that in both the following test vectors, as well as the additional BLS12-381-SHA-256 test vectors in Appendix C.2, when we are referring to a message that will be passed to one of the Sign, Verify, ProofGen or ProofVerify operations, we assume that it will first be mapped into one of the above scalars, using the MapMessageToScalarAsHash operation.

+
+
+
+
+

+7.4.3. Message Generators +

+

Following the procedure defined in Section 4.2 with an input count value of 11, for the BLS12-381-SHA-256 suite, outputs the following values (note that the first one corresponds to Q_1, while the next 10, to the message generators H_1, ..., H_10).

+
+
{{ $generatorFixtures.bls12-381-sha-256.generators.Q1 }}
+
+{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[0] }}
+
+{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[1] }}
+
+{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[2] }}
+
+{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[3] }}
+
+{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[4] }}
+
+{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[5] }}
+
+{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[6] }}
+
+{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[7] }}
+
+{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[8] }}
+
+{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[9] }}
+
+
+
+
+
+
+

+7.4.4. Signature Fixtures +

+
+
+
+7.4.4.1. Valid Single Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature001.header }}
+
+
+

And the following message (the first message defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature001.messages[0] }}
+
+
+

After it is mapped to the first scalar in Section 7.4.2, along with the SK value as defined in Section 7.4.1 as inputs into the Sign operations, yields the following output signature

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature001.signature }}
+
+
+
+
+
+
+
+7.4.4.2. Valid Multi-Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature004.header }}
+
+
+

And the messages defined in Section 7.2 (Note the ordering of the messages MUST be preserved), after they are mapped to the scalars in Section 7.4.2, along with the SK value as defined in Section 7.4.1 as inputs into the Sign operations, yields the following output signature

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature004.signature }}
+
+
+
+
+
+
+
+
+

+7.4.5. Proof Fixtures +

+

Similarly to the proof fixtures for the BLS12381-SHA-256 ciphersuite, the generation of the following fixtures uses the mocked_calculate_random_scalars defined in Mocked Random Scalars, in place of the calculate_random_scalars operation, with the following seed value (hex encoding of the ASCII-encoded 30 first digits of pi).

+
+
SEED = "332e313431353932363533353839373933323338343632363433333833323739"
+
+
+
+

Given the above seed the first 10 scalars returned by the mocked_calculate_random_scalars operation will be,

+
+
{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[0] }}
+{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[1] }}
+{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[2] }}
+{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[3] }}
+{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[4] }}
+{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[5] }}
+{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[6] }}
+{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[7] }}
+{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[8] }}
+{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[9] }}
+
+
+
+
+
+7.4.5.1. Valid Single Message Proof +
+

Using the header, message and signature used in Valid Single Message Signature to create a proof disclosing the message, with the following presentation header

+
+
{{ $proofFixtures.bls12-381-sha-256.proof001.presentationHeader }}
+
+
+

will result to the following proof value

+
+
{{ $proofFixtures.bls12-381-sha-256.proof001.proof }}
+
+
+
+
+
+
+
+7.4.5.2. Valid Multi-Message, All Messages Disclosed Proof +
+

Using the header, messages and signature used in Valid Multi Message Signature to create a proof disclosing all the messages, with the following presentation header

+
+
{{ $proofFixtures.bls12-381-sha-256.proof002.presentationHeader }}
+
+
+

will result to the following proof value

+
+
{{ $proofFixtures.bls12-381-sha-256.proof002.proof }}
+
+
+
+
+
+
+
+7.4.5.3. Valid Multi-Message, Half of Messages Disclosed Proof +
+

Using the same header, messages and signature as in Multi-Message, All Messages Disclosed Proof but this time with only every other messages disclosed (messages in index 0, 2, 4 and 6, in that order), with the following presentation header

+
+
{{ $proofFixtures.bls12-381-sha-256.proof003.presentationHeader }}
+
+
+

will result to the following proof value

+
+
{{ $proofFixtures.bls12-381-sha-256.proof003.proof }}
+
+
+
+
+
+
+
+
+
+
+
+
+

+8. IANA Considerations +

+

This document does not make any requests of IANA.

+
+
+
+
+

+9. Acknowledgements +

+

The authors would like to acknowledge the significant amount of academic work that preceeded the development of this document. In particular the original work of [BBS04] which was subsequently developed in [ASM06] and in [CDL16]. This last academic work is the one mostly used by this document.

+

The current state of this document is the product of the work of the Decentralized Identity Foundation Applied Cryptography Working group, which includes numerous active participants. In particular, the following individuals contributed ideas, feedback and wording that influenced this specification:

+

Orie Steele, Christian Paquin, Alessandro Guggino, Tomislav Markovski and Greg Bernstein.

+
+
+
+

+10. Normative References +

+
+
[DRBG]
+
+NIST, "Recommendation for Random Number Generation Using Deterministic Random Bit Generators", <https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf>.
+
+
[I-D.irtf-cfrg-hash-to-curve]
+
+Faz-Hernandez, A., Scott, S., Sullivan, N., Wahby, R. S., and C. A. Wood, "Hashing to Elliptic Curves", Work in Progress, Internet-Draft, draft-irtf-cfrg-hash-to-curve-16, , <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16>.
+
+
[I-D.irtf-cfrg-pairing-friendly-curves]
+
+Sakemi, Y., Kobayashi, T., Saito, T., and R. S. Wahby, "Pairing-Friendly Curves", Work in Progress, Internet-Draft, draft-irtf-cfrg-pairing-friendly-curves-11, , <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11>.
+
+
[RFC2119]
+
+Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
+
+
[RFC4086]
+
+Eastlake 3rd, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, DOI 10.17487/RFC4086, , <https://www.rfc-editor.org/info/rfc4086>.
+
+
[RFC8017]
+
+Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch, "PKCS #1: RSA Cryptography Specifications Version 2.2", RFC 8017, DOI 10.17487/RFC8017, , <https://www.rfc-editor.org/info/rfc8017>.
+
+
[RFC8937]
+
+Cremers, C., Garratt, L., Smyshlyaev, S., Sullivan, N., and C. Wood, "Randomness Improvements for Security Protocols", RFC 8937, DOI 10.17487/RFC8937, , <https://www.rfc-editor.org/info/rfc8937>.
+
+
[SHA2]
+
+NIST, "Secure Hash Standard (SHS)", <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf>.
+
+
[SHA3]
+
+NIST, "SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions", <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf>.
+
+
+
+
+

+11. Informative References +

+
+
[ADR02]
+
+An, J. H., Dodis, Y., and T. Rabin, "On the Security of Joint Signature and Encryption", In EUROCRYPT, pages 83-107, , <https://doi.org/10.1007/3-540-46035-7_6>.
+
+
[ASM06]
+
+Au, M. H., Susilo, W., and Y. Mu, "Constant-Size Dynamic k-TAA", In International Conference on Security and Cryptography for Networks, pages 111-125, Springer, Berlin, Heidelberg, , <https://link.springer.com/chapter/10.1007/11832072_8>.
+
+
[BBS04]
+
+Boneh, D., Boyen, X., and H. Shacham, "Short Group Signatures", In Advances in Cryptology, pages 41-55, , <https://link.springer.com/chapter/10.1007/978-3-540-28628-8_3>.
+
+
[Bowe19]
+
+Bowe, S., "Faster subgroup checks for BLS12-381", , <https://eprint.iacr.org/2019/814>.
+
+
[CDL16]
+
+Camenisch, J., Drijvers, M., and A. Lehmann, "Anonymous Attestation Using the Strong Diffie Hellman Assumption Revisited", In International Conference on Trust and Trustworthy Computing, pages 1-20, Springer, Cham, , <https://eprint.iacr.org/2016/663.pdf>.
+
+
[HDWH12]
+
+Heninger, N., Durumeric, Z., Wustrow, E., and J.A. Halderman, "Mining your Ps and Qs: Detection of widespread weak keys in network devices", In USENIX Security, pages 205-220, , <https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final228.pdf>.
+
+
[I-D.irtf-cfrg-bls-signature]
+
+Boneh, D., Gorbunov, S., Wahby, R. S., Wee, H., Wood, C. A., and Z. Zhang, "BLS Signatures", Work in Progress, Internet-Draft, draft-irtf-cfrg-bls-signature-05, , <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05>.
+
+
[ZCASH-REVIEW]
+
+NCC Group, "Zcash Overwinter Consensus and Sapling Cryptography Review", <https://research.nccgroup.com/wp-content/uploads/2020/07/NCC_Group_Zcash2018_Public_Report_2019-01-30_v1.3.pdf>.
+
+
+
+
+
+

+Appendix A. BLS12-381 hash_to_curve Definition Using SHAKE-256 +

+

The following defines a hash_to_curve suite [I-D.irtf-cfrg-hash-to-curve] for the BLS12-381 curve for both the G1 and G2 subgroups using the extendable output function (xof) of SHAKE-256 as per the guidance defined in section 8.9 of [I-D.irtf-cfrg-hash-to-curve].

+

Note the notation used in the below definitions is sourced from [I-D.irtf-cfrg-hash-to-curve].

+
+
+

+A.1. BLS12-381 G1 +

+

The suite of BLS12381G1_XOF:SHAKE-256_SSWU_RO_ is defined as follows:

+
+
* encoding type: hash_to_curve (Section 3 of
+                 [@!I-D.irtf-cfrg-hash-to-curve])
+
+* E: y^2 = x^3 + 4
+
+* p: 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f624
+     1eabfffeb153ffffb9feffffffffaaab
+
+* r: 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
+
+* m: 1
+
+* k: 128
+
+* expand_message: expand_message_xof (Section 5.3.2 of
+                  [@!I-D.irtf-cfrg-hash-to-curve])
+
+* hash: SHAKE-256
+
+* L: 64
+
+* f: Simplified SWU for AB == 0 (Section 6.6.3 of
+     [@!I-D.irtf-cfrg-hash-to-curve])
+
+* Z: 11
+
+*  E': y'^2 = x'^3 + A' * x' + B', where
+
+      -  A' = 0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aef
+                d881ac98936f8da0e0f97f5cf428082d584c1d
+
+      -  B' = 0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14f
+                cef35ef55a23215a316ceaa5d1cc48e98e172be0
+
+*  iso_map: the 11-isogeny map from E' to E given in Appendix E.2 of
+            [@!I-D.irtf-cfrg-hash-to-curve]
+
+*  h_eff: 0xd201000000010001
+
+
+

Note that the h_eff values for this suite are copied from that defined for the BLS12381G1_XMD:SHA-256_SSWU_RO_ suite defined in section 8.8.1 of [I-D.irtf-cfrg-hash-to-curve].

+

An optimized example implementation of the Simplified SWU mapping to the curve E' isogenous to BLS12-381 G1 is given in Appendix F.2 [I-D.irtf-cfrg-hash-to-curve].

+
+
+
+
+
+
+

+Appendix B. Use Cases +

+
+
+

+B.1. Non-correlating Security Token +

+

In the most general sense BBS signatures can be used in any application where a cryptographically secured token is required but correlation caused by usage of the token is un-desirable.

+

For example in protocols like OAuth2.0 the most commonly used form of the access token leverages the JWT format alongside conventional cryptographic primitives such as traditional digital signatures or HMACs. These access tokens are then used by a relying party to prove authority to a resource server during a request. However, because the access token is most commonly sent by value as it was issued by the authorization server (e.g in a bearer style scheme), the access token can act as a source of strong correlation for the relying party. Relevant prior art can be found here.

+

BBS Signatures due to their unique properties removes this source of correlation but maintains the same set of guarantees required by a resource server to validate an access token back to its relevant authority (note that an approach to signing JSON tokens with BBS that may be of relevance is the JWP format and serialization). In the context of a protocol like OAuth2.0 the access token issued by the authorization server would feature a BBS Signature, however instead of the relying party providing this access token as issued, in their request to a resource server, they generate a unique proof from the original access token and include that in the request instead, thus removing this vector of correlation.

+
+
+
+
+

+B.2. Improved Bearer Security Token +

+

Bearer based security tokens such as JWT based access tokens used in the OAuth2.0 protocol are a highly popular format for expressing authorization grants. However their usage has several security limitations. Notably a bearer based authorization scheme often has to rely on a secure transport between the authorized party (client) and the resource server to mitigate the potential for a MITM attack or a malicious interception of the access token. The scheme also has to assume a degree of trust in the resource server it is presenting an access token to, particularly when the access token grants more than just access to the target resource server, because in a bearer based authorization scheme, anyone who possesses the access token has authority to what it grants. Bearer based access tokens also suffer from the threat of replay attacks.

+

Improved schemes around authorization protocols often involve adding a layer of proof of cryptographic key possession to the presentation of an access token, which mitigates the deficiencies highlighted above as well as providing a way to detect a replay attack. However, approaches that involve proof of cryptographic key possession such as DPoP (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop-04) suffer from an increase in protocol complexity. A party requesting authorization must pre-generate appropriate key material, share the public portion of this with the authorization server alongside proving possession of the private portion of the key material. The authorization server must also be-able to accommodate receiving this information and validating it.

+

BBS Signatures ofter an alternative model that solves the same problems that proof of cryptographic key possession schemes do for bearer based schemes, but in a way that doesn't introduce new up-front protocol complexity. In the context of a protocol like OAuth2.0 the access token issued by the authorization server would feature a BBS Signature, however instead of the client providing this access token as issued, in their request to a resource server, they generate a unique proof from the original access token and include that in the request instead. Because the access token is not shared in a request to a resource server, attacks such as MITM are mitigated. A resource server also obtains the ability to detect a replay attack by ensuring the proof presented is unique.

+
+
+
+
+

+B.3. Selectively Disclosure Enabled Identity Credentials +

+

BBS signatures when applied to the problem space of identity credentials can help to enhance user privacy. For example a digital drivers license that is cryptographically signed with a BBS signature, allows the holder or subject of the license to disclose different claims from their drivers license to different parties. Furthermore, the unlinkable presentations property of proofs generated by the scheme remove an important possible source of correlation for the holder across multiple presentations.

+
+
+
+
+
+
+

+Appendix C. Additional Test Vectors +

+

NOTE These fixtures are a work in progress and subject to change

+
+
+

+C.1. BLS12-381-SHAKE-256 Ciphersuite +

+
+
+

+C.1.1. Signature Test Vectors +

+
+
+
+C.1.1.1. No Header Valid Signature +
+

Using the messages defined in Section 7.2, with no header, along with the SK and PK values defined in Section 7.3.1 results in the following signature value

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature010.signature }}
+
+
+
+
+
+
+
+C.1.1.2. Modified Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature002.header }}
+
+
+

And the following message (the first message defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature002.messages[0] }}
+
+
+

After is mapped to the first scalar in Section 7.3.2, and with the following signature

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature002.signature }}
+
+
+

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to the message value being different from what was signed

+
+
+
+
+
+C.1.1.3. Extra Unsigned Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature003.header }}
+
+
+

And the following messages (the two first messages defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature003.messages[0] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature003.messages[1] }}
+
+
+

After they are mapped to the first 2 scalars in Section 7.3.2, and with the following signature (which is a signature to only the first of the above two messages)

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature003.signature }}
+
+
+

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to an additional message being supplied that was not signed.

+
+
+
+
+
+C.1.1.4. Missing Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature005.header }}
+
+
+

And the following messages (the two first messages defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature005.messages[0] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature005.messages[1] }}
+
+
+

After they are mapped to the first 2 scalars in Section 7.3.2, and with the following signature (which is a signature on all the messages defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature005.signature }}
+
+
+

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to missing messages that were originally present during the signing.

+
+
+
+
+
+C.1.1.5. Reordered Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature006.header }}
+
+
+

And the following messages (re-ordering of the messages defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[0] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[1] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[2] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[3] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[4] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[5] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[6] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[7] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[8] }}
+
+{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[9] }}
+
+
+

After they are mapped to the corresponding scalars in Section 7.3.2, and with the following signature

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature006.signature }}
+
+
+

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to messages being re-ordered from the order in which they were signed

+
+
+
+
+
+C.1.1.6. Wrong Public Key Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature007.header }}
+
+
+

And the messages as defined in Section 7.2, mapped to the scalars in Section 7.3.2 and with the following signature

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature007.signature }}
+
+
+

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to public key used to verify is in-correct

+
+
+
+
+
+C.1.1.7. Wrong Header Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature008.header }}
+
+
+

And the messages as defined in Section 7.2, mapped to the scalars in Section 7.3.2 and with the following signature

+
+
{{ $signatureFixtures.bls12-381-shake-256.signature008.signature }}
+
+
+

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to header value being modified from what was originally signed

+
+
+
+
+
+
+

+C.1.2. Proof Test Vectors +

+
+
+
+C.1.2.1. No Header Valid Proof +
+

Using messages, PK and signature as in No Header Valid Signature, with only every other messages disclosed (messages in index 0, 2, 4 and 6, in that order), with no header and the following presentation header

+
+
{{ $proofFixtures.bls12-381-shake-256.proof014.presentationHeader }}
+
+
+

while using the mocked rng defined in Section 7.1, will result to the following proof value

+
+
{{ $proofFixtures.bls12-381-shake-256.proof014.proof }}
+
+
+
+
+
+
+
+C.1.2.2. No Presentation Header Valid Proof +
+

Using the same header, PK, messages and signature as in Multi-Message, All Messages Disclosed Proof, with every other message disclosed (messages in index 0, 2, 4 and 6, in that order), with no presentation header, while using the mocked rng defined in Section 7.1, will result to the following proof value

+
+
{{ $proofFixtures.bls12-381-shake-256.proof015.proof }}
+
+
+
+
+
+
+
+
+

+C.1.3. Hash to Scalar Test Vectors +

+

Using the following input message,

+
+
{{ $H2sFixture.bls12-381-shake-256.h2s.message }}
+
+
+

And the default dst defined in hash_to_scalar, i.e.,

+
+
{{ $H2sFixture.bls12-381-shake-256.h2s.dst }}
+
+
+

We get the following scalar, encoded with I2OSP and represented in big endian order,

+
+
{{ $H2sFixture.bls12-381-shake-256.h2s.scalar }}
+
+
+
+
+
+
+
+
+

+C.2. BLS12-381-SHA-256 Ciphersuite +

+
+
+

+C.2.1. Signature Test Vectors +

+
+
+
+C.2.1.1. No Header Valid Signature +
+

Using the messages defined in Section 7.2, with no header, along with the SK and PK values defined in Section 7.4.1 results in the following signature value

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature010.signature }}
+
+
+
+
+
+
+
+C.2.1.2. Modified Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature002.header }}
+
+
+

And the following message (the first message defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature002.messages[0] }}
+
+
+

After is mapped to the first scalar in Section 7.4.2, and with the following signature

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature002.signature }}
+
+
+

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to the message value being different from what was signed.

+
+
+
+
+
+C.2.1.3. Extra Unsigned Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature003.header }}
+
+
+

And the following messages (the two first messages defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature003.messages[0] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature003.messages[1] }}
+
+
+

After they are mapped to the first 2 scalars in Section 7.4.2, and with the following signature (which is a signature to only the first of the above two messages)

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature003.signature }}
+
+
+

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to an additional message being supplied that was not signed.

+
+
+
+
+
+C.2.1.4. Missing Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature005.header }}
+
+
+

And the following messages (the two first messages defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature005.messages[0] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature005.messages[1] }}
+
+
+

After they are mapped to the first 2 scalars in Section 7.4.2, and with the following signature (which is a signature on all the messages defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature005.signature }}
+
+
+

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to missing messages that were originally present during the signing.

+
+
+
+
+
+C.2.1.5. Reordered Message Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature006.header }}
+
+
+

And the following messages (re-ordering of the messages defined in Section 7.2)

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[0] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[1] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[2] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[3] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[4] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[5] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[6] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[7] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[8] }}
+
+{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[9] }}
+
+
+

After they are mapped to the corresponding scalars in Section 7.4.2, and with the following signature

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature006.signature }}
+
+
+

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to messages being re-ordered from the order in which they were signed.

+
+
+
+
+
+C.2.1.6. Wrong Public Key Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature007.header }}
+
+
+

And the messages as defined in Section 7.2, mapped to the scalars in Section 7.4.2 and with the following signature

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature007.signature }}
+
+
+

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to public key used to verify is in-correct.

+
+
+
+
+
+C.2.1.7. Wrong Header Signature +
+

Using the following header

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature008.header }}
+
+
+

And the messages as defined in Section 7.2, mapped to the scalars in Section 7.4.2 and with the following signature

+
+
{{ $signatureFixtures.bls12-381-sha-256.signature008.signature }}
+
+
+

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to header value being modified from what was originally signed.

+
+
+
+
+
+
+

+C.2.2. Proof Test Vectors +

+
+
+
+C.2.2.1. No Header Valid Proof +
+

Using messages, PK and signature as in No Header Valid Signature, with only every other messages disclosed (messages in index 0, 2, 4 and 6, in that order), with no header and the following presentation header

+
+
{{ $proofFixtures.bls12-381-sha-256.proof014.presentationHeader }}
+
+
+

while using the mocked rng defined in Section 7.1, will result to the following proof value

+
+
{{ $proofFixtures.bls12-381-sha-256.proof014.proof }}
+
+
+
+
+
+
+
+C.2.2.2. No Presentation Header Valid Proof +
+

Using the same header, PK, messages and signature as in Multi-Message, All Messages Disclosed Proof, with every other message disclosed (messages in index 0, 2, 4 and 6, in that order), with no presentation header, while using the mocked rng defined in Section 7.1, will result to the following proof value

+
+
{{ $proofFixtures.bls12-381-sha-256.proof015.proof }}
+
+
+
+
+
+
+
+
+

+C.2.3. Hash to Scalar Test Vectors +

+

Using the following input message,

+
+
{{ $H2sFixture.bls12-381-sha-256.h2s.message }}
+
+
+

And the default dst defined in hash_to_scalar, i.e.,

+
+
{{ $H2sFixture.bls12-381-sha-256.h2s.dst }}
+
+
+

We get the following scalar, encoded with I2OSP and represented in big endian order,

+
+
{{ $H2sFixture.bls12-381-sha-256.h2s.scalar }}
+
+
+
+
+
+
+
+
+
+
+

+Appendix D. Proof Generation and Verification Algorithmic Explanation +

+

The following section provides an explanation of how the ProofGen and ProofVerify operations work.

+

Let the prover be in possession of a BBS signature (A, e) on messages msg_1, ..., msg_L and a domain value (see Sign). Let A = B * (1/(e + SK)) where SK the signer's secret key and,

+
+
B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L
+
+
+

Let (i1, ..., iR) be the indexes of generators corresponding to messages the prover wants to disclose and (j1, ..., jU) be the indexes corresponding to undisclosed messages (i.e., (j1, ..., jU) = range(1, L) \ (i1, ..., iR)). To prove knowledge of a signature on the disclosed messages, work as follows,

+
    +
  • +

    Hide the signature by randomizing it. To randomize the signature (A, e), take uniformly random r1 in [1, r-1], and calculate,

    +
    +
    1.  A' = A * r1,
    +2.  Abar = A' * (-e) + B * r1
    +3.  D = B * r1.
    +
    +
    +

    Also set,

    +
    +
    4.  r3 = r1 ^ -1 mod r
    +
    +
    +

    The values (A', Abar, D) will be part of the proof and are used to prove possession of a BBS signature, without revealing the signature itself. Note that; e(A', PK) = e(Abar, P2) where PK the signer's public key and P2 the base element in G2 (used to create the signer’ (U+2019)s PK, see Section 3.3.2). This also serves to bind the proof to the signer's PK.

    +
  • +
  • +

    Set the following,

    +
    +
    1.  C1 = Abar - D
    +2.  C2 = P1 + Q_1 * domain + H_i1 * msg_i1 + ... + H_iR * msg_iR
    +
    +
    +

    Create a non-interactive zero-knowledge proof-of-knowledge (nizk) of the values e, r3 and msg_j1, ..., msg_jU (the undisclosed messages) so that both of the following equalities hold,

    +
    +
    EQ1.  C1 = A' * (-e)
    +EQ2.  C2 = - D * r3 + H_j1 * msg_j1 + ... + H_jU * msg_jU.
    +
    +
    +
  • +
+

Note that the verifier will know the elements in the left side of the above equations (i.e., C1 and C2) but not in the right side (i.e., r3 and the undisclosed messages: msg_j1, ..., msg_jU). However, using the nizk, the prover can convince the verifier that they (the prover) know the elements that satisfy those equations, without disclosing them. Then, if both EQ1 and EQ2 hold, and e(A', PK) = e(Abar, P2), an extractor can return a valid BBS signature from the signer's SK, on the disclosed messages. The proof returned is (A', Abar, D, nizk). To validate the proof, a verifier checks that e(A', PK) = e(Abar, P2) and verifies the nizk. Validating the proof, will guarantee the authenticity and integrity of the disclosed messages, as well as ownership of the undisclosed messages and of the signature.

+
+
+
+
+

+Appendix E. Document History +

+

-00

+
    +
  • Initial version +
  • +
+

-01

+
    +
  • Populated fixtures +
  • +
  • Added SHA-256 based ciphersuite +
  • +
  • Fixed typo in ProofVerify +
  • +
  • Clarify ASCII string usage in DST +
  • +
  • Added MapMessageToScalar test vectors +
  • +
  • Fix typo in ciphersuite name +
  • +
+

-02

+
    +
  • Variety of editiorial clarifications +
  • +
  • Clarified integer endianness +
  • +
  • Revised the encode for hash operation +
  • +
  • Shifted to using CSPRNG instead of PRF +
  • +
  • Removed total number of messages from proof verify operation +
  • +
  • Added deterministic proof fixtures +
  • +
  • Shifted to multiple CSPRNG calls to calculate random elements, instead of expand_message +
  • +
  • Updated hash_to_scalar to a single output +
  • +
+
+
+
+
+

+Authors' Addresses +

+
+
Tobias Looker
+
MATTR
+ +
+
+
Vasilis Kalos
+
MATTR
+ +
+
+
Andrew Whitehead
+
Portage
+ +
+
+
Mike Lodder
+
CryptID
+ +
+
+
+ + + diff --git a/draft-irtf-cfrg-bbs-signatures.md b/draft-irtf-cfrg-bbs-signatures.md index 861203f9..3ea36b74 100644 --- a/draft-irtf-cfrg-bbs-signatures.md +++ b/draft-irtf-cfrg-bbs-signatures.md @@ -542,12 +542,12 @@ Procedure: 7. B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L 8. Abar = A * r1 9. Bbar = B * r1 - Abar * e -10. C = Bbar * r2 + Abar * r3 + H_j1 * m~_j1 + ... + H_jU * m~_jU +10. C = Abar * r2 + Bbar * r3 + H_j1 * m~_j1 + ... + H_jU * m~_jU 11. c = calculate_challenge(Abar, Bbar, C, (i1, ..., iR), (msg_i1, ..., msg_iR), domain, ph) 12. r4 = - r1^-1 (mod r) -13. r2^ = r2 + r4 * c (mod r) -14. r3^ = r3 + e * r4 * c (mod r) +13. r2^ = r2 + e * r4 * c (mod r) +14. r3^ = r3 + r4 * c (mod r) 15. for j in (j1, ..., jU): m^_j = m~_j + msg_j * c (mod r) 16. proof = (Abar, Bbar, r2^, r3^, (m^_j1, ..., m^_jU), c) 17. return proof_to_octets(proof) @@ -630,7 +630,7 @@ Procedure: 4. (H_j1, ..., H_jU) = (MsgGenerators[j1], ..., MsgGenerators[jU]) 5. domain = calculate_domain(PK, Q_1, (H_1, ..., H_L), header) 6. D = P1 + Q_1 * domain + H_i1 * msg_i1 + ... + H_iR * msg_iR -7. C = Bbar * r2^ + Abar * r3^ + H_j1 * m^_j1 + ... + H_jU * m^_jU + D * c +7. C = Abar * r2^ + Bbar * r3^ + H_j1 * m^_j1 + ... + H_jU * m^_jU + D * c 8. cv = calculate_challenge(Abar, Bbar, C, (i1, ..., iR), (msg_i1, ..., msg_iR), domain, ph) 9. if c != cv, return INVALID From faf24eb2147ed01d7f4651701b0039f6a74d281c Mon Sep 17 00:00:00 2001 From: Vasilis Kalos Date: Thu, 6 Jul 2023 14:22:34 +0300 Subject: [PATCH 3/5] rm html files --- .vscode/settings.json | 10 - draft-blind-bbs-signatures.html | 1557 ---------- draft-irtf-cfrg-bbs-signatures.html | 4444 --------------------------- 3 files changed, 6011 deletions(-) delete mode 100644 .vscode/settings.json delete mode 100644 draft-blind-bbs-signatures.html delete mode 100644 draft-irtf-cfrg-bbs-signatures.html diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index f5953e87..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "cSpell.words": [ - "cfrg", - "ciphersuite", - "HKDF", - "irtf", - "octs", - "Shamir" - ] -} \ No newline at end of file diff --git a/draft-blind-bbs-signatures.html b/draft-blind-bbs-signatures.html deleted file mode 100644 index 9b5375e9..00000000 --- a/draft-blind-bbs-signatures.html +++ /dev/null @@ -1,1557 +0,0 @@ - - - - - - -Blind Signatures extension of the BBS Signature Scheme - - - - - - - - - - - - - - - - - - - - - - - - -
Blind Signatures extension of the BBS SiJanuary 2023
Lodder, et al.Informational[Page]
-
-
-
-
Workgroup:
-
none
-
Published:
-
- -
-
Authors:
-
-
-
M. Lodder
-
CryptID
-
-
-
T. Looker
-
Mattr
-
-
-
A. Whitehead
-
-
-
-
-

Blind Signatures extension of the BBS Signature Scheme

-
-

Abstract

-

This document defines an extension to the BBS Signature scheme, a form of short group digital signature scheme that supports multi-message signing that produces a single output digital signature. To enable blind signing capabilities which in the most general sense provide the ability for a signer to blindly sign a set of messages.

-
-
-

-Discussion Venues -

-

This note is to be removed before publishing as an RFC.

-

Source for this draft and an issue tracker can be found at - https://github.com/decentralized-identity/bbs-signature.

-
-
-
-

-Table of Contents -

- -
-
-
-
-

-1. Introduction -

-

// TODO

-
-
-

-1.1. Terminology -

-

All terminology defined by [BBS-DRAFT] is applicable to this draft

-

The following further terminology is defined by this document:

-
-
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. -
-
-
s'
-
The signature blinding factor held by the signature recipient. -
-
-
blind_signature
-
The blind digital signature output. -
-
-
-
-
-
-
-

-1.2. Notation -

-

Terms specific to pairing-friendly elliptic curves that are relevant to this document are restated in [BBS-DRAFT], originally defined in [I-D.irtf-cfrg-pairing-friendly-curves]

-
-
-
-
-
-
-

-2. Conventions -

-

The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, -SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL, when they appear in this -document, are to be interpreted as described in [RFC2119].

-
-
-
-
-

-3. Overview -

-

//TODO

-
-
-
-
-

-4. Example Flow -

-

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.

-
-
+--------+                               +--------+
-|        | <-(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. -
  3. -

    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).

    -
  4. -
  5. -

    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]).

    -
  6. -
-
-
-
-
-

-5. Operations -

-
-
-

-5.1. 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' = HASH(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
-
-
-
-
-
-
-

-5.2. 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 = HASH(PRF(8 \* ceil(log2(r)))) mod r
-
-3. s'' = HASH(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 + P1 + 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
-
-
-
-
-
-
-

-5.3. 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
-
-
-
-
-
-
-

-5.4. 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\~ = HASH(PRF(8 \* ceil(log2(r)))) mod r
-
-4. for i in 1 to U: r\~\[i\] = HASH(PRF(8 \* ceil(log2(r)))) mod r
-
-5. U~ = h0 \* s\~ + h\[i1\] \* r\~\[1\] + ... + h\[iU\] \* r\~\[U\]
-
-6. c = HASH(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^)
-
-
-
-
-
-
-

-5.5. 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 = HASH(U || U^ || nonce)
-
-5. return c == c\_v
-
-
-
-
-
-
-
-
-

-6. Security Considerations -

-

Implementers should consider the security considerations of [BBS-DRAFT] when implementing this work.

-
-
-
-
-

-7. IANA Considerations -

-

This document does not make any requests of IANA.

-
-
-
-

-8. Normative References -

-
-
[I-D.irtf-cfrg-pairing-friendly-curves]
-
-Sakemi, Y., Kobayashi, T., Saito, T., and R. S. Wahby, "Pairing-Friendly Curves", Work in Progress, Internet-Draft, draft-irtf-cfrg-pairing-friendly-curves-11, , <https://www.ietf.org/archive/id/draft-irtf-cfrg-pairing-friendly-curves-11.txt>.
-
-
[RFC2119]
-
-Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
-
-
-
-
-

-9. Informative References -

-
-
[BBS-DRAFT]
-
-Lodder, M., Looker, T., Whitehead, A., and V. Kalos, "The BBS Signature Scheme", <https://identity.foundation/bbs-signature/draft-irtf-cfrg-bbs-signatures.html>.
-
-
-
-
-
-

-Appendix A. Appendix -

-
-
-

-A.1. Test Vectors -

-

//TODO

-
-
-
-
-
-
-

-Authors' Addresses -

-
-
Mike Lodder
-
CryptID
- -
-
-
Tobias Looker
-
Mattr
- -
-
-
Andrew Whitehead
- -
-
-
- - - diff --git a/draft-irtf-cfrg-bbs-signatures.html b/draft-irtf-cfrg-bbs-signatures.html deleted file mode 100644 index 6cbaa469..00000000 --- a/draft-irtf-cfrg-bbs-signatures.html +++ /dev/null @@ -1,4444 +0,0 @@ - - - - - - -The BBS Signature Scheme - - - - - - - - - - - - - - - - - - - - - - - - - -
Internet-DraftThe BBS Signature SchemeJuly 2023
Looker, et al.Expires 5 January 2024[Page]
-
-
-
-
Workgroup:
-
CFRG
-
Internet-Draft:
-
draft-irtf-cfrg-bbs-signatures-latest
-
Published:
-
- -
-
Intended Status:
-
Informational
-
Expires:
-
-
Authors:
-
-
-
T. Looker
-
MATTR
-
-
-
V. Kalos
-
MATTR
-
-
-
A. Whitehead
-
Portage
-
-
-
M. Lodder
-
CryptID
-
-
-
-
-

The BBS Signature Scheme

-
-

Abstract

-

BBS is a digital signature scheme categorized as a form of short group signature that supports several unique properties. Notably, the scheme supports signing multiple messages whilst producing a single output digital signature. Through this capability, the possessor of a signature is able to generate proofs that selectively disclose subsets of the originally signed set of messages, whilst preserving the verifiable authenticity and integrity of the messages. Furthermore, these proofs are said to be zero-knowledge in nature as they do not reveal the underlying signature; instead, what they reveal is a proof of knowledge of the undisclosed signature.

-
-
-

-Discussion Venues -

-

This note is to be removed before publishing as an RFC.

-

Source for this draft and an issue tracker can be found at - https://github.com/decentralized-identity/bbs-signature.

-
-
-
-

-Status of This Memo -

-

- This Internet-Draft is submitted in full conformance with the - provisions of BCP 78 and BCP 79.

-

- Internet-Drafts are working documents of the Internet Engineering Task - Force (IETF). Note that other groups may also distribute working - documents as Internet-Drafts. The list of current Internet-Drafts is - at https://datatracker.ietf.org/drafts/current/.

-

- Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress."

-

- This Internet-Draft will expire on 5 January 2024.

-
-
- -
-
-

-Table of Contents -

- -
-
-
-
-

-1. Introduction -

-

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 message, where anyone in possession of the corresponding public key matching that of the private key is able to verify the signature.

-

The name BBS is derived from the authors of the original academic work of Dan Boneh, Xavier Boyen, and Hovav Shacham, where the scheme was first described.

-

Beyond the core properties of a digital signature scheme, BBS signatures provide multiple additional unique properties, three key ones are:

-

Selective Disclosure - The scheme allows a signer to sign multiple messages and produce a single -constant size- output signature. A holder/prover then possessing the messages and the signature can generate a proof whereby they can choose which messages to disclose, while revealing no-information about the undisclosed messages. The proof itself guarantees the integrity and authenticity of the disclosed messages (e.g. that they were originally signed by the signer).

-

Unlinkable Proofs - The proofs generated by the scheme are known as zero-knowledge, proofs-of-knowledge of the signature, meaning a verifying party in receipt of a proof is unable to determine which signature was used to generate the proof, removing a common source of correlation. In general, each proof generated is indistinguishable from random even for two proofs generated from the same signature.

-

Proof of Possession - The proofs generated by the scheme prove to a verifier that the party who generated the proof (holder/prover) was in possession of a signature without revealing it. The scheme also supports binding a presentation header to the generated proof. The presentation header can include arbitrary information such as a cryptographic nonce, an audience/domain identifier and or time based validity information.

-

Refer to the Appendix B for an elaboration on situations where these properties are useful

-

Below is a basic diagram describing the main entities involved in the scheme

-
-
-
  (1) sign                                      (3) ProofGen
-   +-----                                         +-----
-   |    |                                         |    |
-   |    |                                         |    |
-   |   \ /                                        |   \ /
-+----------+                                   +-----------+
-|          |                                   |           |
-|          |                                   |           |
-|          |                                   |           |
-|  Signer  |---(2)* Send signature + msgs----->|  Holder/  |
-|          |                                   |  Prover   |
-|          |                                   |           |
-|          |                                   |           |
-+----------+                                   +-----------+
-                                                     |
-                                                     |
-                                                     |
-                                      (4)* Send proof + disclosed msgs
-                                                     |
-                                                     |
-                                                    \ /
-                                               +-----------+
-                                               |           |
-                                               |           |
-                                               |           |
-                                               | Verifier  |
-                                               |           |
-                                               |           |
-                                               |           |
-                                               +-----------+
-                                                  |   / \
-                                                  |    |
-                                                  |    |
-                                                  +-----
-                                             (5) ProofVerify
-
-
-
-
-
Figure 1: -Basic diagram capturing the main entities involved in using the scheme -
-

Note The protocols implied by the items annotated by an asterisk are out of scope for this specification

-
-
-

-1.1. Terminology -

-

The following terminology is used throughout this document:

-
-
SK
-
The secret key for the signature scheme. -
-
-
PK
-
The public key for the signature scheme. -
-
-
L
-
The total number of signed messages. -
-
-
R
-
The number of message indexes that are disclosed (revealed) in a proof-of-knowledge of a signature. -
-
-
U
-
The number of message indexes that are undisclosed in a proof-of-knowledge of a signature. -
-
-
msg
-
An input message to be signed by the signature scheme. -
-
-
generator
-
A valid point on the selected subgroup of the curve being used that is employed to commit a value. -
-
-
scalar
-
An integer between 0 and r-1, where r is the prime order of the selected groups, defined by each ciphersuite (see also Notation). -
-
-
signature
-
The digital signature output. -
-
-
nonce
-
A cryptographic nonce -
-
-
presentation_header (ph)
-
A payload generated and bound to the context of a specific spk. -
-
-
nizk
-
A non-interactive zero-knowledge proof from the Fiat-Shamir heuristic. -
-
-
dst
-
The domain separation tag. -
-
-
I2OSP
-
An operation that transforms a non-negative integer into an octet string, defined in Section 4 of [RFC8017]. Note, the output of this operation is in big-endian order. -
-
-
OS2IP
-
An operation that transforms a octet string into an non-negative integer, defined in Section 4 of [RFC8017]. Note, the input of this operation must be in big-endian order. -
-
-
-
-
-
-
-

-1.2. Notation -

-

The following notation and primitives are used:

-
-
a || b
-
Denotes the concatenation of octet strings a and b. -
-
-
I \ J
-
For sets I and J, denotes the difference of the two sets i.e., all the elements of I that do not appear in J, in the same order as they were in I. -
-
-
X[a..b]
-
Denotes a slice of the array X containing all elements from and including the value at index a until and including the value at index b. Note when this syntax is applied to an octet string, each element in the array X is assumed to be a single byte. -
-
-
range(a, b)
-
For integers a and b, with a <= b, denotes the ascending ordered list of all integers between a and b inclusive (i.e., the integers "i" such that a <= i <= b). -
-
-
length(input)
-
Takes as input either an array or an octet string. If the input is an array, returns the number of elements of the array. If the input is an octet string, returns the number of bytes of the inputted octet string. -
-
-
-

Terms specific to pairing-friendly elliptic curves that are relevant to this document are restated below, originally defined in [I-D.irtf-cfrg-pairing-friendly-curves]

-
-
E1, E2
-
elliptic curve groups defined over finite fields. This document assumes that E1 has a more compact representation than E2, i.e., because E1 is defined over a smaller field than E2. -
-
-
G1, G2
-
subgroups of E1 and E2 (respectively) having prime order r. -
-
-
GT
-
a subgroup, of prime order r, of the multiplicative group of a field extension. -
-
-
e
-
G1 x G2 -> GT: a non-degenerate bilinear map. -
-
-
r
-
The prime order of the G1 and G2 subgroups. -
-
-
P1, P2
-
points on G1 and G2 respectively. For a pairing-friendly curve, this document denotes operations in E1 and E2 in additive notation, i.e., P + Q denotes point addition and x * P denotes scalar multiplication. Operations in GT are written in multiplicative notation, i.e., a * b is field multiplication. -
-
-
Identity_G1, Identity_G2, Identity_GT
-
The identity element for the G1, G2, and GT subgroups respectively. -
-
-
hash_to_curve_g1(ostr, dst) -> P
-
A cryptographic hash function that takes an arbitrary octet string as input and returns a point in G1, using the hash_to_curve operation defined in [I-D.irtf-cfrg-hash-to-curve] and the inputted dst as the domain separation tag for that operation (more specifically, the inputted dst will become the DST parameter for the hash_to_field operation, called by hash_to_curve). -
-
-
point_to_octets_g1(P) -> ostr, point_to_octets_g2(P) -> ostr
-
returns the canonical representation of the point P for the respective subgroup as an octet string. This operation is also known as serialization. -
-
-
octets_to_point_g1(ostr) -> P, octets_to_point_g2(ostr) -> P
-
returns the point P for the respective subgroup corresponding to the canonical representation ostr, or INVALID if ostr is not a valid output of the respective point_to_octets_g* function. This operation is also known as deserialization. -
-
-
subgroup_check(P) -> VALID or INVALID
-
returns VALID when the point P is an element of the subgroup of order r, and INVALID otherwise. This function can always be implemented by checking that r * P is equal to the identity element. In some cases, faster checks may also exist, e.g., [Bowe19]. -
-
-
-
-
-
-
-

-1.3. Document Organization -

-

This document is organized as follows:

-
    -
  • -

    Scheme Definition defines the core operations and parameters for the BBS signature scheme.

    -
  • -
  • -

    Utility Operations defines utilities used by the BBS signature scheme.

    -
  • -
  • -

    Security Considerations describes a set of security considerations associated to the signature scheme.

    -
  • -
  • -

    Ciphersuites defines the format of a ciphersuite, alongside a concrete ciphersuite based on the BLS12-381 curve.

    -
  • -
-
-
-
-
-
-
-

-2. Conventions -

-

The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, -SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL, when they appear in this -document, are to be interpreted as described in [RFC2119].

-
-
-
-
-

-3. Scheme Definition -

-

This section defines the BBS signature scheme, including the parameters required to define a concrete ciphersuite.

-
-
-

-3.1. Parameters -

-

The schemes operations defined in this section depend on the following parameters:

-
    -
  • -

    A pairing-friendly elliptic curve, plus associated functionality given in Section 1.2.

    -
  • -
  • -

    A hash-to-curve suite as defined in [I-D.irtf-cfrg-hash-to-curve], using the aforementioned pairing-friendly curve. This defines the hash_to_curve and expand_message operations, used by this document.

    -
  • -
  • -

    get_random(n): returns a random octet string with a length of n bytes, sampled uniformly at random using a cryptographically secure pseudo-random number generator (CSPRNG) or a pseudo random function. See [RFC4086] for recommendations and requirements on the generation of random numbers.

    -
  • -
-
-
-
-
-

-3.2. Considerations -

-
-
-

-3.2.1. Subgroup Selection -

-

In definition of this signature scheme there are two possible variations based upon the sub-group selection, namely where public keys are defined in G2 and signatures in G1 OR the opposite where public keys are defined in G1 and signatures in G2. Some pairing cryptography based digital signature schemes such as [I-D.irtf-cfrg-bls-signature] elect to allow for both variations, because they optimize for different things. However, in the case of this scheme, due to the operations involved in both signature and proof generation being computational in-efficient when performed in G2 and in the pursuit of simplicity, the scheme is limited to a construction where public keys are in G2 and signatures in G1.

-
-
-
-
-

-3.2.2. Messages -

-

Each of the core operations of the BBS signature scheme expect the inputted messages to be scalar values within a given range (specifically 1 and r-1, where r is the prime order of the G1 and G2 subgroups, defined by each ciphersuite, see Notation). There are multiple ways to transform a message from an octet string to a scalar value. This document defines the MapMessageToScalarAsHash operation, which hashes an octet string to a scalar (see Section 4.3.1). An application can use a different MapMessageToScalar operation, but it MUST be clearly and unambiguously defined, for all parties involved. Before using the core operations, all messages MUST be mapped to their respective scalars using the same operation. The defined Section 4.3.1 is the RECOMMENDED way of mapping octet strings to scalar values.

-
-
-
-
-

-3.2.3. Generators -

-

Throughout the operations of this signature scheme, each message that is signed is paired with a specific generator (point in G1). Specifically, if a generator H_1 is multiplied with msg_1 during signing, then H_1 MUST be multiplied with msg_1 in all other operations (signature verification, proof generation and proof verification).

-

Aside from the message generators, the scheme uses one additional generator Q_1 to sign the signature's domain, which binds both the signature and generated proofs to a specific context and cryptographically protects any potential application-specific information (for example, messages that must always be disclosed etc.).

-
-
-
-
-

-3.2.4. Serializing to Octets -

-

When serializing one or more values to produce an octet string, each element will be encoded using a specific operation determined by its type. More concretely,

-
    -
  • Points in G* will be serialized using the point_to_octets_g* implementation for a particular ciphersuite. -
  • -
  • Non-negative integers will be serialized using I2OSP with an output length of 8 bytes. -
  • -
  • Scalars will be serialized using I2OSP with a constant output length defined by a particular ciphersuite. -
  • -
-

We also use strings in double quotes to represent ASCII-encoded literals. For example "BBS" will be used to refer to the octet string, 010000100100001001010011.

-

Those rules will be used explicitly on every operation. See also Serialize.

-
-
-
-
-
-
-

-3.3. Key Generation Operations -

-
-
-

-3.3.1. Secret Key -

-

This operation generates a secret key (SK) deterministically from a secret octet string (key_material). This operation is the RECOMMENDED way of generating a secret key, but its use is not required for compatibility, and implementations MAY use a different key generation procedure. For security, such an alternative MUST output a secret key that is statistically close to uniformly random in the range from 1 to r-1. An example of an HKDF-based alternative is the KeyGen operation defined in Section 2.3 of [I-D.irtf-cfrg-bls-signature] (with an appropriate, BBS specific, salt value, like "BBS_SIG_KEYGENSALT").

-

For security, key_material MUST be random and infeasible to guess, e.g. generated by a trusted source of randomness and with enough entropy. See [RFC4086] for suggestions on generating randomness. key_material MUST be at least 32 bytes long, but it MAY be longer.

-

KeyGen takes an optional input, key_info. This parameter MAY be used to derive distinct keys from the same key material.

-

Because KeyGen is deterministic, implementations MAY choose either to store the resulting SK or to store key_material and key_info and call KeyGen to derive SK when necessary.

-
-
SK = KeyGen(key_material, key_info, key_dst)
-
-Inputs:
-
-- key_material (REQUIRED), a secret octet string. See requirements
-                           above.
-- key_info (OPTIONAL), an octet string. Defaults to an empty string if
-                       not supplied.
-- key_dst (OPTIONAL), an octet string representing the domain separation tag.
-                      Defaults to the octet string ciphersuite_id || "KEYGEN_DST_"
-                      if not supplied.
-
-Outputs:
-
-- SK, a uniformly random integer such that 0 < SK < r.
-
-Procedure:
-
-1. if length(key_material) < 32, return INVALID
-2. if length(key_info) > 65535, return INVALID
-3. derive_input = key_material || I2OSP(length(key_info), 2) || key_info
-4. SK = hash_to_scalar(derive_input, key_dst)
-5. if SK is INVALID, return INVALID
-6. return SK
-
-
-
-
-
-
-

-3.3.2. Public Key -

-

This operation takes a secret key (SK) and outputs a corresponding public key (PK).

-
-
PK = SkToPk(SK)
-
-Inputs:
-
-- SK (REQUIRED), a secret integer such that 0 < SK < r.
-
-Outputs:
-
-- PK, a public key encoded as an octet string.
-
-Procedure:
-
-1. W = SK * P2
-2. return point_to_octets_g2(W)
-
-
-
-
-
-
-
-
-

-3.4. Core Operations -

-

The operations of this section make use of functions and sub-routines defined in Utility Operations. More specifically,

-
    -
  • - hash_to_scalar is defined in Section 4.4 -
  • -
  • - calculate_domain and calculate_challenge are defined in Section 4.5 and Section 4.6 correspondingly. -
  • -
  • - serialize, signature_to_octets, octets_to_signature, proof_to_octets, octets_to_proof and octets_to_pubkey are defined in Section 4.7 -
  • -
-

The following operations also make use of the create_generators operation defined in Section 4.2, to create generator points on G1 (see Messages and Generators). Note that the values of those points depends only on a cipheruite defined seed. As a result, the output of that operation can be cached to avoid unnecessary calls to the create_generators procedure. See Section 4.2 for more details.

-
-
-

-3.4.1. Signature Generation (Sign) -

-

This operation computes a deterministic signature from a secret key (SK) and optionally over a header and or a vector of messages (as scalar values, see Messages).

-
-
signature = Sign(SK, PK, header, messages)
-
-Inputs:
-
-- SK (REQUIRED), a non negative integer mod r outputted by the KeyGen
-                 operation.
-- PK (REQUIRED), an octet string of the form outputted by the SkToPk
-                 operation provided the above SK as input.
-- header (OPTIONAL), an octet string containing context and application
-                     specific information. If not supplied, it defaults
-                     to an empty string.
-- messages (OPTIONAL), a vector of scalars. If not supplied, it defaults
-                       to the empty array "()".
-
-Parameters:
-
-- P1, fixed point of G1, defined by the ciphersuite.
-- expand_message, the expand_message operation defined by the suite
-                  specified by the hash_to_curve_suite parameter.
-- octet_scalar_length, non-negative integer. The length of a scalar
-                       octet representation, defined by the ciphersuite.
-- create_generators, an operation that returns a number of generator
-                     points, defined by the ciphersuite.
-
-Definitions:
-
-- L, is the non-negative integer representing the number of messages to
-     be signed.
-
-Outputs:
-
-- signature, a signature encoded as an octet string.
-
-Deserialization:
-
-1. L = length(messages)
-2. (msg_1, ..., msg_L) = messages
-
-Procedure:
-
-1. (Q_1, H_1, ..., H_L) = create_generators(L+1, PK)
-2. domain = calculate_domain(PK, Q_1, (H_1, ..., H_L), header)
-3. if domain is INVALID, return INVALID
-4. e = hash_to_scalar(serialize((SK, domain, msg_1, ..., msg_L)))
-5. if e is INVALID, return INVALID
-6. B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L
-7. A = B * (1 / (SK + e))
-8. return signature_to_octets(A, e)
-
-
-

Note When computing step 12 of the above procedure there is an extremely small probability (around 2^(-r)) that the condition (SK + e) = 0 mod r will be met. How implementations evaluate the inverse of the scalar value 0 may vary, with some returning an error and others returning 0 as a result. If the returned value from the inverse operation 1/(SK + e) does evaluate to 0 the value of A will equal Identity_G1 thus an invalid signature. Implementations MAY elect to check (SK + e) = 0 mod r prior to step 9, and or A != Identity_G1 after step 9 to prevent the production of invalid signatures.

-
-
-
-
-

-3.4.2. Signature Verification (Verify) -

-

This operation checks that a signature is valid for a given header and vector of messages against a supplied public key (PK). The messages MUST be supplied in this operation in the same order they were supplied to Sign when creating the signature.

-
-
result = Verify(PK, signature, header, messages)
-
-Inputs:
-
-- PK (REQUIRED), an octet string of the form outputted by the SkToPk
-                 operation.
-- signature (REQUIRED), an octet string of the form outputted by the
-                        Sign operation.
-- header (OPTIONAL), an octet string containing context and application
-                     specific information. If not supplied, it defaults
-                     to an empty string.
-- messages (OPTIONAL), a vector of scalars. If not supplied, it defaults
-                       to the empty array "()".
-
-Parameters:
-
-- P1, fixed point of G1, defined by the ciphersuite.
-- create_generators, an operation that returns a number of generator
-                     points, defined by the ciphersuite.
-
-Definitions:
-
-- L, is the non-negative integer representing the number of signed
-     messages.
-
-Outputs:
-
-- result, either VALID or INVALID.
-
-Deserialization:
-
-1. signature_result = octets_to_signature(signature)
-2. if signature_result is INVALID, return INVALID
-3. (A, e) = signature_result
-4. W = octets_to_pubkey(PK)
-5. if W is INVALID, return INVALID
-6. L = length(messages)
-7. (msg_1, ..., msg_L) = messages
-
-Procedure:
-
-1. (Q_1, H_1, ..., H_L) = create_generators(L+1, PK)
-2. domain = calculate_domain(PK, Q_1, (H_1, ..., H_L), header)
-3. if domain is INVALID, return INVALID
-4. B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L
-5. if e(A, W + P2 * e) * e(B, -P2) != Identity_GT, return INVALID
-6. return VALID
-
-
-
-
-
-
-

-3.4.3. Proof Generation (ProofGen) -

-

This operation computes a zero-knowledge proof-of-knowledge of a signature, while optionally selectively disclosing from the original set of signed messages. The "prover" may also supply a presentation header, see Presentation header selection for more details.

-

The messages supplied in this operation MUST be in the same order as when supplied to Sign. To specify which of those messages will be disclosed, the prover can supply the list of indexes (disclosed_indexes) that the disclosed messages have in the array of signed messages. Each element in disclosed_indexes MUST be a non-negative integer, in the range from 1 to length(messages).

-

The operation calculates multiple random scalars using the calculate_random_scalars utility operation defined in Section 4.1. See also Section 5.10 for considerations and requirements on random scalars generation.

-

To allow for flexibility in implementations, although ProofGen defines a specific value for expand_len, applications may use any value larger than ceil((ceil(log2(r))+k)/8) (for example, for the BLS12-381-SHAKE-256 and BLS12-381-SHA-256 ciphersuites, an implementation can elect to use a value of 64, instead of 48, as to allow for certain optimizations).

-
-
proof = ProofGen(PK, signature, header, ph, messages, disclosed_indexes)
-
-Inputs:
-
-- PK (REQUIRED), an octet string of the form outputted by the SkToPk
-                 operation.
-- signature (REQUIRED), an octet string of the form outputted by the
-                        Sign operation.
-- header (OPTIONAL), an octet string containing context and application
-                     specific information. If not supplied, it defaults
-                     to an empty string.
-- ph (OPTIONAL), an octet string containing the presentation header. If not
-                 supplied, it defaults to an empty string.
-- messages (OPTIONAL), a vector of scalars. If not supplied, it defaults
-                       to the empty array "()".
-- disclosed_indexes (OPTIONAL), vector of unsigned integers in ascending
-                                order. Indexes of disclosed messages. If
-                                not supplied, it defaults to the empty
-                                array "()".
-
-Parameters:
-
-- P1, fixed point of G1, defined by the ciphersuite.
-- create_generators, an operation that returns a number of generator
-                     points, defined by the ciphersuite.
-
-Definitions:
-
-- L, is the non-negative integer representing the number of messages.
-- R, is the non-negative integer representing the number of disclosed
-     (revealed) messages.
-- U, is the non-negative integer representing the number of undisclosed
-     messages, i.e., U = L - R.
-
-Outputs:
-
-- proof, an octet string; or INVALID.
-
-Deserialization:
-
-1.  signature_result = octets_to_signature(signature)
-2.  if signature_result is INVALID, return INVALID
-3.  (A, e) = signature_result
-4.  L = length(messages)
-5.  R = length(disclosed_indexes)
-6.  U = L - R
-7.  (i1, ..., iR) = disclosed_indexes
-8.  (j1, ..., jU) = range(1, L) \ disclosed_indexes
-9.  (msg_1, ..., msg_L) = messages
-10. (msg_i1, ..., msg_iR) = (messages[i1], ..., messages[iR])
-11. (msg_j1, ..., msg_jU) = (messages[j1], ..., messages[jU])
-
-Procedure:
-
-1.  (Q_1, MsgGenerators) = create_generators(L+1, PK)
-2.  (H_1, ..., H_L) = MsgGenerators
-3.  (H_j1, ..., H_jU) = (MsgGenerators[j1], ..., MsgGenerators[jU])
-4.  domain = calculate_domain(PK, Q_1, (H_1, ..., H_L), header)
-5.  if domain is INVALID, return INVALID
-6.  random_scalars = calculate_random_scalars(3+U)
-7.  (r1, r2, r3, m~_j1, ..., m~_jU) = random_scalars
-8.  B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L
-9.  Abar = A * r1
-10. Bbar = B * r1 - Abar * e
-11. C = Bbar * r2 + Abar * r3 + H_j1 * m~_j1 + ... + H_jU * m~_jU
-12. c = calculate_challenge(Abar, Bbar, C, (i1, ..., iR),
-                            (msg_i1, ..., msg_iR), domain, ph)
-13. if c is INVALID, return INVALID
-14. r4 = - r1^-1 (mod r)
-15. r2^ = r2 + r4 * c (mod r)
-16. r3^ = r3 + e * r4 * c (mod r)
-17. for j in (j1, ..., jU): m^_j = m~_j + msg_j * c (mod r)
-18. proof = (Abar, Bbar, r2^, r3^, (m^_j1, ..., m^_jU), c)
-19. return proof_to_octets(proof)
-
-
-
-
-
-
-

-3.4.4. Proof Verification (ProofVerify) -

-

This operation checks that a proof is valid for a header, vector of disclosed messages (along side their index corresponding to their original position when signed) and presentation header against a public key (PK).

-

The operation accepts the list of messages the prover indicated to be disclosed. Those messages MUST be in the same order as when supplied to Sign (as a subset of the signed messages list). The operation also requires the total number of signed messages (L). Lastly, it also accepts the indexes that the disclosed messages had in the original array of messages supplied to Sign (i.e., the disclosed_indexes list supplied to ProofGen). Every element in this list MUST be a non-negative integer in the range from 1 to L, in ascending order.

-
-
result = ProofVerify(PK, proof, header, ph,
-                     disclosed_messages,
-                     disclosed_indexes)
-
-Inputs:
-
-- PK (REQUIRED), an octet string of the form outputted by the SkToPk
-                 operation.
-- proof (REQUIRED), an octet string of the form outputted by the
-                    ProofGen operation.
-- header (OPTIONAL), an optional octet string containing context and
-                     application specific information. If not supplied,
-                     it defaults to an empty string.
-- ph (OPTIONAL), an octet string containing the presentation header. If not
-                 supplied, it defaults to an empty string.
-- disclosed_messages (OPTIONAL), a vector of scalars. If not supplied,
-                                 it defaults to the empty array "()".
-- disclosed_indexes (OPTIONAL), vector of unsigned integers in ascending
-                                order. Indexes of disclosed messages. If
-                                not supplied, it defaults to the empty
-                                array "()".
-
-Parameters:
-
-- P1, fixed point of G1, defined by the ciphersuite.
-- create_generators, an operation that returns a number of generator
-                     points, defined by the ciphersuite.
-
-Definitions:
-
-- R, is the non-negative integer representing the number of disclosed
-     (revealed) messages.
-- U, is the non-negative integer representing the number of undisclosed
-     messages.
-- L, is the non-negative integer representing the number of total,
-     messages i.e., L = U + R.
-
-Outputs:
-
-- result, either VALID or INVALID.
-
-Deserialization:
-
-1.  proof_result = octets_to_proof(proof)
-2.  if proof_result is INVALID, return INVALID
-3.  (Abar, Bbar, r2^, r3^, commitments, c) = proof_result
-4.  W = octets_to_pubkey(PK)
-5.  if W is INVALID, return INVALID
-6.  U = length(commitments)
-7.  R = length(disclosed_indexes)
-8.  L = R + U
-9.  (i1, ..., iR) = disclosed_indexes
-10. (j1, ..., jU) = range(1, L) \ disclosed_indexes
-11. (msg_i1, ..., msg_iR) = disclosed_messages
-12. (m^_j1, ...., m^_jU) = commitments
-
-Preconditions:
-
-1. for i in (i1, ..., iR), if i < 1 or i > L, return INVALID
-2. if length(disclosed_messages) != R, return INVALID
-
-Procedure:
-
-1.  (Q_1, MsgGenerators) = create_generators(L+1, PK)
-2.  (H_1, ..., H_L) = MsgGenerators
-3.  (H_i1, ..., H_iR) = (MsgGenerators[i1], ..., MsgGenerators[iR])
-4.  (H_j1, ..., H_jU) = (MsgGenerators[j1], ..., MsgGenerators[jU])
-
-5.  domain = calculate_domain(PK, Q_1, (H_1, ..., H_L), header)
-6.  if domain is INVALID, return INVALID
-7.  D = P1 + Q_1 * domain + H_i1 * msg_i1 + ... + H_iR * msg_iR
-8.  C = Bbar * r2^ + Abar * r3^ + H_j1 * m^_j1 + ... + H_jU * m^_jU + D * c
-9.  cv = calculate_challenge(Abar, Bbar, C, (i1, ..., iR),
-                             (msg_i1, ..., msg_iR), domain, ph)
-10. if cv is INVALID, return INVALID
-11. if c != cv, return INVALID
-12. if e(Abar, W) * e(Bbar, -P2) != Identity_GT, return INVALID
-13. return VALID
-
-
-
-
-
-
-
-
-
-
-

-4. Utility Operations -

-
-
-

-4.1. Random Scalars -

-

This operation returns the requested number of pseudo-random scalars, using the get_random operation (see Parameters). The operation makes multiple calls to get_random. It is REQUIRED that each call will be independent from each other, as to ensure independence of the returned pseudo-random scalars.

-

The required length of the get_random output is defined as expand_len. Each value returned by the get_random function is reduced modulo the group order r. To avoid biased results when creating the random scalars, the output of get_random MUST be at least (ceil(log2(r))+k bytes long, where k is the targeted security level specified by the ciphersuite (see Section 5 in [I-D.irtf-cfrg-hash-to-curve] for more details). ProofGen defines expand_len = ceil((ceil(log2(r))+k)/8). For both the BLS12-381-SHAKE-256 and BLS12-381-SHA-256 ciphersuites, log2(r) = 255 and k = 128 resulting to expand_len = 48. See Section 5.10 for further security considerations and requirements around the generated randomness.

-

Note: The security of the proof generation algorithm (ProofGen) is highly dependant on the quality of the get_random function. Care must be taken to ensure that a cryptographically secure pseudo-random generator is chosen, and that its outputs are not leaked to an adversary. See also Section 5.10 for more details.

-
-
random_scalars = calculate_random_scalars(count)
-
-Inputs:
-
-- count (REQUIRED), non negative integer. The number of pseudo random
-                    scalars to return.
-
-Parameters:
-
-- get_random, a pseudo random function with extendable output, returning
-              uniformly distributed pseudo random bytes.
-- expand_len = ceil((ceil(log2(r))+k)/8), where r and k are defined by
-                                          the ciphersuite.
-
-Outputs:
-
-- random_scalars, a list of pseudo random scalars,
-
-Procedure:
-
-1. for i in (1, ..., count):
-2.     r_i = OS2IP(get_random(expand_len)) mod r
-3. return (r_1, r_2, ..., r_count)
-
-
-
-
-
-
-

-4.2. Generators Calculation -

-

A create_generators procedure defines how to create a set of randomly sampled points from the G1 subgroup, called the generators. Generators form a part of the public parameters used by the BBS Signature scheme to accomplish operations such as Sign, Verify, ProofGen and ProofVerify. A create_generators operation takes as input the following arguments,

-
    -
  • count (REQUIRED), a non-negative integer describing the number of generator points to create, which is determined in part by the number of signed messages. -
  • -
  • PK (OPTIONAL), a point of G2, representing the Signer's public key. -
  • -
-

As a result, the create_generators operation has the following signature,

-
-
(G_1, G_2, ..., G_count) = create_generators(count, PK)
-
-
-

Each procedure MUST define a unique CREATE_GENERATORS_ID to be used by the ciphersuite. This value MUST only contain ASCII encoded characters with codes between 0x21 and 0x7e (inclusive) and MUST end with an underscore (ASCII code: 0x5f), other than the last character the string MUST not contain any other underscores (ASCII code: 0x5f).

-
-
-

-4.2.1. Hash to Generators -

-

The hash_to_generators operation makes use of the primitives defined in [I-D.irtf-cfrg-hash-to-curve] (more specifically of hash_to_curve and expand_message) to hash a predefined seed to a set of generators. Those primitives are implicitly defined by the ciphersuite, through the choice of a hash-to-curve suite (see the hash_to_curve_suite parameter in Section 6.1).

-

NOTE: The hash_to_generators operation ignores the PK input, creating the same generators across different Signers and signatures. The final create_generators operation defined by the ciphersuites in Section 6, will be,

-
-
create_generators(count, PK) := hash_to_generator(count)
-
-
-

Since hash_to_generator creates constant points, as an optimization, implementations MAY cache its result for a specific count (which can be arbitrarily large, depending on the application). Care must be taken, to guarantee that the generators will be fetched from the cache in the same order they had when they where created (i.e., an application should not short or in any way rearrange the cached generators).

-
-
generators = hash_to_generators(count)
-
-Inputs:
-
-- count (REQUIRED), unsigned integer. Number of generators to create.
-
-Parameters:
-
-- hash_to_curve_g1, the hash_to_curve operation for the G1 subgroup,
-                    defined by the suite specified by the
-                    hash_to_curve_suite parameter of the ciphersuite.
-- expand_message, the expand_message operation defined by the suite
-                  specified by the hash_to_curve_suite parameter of the
-                  ciphersuite.
-- generator_seed, an octet string representing the seed from which the
-                  generators are created, defined by the ciphersuite.
-
-Definitions:
-
-- seed_dst, an octet string representing the domain separation tag:
-            ciphersuite_id || "SIG_GENERATOR_SEED_" where
-            ciphersuite_id is defined by the ciphersuite and
-            "SIG_GENERATOR_SEED_" is an ASCII string comprised of 19
-            bytes.
-- generator_dst, an octet string representing the domain separation tag:
-                 ciphersuite_id || "SIG_GENERATOR_DST_", where
-                 ciphersuite_id is defined by the ciphersuite and
-                 "SIG_GENERATOR_DST_" is an ASCII string comprised of
-                 18 bytes.
-- seed_len = ceil((ceil(log2(r)) + k)/8), where r and k are defined by
-                                          the ciphersuite.
-
-Outputs:
-
-- generators, an array of generators.
-
-Procedure:
-
-1.  v = expand_message(generator_seed, seed_dst, seed_len)
-2.  n = 1
-3.  for i in range(1, count):
-4.     v = expand_message(v || I2OSP(n, 4), seed_dst, seed_len)
-5.     n = n + 1
-6.     generator_i = Identity_G1
-7.     candidate = hash_to_curve_g1(v, generator_dst)
-8.     if candidate in (generator_1, ..., generator_i, P_1):
-9.        go back to step 4
-10.    generator_i = candidate
-11. return (generator_1, ..., generator_count)
-
-
-

The values n and v MAY also be cached in order to efficiently extend an existing list of cached generator points. The CREATE_GENERATORS_ID of the above operation is define as,

-
-
CREATE_GENERATORS_ID = "H2G_"
-
-
-
-
-
-
-

-4.2.2. Defining new ways to create generators -

-

When defining a new create_generators procedure, the most important property is that the returned points are pseudo-randomly chosen from the G1 group, given reasonable assumptions and cryptographic primitives. More specifically, the required properties are

-
    -
  • The returned points should be indistinguishable from count uniformly radom points of G1. This means that given only the points H_1, ..., H_i it should be infeasible to guess H_(i+1) (or any H_j with j > i), for any i between 1 and count. -
  • -
  • The returned points must be unique with very high probability, that would not lessen the targeted security level of the ciphersuite. Specifically, for a security level k, the probability of a collision should be at least 1/2^k. -
  • -
  • It should be infeasible to guess the discrete logarithm of the returned points, for any base, even with knowledge of the public parameters that were used to create those generators (like the generator_seed value in Hash to Generators). Note that pseudo randomness does not necessarily imply this property. For example, an implementation that repeatably hashes a public seed value to create exponents r_1, r_2, ..., r_count (where r_1 = hash(seed), r_2 = hash(r_1), ...) and then returns the points H_1 = P1 * r_1, H_2 = P_1 * r_2, ..., H_count = P_1 * r_count would be insecure (given knowledge of the seed), but given knowledge of only the points H_1, ..., H_count, the sequence would appear random. -
  • -
  • The returned points must be different from the Identity point of G1 as well as the constant point P1 defined by the ciphersuite. -
  • -
  • Must be constant time for a specific count value. -
  • -
  • MUST be deterministic. -
  • -
  • Must use proper domain separation for both the create_generators procedure, as well as all of the internally-called procedures. -
  • -
-
-
-
-
-
-
-

-4.3. Message to Scalar -

-

There are multiple ways in which messages can be mapped to their respective scalar values, which is their required form to be used with the Sign, Verify, ProofGen and ProofVerify operations.

-
-
-

-4.3.1. Message to Scalar as Hash -

-

This operation takes an input message and maps it to a scalar value via a cryptographic hash function for the given curve. The operation takes also as an optional input a domain separation tag (dst). If a dst is not supplied, its value MUST default to the octet string returned from ciphersuite_id || "MAP_MSG_TO_SCALAR_AS_HASH_", where ciphersuite_id is the ASCII string representing the unique ID of the ciphersuite "MAP_MSG_TO_SCALAR_AS_HASH_" is an ASCII string comprised of 26 bytes.

-
-
msg_scalar = MapMessageToScalarAsHash(msg, dst)
-
-Inputs:
-
-- msg (REQUIRED), an octet string.
-- dst (OPTIONAL), an octet string representing a domain separation tag.
-                  If not supplied, it default to the octet string
-                  ciphersuite_id || "MAP_MSG_TO_SCALAR_AS_HASH_" where
-                  ciphersuite_id is defined by the ciphersuite.
-
-Outputs:
-
-- msg_scalar, a scalar value.
-
-Procedure:
-
-1. if length(msg) > 2^64 - 1 or length(dst) > 255 return INVALID
-2. msg_scalar = hash_to_scalar(msg, dst)
-3. if msg_scalar is INVALID, return INVALID
-4. return msg_scalar
-
-
-
-
-
-
-
-
-

-4.4. Hash to Scalar -

-

This operation describes how to hash an arbitrary octet string to n scalar values in the multiplicative group of integers mod r (i.e., values in the range [1, r-1]). This procedure acts as a helper function, used internally in various places within the operations described in the spec. To hash a message to a scalar that would be passed as input to the Sign, Verify, ProofGen and ProofVerify functions, one must use MapMessageToScalarAsHash instead.

-

This operation makes use of expand_message defined in [I-D.irtf-cfrg-hash-to-curve], in a similar way used by the hash_to_field operation of Section 5 from the same document (with the additional checks for getting a scalar that is 0). If an implementer wants to use hash_to_field instead, they MUST use the multiplicative group of integers mod r (Fr), as the target group (F). Note however, that the hash_to_curve document, makes use of hash_to_field with the target group being the multiplicative group of integers mod p (Fp). For this reason, we don’ (U+2019)t directly use hash_to_field here, rather we define a similar operation (hash_to_scalar), making direct use of the expand_message function, that will be defined by the hash-to-curve suite used (i.e., either expand_message_xmd or expand_message_xof). If someone also has a hash_to_field implementation available, with the target group been Fr, they can use this instead (adding the check for a scalar been 0).

-

The operation takes as input an octet string representing the message to hash (msg), the number of the scalars to return (count) as well as an optional domain separation tag (dst). If a dst is not supplied, its value MUST default to the octet string returned from ciphersuit_id || "H2S_", where ciphersuite_id is the octet string representing the unique ID of the ciphersuite and "H2S_" is an ASCII string comprised of 4 bytes.

-

Note It is possible that the hash_to_scalar procedure will return an error, if the underlying expand_message operation aborts. See [I-D.irtf-cfrg-hash-to-curve], Section 5.3, for more details on the cases that expand_message will abort (note that the input term len_in_bytes of expand_message in the Hash-to-Curve document equals count * expand_len in our case).

-
-
hashed_scalar = hash_to_scalar(msg_octets, dst)
-
-Inputs:
-
-- msg_octets (REQUIRED), an octet string. The message to be hashed.
-- dst (OPTIONAL), an octet string representing a domain separation tag.
-                  If not supplied, it defaults to the octet string given
-                  by ciphersuite_id || "H2S_", where ciphersuite_id is
-                  defined by the ciphersuite.
-
-Parameters:
-
-- hash_to_curve_suite, the hash to curve suite id defined by the
-                       ciphersuite.
-- expand_message, the expand_message operation defined by the suite
-                  specified by the hash_to_curve_suite parameter.
-
-Definitions:
-
-- expand_len = ceil((ceil(log2(r))+k)/8), where r and k are defined by
-                                          the ciphersuite.
-
-Outputs:
-
-- hashed_scalar, a non-zero scalar mod r.
-
-Procedure:
-
-1.  counter = 0
-2.  hashed_scalar = 0
-3.  while hashed_scalar == 0:
-4.      if counter > 255, return INVALID
-5.      msg_prime = msg_octets || I2OSP(counter, 1)
-6.      uniform_bytes = expand_message(msg_prime, dst, expand_len)
-7.      if uniform_bytes is INVALID, return INVALID
-8.      hashed_scalar = OS2IP(uniform_bytes) mod r
-9.      counter = counter + 1
-10. return hashed_scalar
-
-
-
-
-
-
-

-4.5. Domain Calculation -

-

This operation calculates the domain value, a scalar representing the distillation of all essential contextual information for a signature. The same domain value must be calculated by all parties (the signer, the prover, and the verifier) for both the signature and proofs to be validated.

-

The input to the domain value includes an octet string called the header, chosen by the signer and meant to encode any information that is required to be revealed by the prover (such as an expiration date, or an identifier for the target audience). This is in contrast to the signed message values, which may be withheld during a proof.

-

When a signature is calculated, the domain value is combined with a specific generator point (Q_1, see Sign) to protect the integrity of the public parameters and the header.

-

This operation makes use of the serialize function, defined in Section 4.6.1.

-
-
domain = calculate_domain(PK, Q_1, H_Points, header)
-
-Inputs:
-
-- PK (REQUIRED), an octet string, representing the public key of the
-                 Signer of the form outputted by the SkToPk operation.
-- Q_1 (REQUIRED), point of G1 (the first point returned from
-                  create_generators).
-- H_Points (REQUIRED), array of points of G1.
-- header (OPTIONAL), an octet string. If not supplied, it must default to
-                     the empty octet string ("").
-
-Parameters:
-
-- ciphersuite_id, an octet string. The unique ID of the ciphersuite.
-
-Outputs:
-
-- domain, a scalar value or INVALID.
-
-Procedure:
-
-1.  L = length(H_Points)
-2.  if length(header) > 2^64 - 1 or L > 2^64 - 1, return INVALID
-3.  (H_1, ..., H_L) = H_Points
-4.  dom_array = (L, Q_1, H_1, ..., H_L)
-5.  dom_octs = serialize(dom_array) || ciphersuite_id
-6.  if dom_octs is INVALID, return INVALID
-7.  dom_input = PK || dom_octs || I2OSP(length(header), 8) || header
-8.  domain = hash_to_scalar(dom_input)
-9.  if domain is INVALID, return INVALID
-10. return domain
-
-
-

Note: If the header is not supplied in calculate_domain, it defaults to the empty octet string (""). This means that in the concatenation step of the above procedure (step 7), 8 bytes representing a length of 0 (i.e., 0x0000000000000000), will still need to be appended at the end, even though a header value is not provided.

-
-
-
-
-

-4.6. Challenge Calculation -

-

This operation calculates the challenge scalar value, used during ProofGen and ProofVerify, as part of the Fiat-Shamir heuristic, for making the proof protocol non-interactive (in a interactive sating, the challenge would be a random value supplied by the verifier).

-

This operation makes use of the serialize function, defined in Section 4.6.1.

-
-
challenge = calculate_challenge(Abar, Bbar, C, i_array,
-                                                  msg_array, domain, ph)
-
-Inputs:
-
-- (Abar, Bbar, C) (REQUIRED), points of G1, as calculated in
-                                    ProofGen.
-- i_array (REQUIRED), array of non-negative integers (the indexes of
-                      the disclosed messages).
-- msg_array (REQUIRED), array of scalars (the disclosed messages).
-- domain (REQUIRED), a scalar.
-- ph (OPTIONAL), an octet string. If not supplied, it must default to the
-                 empty octet string ("").
-
-Outputs:
-
-- challenge, a scalar or INVALID.
-
-Procedure:
-
-1.  R = length(i_array)
-2.  if R > 2^64 - 1 or R != length(msg_array), return INVALID
-3.  if length(ph) > 2^64 - 1, return INVALID
-4.  (i1, ..., iR) = i_array
-5.  (msg_i1, ..., msg_iR) = msg_array
-6.  c_array = (Abar, Bbar, C, R, i1, ..., iR,
-                                   msg_i1, ..., msg_iR, domain)
-7.  c_octs = serialize(c_array)
-8.  if c_octs is INVALID, return INVALID
-9.  c_input = c_octs || I2OSP(length(ph), 8) || ph
-10. challenge = hash_to_scalar(c_input)
-11. if challenge is INVALID, return INVALID
-12. return challenge
-
-
-

Note: Similarly to the header value in Domain Calculation, if the presentation header (ph) is not supplied in calculate_challenge, 8 bytes representing a length of 0 (i.e., 0x0000000000000000), must still be appended after the c_octs value, during the concatenation step of the above procedure (step 9).

-
-
-
-
-

-4.7. Serialization -

-
-
-

-4.7.1. Serialize -

-

This operation describes how to transform multiple elements of different types (i.e., elements that are not already in a octet string format) to a single octet string (see Section 3.2.4). The inputted elements can be points, scalars (see Terminology) or integers between 0 and 2^64-1. The resulting octet string will then either be used as an input to a hash function (i.e., in Sign, ProofGen etc.), or to serialize a signature or proof (see SignatureToOctets and ProofToOctets).

-
-
octets_result = serialize(input_array)
-
-Inputs:
-
-- input_array (REQUIRED), an array of elements to be serialized. Each
-                          element must be either a point of G1 or G2, a
-                          scalar, an ASCII string or an integer value
-                          between 0 and 2^64 - 1.
-
-Parameters:
-
-- octet_scalar_length, non-negative integer. The length of a scalar
-                       octet representation, defined by the ciphersuite.
-- r, the prime order of the subgroups G1 and G2, defined by the
-     ciphersuite.
-- point_to_octets_g*, operations that serialize a point of G1 or G2 to
-                      an octet string of fixed length, defined by the
-                      ciphersuite.
-
-Outputs:
-
-- octets_result, a scalar value or INVALID.
-
-Procedure:
-
-1.  let octets_result be an empty octet string.
-2.  for el in input_array:
-3.      if el is a point of G1: el_octs = point_to_octets_g1(el)
-4.      else if el is a point of G2: el_octs = point_to_octets_g2(el)
-5.      else if el is a scalar: el_octs = I2OSP(el, octet_scalar_length)
-6.      else if el is an integer between 0 and 2^64 - 1:
-7.          el_octs = I2OSP(el, 8)
-8.      else: return INVALID
-9.      octets_result = octets_result || el_octs
-10. return octets_result
-
-
-
-
-
-
-

-4.7.2. Signature to Octets -

-

This operation describes how to encode a signature to an octet string.

-

Note this operation deliberately does not perform the relevant checks on the inputs A and e -because its assumed these are done prior to its invocation, e.g as is the case with the Sign operation.

-
-
signature_octets = signature_to_octets(signature)
-
-Inputs:
-
-- signature (REQUIRED), a valid signature, in the form (A, e), where
-                        A is a point in G1 and e is a non-zero scalar mod r.
-
-Outputs:
-
-- signature_octets, an octet string or INVALID.
-
-Procedure:
-
-1. (A, e) = signature
-2. return serialize((A, e))
-
-
-
-
-
-
-

-4.7.3. Octets to Signature -

-

This operation describes how to decode an octet string, validate it and return the underlying components that make up the signature.

-
-
signature = octets_to_signature(signature_octets)
-
-Inputs:
-
-- signature_octets (REQUIRED), an octet string of the form output from
-                               signature_to_octets operation.
-
-Outputs:
-
-signature, a signature in the form (A, e), where A is a point in G1
-           and e is a non-zero scalar mod r.
-
-Procedure:
-
-1.  expected_len = octet_point_length + octet_scalar_length
-2.  if length(signature_octets) != expected_len, return INVALID
-3.  A_octets = signature_octets[0..(octet_point_length - 1)]
-4.  A = octets_to_point_g1(A_octets)
-5.  if A is INVALID, return INVALID
-6.  if A == Identity_G1, return INVALID
-7.  index = octet_point_length
-8.  end_index = index + octet_scalar_length - 1
-9.  e = OS2IP(signature_octets[index..end_index])
-10. if e = 0 OR e >= r, return INVALID
-11. return (A, e)
-
-
-
-
-
-
-

-4.7.4. Proof to Octets -

-

This operation describes how to encode a proof, as computed at step 25 in ProofGen, to an octet string. The input to the operation MUST be a valid proof.

-

The inputted proof value must consist of the following components, in that order:

-
    -
  1. Two (2) valid points of the G1 subgroup, different from the identity point of G1 (i.e., Abar, Bbar, in ProofGen) -
  2. -
  3. Three (3) integers representing scalars in the range of 1 to r-1 inclusive (i.e., c, r2^, r3^, in ProofGen). -
  4. -
  5. A number of integers representing scalars in the range of 1 to r-1 inclusive, corresponding to the undisclosed from the proof messages (i.e., m^_j1, ..., m^_jU, in ProofGen, where U the number of undisclosed messages). -
  6. -
-
-
proof_octets = proof_to_octets(proof)
-
-Inputs:
-
-- proof (REQUIRED), a BBS proof in the form calculated by ProofGen in
-                    step 27 (see above).
-
-Parameters:
-
-- octet_scalar_length (REQUIRED), non-negative integer. The length of
-                                  a scalar octet representation, defined
-                                  by the ciphersuite.
-
-Outputs:
-
-- proof_octets, an octet string or INVALID.
-
-Procedure:
-
-1. (Abar, Bbar, r2^, r3^, (m^_1, ..., m^_U), c) = proof
-2. return serialize((Abar, Bbar, r2^, r3^, m^_1, ..., m^_U), c)
-
-
-
-
-
-
-

-4.7.5. Octets to Proof -

-

This operation describes how to decode an octet string representing a proof, validate it and return the underlying components that make up the proof value.

-

The proof value outputted by this operation consists of the following components, in that order:

-
    -
  1. Two (2) valid points of the G1 subgroup, each of which must not equal the identity point. -
  2. -
  3. Three (3) integers representing scalars in the range of 1 to r-1 inclusive. -
  4. -
  5. A set of integers representing scalars in the range of 1 to r-1 inclusive, corresponding to the undisclosed from the proof message commitments. This set can be empty (i.e., "()"). -
  6. -
-
-
proof = octets_to_proof(proof_octets)
-
-Inputs:
-
-- proof_octets (REQUIRED), an octet string of the form outputted from the
-                           proof_to_octets operation.
-
-Parameters:
-
-- r (REQUIRED), non-negative integer. The prime order of the G1 and
-                G2 groups, defined by the ciphersuite.
-- octet_scalar_length (REQUIRED), non-negative integer. The length of
-                                  a scalar octet representation, defined
-                                  by the ciphersuite.
-- octet_point_length (REQUIRED), non-negative integer. The length of
-                                 a point in G1 octet representation,
-                                 defined by the ciphersuite.
-
-Outputs:
-
-- proof, a proof value in the form described above or INVALID
-
-Procedure:
-
-1.  proof_len_floor = 2 * octet_point_length + 3 * octet_scalar_length
-2.  if length(proof_octets) < proof_len_floor, return INVALID
-
-// Points (i.e., (Abar, Bbar) in ProofGen) de-serialization.
-3.  index = 0
-4.  for i in range(0, 1):
-5.      end_index = index + octet_point_length - 1
-6.      A_i = octets_to_point_g1(proof_octets[index..end_index])
-7.      if A_i is INVALID or Identity_G1, return INVALID
-8.      index += octet_point_length
-
-// Scalars (i.e., (r2^, r3^, (m^_j1, ..., m^_jU), c) in
-// ProofGen) de-serialization.
-9.  j = 0
-10. while index < length(proof_octets):
-11.     end_index = index + octet_scalar_length - 1
-12.     s_j = OS2IP(proof_octets[index..end_index])
-13.     if s_j = 0 or if s_j >= r, return INVALID
-14.     index += octet_scalar_length
-15.     j += 1
-
-16. if index != length(proof_octets), return INVALID
-17. msg_commitments = ()
-18. If j > 3, set msg_commitments = (s_2, ..., s_(j-2))
-19. return (A_0, A_1, s_0, s_1, msg_commitments, s_(j-1))
-
-
-
-
-
-
-

-4.7.6. Octets to Public Key -

-

This operation describes how to decode an octet string representing a public key, validates it and returns the corresponding point in G2. Steps 2 to 5 check if the public key is valid. As an optimization, implementations MAY cache the result of those steps, to avoid unnecessarily repeating validation for known public keys.

-
-
W = octets_to_pubkey(PK)
-
-Inputs:
-
-- PK, an octet string. A public key in the form outputted by the SkToPK
-      operation
-
-Outputs:
-
-- W, a valid point in G2 or INVALID
-
-Procedure:
-
-1. W = octets_to_point_g2(PK)
-2. If W is INVALID, return INVALID
-3. if subgroup_check(W) is INVALID, return INVALID
-4. If W == Identity_G2, return INVALID
-5. return W
-
-
-
-
-
-
-
-
-
-
-

-5. Security Considerations -

-
-
-

-5.1. Validating Public Keys -

-

It is RECOMENDED for any operation in Core Operations involving public keys, that they deserialize the public key first using the OctetsToPublicKey operation, even if they only require the octet-string representation of the public key. If the octets_to_pubkey procedure (see the OctetsToPublicKey section) returns INVALID, the calling operation should also return INVALID and abort. An example of where this recommendation applies is the Sign operation. An example of where an explicit invocation to the octets_to_pubkey operation is already defined and therefore required is the Verify operation.

-
-
-
-
-

-5.2. Point Deserialization -

-

This document makes use of octet_to_point_g* to parse octet strings to elliptic curve points (either in G1 or G2). It is assumed (even if not explicitly described) that the result of this operation will not be INVALID. If octet_to_point_g* returns INVALID, then the calling operation should immediately return INVALID as well and abort the operation. Note that the only place where the output is assumed to be VALID implicitly is in the EncodingForHash section.

-
-
-
-
-

-5.3. Skipping Membership Checks -

-

Some existing implementations skip the subgroup_check invocation in Verify, whose purpose is ensuring that the signature is an element of a prime-order subgroup. This check is REQUIRED of conforming implementations, for two reasons.

-
    -
  1. -

    For most pairing-friendly elliptic curves used in practice, the pairing operation e Section 1.2 is undefined when its input points are not in the prime-order subgroups of E1 and E2. The resulting behavior is unpredictable, and may enable forgeries.

    -
  2. -
  3. -

    Even if the pairing operation behaves properly on inputs that are outside the correct subgroups, skipping the subgroup check breaks the strong unforgeability property [ADR02].

    -
  4. -
-
-
-
-
-

-5.4. Side Channel Attacks -

-

Implementations of the signing algorithm SHOULD protect the secret key from side-channel attacks. One method for protecting against certain side-channel attacks is ensuring that the implementation executes exactly the same sequence of instructions and performs exactly the same memory accesses, for any value of the secret key. In other words, implementations on the underlying pairing-friendly elliptic curve SHOULD run in constant time.

-
-
-
-
-

-5.5. Randomness Considerations -

-

The IKM input to KeyGen MUST be infeasible to guess and MUST be kept secret. One possibility is to generate IKM from a trusted source of randomness. Guidelines on constructing such a source are outside the scope of this document.

-

Secret keys MAY be generated using other methods; in this case they MUST be infeasible to guess and MUST be indistinguishable from uniformly random modulo r.

-

BBS proofs are nondeterministic, meaning care must be taken against attacks arising from using bad randomness, for example, the nonce reuse attack on ECDSA [HDWH12]. It is RECOMMENDED that the presentation header used in this specification contain a nonce chosen at random from a trusted source of randomness, see the Section 5.6 for additional considerations.

-

When a trusted source of randomness is used, signatures and proofs are much harder to forge or break due to the use of multiple nonces.

-
-
-
-
-

-5.6. Presentation Header Selection -

-

The signature proofs of knowledge generated in this specification are created using a specified presentation header. A verifier-specified cryptographically random value (e.g., a nonce) featuring in the presentation header provides strong protections against replay attacks, and is RECOMMENDED in most use cases. In some settings, proofs can be generated in a non-interactive fashion, in which case verifiers MUST be able to verify the uniqueness of the presentation header values.

-
-
-
-
-

-5.7. Implementing hash_to_curve_g1 -

-

The security analysis models hash_to_curve_g1 as random oracles. It is crucial that these functions are implemented using a cryptographically secure hash function. For this purpose, implementations MUST meet the requirements of [I-D.irtf-cfrg-hash-to-curve].

-

In addition, ciphersuites MUST specify unique domain separation tags for hash_to_curve. Some guidance around defining this can be found in Section 6.

-
-
-
-
-

-5.8. Choice of Underlying Curve -

-

BBS signatures can be implemented on any pairing-friendly curve. However care MUST be taken when selecting one that is appropriate, this specification defines a ciphersuite for using the BLS12-381 curve in Section 6 which as a curve achieves around 117 bits of security according to a recent NCC ZCash cryptography review [ZCASH-REVIEW].

-
-
-
-
-

-5.9. ProofGen Security -

-

The proof, as returned by ProofGen, is a zero-knowledge proof-of-knowledge [CDL16]. This guarantees that no information will be revealed about the signature itself or the undisclosed messages, from the output of ProofGen. Note that the security proofs in [CDL16] work on type 3 pairing setting. This means that G1 should be different from G2 and with no efficient isomorphism between them.

-
-
-
-
-

-5.10. Randomness Requirements -

-

ProofGen is by its nature a randomized algorithm, requiring the generation of multiple uniformly distributed, pseudo random scalars. This makes ProofGen vulnerable to bad entropy in certain applications. As an example of such application, consider systems that need to monitor and potentially restrict outbound traffic, in order to minimize data leakage during a breach. In such cases, the attacker could manipulate couple of bits in the output of the get_random function to create an undetected chanel out of the system. Although the applicability of such attacks is limited for most of the targeted use cases of the BBS scheme, some applications may want to take measures towards mitigating them. To that end, it is RECOMMENDED to use a deterministic RNG (like a ChaCha20 based deterministic RNG), seeded with a unique, uniformly random, single seed [DRBG]. This will limit the amount of bits the attacker can manipulate (note that some randomness is always needed).

-

In any case, the randomness used in ProofGen MUST be unique in each call and MUST have a distribution that is indistinguishable from uniform. If the random scalars are re-used, are created from "bad randomness" (for example with a known relationship to each other) or are in any way predictable, an adversary will be able to unveil the undisclosed from the proof messages or the hidden signature value. Naturally, a cryptographically secure pseudorandom number generator or pseudo random function is REQUIRED to implement the get_random functionality. See also [RFC8937], for recommendations on generating good randomness in cases where the Prover has direct or in-direct access to a secret key.

-
-
-
-
-
-
-

-6. Ciphersuites -

-

This section defines the format for a BBS ciphersuite. It also gives concrete ciphersuites based on the BLS12-381 pairing-friendly elliptic curve [I-D.irtf-cfrg-pairing-friendly-curves].

-
-
-

-6.1. Ciphersuite Format -

-
-
-

-6.1.1. Ciphersuite ID -

-

The following section defines the format of the unique identifier for the ciphersuite denoted ciphersuite_id, which will be represented as an ASCII encoded octet string. The REQUIRED format for this string is

-
-
  "BBS_" || H2C_SUITE_ID || CG_ID || ADD_INFO
-
-
-
    -
  • -

    H2C_SUITE_ID is the suite ID of the hash-to-curve suite used to define the hash_to_curve function.

    -
  • -
  • -

    CG_ID is the ID of the create generators used, i.e., CREATE_GENERATORS_ID as defined in the Section 4.2 section.

    -
  • -
  • -

    ADD_INFO is an optional octet string indicating any additional information used to uniquely qualify the ciphersuite. When present this value MUST only contain ASCII encoded characters with codes between 0x21 and 0x7e (inclusive) and MUST end with an underscore (ASCII code: 0x5f), other than the last character the string MUST not contain any other underscores (ASCII code: 0x5f).

    -
  • -
-
-
-
-
-

-6.1.2. Additional Parameters -

-

The parameters that each ciphersuite needs to define are generally divided into three main categories; the basic parameters (a hash function etc.,), the serialization operations (point_to_octets_g1 etc.,) and the generator parameters. See below for more details.

-

Basic parameters:

-
    -
  • -

    hash: a cryptographic hash function.

    -
  • -
  • -

    octet_scalar_length: Number of bytes to represent a scalar value, in the multiplicative group of integers mod r, encoded as an octet string. It is RECOMMENDED this value be set to ceil(log2(r)/8).

    -
  • -
  • -

    octet_point_length: Number of bytes to represent a point encoded as an octet string outputted by the point_to_octets_g* function. It is RECOMMENDED that this value is set to ceil(log2(p)/8).

    -
  • -
  • -

    hash_to_curve_suite: The hash-to-curve ciphersuite id, in the form defined in [I-D.irtf-cfrg-hash-to-curve]. This defines the hash_to_curve_g1 (the hash_to_curve operation for the G1 subgroup, see the Notation section) and the expand_message (either expand_message_xmd or expand_message_xof) operations used in this document.

    -
  • -
  • -

    P1: A fixed point in the G1 subgroup.

    -
  • -
-

Serialization functions:

-
    -
  • -

    point_to_octets_g1: -a function that returns the canonical representation of the point P for the G1 subgroup as an octet string.

    -
  • -
  • -

    point_to_octets_g2: -a function that returns the canonical representation of the point P for the G2 subgroup as an octet string.

    -
  • -
  • -

    octets_to_point_g1: -a function that returns the point P in the subgroup G1 corresponding to the canonical representation ostr, or INVALID if ostr is not a valid output of point_to_octets_g1.

    -
  • -
  • -

    octets_to_point_g2: -a function that returns the point P in the subgroup G2 corresponding to the canonical representation ostr, or INVALID if ostr is not a valid output of point_to_octets_g2.

    -
  • -
-

Generator parameters:

-
    -
  • create_generators: the operation with which to create a set of generators. See Section 4.2. -
  • -
-
-
-
-
-
-
-

-6.2. BLS12-381 Ciphersuites -

-

The following two ciphersuites are based on the BLS12-381 elliptic curves defined in Section 4.2.1 of [I-D.irtf-cfrg-pairing-friendly-curves]. The targeted security level of both suites in bits is k = 128.

-

The first ciphersuite makes use of an extendable output function, and most specifically of SHAKE-256, as defined in Section 6.2 of [SHA3]. It also uses the hash-to-curve suite defined by this document in Appendix A.1, which also makes use of the SHAKE-256 function.

-

The second ciphersuite uses SHA-256, as defined in Section 6.2 of [SHA2] and the BLS12-381 G1 hash-to-curve suite defined in Section 8.8.1 of the [I-D.irtf-cfrg-hash-to-curve] document.

-

Note that these two ciphersuites differ only in the hash function (SHAKE-256 vs SHA-256) and in the hash-to-curve suites used. The hash-to-curve suites differ in the expand_message variant and underlying hash function. More concretely, the BLS12-381-SHAKE-256 ciphersuite makes use of expand_message_xof with SHAKE-256, while BLS12-381-SHA-256 makes use of expand_message_xmd with SHA-256. Curve parameters are common between the two ciphersuites.

-
-
-

-6.2.1. BLS12-381-SHAKE-256 -

-

Basic parameters:

-
    -
  • -

    ciphersuite_id: "BBS_BLS12381G1_XOF:SHAKE-256_SSWU_RO_H2G_"

    -
  • -
  • -

    hash: SHAKE-256 as defined in [SHA3].

    -
  • -
  • -

    octet_scalar_length: 32, based on the RECOMMENDED approach of ceil(log2(r)/8).

    -
  • -
  • -

    octet_point_length: 48, based on the RECOMMENDED approach of ceil(log2(p)/8).

    -
  • -
  • -

    hash_to_curve_suite: "BLS12381G1_XOF:SHAKE-256_SSWU_RO_" as defined in Appendix A.1 for the G1 subgroup.

    -
  • -
  • -

    P1: The G1 point returned from the hash_to_generators procedure (Section 4.2.1), with count = 1 and generator_seed = ciphersuite_id || "BP_MESSAGE_GENERATOR_SEED". More specifically,

    -
    -
    P1 = {{ $generatorFixtures.bls12-381-shake-256.generators.BP }}
    -
    -
    -
  • -
-

Serialization functions:

- -

Generator parameters:

-
    -
  • -

    create_generators: the operation is using hash_to_generators as defined in Section 4.2.1, with generator_seed = ciphersuite_id || "MESSAGE_GENERATOR_SEED" and the expand_message and hash_to_curve_g1 defined by the hash_to_curve_suite,

    -
    -
    create_generators(count, PK) := hash_to_generators(count)
    -
    -
    -
  • -
-
-
-
-
-

-6.2.2. BLS12-381-SHA-256 -

-

Basic parameters:

-
    -
  • -

    Ciphersuite_ID: "BBS_BLS12381G1_XMD:SHA-256_SSWU_RO_H2G_"

    -
  • -
  • -

    hash: SHA-256 as defined in [SHA2].

    -
  • -
  • -

    octet_scalar_length: 32, based on the RECOMMENDED approach of ceil(log2(r)/8).

    -
  • -
  • -

    octet_point_length: 48, based on the RECOMMENDED approach of ceil(log2(p)/8).

    -
  • -
  • -

    hash_to_curve_suite: "BLS12381G1_XMD:SHA-256_SSWU_RO_" as defined in Section 8.8.1 of the [I-D.irtf-cfrg-hash-to-curve] for the G1 subgroup.

    -
  • -
  • -

    P1: The G1 point returned from the hash_to_generators procedure, with count = 1 and generator_seed = ciphersuite_id || "BP_MESSAGE_GENERATOR_SEED". More specifically,

    -
    -
    P1 = {{ $generatorFixtures.bls12-381-sha-256.generators.BP }}
    -
    -
    -
  • -
-

Serialization functions:

- -

Generator parameters:

-
    -
  • -

    create_generators: the operation is using hash_to_generators as defined in Section 4.2.1, with generator_seed = ciphersuite_id || "MESSAGE_GENERATOR_SEED" and the expand_message and hash_to_curve_g1 defined by the hash_to_curve_suite,

    -
    -
    create_generators(count, PK) := hash_to_generators(count)
    -
    -
    -
  • -
-
-
-
-
-
-
-
-
-

-7. Test Vectors -

-

The following section details a basic set of test vectors that can be used to confirm an implementations correctness

-

NOTE All binary data below is represented as octet strings in big endian order, encoded in hexadecimal format.

-

NOTE These fixtures are a work in progress and subject to change.

-
-
-

-7.1. Mocked Random Scalars -

-

For the purpose of presenting fixtures for the ProofGen operation we describe here a way to mock the calculate_random_scalars operation (Random scalars computation), used by ProofGen to create all the necessary random scalars.

-

To that end, the seeded_random_scalars(SEED) operation is defined, which will deterministically calculate count random-looking scalars from a single SEED. The proof test vector will then define a SEED (as a nothing-up-my-sleeve value) and set

-
-
mocked_calculate_random_scalars(count) :=
-                             seeded_random_scalars(SEED, count)
-
-
-

The mocked_calculate_random_scalars operation will then be used in place of calculate_random_scalars during the ProofGen operation's procedure.

-

Note For the BLS12-381-SHA-256 ciphersuite if more than 170 mocked random scalars are required, the operation will return INVALID. Similarly, for the BLS12-381-SHAKE-256 ciphersuite, if more than 1365 mocked random scalars are required, the operation will return INVALID. For the purpose of describing ProofGen test vectors, those limits are inconsequential.

-
-
seeded_scalars = seeded_random_scalars(SEED, count)
-
-Inputs:
-
-- count (REQUIRED), non negative integer. The number of scalars to
-                    return.
-- SEED (REQUIRED), an octet string. The random seed from which to generate
-                   the scalars.
-
-Parameters:
-
-- expand_message, the expand_message operation defined by the
-                  ciphersuite.
-- expand_len = ceil((ceil(log2(r))+k)/8), where r and k are defined by
-                                          the ciphersuite.
-- dst = ciphersuite_id || "MOCK_RANDOM_SCALARS_DST_", where
-        ciphersuite_id is defined by the ciphersuite.
-
-Outputs:
-
-- mocked_random_scalars, a list of "count" pseudo random scalars
-
-Preconditions:
-
-1. if count * expand_len > 65535, return INVALID
-
-Procedure:
-
-1. out_len = expand_len * count
-2. v = expand_message(SEED, dst, out_len)
-3. if v is INVALID, return INVALID
-
-4. for i in (1, ..., count):
-5.     start_idx = (i-1) * expand_len
-6.     end_idx = i * expand_len - 1
-7.     r_i = OS2IP(v[start_idx..end_idx]) mod r
-8. return (r_1, ...., r_count)
-
-
-
-
-
-
-

-7.2. Messages -

-

The following messages are used by the test vectors of both ciphersuites (unless otherwise stated).

-
-
{{ $messages[0] }}
-
-{{ $messages[1] }}
-
-{{ $messages[2] }}
-
-{{ $messages[3] }}
-
-{{ $messages[4] }}
-
-{{ $messages[5] }}
-
-{{ $messages[6] }}
-
-{{ $messages[7] }}
-
-{{ $messages[8] }}
-
-{{ $messages[9] }}
-
-
-
-
-
-
-

-7.3. BLS12-381-SHAKE-256 Test Vectors -

-

Test vectors of the BLS12-381-SHAKE-256 ciphersuite. Further fixtures are available in additional BLS12-381-SHAKE-256 test vectors.

-
-
-

-7.3.1. Key Pair -

-

The following key pair will be used for the test vectors of the BLS12-381-SHAKE-256 ciphersuite.

-

Following the procedure defined in Section 3.3.1 with an input key_material value as follows

-
-
{{ $KeyPairFixtures.bls12-381-shake-256.keypair.keyMaterial }}
-
-
-

and the following key_info value

-
-
{{ $KeyPairFixtures.bls12-381-shake-256.keypair.keyInfo }}
-
-
-

Outputs the following SK value

-
-
{{ $KeyPairFixtures.bls12-381-shake-256.keypair.keyPair.secretKey }}
-
-
-

Following the procedure defined in Section 3.3.2 with an input SK value as above produces the following PK value

-
-
{{ $KeyPairFixtures.bls12-381-shake-256.keypair.keyPair.publicKey }}
-
-
-
-
-
-
-

-7.3.2. Map Messages to Scalars -

-

The messages in Section 7.2 must be mapped to scalars before passed to the Sign, Verify, ProofGen and ProofVerify operations. For the purpose of the test vectors presented in this document we are using the MapMessageToScalarAsHash operation to map each message to a scalar. For the BLS12-381-SHAKE-256 ciphersuite, on input each message in Section 7.2 and the following default dst

-
-
{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.dst }}
-
-
-

The output scalars, encoded to octets using I2OSP and represented in big endian order, are the following,

-
-
{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[0].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[1].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[2].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[3].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[4].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[5].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[6].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[7].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[8].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-shake-256.MapMessageToScalarAsHash.cases[9].scalar }}
-
-
-

Note that in both the following test vectors, as well as the additional BLS12-381-SHAKE-256 test vectors in Appendix C.1, when we are referring to a message that will be passed to one of the Sign, Verify, ProofGen or ProofVerify operations, we assume that it will first be mapped into one of the above scalars, using the MapMessageToScalarAsHash operation.

-
-
-
-
-

-7.3.3. Message Generators -

-

Following the procedure defined in Section 4.2 with an input count value of 11, for the BLS12-381-SHAKE-256 suite, outputs the following values (note that the first one corresponds to Q_1, while the next 10, to the message generators H_1, ..., H_10).

-
-
{{ $generatorFixtures.bls12-381-shake-256.generators.Q1 }}
-
-{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[0] }}
-
-{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[1] }}
-
-{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[2] }}
-
-{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[3] }}
-
-{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[4] }}
-
-{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[5] }}
-
-{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[6] }}
-
-{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[7] }}
-
-{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[8] }}
-
-{{ $generatorFixtures.bls12-381-shake-256.generators.MsgGenerators[9] }}
-
-
-
-
-
-
-

-7.3.4. Signature Fixtures -

-
-
-
-7.3.4.1. Valid Single Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature001.header }}
-
-
-

And the following message (the first message defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature001.messages[0] }}
-
-
-

After it is mapped to the first scalar in Section 7.3.2, along with the SK value as defined in Section 7.3.1 as inputs into the Sign operations, yields the following output signature

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature001.signature }}
-
-
-
-
-
-
-
-7.3.4.2. Valid Multi-Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature004.header }}
-
-
-

And the messages defined in Section 7.2 (Note the ordering of the messages MUST be preserved), after they are mapped to the scalars in Section 7.3.2, along with the SK value as defined in Section 7.3.1 as inputs into the Sign operations, yields the following output signature

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature004.signature }}
-
-
-
-
-
-
-
-
-

-7.3.5. Proof Fixtures -

-

For the generation of the following fixtures the mocked_calculate_random_scalars defined in Mocked Random Scalars is used, in place of the calculate_random_scalars operation, with the following seed value (hex encoding of the ASCII-encoded 30 first digits of pi)

-
-
SEED = "332e313431353932363533353839373933323338343632363433333833323739"
-
-
-

Given the above seed the first 10 scalars returned by the mocked_calculate_random_scalars operation will be,

-
-
{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[0] }}
-{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[1] }}
-{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[2] }}
-{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[3] }}
-{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[4] }}
-{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[5] }}
-{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[6] }}
-{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[7] }}
-{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[8] }}
-{{ $MockRngFixtures.bls12-381-shake-256.mockedRng.mockedScalars[9] }}
-
-
-
-
-
-7.3.5.1. Valid Single Message Proof -
-

Using the header, message and signature used in Valid Single Message Signature to create a proof disclosing the message, with the following presentation header

-
-
{{ $proofFixtures.bls12-381-shake-256.proof001.presentationHeader }}
-
-
-

will result to the following proof value

-
-
{{ $proofFixtures.bls12-381-shake-256.proof001.proof }}
-
-
-
-
-
-
-
-7.3.5.2. Valid Multi-Message, All Messages Disclosed Proof -
-

Using the header, messages and signature used in Valid Multi Message Signature to create a proof disclosing all the messages, with the following presentation header

-
-
{{ $proofFixtures.bls12-381-shake-256.proof002.presentationHeader }}
-
-
-

will result to the following proof value

-
-
{{ $proofFixtures.bls12-381-shake-256.proof002.proof }}
-
-
-
-
-
-
-
-7.3.5.3. Valid Multi-Message, Half of Messages Disclosed Proof -
-

Using the same header, messages and signature as in Multi-Message, All Messages Disclosed Proof but this time with only every other messages disclosed (messages in index 0, 2, 4 and 6, in that order), with the following presentation header

-
-
{{ $proofFixtures.bls12-381-shake-256.proof003.presentationHeader }}
-
-
-

will result to the following proof value

-
-
{{ $proofFixtures.bls12-381-shake-256.proof003.proof }}
-
-
-
-
-
-
-
-
-
-
-

-7.4. BLS12381-SHA-256 Test Vectors -

-

Test vectors of the BLS12-381-SHA-256 ciphersuite. Further fixtures are available in additional BLS12-381-SHA-256 test vectors.

-
-
-

-7.4.1. Key Pair -

-

The following key pair will be used for the test vectors of the BLS12-381-SHA-256 ciphersuite.

-

Following the procedure defined in Section 3.3.1 with an input key_material value as follows

-
-
{{ $KeyPairFixtures.bls12-381-sha-256.keypair.keyMaterial }}
-
-
-

and the following key_info value

-
-
{{ $KeyPairFixtures.bls12-381-sha-256.keypair.keyInfo }}
-
-
-

Outputs the following SK value

-
-
{{ $KeyPairFixtures.bls12-381-sha-256.keypair.keyPair.secretKey }}
-
-
-

Following the procedure defined in Section 3.3.2 with an input SK value as above produces the following PK value

-
-
{{ $KeyPairFixtures.bls12-381-sha-256.keypair.keyPair.publicKey }}
-
-
-
-
-
-
-

-7.4.2. Map Messages to Scalars -

-

Similarly to how messages are mapped to scalars in BLS12381-SHAKE-256 Test Vectors, we are using the MapMessageToScalarAsHash operation to map each message to a scalar. For the BLS12-381-SHA-256 ciphersuite, on input each message in Section 7.2 and the following default dst

-
-
{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.dst }}
-
-
-

The output scalars, encoded to octets using I2OSP and represented in big endian order, are the following,

-
-
{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[0].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[1].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[2].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[3].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[4].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[5].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[6].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[7].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[8].scalar }}
-
-{{ $MapMessageToScalarFixtures.bls12-381-sha-256.MapMessageToScalarAsHash.cases[9].scalar }}
-
-
-

Note that in both the following test vectors, as well as the additional BLS12-381-SHA-256 test vectors in Appendix C.2, when we are referring to a message that will be passed to one of the Sign, Verify, ProofGen or ProofVerify operations, we assume that it will first be mapped into one of the above scalars, using the MapMessageToScalarAsHash operation.

-
-
-
-
-

-7.4.3. Message Generators -

-

Following the procedure defined in Section 4.2 with an input count value of 11, for the BLS12-381-SHA-256 suite, outputs the following values (note that the first one corresponds to Q_1, while the next 10, to the message generators H_1, ..., H_10).

-
-
{{ $generatorFixtures.bls12-381-sha-256.generators.Q1 }}
-
-{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[0] }}
-
-{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[1] }}
-
-{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[2] }}
-
-{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[3] }}
-
-{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[4] }}
-
-{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[5] }}
-
-{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[6] }}
-
-{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[7] }}
-
-{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[8] }}
-
-{{ $generatorFixtures.bls12-381-sha-256.generators.MsgGenerators[9] }}
-
-
-
-
-
-
-

-7.4.4. Signature Fixtures -

-
-
-
-7.4.4.1. Valid Single Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature001.header }}
-
-
-

And the following message (the first message defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature001.messages[0] }}
-
-
-

After it is mapped to the first scalar in Section 7.4.2, along with the SK value as defined in Section 7.4.1 as inputs into the Sign operations, yields the following output signature

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature001.signature }}
-
-
-
-
-
-
-
-7.4.4.2. Valid Multi-Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature004.header }}
-
-
-

And the messages defined in Section 7.2 (Note the ordering of the messages MUST be preserved), after they are mapped to the scalars in Section 7.4.2, along with the SK value as defined in Section 7.4.1 as inputs into the Sign operations, yields the following output signature

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature004.signature }}
-
-
-
-
-
-
-
-
-

-7.4.5. Proof Fixtures -

-

Similarly to the proof fixtures for the BLS12381-SHA-256 ciphersuite, the generation of the following fixtures uses the mocked_calculate_random_scalars defined in Mocked Random Scalars, in place of the calculate_random_scalars operation, with the following seed value (hex encoding of the ASCII-encoded 30 first digits of pi).

-
-
SEED = "332e313431353932363533353839373933323338343632363433333833323739"
-
-
-
-

Given the above seed the first 10 scalars returned by the mocked_calculate_random_scalars operation will be,

-
-
{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[0] }}
-{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[1] }}
-{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[2] }}
-{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[3] }}
-{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[4] }}
-{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[5] }}
-{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[6] }}
-{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[7] }}
-{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[8] }}
-{{ $MockRngFixtures.bls12-381-sha-256.mockedRng.mockedScalars[9] }}
-
-
-
-
-
-7.4.5.1. Valid Single Message Proof -
-

Using the header, message and signature used in Valid Single Message Signature to create a proof disclosing the message, with the following presentation header

-
-
{{ $proofFixtures.bls12-381-sha-256.proof001.presentationHeader }}
-
-
-

will result to the following proof value

-
-
{{ $proofFixtures.bls12-381-sha-256.proof001.proof }}
-
-
-
-
-
-
-
-7.4.5.2. Valid Multi-Message, All Messages Disclosed Proof -
-

Using the header, messages and signature used in Valid Multi Message Signature to create a proof disclosing all the messages, with the following presentation header

-
-
{{ $proofFixtures.bls12-381-sha-256.proof002.presentationHeader }}
-
-
-

will result to the following proof value

-
-
{{ $proofFixtures.bls12-381-sha-256.proof002.proof }}
-
-
-
-
-
-
-
-7.4.5.3. Valid Multi-Message, Half of Messages Disclosed Proof -
-

Using the same header, messages and signature as in Multi-Message, All Messages Disclosed Proof but this time with only every other messages disclosed (messages in index 0, 2, 4 and 6, in that order), with the following presentation header

-
-
{{ $proofFixtures.bls12-381-sha-256.proof003.presentationHeader }}
-
-
-

will result to the following proof value

-
-
{{ $proofFixtures.bls12-381-sha-256.proof003.proof }}
-
-
-
-
-
-
-
-
-
-
-
-
-

-8. IANA Considerations -

-

This document does not make any requests of IANA.

-
-
-
-
-

-9. Acknowledgements -

-

The authors would like to acknowledge the significant amount of academic work that preceeded the development of this document. In particular the original work of [BBS04] which was subsequently developed in [ASM06] and in [CDL16]. This last academic work is the one mostly used by this document.

-

The current state of this document is the product of the work of the Decentralized Identity Foundation Applied Cryptography Working group, which includes numerous active participants. In particular, the following individuals contributed ideas, feedback and wording that influenced this specification:

-

Orie Steele, Christian Paquin, Alessandro Guggino, Tomislav Markovski and Greg Bernstein.

-
-
-
-

-10. Normative References -

-
-
[DRBG]
-
-NIST, "Recommendation for Random Number Generation Using Deterministic Random Bit Generators", <https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf>.
-
-
[I-D.irtf-cfrg-hash-to-curve]
-
-Faz-Hernandez, A., Scott, S., Sullivan, N., Wahby, R. S., and C. A. Wood, "Hashing to Elliptic Curves", Work in Progress, Internet-Draft, draft-irtf-cfrg-hash-to-curve-16, , <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16>.
-
-
[I-D.irtf-cfrg-pairing-friendly-curves]
-
-Sakemi, Y., Kobayashi, T., Saito, T., and R. S. Wahby, "Pairing-Friendly Curves", Work in Progress, Internet-Draft, draft-irtf-cfrg-pairing-friendly-curves-11, , <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-pairing-friendly-curves-11>.
-
-
[RFC2119]
-
-Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
-
-
[RFC4086]
-
-Eastlake 3rd, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, DOI 10.17487/RFC4086, , <https://www.rfc-editor.org/info/rfc4086>.
-
-
[RFC8017]
-
-Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch, "PKCS #1: RSA Cryptography Specifications Version 2.2", RFC 8017, DOI 10.17487/RFC8017, , <https://www.rfc-editor.org/info/rfc8017>.
-
-
[RFC8937]
-
-Cremers, C., Garratt, L., Smyshlyaev, S., Sullivan, N., and C. Wood, "Randomness Improvements for Security Protocols", RFC 8937, DOI 10.17487/RFC8937, , <https://www.rfc-editor.org/info/rfc8937>.
-
-
[SHA2]
-
-NIST, "Secure Hash Standard (SHS)", <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf>.
-
-
[SHA3]
-
-NIST, "SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions", <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf>.
-
-
-
-
-

-11. Informative References -

-
-
[ADR02]
-
-An, J. H., Dodis, Y., and T. Rabin, "On the Security of Joint Signature and Encryption", In EUROCRYPT, pages 83-107, , <https://doi.org/10.1007/3-540-46035-7_6>.
-
-
[ASM06]
-
-Au, M. H., Susilo, W., and Y. Mu, "Constant-Size Dynamic k-TAA", In International Conference on Security and Cryptography for Networks, pages 111-125, Springer, Berlin, Heidelberg, , <https://link.springer.com/chapter/10.1007/11832072_8>.
-
-
[BBS04]
-
-Boneh, D., Boyen, X., and H. Shacham, "Short Group Signatures", In Advances in Cryptology, pages 41-55, , <https://link.springer.com/chapter/10.1007/978-3-540-28628-8_3>.
-
-
[Bowe19]
-
-Bowe, S., "Faster subgroup checks for BLS12-381", , <https://eprint.iacr.org/2019/814>.
-
-
[CDL16]
-
-Camenisch, J., Drijvers, M., and A. Lehmann, "Anonymous Attestation Using the Strong Diffie Hellman Assumption Revisited", In International Conference on Trust and Trustworthy Computing, pages 1-20, Springer, Cham, , <https://eprint.iacr.org/2016/663.pdf>.
-
-
[HDWH12]
-
-Heninger, N., Durumeric, Z., Wustrow, E., and J.A. Halderman, "Mining your Ps and Qs: Detection of widespread weak keys in network devices", In USENIX Security, pages 205-220, , <https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final228.pdf>.
-
-
[I-D.irtf-cfrg-bls-signature]
-
-Boneh, D., Gorbunov, S., Wahby, R. S., Wee, H., Wood, C. A., and Z. Zhang, "BLS Signatures", Work in Progress, Internet-Draft, draft-irtf-cfrg-bls-signature-05, , <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05>.
-
-
[ZCASH-REVIEW]
-
-NCC Group, "Zcash Overwinter Consensus and Sapling Cryptography Review", <https://research.nccgroup.com/wp-content/uploads/2020/07/NCC_Group_Zcash2018_Public_Report_2019-01-30_v1.3.pdf>.
-
-
-
-
-
-

-Appendix A. BLS12-381 hash_to_curve Definition Using SHAKE-256 -

-

The following defines a hash_to_curve suite [I-D.irtf-cfrg-hash-to-curve] for the BLS12-381 curve for both the G1 and G2 subgroups using the extendable output function (xof) of SHAKE-256 as per the guidance defined in section 8.9 of [I-D.irtf-cfrg-hash-to-curve].

-

Note the notation used in the below definitions is sourced from [I-D.irtf-cfrg-hash-to-curve].

-
-
-

-A.1. BLS12-381 G1 -

-

The suite of BLS12381G1_XOF:SHAKE-256_SSWU_RO_ is defined as follows:

-
-
* encoding type: hash_to_curve (Section 3 of
-                 [@!I-D.irtf-cfrg-hash-to-curve])
-
-* E: y^2 = x^3 + 4
-
-* p: 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f624
-     1eabfffeb153ffffb9feffffffffaaab
-
-* r: 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
-
-* m: 1
-
-* k: 128
-
-* expand_message: expand_message_xof (Section 5.3.2 of
-                  [@!I-D.irtf-cfrg-hash-to-curve])
-
-* hash: SHAKE-256
-
-* L: 64
-
-* f: Simplified SWU for AB == 0 (Section 6.6.3 of
-     [@!I-D.irtf-cfrg-hash-to-curve])
-
-* Z: 11
-
-*  E': y'^2 = x'^3 + A' * x' + B', where
-
-      -  A' = 0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aef
-                d881ac98936f8da0e0f97f5cf428082d584c1d
-
-      -  B' = 0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14f
-                cef35ef55a23215a316ceaa5d1cc48e98e172be0
-
-*  iso_map: the 11-isogeny map from E' to E given in Appendix E.2 of
-            [@!I-D.irtf-cfrg-hash-to-curve]
-
-*  h_eff: 0xd201000000010001
-
-
-

Note that the h_eff values for this suite are copied from that defined for the BLS12381G1_XMD:SHA-256_SSWU_RO_ suite defined in section 8.8.1 of [I-D.irtf-cfrg-hash-to-curve].

-

An optimized example implementation of the Simplified SWU mapping to the curve E' isogenous to BLS12-381 G1 is given in Appendix F.2 [I-D.irtf-cfrg-hash-to-curve].

-
-
-
-
-
-
-

-Appendix B. Use Cases -

-
-
-

-B.1. Non-correlating Security Token -

-

In the most general sense BBS signatures can be used in any application where a cryptographically secured token is required but correlation caused by usage of the token is un-desirable.

-

For example in protocols like OAuth2.0 the most commonly used form of the access token leverages the JWT format alongside conventional cryptographic primitives such as traditional digital signatures or HMACs. These access tokens are then used by a relying party to prove authority to a resource server during a request. However, because the access token is most commonly sent by value as it was issued by the authorization server (e.g in a bearer style scheme), the access token can act as a source of strong correlation for the relying party. Relevant prior art can be found here.

-

BBS Signatures due to their unique properties removes this source of correlation but maintains the same set of guarantees required by a resource server to validate an access token back to its relevant authority (note that an approach to signing JSON tokens with BBS that may be of relevance is the JWP format and serialization). In the context of a protocol like OAuth2.0 the access token issued by the authorization server would feature a BBS Signature, however instead of the relying party providing this access token as issued, in their request to a resource server, they generate a unique proof from the original access token and include that in the request instead, thus removing this vector of correlation.

-
-
-
-
-

-B.2. Improved Bearer Security Token -

-

Bearer based security tokens such as JWT based access tokens used in the OAuth2.0 protocol are a highly popular format for expressing authorization grants. However their usage has several security limitations. Notably a bearer based authorization scheme often has to rely on a secure transport between the authorized party (client) and the resource server to mitigate the potential for a MITM attack or a malicious interception of the access token. The scheme also has to assume a degree of trust in the resource server it is presenting an access token to, particularly when the access token grants more than just access to the target resource server, because in a bearer based authorization scheme, anyone who possesses the access token has authority to what it grants. Bearer based access tokens also suffer from the threat of replay attacks.

-

Improved schemes around authorization protocols often involve adding a layer of proof of cryptographic key possession to the presentation of an access token, which mitigates the deficiencies highlighted above as well as providing a way to detect a replay attack. However, approaches that involve proof of cryptographic key possession such as DPoP (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop-04) suffer from an increase in protocol complexity. A party requesting authorization must pre-generate appropriate key material, share the public portion of this with the authorization server alongside proving possession of the private portion of the key material. The authorization server must also be-able to accommodate receiving this information and validating it.

-

BBS Signatures ofter an alternative model that solves the same problems that proof of cryptographic key possession schemes do for bearer based schemes, but in a way that doesn't introduce new up-front protocol complexity. In the context of a protocol like OAuth2.0 the access token issued by the authorization server would feature a BBS Signature, however instead of the client providing this access token as issued, in their request to a resource server, they generate a unique proof from the original access token and include that in the request instead. Because the access token is not shared in a request to a resource server, attacks such as MITM are mitigated. A resource server also obtains the ability to detect a replay attack by ensuring the proof presented is unique.

-
-
-
-
-

-B.3. Selectively Disclosure Enabled Identity Credentials -

-

BBS signatures when applied to the problem space of identity credentials can help to enhance user privacy. For example a digital drivers license that is cryptographically signed with a BBS signature, allows the holder or subject of the license to disclose different claims from their drivers license to different parties. Furthermore, the unlinkable presentations property of proofs generated by the scheme remove an important possible source of correlation for the holder across multiple presentations.

-
-
-
-
-
-
-

-Appendix C. Additional Test Vectors -

-

NOTE These fixtures are a work in progress and subject to change

-
-
-

-C.1. BLS12-381-SHAKE-256 Ciphersuite -

-
-
-

-C.1.1. Signature Test Vectors -

-
-
-
-C.1.1.1. No Header Valid Signature -
-

Using the messages defined in Section 7.2, with no header, along with the SK and PK values defined in Section 7.3.1 results in the following signature value

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature010.signature }}
-
-
-
-
-
-
-
-C.1.1.2. Modified Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature002.header }}
-
-
-

And the following message (the first message defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature002.messages[0] }}
-
-
-

After is mapped to the first scalar in Section 7.3.2, and with the following signature

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature002.signature }}
-
-
-

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to the message value being different from what was signed

-
-
-
-
-
-C.1.1.3. Extra Unsigned Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature003.header }}
-
-
-

And the following messages (the two first messages defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature003.messages[0] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature003.messages[1] }}
-
-
-

After they are mapped to the first 2 scalars in Section 7.3.2, and with the following signature (which is a signature to only the first of the above two messages)

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature003.signature }}
-
-
-

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to an additional message being supplied that was not signed.

-
-
-
-
-
-C.1.1.4. Missing Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature005.header }}
-
-
-

And the following messages (the two first messages defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature005.messages[0] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature005.messages[1] }}
-
-
-

After they are mapped to the first 2 scalars in Section 7.3.2, and with the following signature (which is a signature on all the messages defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature005.signature }}
-
-
-

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to missing messages that were originally present during the signing.

-
-
-
-
-
-C.1.1.5. Reordered Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature006.header }}
-
-
-

And the following messages (re-ordering of the messages defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[0] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[1] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[2] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[3] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[4] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[5] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[6] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[7] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[8] }}
-
-{{ $signatureFixtures.bls12-381-shake-256.signature006.messages[9] }}
-
-
-

After they are mapped to the corresponding scalars in Section 7.3.2, and with the following signature

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature006.signature }}
-
-
-

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to messages being re-ordered from the order in which they were signed

-
-
-
-
-
-C.1.1.6. Wrong Public Key Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature007.header }}
-
-
-

And the messages as defined in Section 7.2, mapped to the scalars in Section 7.3.2 and with the following signature

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature007.signature }}
-
-
-

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to public key used to verify is in-correct

-
-
-
-
-
-C.1.1.7. Wrong Header Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature008.header }}
-
-
-

And the messages as defined in Section 7.2, mapped to the scalars in Section 7.3.2 and with the following signature

-
-
{{ $signatureFixtures.bls12-381-shake-256.signature008.signature }}
-
-
-

Along with the PK value as defined in Section 7.3.1 as inputs into the Verify operation should fail signature validation due to header value being modified from what was originally signed

-
-
-
-
-
-
-

-C.1.2. Proof Test Vectors -

-
-
-
-C.1.2.1. No Header Valid Proof -
-

Using messages, PK and signature as in No Header Valid Signature, with only every other messages disclosed (messages in index 0, 2, 4 and 6, in that order), with no header and the following presentation header

-
-
{{ $proofFixtures.bls12-381-shake-256.proof014.presentationHeader }}
-
-
-

while using the mocked rng defined in Section 7.1, will result to the following proof value

-
-
{{ $proofFixtures.bls12-381-shake-256.proof014.proof }}
-
-
-
-
-
-
-
-C.1.2.2. No Presentation Header Valid Proof -
-

Using the same header, PK, messages and signature as in Multi-Message, All Messages Disclosed Proof, with every other message disclosed (messages in index 0, 2, 4 and 6, in that order), with no presentation header, while using the mocked rng defined in Section 7.1, will result to the following proof value

-
-
{{ $proofFixtures.bls12-381-shake-256.proof015.proof }}
-
-
-
-
-
-
-
-
-

-C.1.3. Hash to Scalar Test Vectors -

-

Using the following input message,

-
-
{{ $H2sFixture.bls12-381-shake-256.h2s.message }}
-
-
-

And the default dst defined in hash_to_scalar, i.e.,

-
-
{{ $H2sFixture.bls12-381-shake-256.h2s.dst }}
-
-
-

We get the following scalar, encoded with I2OSP and represented in big endian order,

-
-
{{ $H2sFixture.bls12-381-shake-256.h2s.scalar }}
-
-
-
-
-
-
-
-
-

-C.2. BLS12-381-SHA-256 Ciphersuite -

-
-
-

-C.2.1. Signature Test Vectors -

-
-
-
-C.2.1.1. No Header Valid Signature -
-

Using the messages defined in Section 7.2, with no header, along with the SK and PK values defined in Section 7.4.1 results in the following signature value

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature010.signature }}
-
-
-
-
-
-
-
-C.2.1.2. Modified Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature002.header }}
-
-
-

And the following message (the first message defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature002.messages[0] }}
-
-
-

After is mapped to the first scalar in Section 7.4.2, and with the following signature

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature002.signature }}
-
-
-

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to the message value being different from what was signed.

-
-
-
-
-
-C.2.1.3. Extra Unsigned Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature003.header }}
-
-
-

And the following messages (the two first messages defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature003.messages[0] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature003.messages[1] }}
-
-
-

After they are mapped to the first 2 scalars in Section 7.4.2, and with the following signature (which is a signature to only the first of the above two messages)

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature003.signature }}
-
-
-

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to an additional message being supplied that was not signed.

-
-
-
-
-
-C.2.1.4. Missing Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature005.header }}
-
-
-

And the following messages (the two first messages defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature005.messages[0] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature005.messages[1] }}
-
-
-

After they are mapped to the first 2 scalars in Section 7.4.2, and with the following signature (which is a signature on all the messages defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature005.signature }}
-
-
-

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to missing messages that were originally present during the signing.

-
-
-
-
-
-C.2.1.5. Reordered Message Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature006.header }}
-
-
-

And the following messages (re-ordering of the messages defined in Section 7.2)

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[0] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[1] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[2] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[3] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[4] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[5] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[6] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[7] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[8] }}
-
-{{ $signatureFixtures.bls12-381-sha-256.signature006.messages[9] }}
-
-
-

After they are mapped to the corresponding scalars in Section 7.4.2, and with the following signature

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature006.signature }}
-
-
-

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to messages being re-ordered from the order in which they were signed.

-
-
-
-
-
-C.2.1.6. Wrong Public Key Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature007.header }}
-
-
-

And the messages as defined in Section 7.2, mapped to the scalars in Section 7.4.2 and with the following signature

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature007.signature }}
-
-
-

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to public key used to verify is in-correct.

-
-
-
-
-
-C.2.1.7. Wrong Header Signature -
-

Using the following header

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature008.header }}
-
-
-

And the messages as defined in Section 7.2, mapped to the scalars in Section 7.4.2 and with the following signature

-
-
{{ $signatureFixtures.bls12-381-sha-256.signature008.signature }}
-
-
-

Along with the PK value as defined in Section 7.4.1 as inputs into the Verify operation should fail signature validation due to header value being modified from what was originally signed.

-
-
-
-
-
-
-

-C.2.2. Proof Test Vectors -

-
-
-
-C.2.2.1. No Header Valid Proof -
-

Using messages, PK and signature as in No Header Valid Signature, with only every other messages disclosed (messages in index 0, 2, 4 and 6, in that order), with no header and the following presentation header

-
-
{{ $proofFixtures.bls12-381-sha-256.proof014.presentationHeader }}
-
-
-

while using the mocked rng defined in Section 7.1, will result to the following proof value

-
-
{{ $proofFixtures.bls12-381-sha-256.proof014.proof }}
-
-
-
-
-
-
-
-C.2.2.2. No Presentation Header Valid Proof -
-

Using the same header, PK, messages and signature as in Multi-Message, All Messages Disclosed Proof, with every other message disclosed (messages in index 0, 2, 4 and 6, in that order), with no presentation header, while using the mocked rng defined in Section 7.1, will result to the following proof value

-
-
{{ $proofFixtures.bls12-381-sha-256.proof015.proof }}
-
-
-
-
-
-
-
-
-

-C.2.3. Hash to Scalar Test Vectors -

-

Using the following input message,

-
-
{{ $H2sFixture.bls12-381-sha-256.h2s.message }}
-
-
-

And the default dst defined in hash_to_scalar, i.e.,

-
-
{{ $H2sFixture.bls12-381-sha-256.h2s.dst }}
-
-
-

We get the following scalar, encoded with I2OSP and represented in big endian order,

-
-
{{ $H2sFixture.bls12-381-sha-256.h2s.scalar }}
-
-
-
-
-
-
-
-
-
-
-

-Appendix D. Proof Generation and Verification Algorithmic Explanation -

-

The following section provides an explanation of how the ProofGen and ProofVerify operations work.

-

Let the prover be in possession of a BBS signature (A, e) on messages msg_1, ..., msg_L and a domain value (see Sign). Let A = B * (1/(e + SK)) where SK the signer's secret key and,

-
-
B = P1 + Q_1 * domain + H_1 * msg_1 + ... + H_L * msg_L
-
-
-

Let (i1, ..., iR) be the indexes of generators corresponding to messages the prover wants to disclose and (j1, ..., jU) be the indexes corresponding to undisclosed messages (i.e., (j1, ..., jU) = range(1, L) \ (i1, ..., iR)). To prove knowledge of a signature on the disclosed messages, work as follows,

-
    -
  • -

    Hide the signature by randomizing it. To randomize the signature (A, e), take uniformly random r1 in [1, r-1], and calculate,

    -
    -
    1.  A' = A * r1,
    -2.  Abar = A' * (-e) + B * r1
    -3.  D = B * r1.
    -
    -
    -

    Also set,

    -
    -
    4.  r3 = r1 ^ -1 mod r
    -
    -
    -

    The values (A', Abar, D) will be part of the proof and are used to prove possession of a BBS signature, without revealing the signature itself. Note that; e(A', PK) = e(Abar, P2) where PK the signer's public key and P2 the base element in G2 (used to create the signer’ (U+2019)s PK, see Section 3.3.2). This also serves to bind the proof to the signer's PK.

    -
  • -
  • -

    Set the following,

    -
    -
    1.  C1 = Abar - D
    -2.  C2 = P1 + Q_1 * domain + H_i1 * msg_i1 + ... + H_iR * msg_iR
    -
    -
    -

    Create a non-interactive zero-knowledge proof-of-knowledge (nizk) of the values e, r3 and msg_j1, ..., msg_jU (the undisclosed messages) so that both of the following equalities hold,

    -
    -
    EQ1.  C1 = A' * (-e)
    -EQ2.  C2 = - D * r3 + H_j1 * msg_j1 + ... + H_jU * msg_jU.
    -
    -
    -
  • -
-

Note that the verifier will know the elements in the left side of the above equations (i.e., C1 and C2) but not in the right side (i.e., r3 and the undisclosed messages: msg_j1, ..., msg_jU). However, using the nizk, the prover can convince the verifier that they (the prover) know the elements that satisfy those equations, without disclosing them. Then, if both EQ1 and EQ2 hold, and e(A', PK) = e(Abar, P2), an extractor can return a valid BBS signature from the signer's SK, on the disclosed messages. The proof returned is (A', Abar, D, nizk). To validate the proof, a verifier checks that e(A', PK) = e(Abar, P2) and verifies the nizk. Validating the proof, will guarantee the authenticity and integrity of the disclosed messages, as well as ownership of the undisclosed messages and of the signature.

-
-
-
-
-

-Appendix E. Document History -

-

-00

-
    -
  • Initial version -
  • -
-

-01

-
    -
  • Populated fixtures -
  • -
  • Added SHA-256 based ciphersuite -
  • -
  • Fixed typo in ProofVerify -
  • -
  • Clarify ASCII string usage in DST -
  • -
  • Added MapMessageToScalar test vectors -
  • -
  • Fix typo in ciphersuite name -
  • -
-

-02

-
    -
  • Variety of editiorial clarifications -
  • -
  • Clarified integer endianness -
  • -
  • Revised the encode for hash operation -
  • -
  • Shifted to using CSPRNG instead of PRF -
  • -
  • Removed total number of messages from proof verify operation -
  • -
  • Added deterministic proof fixtures -
  • -
  • Shifted to multiple CSPRNG calls to calculate random elements, instead of expand_message -
  • -
  • Updated hash_to_scalar to a single output -
  • -
-
-
-
-
-

-Authors' Addresses -

-
-
Tobias Looker
-
MATTR
- -
-
-
Vasilis Kalos
-
MATTR
- -
-
-
Andrew Whitehead
-
Portage
- -
-
-
Mike Lodder
-
CryptID
- -
-
-
- - - From 45921706025e01fe15b331b23c24be4d05add9e5 Mon Sep 17 00:00:00 2001 From: Vasilis Kalos Date: Fri, 7 Jul 2023 18:44:40 +0300 Subject: [PATCH 4/5] Christian's suggestions: editorial fixes --- draft-irtf-cfrg-bbs-signatures.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/draft-irtf-cfrg-bbs-signatures.md b/draft-irtf-cfrg-bbs-signatures.md index 3ea36b74..bd8649aa 100644 --- a/draft-irtf-cfrg-bbs-signatures.md +++ b/draft-irtf-cfrg-bbs-signatures.md @@ -1130,7 +1130,7 @@ Outputs: Procedure: 1. (Abar, Bbar, r2^, r3^, (m^_1, ..., m^_U), c) = proof -2. return serialize((Abar, Bbar, r2^, r3^, m^_1, ..., m^_U), c) +2. return serialize((Abar, Bbar, r2^, r3^, m^_1, ..., m^_U, c)) ``` ### Octets to Proof @@ -1179,7 +1179,7 @@ Procedure: 7. if A_i is INVALID or Identity_G1, return INVALID 8. index += octet_point_length -// Scalars (i.e., (r2^, r3^, (m^_j1, ..., m^_jU), c) in +// Scalars (i.e., (r2^, r3^, m^_j1, ..., m^_jU, c) in // ProofGen) de-serialization. 9. j = 0 10. while index < length(proof_octets): From 2b7469f842aef123a63b9eccc8f281a4a808f7e9 Mon Sep 17 00:00:00 2001 From: Vasilis Kalos Date: Mon, 10 Jul 2023 19:41:45 +0300 Subject: [PATCH 5/5] fix proof deserialize description --- draft-irtf-cfrg-bbs-signatures.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/draft-irtf-cfrg-bbs-signatures.md b/draft-irtf-cfrg-bbs-signatures.md index bd8649aa..ac055f85 100644 --- a/draft-irtf-cfrg-bbs-signatures.md +++ b/draft-irtf-cfrg-bbs-signatures.md @@ -1140,8 +1140,9 @@ This operation describes how to decode an octet string representing a proof, val The proof value outputted by this operation consists of the following components, in that order: 1. Two (2) valid points of the G1 subgroup, each of which must not equal the identity point. -2. Three (3) integers representing scalars in the range of 1 to r-1 inclusive. +2. Two (2) integers representing scalars in the range of 1 to r-1 inclusive. 3. A set of integers representing scalars in the range of 1 to r-1 inclusive, corresponding to the undisclosed from the proof message commitments. This set can be empty (i.e., "()"). +4. One (1) integer representing a scalar in the range of 1 to r-1 inclusive, corresponding to the proof's challenge (`c`). ``` proof = octets_to_proof(proof_octets)