Skip to content

Commit

Permalink
port fixed kes key size
Browse files Browse the repository at this point in the history
  • Loading branch information
vincenthz authored and zeegomo committed Sep 23, 2021
1 parent 08317e6 commit d2cff57
Showing 1 changed file with 138 additions and 37 deletions.
175 changes: 138 additions & 37 deletions chain-crypto/src/algorithms/sumed25519/sum.rs
Expand Up @@ -11,6 +11,7 @@ pub enum Error {
InvalidPublicKeySize(usize),
InvalidSignatureSize(usize),
InvalidSignatureCount(usize, Depth),
DataInZeroArea,
KeyCannotBeUpdatedMore,
}

Expand All @@ -20,6 +21,8 @@ impl From<ed25519::SignatureError> for Error {
}
}

const USE_TRUNCATE: bool = false;

type PeriodSerialized = u32;
const PERIOD_SERIALIZE_SIZE: usize = 4;

Expand Down Expand Up @@ -55,6 +58,13 @@ pub const fn minimum_secretkey_size(depth: Depth) -> usize {
+ depth.0 * 2 * PUBLIC_KEY_SIZE
}

pub const fn maximum_secretkey_size(depth: Depth) -> usize {
PERIOD_SERIALIZE_SIZE
+ INDIVIDUAL_SECRET_SIZE + INDIVIDUAL_PUBLIC_SIZE // keypair
+ depth.0 * 2 * PUBLIC_KEY_SIZE
+ depth.0 * Seed::SIZE
}

pub struct MerklePublicKeys<'a>(&'a [u8]);

impl<'a> MerklePublicKeys<'a> {
Expand Down Expand Up @@ -121,6 +131,17 @@ impl<'a> Iterator for Seeds<'a> {
}
}

impl<'a> ExactSizeIterator for Seeds<'a> {
fn len(&self) -> usize {
self.0.len() / Seed::SIZE
}
}

fn rs_from_period(depth: Depth, t: usize) -> u32 {
let bits = (depth.total() - 1).count_ones();
bits - t.count_ones()
}

