Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve utils and add Circulant extractor #6

Merged
merged 28 commits into from
Jan 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5028383
update utils
cforeman-cqc Dec 22, 2023
d1cb13c
improve utils and dodis from_params
cforeman-cqc Dec 22, 2023
ac0f7ea
add circulant extractor
cforeman-cqc Dec 22, 2023
ca16129
update toeplitz from_params
cforeman-cqc Dec 22, 2023
b939e01
update Trevisan from_params
cforeman-cqc Dec 22, 2023
3a73c61
update docs
cforeman-cqc Dec 22, 2023
5db920f
add logo
cforeman-cqc Dec 22, 2023
643831e
improve linting circulant
cforeman-cqc Dec 24, 2023
d3813b4
improve linting
cforeman-cqc Dec 24, 2023
87909bb
linting
cforeman-cqc Dec 24, 2023
6c83ea8
linting + improv Trevisan from_params code
cforeman-cqc Dec 24, 2023
bc9c008
add circulant tests
cforeman-cqc Dec 24, 2023
e7d3547
fix linting
cforeman-cqc Dec 24, 2023
a1029c9
fix tests
cforeman-cqc Dec 24, 2023
abf5d25
fix tests 2
cforeman-cqc Dec 24, 2023
d5641f4
replace (some) while statements with if
cforeman-cqc Dec 27, 2023
5745987
Fix logo
y-richie-y Dec 28, 2023
615227c
fix comment + define circulant for weak input length vs. seed length
cforeman-cqc Jan 12, 2024
6a94942
fix tests
cforeman-cqc Jan 12, 2024
7b2c7e6
update description
cforeman-cqc Jan 12, 2024
5372ad9
fix circulant
cforeman-cqc Jan 12, 2024
2181d6b
fix circulant and adjust tests
cforeman-cqc Jan 12, 2024
92c7036
undo circulant changes
cforeman-cqc Jan 12, 2024
031294b
revert changes
cforeman-cqc Jan 12, 2024
6d8a197
fix input1 adjusting
cforeman-cqc Jan 12, 2024
6befbc5
update circulant
cforeman-cqc Jan 12, 2024
dc624c0
fix circulant
cforeman-cqc Jan 12, 2024
c32719b
update docs
cforeman-cqc Jan 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions cryptomite/circulant.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
"""
Circulant is a seeded extractor that takes an input of
n - 1 bits and a seed of n bits, where n is prime, to
produce some error-perfect random bits.
"""
from __future__ import annotations

from math import floor, log2
from typing import cast

from cryptomite.utils import BitsT, closest_prime, conv, log_2

__all__ = ['Circulant']


class Circulant:
""" Circulant extractor based on [Foreman23]_. """
def __init__(self, n: int, m: int):
"""Create a Circulant Extractor.

Parameters
----------
n : int
The length of the input bits.
*** n + 1 should be prime. ***
m : int
The length of the output bits.
"""
self.n, self.m = n, m

def extract(self, input1: BitsT, input2: BitsT) -> BitsT:
""" Extract randomness.

Parameters
----------
input1 : list of bits
The first list of bits, the 'input'.
input2 : list of bits
The second list of bits, the '(weak) seed'.

Returns
-------
list of bits
The extracted output.
"""
n, m = self.n, self.m
assert len(input1) == len(input2) - 1 == n
assert n >= m
n = n + 1
l = log_2(2 * n - 2)
L = 1 << l
input1 = input1 + [0]
input1, input2 = list(input1), list(input2)
input1 = input1[0:1] + input1[1:][::-1] + [0] * (L - n)
input2 = input2 + [0] * (L - len(input2))
conv_output = conv(l, input1, input2)
output: BitsT = cast(BitsT, [
(conv_output[i] + conv_output[i + n]) & 1 for i in range(m)])
return output

