mirror of https://github.com/nucypher/pyUmbral.git
262 lines
7.2 KiB
Python
262 lines
7.2 KiB
Python
import json
|
|
import os
|
|
|
|
from umbral import (
|
|
SecretKey, Signer, KeyFrag, CapsuleFrag,
|
|
encrypt, generate_kfrags, reencrypt)
|
|
from umbral.curve_scalar import CurveScalar
|
|
from umbral.curve_point import CurvePoint
|
|
from umbral.hashing import Hash, unsafe_hash_to_point
|
|
from umbral.dem import DEM, kdf
|
|
|
|
|
|
#######################
|
|
# Auxiliary functions #
|
|
#######################
|
|
|
|
def hexlify(data):
|
|
if isinstance(data, int):
|
|
return hex(data)[2:]
|
|
else:
|
|
return bytes(data).hex()
|
|
|
|
|
|
def create_test_vector_file(vector, filename, generate_again=False):
|
|
path = os.path.join(os.path.dirname(__file__), filename)
|
|
|
|
mode = 'w' if generate_again else 'x'
|
|
try:
|
|
with open(path, mode) as f:
|
|
json.dump(vector, f, indent=2)
|
|
except FileExistsError:
|
|
pass
|
|
|
|
|
|
# If True, this will overwrite existing test vector files with new randomly generated instances
|
|
generate_again = True
|
|
|
|
#########
|
|
# SETUP #
|
|
#########
|
|
|
|
# We create also some Umbral objects for later
|
|
delegating_sk = SecretKey.random()
|
|
receiving_sk = SecretKey.random()
|
|
signing_sk = SecretKey.random()
|
|
|
|
verifying_pk = signing_sk.public_key()
|
|
delegating_pk = delegating_sk.public_key()
|
|
receiving_pk = receiving_sk.public_key()
|
|
|
|
kfrags = generate_kfrags(delegating_sk=delegating_sk,
|
|
receiving_pk=receiving_pk,
|
|
signer=Signer(signing_sk),
|
|
threshold=6,
|
|
num_kfrags=10,
|
|
)
|
|
|
|
plain_data = b'peace at dawn'
|
|
|
|
capsule, ciphertext = encrypt(delegating_pk, plain_data)
|
|
|
|
cfrag = CapsuleFrag.from_bytes(bytes(reencrypt(capsule, kfrags[0])))
|
|
points = [capsule.point_e, cfrag.point_e1, cfrag.proof.point_e2,
|
|
capsule.point_v, cfrag.point_v1, cfrag.proof.point_v2,
|
|
cfrag.proof.kfrag_commitment, cfrag.proof.kfrag_pok]
|
|
|
|
z = cfrag.proof.signature
|
|
|
|
|
|
###########################
|
|
# CurveScalar arithmetics #
|
|
###########################
|
|
|
|
# Let's generate two random CurveScalars
|
|
bn1 = CurveScalar.random_nonzero()
|
|
bn2 = CurveScalar.random_nonzero()
|
|
|
|
# Expected results for some binary operations
|
|
expected = [('Addition', bn1 + bn2),
|
|
('Subtraction', bn1 - bn2),
|
|
('Multiplication', bn1 * bn2),
|
|
('Inverse', bn1.invert()),
|
|
]
|
|
|
|
expected = [{'operation': op, 'result': hexlify(result)} for (op, result) in expected]
|
|
|
|
# Definition of test vector
|
|
vector_suite = {
|
|
'name': 'Test vectors for CurveScalar operations',
|
|
'params': 'default',
|
|
'first operand': hexlify(bn1),
|
|
'second operand': hexlify(bn2),
|
|
'vectors': expected
|
|
}
|
|
|
|
json_file = 'vectors_scalar_operations.json'
|
|
|
|
create_test_vector_file(vector_suite, json_file, generate_again=generate_again)
|
|
|
|
|
|
|
|
###############################
|
|
# CurveScalar.from_digest() #
|
|
###############################
|
|
|
|
# Test vectors for different kinds of inputs (bytes, CurvePoints, CurveScalars, etc.)
|
|
inputs = ([b''],
|
|
[b'abc'],
|
|
[capsule.point_e],
|
|
[z],
|
|
[capsule.point_e, z],
|
|
points,
|
|
)
|
|
|
|
vectors = list()
|
|
for input_to_hash in inputs:
|
|
digest = Hash(b'some_dst')
|
|
for input_ in input_to_hash:
|
|
digest.update(input_)
|
|
scalar = CurveScalar.from_digest(digest)
|
|
json_input = [{'class': data.__class__.__name__,
|
|
'bytes': hexlify(data),
|
|
} for data in input_to_hash]
|
|
|
|
json_input = {'input': json_input, 'output': hexlify(scalar) }
|
|
|
|
vectors.append(json_input)
|
|
|
|
vector_suite = {
|
|
'name' : 'Test vectors for umbral.curvebn.CurveScalar.from_digest()',
|
|
'params' : 'default',
|
|
'vectors' : vectors
|
|
}
|
|
|
|
create_test_vector_file(vector_suite, 'vectors_scalar_from_digest.json', generate_again=generate_again)
|
|
#print(json.dumps(vector_suite, indent=2))
|
|
|
|
|
|
###############
|
|
# CurvePoints #
|
|
###############
|
|
|
|
point1 = CurvePoint.random()
|
|
point2 = CurvePoint.random()
|
|
|
|
# Expected results for some CurvePoint operations
|
|
expected = [('Addition', point1 + point2),
|
|
('Subtraction', point1 - point2),
|
|
('Multiplication', point1 * bn1),
|
|
('Inversion', -point1),
|
|
('To_affine.X', point1.to_affine()[0]),
|
|
('To_affine.Y', point1.to_affine()[1]),
|
|
('kdf', kdf(bytes(point1), DEM.KEY_SIZE)),
|
|
]
|
|
|
|
expected = [{'operation': op, 'result': hexlify(result)} for (op, result) in expected]
|
|
|
|
# Definition of test vector
|
|
vector_suite = {
|
|
'name': 'Test vectors for CurvePoint operations',
|
|
'params': 'default',
|
|
'first CurvePoint operand': hexlify(point1),
|
|
'second CurvePoint operand': hexlify(point2),
|
|
'CurveScalar operand': hexlify(bn1),
|
|
'vectors': expected
|
|
}
|
|
|
|
json_file = 'vectors_point_operations.json'
|
|
|
|
create_test_vector_file(vector_suite, json_file, generate_again=generate_again)
|
|
|
|
|
|
########################
|
|
# unsafe_hash_to_point #
|
|
########################
|
|
|
|
inputs = (b'',
|
|
b'abc',
|
|
b'NuCypher',
|
|
b'Nucypher',
|
|
)
|
|
|
|
vectors = list()
|
|
for data in inputs:
|
|
for dst in inputs:
|
|
point = unsafe_hash_to_point(dst=dst, data=data)
|
|
json_input = {'data': hexlify(data),
|
|
'dst': hexlify(dst),
|
|
'point': hexlify(point),
|
|
}
|
|
|
|
vectors.append(json_input)
|
|
|
|
vector_suite = {
|
|
'name': 'Test vectors for unsafe_hash_to_point()',
|
|
'params': 'default',
|
|
'vectors': vectors
|
|
}
|
|
|
|
create_test_vector_file(vector_suite, 'vectors_unsafe_hash_to_point.json', generate_again=generate_again)
|
|
#print(json.dumps(vector_suite, indent=2))
|
|
|
|
|
|
##########
|
|
# KFrags #
|
|
##########
|
|
|
|
vectors = list()
|
|
for kfrag in kfrags:
|
|
kfrag = KeyFrag.from_bytes(bytes(kfrag))
|
|
kfrag.verify(verifying_pk, delegating_pk, receiving_pk)
|
|
|
|
json_input = {'kfrag': hexlify(kfrag)}
|
|
|
|
vectors.append(json_input)
|
|
|
|
vector_suite = {
|
|
'name': 'Test vectors for KFrags',
|
|
'description': ('This is a collection of KFrags generated under the '
|
|
'enclosed delegating, verifying and receiving keys. '
|
|
'Each of them must deserialize correctly and the '
|
|
'call to verify() must succeed.'),
|
|
'params': 'default',
|
|
'verifying_pk': hexlify(verifying_pk),
|
|
'delegating_pk': hexlify(delegating_pk),
|
|
'receiving_pk': hexlify(receiving_pk),
|
|
'vectors': vectors
|
|
}
|
|
|
|
#print(json.dumps(vector_suite, indent=2))
|
|
create_test_vector_file(vector_suite, 'vectors_kfrags.json', generate_again=generate_again)
|
|
|
|
|
|
##########
|
|
# CFrags #
|
|
##########
|
|
|
|
vectors = list()
|
|
|
|
for kfrag in kfrags:
|
|
cfrag = reencrypt(capsule, kfrag)
|
|
json_input = {'kfrag': hexlify(kfrag), 'cfrag': hexlify(cfrag)}
|
|
vectors.append(json_input)
|
|
|
|
vector_suite = {
|
|
'name': 'Test vectors for CFrags',
|
|
'description': ('This is a collection of CFrags, originated from the '
|
|
'enclosed Capsule, under the enclosed delegating, '
|
|
'verifying and receiving keys. Each CFrag must deserialize '
|
|
'correctly and can be replicated with a call to '
|
|
'`reencrypt(kfrag, capsule)`'),
|
|
'params': 'default',
|
|
'capsule': hexlify(capsule),
|
|
'verifying_pk': hexlify(verifying_pk),
|
|
'delegating_pk': hexlify(delegating_pk),
|
|
'receiving_pk': hexlify(receiving_pk),
|
|
'vectors': vectors
|
|
}
|
|
|
|
#print(json.dumps(vector_suite, indent=2))
|
|
create_test_vector_file(vector_suite, 'vectors_cfrags.json', generate_again=generate_again)
|