impl SecretKey {
const T_OFFSET: usize = 0;
const KEYPAIR_OFFSET: usize = Self::T_OFFSET + PERIOD_SERIALIZE_SIZE;
Expand All @@ -130,6 +151,10 @@ impl SecretKey {
Self::MERKLE_PKS_OFFSET + depth.0 * PUBLIC_KEY_SIZE * 2
}

const fn seed_offset_index(depth: Depth, i: usize) -> usize {
Self::seed_offset(depth) + i * Seed::SIZE
}

// --------------------------------------
// accessors
pub fn t(&self) -> usize {
Expand All @@ -143,16 +168,29 @@ impl SecretKey {
ed25519::Keypair::from_bytes(bytes).expect("internal error: keypair invalid")
}

fn merkle_pks(&self) -> MerklePublicKeys {
#[doc(hidden)]
pub fn merkle_pks(&self) -> MerklePublicKeys {
let bytes = &self.data[Self::MERKLE_PKS_OFFSET..Self::seed_offset(self.depth)];
MerklePublicKeys::new(bytes)
}

fn rs(&self) -> Seeds {
let bytes = &self.data[Self::seed_offset(self.depth)..];
#[doc(hidden)]
pub fn rs(&self) -> Seeds {
let start = Self::seed_offset(self.depth);
let end = start + (self.rs_len() as usize * Seed::SIZE);
let bytes = &self.data[start..end];
if USE_TRUNCATE {
let checked_bytes = &self.data[Self::seed_offset(self.depth)..];
assert_eq!(checked_bytes.len(), self.rs_len() as usize * Seed::SIZE);
}
Seeds(bytes)
}

#[doc(hidden)]
pub fn rs_len(&self) -> u32 {
rs_from_period(self.depth(), self.t())
}

fn set_t(&mut self, t: usize) {
let t_bytes = PeriodSerialized::to_le_bytes(t as PeriodSerialized);
let out = &mut self.data[0..PERIOD_SERIALIZE_SIZE];
Expand Down Expand Up @@ -225,31 +263,62 @@ impl SecretKey {
out.extend_from_slice(r.as_ref());
}

assert_eq!(out.len(), maximum_secretkey_size(depth));

SecretKey { depth, data: out }
}

// Get the latest seed and drop it from the buffer
pub fn rs_pop(&mut self) -> Option<Seed> {
let seed_offset = Self::seed_offset(self.depth);
if self.data.len() - seed_offset > 0 {
// grab the last seed
let last = self.data.len() - Seed::SIZE;
let seed = Seed::from_slice(&self.data[last..]);
// clear the seed memory in the secret key, then truncate
self.data[last..].copy_from_slice(&[0u8; Seed::SIZE]);
self.data.truncate(last);
Some(seed)
if USE_TRUNCATE {
let seed_offset = Self::seed_offset(self.depth);
let rs_x = self.rs_len();
let seed_data_len = self.data.len() - seed_offset;
assert_eq!(rs_x as usize * Seed::SIZE, seed_data_len);

if self.data.len() - seed_offset > 0 {
// grab the last seed
let last = self.data.len() - Seed::SIZE;
let seed = Seed::from_slice(&self.data[last..]);
// clear the seed memory in the secret key, then truncate
self.data[last..].copy_from_slice(&[0u8; Seed::SIZE]);
self.data.truncate(last);
Some(seed)
} else {
None
}
} else {
None
let rs_len = self.rs_len();
if rs_len == 0 {
None
} else {
let start = Self::seed_offset_index(self.depth, rs_len as usize - 1);
let slice = &mut self.data[start..start + Seed::SIZE];
let seed = Seed::from_slice(&slice);
slice.copy_from_slice(&[0u8; Seed::SIZE]);
Some(seed)
}
}
}

pub fn rs_extend<I>(&mut self, rs: I)
where
I: Iterator<Item = Seed>,
{
for r in rs {
self.data.extend_from_slice(r.as_ref())
pub fn rs_extend<'a>(&mut self, seed_offset: usize, rs: Seeds<'a>) {
if USE_TRUNCATE {
let seed_start = Self::seed_offset(self.depth);
let extend_start = seed_offset * Seed::SIZE;

let expected = self.data.len() - seed_start;
assert_eq!(extend_start, expected);

for r in rs {
self.data.extend_from_slice(r.as_ref())
}
} else {
let current = seed_offset as u32;
let expect = rs_from_period(self.depth(), self.t() + 1);
let diff = expect - current;
let start = Self::seed_offset_index(self.depth, seed_offset);
let end = start + diff as usize * Seed::SIZE;
self.data[start..end].copy_from_slice(&rs.0)
}
}

Expand All @@ -270,26 +339,54 @@ impl SecretKey {
// check if the remaining length is valid
let rem = (bytes.len() - minimum_size) % 32;
if rem > 0 {
return Err(Error::InvalidSignatureSize(bytes.len()));
return Err(Error::InvalidSecretKeySize(bytes.len()));
}

// get T and make sure it's under the total
let mut t_bytes = [0u8; PERIOD_SERIALIZE_SIZE];
t_bytes.copy_from_slice(&bytes[0..PERIOD_SERIALIZE_SIZE]);
let t = PeriodSerialized::from_le_bytes(t_bytes) as usize;
if t >= depth.total() {
return Err(Error::InvalidSignatureCount(t, depth));
}
if USE_TRUNCATE {
// get T and make sure it's under the total
let mut t_bytes = [0u8; PERIOD_SERIALIZE_SIZE];
t_bytes.copy_from_slice(&bytes[0..PERIOD_SERIALIZE_SIZE]);
let t = PeriodSerialized::from_le_bytes(t_bytes) as usize;
if t >= depth.total() {
return Err(Error::InvalidSignatureCount(t, depth));
}

let keypair_slice = &bytes[Self::KEYPAIR_OFFSET..Self::MERKLE_PKS_OFFSET];
let keypair_slice = &bytes[Self::KEYPAIR_OFFSET..Self::MERKLE_PKS_OFFSET];

// verify sigma and pk format, no need to verify pks nor rs
let _ = ed25519::Keypair::from_bytes(keypair_slice)?;
// verify sigma and pk format, no need to verify pks nor rs
let _ = ed25519::Keypair::from_bytes(keypair_slice)?;

let mut out = Vec::with_capacity(bytes.len());
out.extend_from_slice(bytes);
let mut out = Vec::with_capacity(bytes.len());
out.extend_from_slice(bytes);
Ok(SecretKey { depth, data: out })
} else {
if bytes.len() != maximum_secretkey_size(depth) {
return Err(Error::InvalidSecretKeySize(bytes.len()));
}

let keypair_slice = &bytes[Self::KEYPAIR_OFFSET..Self::MERKLE_PKS_OFFSET];
// verify sigma and pk format
let _ = ed25519::Keypair::from_bytes(keypair_slice)?;

let mut tbuf = [0u8; PERIOD_SERIALIZE_SIZE];
tbuf.copy_from_slice(&bytes[0..PERIOD_SERIALIZE_SIZE]);
let t = PeriodSerialized::from_le_bytes(tbuf) as usize;

if t >= depth.total() {
return Err(Error::InvalidSignatureCount(t, depth));
}

let expected_rs = rs_from_period(depth, t);
let start_of_zeroes = Self::seed_offset_index(depth, expected_rs as usize);
let all_zeroes = bytes[start_of_zeroes..].iter().all(|b| *b == 0);
if !all_zeroes {
return Err(Error::DataInZeroArea);
}

Ok(SecretKey { depth, data: out })
let out = bytes.to_owned();

Ok(SecretKey { depth, data: out })
}
}
}

Expand Down Expand Up @@ -431,11 +528,14 @@ impl Signature {
let mut out = Vec::with_capacity(96 + PERIOD_SERIALIZE_SIZE + PUBLIC_KEY_SIZE * pks.len());
let t_bytes = PeriodSerialized::to_le_bytes(t as PeriodSerialized);
out.extend_from_slice(&t_bytes);
assert_eq!(out.len(), 4);
assert_eq!(out.len(), PERIOD_SERIALIZE_SIZE);
out.extend_from_slice(&sigma.to_bytes());
assert_eq!(out.len(), 68);
assert_eq!(out.len(), PERIOD_SERIALIZE_SIZE + SIGMA_SIZE);
out.extend_from_slice(pk.as_bytes());
assert_eq!(out.len(), 100);
assert_eq!(
out.len(),
PERIOD_SERIALIZE_SIZE + SIGMA_SIZE + INDIVIDUAL_PUBLIC_SIZE
);
for p in pks {
out.extend_from_slice(&p.0);
}
Expand Down Expand Up @@ -665,8 +765,9 @@ pub fn update(secret: &mut SecretKey) -> Result<(), Error> {
secret.get_merkle_pks(secret.depth().0 - diff as usize).1,
pub_child
);
let rs_x = secret.rs_len() as usize - 1;

secret.rs_extend(sec_child.rs());
secret.rs_extend(rs_x, sec_child.rs());
let offset = secret.merkle_pks().len() - sec_child.merkle_pks().len();
for (i, c) in sec_child.merkle_pks().enumerate() {
secret.set_merkle_pks(offset + i, &c)
Expand Down

0 comments on commit d2cff57

Please sign in to comment.