Files
nym/common/crypto/dkg/src/share.rs
T
Jędrzej Stuczyński 37de4bf2f7 Crypto part of the Groth's NIDKG (#1182)
* Work in progress NIDKG

* Encryption of multiple shares

* Extracted baby-step giant-step lookup table as a separate entity

* Proof of discrete log

* Adjusted discrete log domainn

* Producing proof of log during keygen

* Zeroize for epoch

* Proof of secret sharing

* empty main for compiler appeasement

* Construction of proof of chunking

* Initial untested verification of proof of chunking

* Converted chunk responses from Scalar to u64

* Additional tests for proof of chunking

* Minor cleanup and reorganisation

* Fixed enc/dec to use f0

* Deriving node coverage of required tree nodes

* Finally seemingnly working encryption under nonzero epoch

* Branch park

* Decryption key updates to specified epochs

* Ciphertext integrity checks

* Progress in integration tests

* Fixed ciphertext combining and integration test

* Dealing type and simplification of the integration test

* Benchmark for creation of baby-step-giant-step lookup table

* Initial import cleanup + broken 2nd integration test

* Using correct assertions in the integration test (and correctly combining shares)

* Removed unused modules

* Changed proof of sharing to allow for node indices being different from [1,2,...n]

* Reorganised bte module

* Benchmark for g2 precomputation

* Created more strongly typed Epoch type

which is essentially a Tau such that it is a leaf node

* Extending tau with a temporary oracle output

* Using random oracle for tau extension

* More benchmarks!

* encryption-related benchmarks

* Serialization of PublicKeyWithProof

* Typos

* Removed any changes made in validator-api or smart contracts

* Made the integration test slightly more concise

* Further purge of unused modules

* Fixed combining share to use lagrangian interpolation

* Recovery of verification keys from the dealings

* Verification key verification + extended integration tests

* Fixed Tau not being included in digest for producing Tau_h

* Tau serialization

* Serialization of a BTE Node

* Serialization of DecryptionKey

* Serialization of PublicCoefficients

* Utility method for setting constant coefficient of a polynomial

* Serialization of Ciphertexts

* Serialization of Proof of Secret Sharing

* Serialization of Proof of Chunking

* Serialization of Dealing

* Adjusted capacity of responses_r in proof of chunking

* Made notation more consistent with the paper equivalents

* Optional arguments for creating/verifying resharing dealings
2022-04-12 11:59:26 +01:00

131 lines
3.4 KiB
Rust

// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::bte::{CHUNK_BYTES, NUM_CHUNKS, SCALAR_SIZE};
use crate::error::DkgError;
use crate::interpolation::perform_lagrangian_interpolation_at_origin;
use crate::NodeIndex;
use bls12_381::Scalar;
use zeroize::Zeroize;
// if this type is changed, one must ensure all values can fit in it
pub type Chunk = u16;
#[derive(PartialEq, Eq, Debug, Zeroize)]
#[cfg_attr(test, derive(Clone))]
#[zeroize(drop)]
pub struct Share(pub(crate) Scalar);
pub fn combine_shares(shares: Vec<Share>, node_indices: &[NodeIndex]) -> Result<Scalar, DkgError> {
if shares.len() != node_indices.len() {
return Err(DkgError::MismatchedLagrangianSamplesLengths {
x: node_indices.len(),
y: shares.len(),
});
}
let samples = shares
.into_iter()
.zip(node_indices.iter())
.map(|(share, index)| (Scalar::from(*index), share.0))
.collect::<Vec<_>>();
perform_lagrangian_interpolation_at_origin(&samples)
}
impl Share {
// not really used outside tests
#[cfg(test)]
pub(crate) fn random(mut rng: impl rand_core::RngCore) -> Self {
use ff::Field;
Share(Scalar::random(&mut rng))
}
pub(crate) fn to_chunks(&self) -> ChunkedShare {
let mut chunks = [0; NUM_CHUNKS];
let mut bytes = self.0.to_bytes();
for (chunk, chunk_bytes) in chunks.iter_mut().zip(bytes[..].chunks_exact(CHUNK_BYTES)) {
let mut tmp = [0u8; CHUNK_BYTES];
tmp.copy_from_slice(chunk_bytes);
*chunk = Chunk::from_le_bytes(tmp)
}
bytes.zeroize();
ChunkedShare { chunks }
}
pub(crate) fn inner(&self) -> &Scalar {
&self.0
}
}
impl From<Scalar> for Share {
fn from(s: Scalar) -> Self {
Share(s)
}
}
#[derive(Default, Zeroize)]
#[cfg_attr(test, derive(Clone))]
#[zeroize(drop)]
pub(crate) struct ChunkedShare {
pub(crate) chunks: [Chunk; NUM_CHUNKS],
}
impl From<Share> for ChunkedShare {
fn from(share: Share) -> ChunkedShare {
share.to_chunks()
}
}
impl TryFrom<ChunkedShare> for Share {
type Error = DkgError;
fn try_from(chunked: ChunkedShare) -> Result<Share, Self::Error> {
let mut bytes = [0u8; SCALAR_SIZE];
for (chunk, chunk_bytes) in chunked
.chunks
.iter()
.zip(bytes[..].chunks_exact_mut(CHUNK_BYTES))
{
let tmp = chunk.to_le_bytes();
chunk_bytes.copy_from_slice(&tmp[..]);
}
let recovered = Option::from(Scalar::from_bytes(&bytes))
.map(Share)
.ok_or(DkgError::MalformedShare)?;
bytes.zeroize();
Ok(recovered)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::combine_scalar_chunks;
use rand_core::SeedableRng;
#[test]
fn chunking_share() {
let dummy_seed = [1u8; 32];
let mut rng = rand_chacha::ChaCha20Rng::from_seed(dummy_seed);
let share = Share::random(&mut rng);
let chunks: ChunkedShare = share.clone().into();
let scalar_chunks = chunks
.chunks
.iter()
.map(|c| Scalar::from(*c as u64))
.collect::<Vec<_>>();
let expected = combine_scalar_chunks(&scalar_chunks);
assert_eq!(expected, share.0);
let recombined: Share = chunks.try_into().unwrap();
assert_eq!(expected, recombined.0);
}
}