@staticmethod
def from_params(
min_entropy1: float,
min_entropy2: float,
log2_error: float,
input_length1: int,
input_length2: int,
markov_q_proof: bool,
verbose: bool = True) -> Circulant:
"""
Calculate a valid input and output size for this extractor,
given the initial lengths and min-entropies of the input sources
and generate the associated extractor.

The input_length2 must be prime, else the code will chose a
valid input_length2 choice and adjust the other parameters
accordingly.
The min_entropy inputs are a lower bound on the
:term:`min-entropy` of the related input string.

Parameters
----------
min_entropy1 : float
The min-entropy of input source 1, the 'input'.
min_entropy2 : float
The min-entropy of input source 2, the '(weak) seed'.
log2_error : float
The acceptable maximum extractor error, in the
form error = b where extractor error = :math:`2 ^ b`.
input_length1 : int
The initial length of input source.
input_length2 : int
The initial length of the (weak) seed.
markov_q_proof : bool
Boolean indicator of whether the extractor parameters
should be calculated to account for being quantum-proof
in the Markov model or not.

Returns
-------
Circulant
The Circulant extractor.
"""
if log2_error >= 0:
raise Exception("""Cannot extract with these parameters.
log2_error must be < 0.""")
input_length = closest_prime((input_length1 + input_length2)//2)
if input_length1 > input_length - 1:
min_entropy1 -= input_length1 - input_length
if input_length2 > input_length:
min_entropy2 -= input_length2 - input_length
output_length = floor(min_entropy1 + min_entropy2
- input_length + 2 * log2_error)
if markov_q_proof:
output_length = floor(0.2 * (min_entropy1 + min_entropy2
- input_length + 8 * log2_error
+ 8 - 4 * log2(3)))
if output_length <= 0:
raise Exception("""Cannot extract with these parameters.
Increase min_entropy1 and/or min_entropy2
and/or log2_error.""")
if verbose:
print('Min entropy1: ', min_entropy1,
'Min entropy2: ', min_entropy2,
'Log error: ', log2_error,
'Input length1: ', input_length - 1,
'Input length2: ', input_length,
'Output length: ', output_length)
print('Adjust length of the input and (weak) seed accordingly')
return Circulant(n=input_length, m=output_length)
93 changes: 55 additions & 38 deletions cryptomite/dodis.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,21 @@
from math import floor, log2
from typing import cast

from cryptomite.utils import BitsT, conv, log_2, na_set
from cryptomite.utils import BitsT, closest_na_set, conv, log_2

__all__ = ['Dodis']


class Dodis:
""" Dodis extractor based on [Dodis20]_. """
""" Dodis extractor based on [Dodis2004]_. """
def __init__(self, n: int, m: int):
"""Create a Dodis Extractor.

Parameters
----------
n : int
The length of the two input bits.
*** This should be prime with primitive root 2. ***
m : int
The length of the output bits.
"""
Expand All @@ -32,9 +33,9 @@ def extract(self, input1: BitsT, input2: BitsT) -> BitsT:
Parameters
----------
input1 : list of bits
The first list of bits.
The first list of bits, the 'input'.
input2 : list of bits
The second list of bits.
The second list of bits, the '(weak) seed'.

Returns
-------
Expand All @@ -56,55 +57,71 @@ def extract(self, input1: BitsT, input2: BitsT) -> BitsT:

@staticmethod
def from_params(
min_entropy1: float,
min_entropy2: float,
log2_error: float,
input_length1: int,
input_length2: int,
entropy1: int,
entropy2: int,
error: int,
q_proof: bool) -> Dodis:
markov_q_proof: bool,
verbose: bool = True) -> Dodis:
"""
Calculate the input size and output size for this 2-source
extractor.
Calculate a valid input and output size for this extractor,
given the initial lengths and min-entropies of the input sources
and generate the associated extractor.

The input_length -1 must be in :py:func:`~.na_set`.
The entropy inputs are a lower bound on the :term:`min-entropy`
of the related input string.
The input_length must be prime with primitive root 2, else
the code will chose a valid input_length choice and adjust the
other parameters accordingly.
The min entropy inputs are a lower bound on the
:term:`min-entropy` of the related input string.

Parameters
----------
input_length1 : int
The initial length of input source 1.
input_length2 : int
The initial length of input source 2.
entropy1 : int
The min-entropy of input source 1.
entropy2 : int
The min-entropy of input source 2.
error : int
min_entropy1 : float
The min-entropy of input source 1, the 'input'.
min_entropy2 : float
The min-entropy of input source 2, the '(weak) seed'.
log2_error : float
The acceptable maximum extractor error, in the
form error = b where extractor error = :math:`2 ^ b`.
q_proof : bool
input_length1 : int
The initial length of input source.
input_length2 : int
The initial length of the (weak) seed.
markov_q_proof : bool
Boolean indicator of whether the extractor parameters
should be calculated to account for quantum side
information or not.
should be calculated to account for being quantum-proof
in the Markov model or not.

Returns
-------
Dodis
The Dodis extractor.
"""
if error > 0:
raise Exception('Cannot extract with these parameters.'
'Error must be < 0.')
input_length = na_set(min(input_length1, input_length2) - 1) + 1
entropy1 -= input_length1 - input_length
entropy2 -= input_length2 - input_length
output_length = floor(
entropy1 + entropy2 - input_length + 1 + 2 * error)
if q_proof:
output_length = floor(0.2 * (entropy1 + entropy2 - input_length)
+ 8 * error + 9 - 4 * log2(3))
if log2_error >= 0:
raise Exception("""Cannot extract with these parameters.
log2_error must be < 0.""")
input_length = closest_na_set((input_length1 + input_length2)//2)
if input_length1 > input_length:
min_entropy1 -= input_length1 - input_length
if input_length2 > input_length:
min_entropy2 -= input_length2 - input_length
output_length = floor(min_entropy1 + min_entropy2
- input_length + 1 + 2 * log2_error)
if markov_q_proof:
output_length = floor(0.2 * (min_entropy1 + min_entropy2
- input_length + 8 * log2_error
+ 9 - 4 * log2(3)))
if output_length <= 0:
raise Exception('Cannot extract with these parameters. '
'Increase entropy1 and/or entropy2.')
raise Exception("""Cannot extract with these parameters.
Increase min_entropy1 and/or min_entropy2
and/or log2_error.""")
if verbose:
print('Min entropy1: ', min_entropy1,
'Min entropy2: ', min_entropy2,
'Log error: ', log2_error,
'Input length1: ', input_length,
'Input length2: ', input_length,
'Output length: ', output_length)
print('Adjust length of the input and (weak) seed accordingly')
return Dodis(n=input_length, m=output_length)
Loading