Skip to content
Snippets Groups Projects
Commit eac04696 authored by Éloïs's avatar Éloïs
Browse files

[fix] keys:ed25519: pubkey as_ref/to_bytes must be consistent with serde

parent 69c493b2
Branches
Tags
No related merge requests found
...@@ -24,7 +24,7 @@ pub trait ToBase58 { ...@@ -24,7 +24,7 @@ pub trait ToBase58 {
} }
/// Create an array of 32 bytes from a Base58 string. /// Create an array of 32 bytes from a Base58 string.
pub fn str_base58_to_32bytes(base58_data: &str) -> Result<([u8; 32], usize), BaseConvertionError> { pub fn str_base58_to_32bytes(base58_data: &str) -> Result<([u8; 32], u8), BaseConvertionError> {
let mut source = base58_data; let mut source = base58_data;
let mut count_leading_1 = 0; let mut count_leading_1 = 0;
while !source.is_empty() && &source[0..1] == "1" { while !source.is_empty() && &source[0..1] == "1" {
...@@ -58,7 +58,7 @@ pub fn str_base58_to_32bytes(base58_data: &str) -> Result<([u8; 32], usize), Bas ...@@ -58,7 +58,7 @@ pub fn str_base58_to_32bytes(base58_data: &str) -> Result<([u8; 32], usize), Bas
} }
/// Create a Base58 string from a slice of bytes. /// Create a Base58 string from a slice of bytes.
pub fn bytes_to_str_base58(bytes: &[u8], count_leading_1: usize) -> String { pub fn bytes_to_str_base58(bytes: &[u8], count_leading_1: u8) -> String {
let mut str_base58 = String::new(); let mut str_base58 = String::new();
let mut remaining_leading_1 = count_leading_1; let mut remaining_leading_1 = count_leading_1;
while remaining_leading_1 > 0 { while remaining_leading_1 > 0 {
...@@ -72,7 +72,7 @@ pub fn bytes_to_str_base58(bytes: &[u8], count_leading_1: usize) -> String { ...@@ -72,7 +72,7 @@ pub fn bytes_to_str_base58(bytes: &[u8], count_leading_1: usize) -> String {
let bytes = if count_leading_1 == 0 && !bytes.is_empty() && bytes[0] == 0 { let bytes = if count_leading_1 == 0 && !bytes.is_empty() && bytes[0] == 0 {
&bytes[1..] &bytes[1..]
} else { } else {
&bytes[count_leading_1..] &bytes[count_leading_1 as usize..]
}; };
str_base58.push_str(&bs58::encode(bytes).into_string()); str_base58.push_str(&bs58::encode(bytes).into_string());
......
...@@ -42,8 +42,9 @@ use std::marker::PhantomData; ...@@ -42,8 +42,9 @@ use std::marker::PhantomData;
use unwrap::unwrap; use unwrap::unwrap;
use zeroize::Zeroize; use zeroize::Zeroize;
/// Maximal size of a public key in bytes /// Size of a public key in bytes
pub const PUBKEY_SIZE_IN_BYTES: usize = 32; pub const PUBKEY_SIZE_IN_BYTES: usize = 33;
const PUBKEY_INTERNAL_SIZE_IN_BYTES: usize = 32;
/// constf a signature in bytes /// constf a signature in bytes
pub const SIG_SIZE_IN_BYTES: usize = 64; pub const SIG_SIZE_IN_BYTES: usize = 64;
...@@ -157,8 +158,8 @@ impl Eq for Signature {} ...@@ -157,8 +158,8 @@ impl Eq for Signature {}
#[cfg_attr(feature = "ser", derive(Deserialize, Serialize))] #[cfg_attr(feature = "ser", derive(Deserialize, Serialize))]
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct PublicKey { pub struct PublicKey {
datas: [u8; 32], pub(crate) datas: [u8; 32],
count_leading_zero: usize, count_leading_zero: u8,
} }
impl Default for PublicKey { impl Default for PublicKey {
...@@ -172,7 +173,7 @@ impl Default for PublicKey { ...@@ -172,7 +173,7 @@ impl Default for PublicKey {
impl AsRef<[u8]> for PublicKey { impl AsRef<[u8]> for PublicKey {
fn as_ref(&self) -> &[u8] { fn as_ref(&self) -> &[u8] {
&self.datas[..] unsafe { std::slice::from_raw_parts(self.datas.as_ptr(), PUBKEY_SIZE_IN_BYTES) }
} }
} }
...@@ -186,11 +187,17 @@ impl TryFrom<&[u8]> for PublicKey { ...@@ -186,11 +187,17 @@ impl TryFrom<&[u8]> for PublicKey {
found: bytes.len(), found: bytes.len(),
}) })
} else { } else {
let mut u8_array = [0; PUBKEY_SIZE_IN_BYTES]; let mut u8_array = [0; PUBKEY_INTERNAL_SIZE_IN_BYTES];
u8_array[(PUBKEY_SIZE_IN_BYTES - bytes.len())..].copy_from_slice(&bytes); let count_leading_zero = if bytes.len() <= PUBKEY_INTERNAL_SIZE_IN_BYTES {
u8_array[(PUBKEY_INTERNAL_SIZE_IN_BYTES - bytes.len())..].copy_from_slice(&bytes);
0
} else {
u8_array.copy_from_slice(&bytes[..PUBKEY_INTERNAL_SIZE_IN_BYTES]);
bytes[PUBKEY_INTERNAL_SIZE_IN_BYTES]
};
Ok(PublicKey { Ok(PublicKey {
datas: u8_array, datas: u8_array,
count_leading_zero: 0, count_leading_zero,
}) })
} }
} }
...@@ -198,7 +205,7 @@ impl TryFrom<&[u8]> for PublicKey { ...@@ -198,7 +205,7 @@ impl TryFrom<&[u8]> for PublicKey {
impl ToBase58 for PublicKey { impl ToBase58 for PublicKey {
fn to_base58(&self) -> String { fn to_base58(&self) -> String {
bytes_to_str_base58(self.as_ref(), self.count_leading_zero) bytes_to_str_base58(self.datas.as_ref(), self.count_leading_zero)
} }
} }
...@@ -207,7 +214,7 @@ impl Display for PublicKey { ...@@ -207,7 +214,7 @@ impl Display for PublicKey {
write!( write!(
f, f,
"{}", "{}",
bytes_to_str_base58(self.as_ref(), self.count_leading_zero) bytes_to_str_base58(self.datas.as_ref(), self.count_leading_zero)
) )
} }
} }
...@@ -236,7 +243,7 @@ impl super::PublicKey for PublicKey { ...@@ -236,7 +243,7 @@ impl super::PublicKey for PublicKey {
} }
fn verify(&self, message: &[u8], signature: &Self::Signature) -> Result<(), SigError> { fn verify(&self, message: &[u8], signature: &Self::Signature) -> Result<(), SigError> {
Ok(UnparsedPublicKey::new(&ED25519, self.as_ref()) Ok(UnparsedPublicKey::new(&ED25519, self.datas.as_ref())
.verify(message, &signature.0) .verify(message, &signature.0)
.map_err(|_| SigError::InvalidSig)?) .map_err(|_| SigError::InvalidSig)?)
} }
...@@ -292,7 +299,7 @@ impl super::KeyPair for Ed25519KeyPair { ...@@ -292,7 +299,7 @@ impl super::KeyPair for Ed25519KeyPair {
fn generate_signator(&self) -> Result<Self::Signator, super::SignError> { fn generate_signator(&self) -> Result<Self::Signator, super::SignError> {
Ok(Signator( Ok(Signator(
RingKeyPair::from_seed_and_public_key(self.seed.as_ref(), self.pubkey.as_ref()) RingKeyPair::from_seed_and_public_key(self.seed.as_ref(), self.pubkey.datas.as_ref())
.map_err(|_| super::SignError::CorruptedKeyPair)?, .map_err(|_| super::SignError::CorruptedKeyPair)?,
)) ))
} }
...@@ -448,13 +455,6 @@ mod tests { ...@@ -448,13 +455,6 @@ mod tests {
assert!(!seed.eq(&other_seed)); assert!(!seed.eq(&other_seed));
// Test seed parsing // Test seed parsing
/*assert_eq!(
Seed32::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQd",).unwrap_err(),
BaseConvertionError::InvalidLength {
found: 31,
expected: 32
}
);*/
assert_eq!( assert_eq!(
Seed32::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQd<<").unwrap_err(), Seed32::from_base58("DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQd<<").unwrap_err(),
BaseConvertionError::InvalidCharacter { BaseConvertionError::InvalidCharacter {
...@@ -465,24 +465,67 @@ mod tests { ...@@ -465,24 +465,67 @@ mod tests {
} }
#[test] #[test]
fn test_pubkey_111_from_base58() { fn test_pubkey_111_from_base58() -> Result<(), bincode::Error> {
let public58 = "11111111111111111111111111111111111111111111"; let public58 = "11111111111111111111111111111111111111111111";
let _ = unwrap!(super::PublicKey::from_base58(public58)); let public_key = unwrap!(super::PublicKey::from_base58(public58));
assert_eq!(
&[
0u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 44
][..],
public_key.as_ref(),
);
assert_eq!(
bincode::serialize(&public_key)?,
public_key.to_bytes_vector(),
);
Ok(())
} }
#[test] #[test]
fn base58_public_key() { fn test_pubkey_with_leading_1() -> Result<(), bincode::Error> {
let public58 = "13fn6X3XWVgshHTgS8beZMo9XiyScx6MB6yPsBB5ZBia";
let public_key = unwrap!(super::PublicKey::from_base58(public58));
assert_eq!(
bincode::serialize(&public_key)?,
public_key.to_bytes_vector(),
);
Ok(())
}
#[test]
fn test_other_pubkey_with_leading_1() -> Result<(), bincode::Error> {
let public58 = "1V27SH9TiVEDs8TWFPydpRKxhvZari7wjGwQnPxMnkr";
let public_key = unwrap!(super::PublicKey::from_base58(public58));
assert_eq!(
bincode::serialize(&public_key)?,
public_key.to_bytes_vector(),
);
Ok(())
}
#[test]
fn base58_public_key() -> Result<(), bincode::Error> {
let public58 = "DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV"; let public58 = "DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV";
let public_key = unwrap!(super::PublicKey::from_base58(public58)); let public_key = unwrap!(super::PublicKey::from_base58(public58));
// Test base58 encoding/decoding (loop for every bytes) // Test base58 encoding/decoding (loop for every bytes)
assert_eq!(public_key.to_base58(), public58); assert_eq!(public_key.to_base58(), public58);
let public_raw = unwrap!(b58::str_base58_to_32bytes(public58)); let public_raw = unwrap!(b58::str_base58_to_32bytes(public58));
assert_eq!(public_raw.0.to_vec(), public_key.to_bytes_vector()); assert_eq!(
for (key, raw) in public_key.as_ref().iter().zip(public_raw.0.iter()) { public_raw.0.to_vec(),
&public_key.to_bytes_vector()[..PUBKEY_INTERNAL_SIZE_IN_BYTES]
);
for (key, raw) in public_key.datas.as_ref().iter().zip(public_raw.0.iter()) {
assert_eq!(key, raw); assert_eq!(key, raw);
} }
// Test binary encoding/decoding
assert_eq!(
bincode::serialize(&public_key)?,
public_key.to_bytes_vector(),
);
// Test pubkey debug // Test pubkey debug
assert_eq!( assert_eq!(
"PublicKey { DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV }".to_owned(), "PublicKey { DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV }".to_owned(),
...@@ -490,8 +533,8 @@ mod tests { ...@@ -490,8 +533,8 @@ mod tests {
); );
// Test pubkey with 43 characters // Test pubkey with 43 characters
let pubkey43 = let pubkey43 = super::PublicKey::from_base58("2nV7Dv4nhTJ9dZUvRJpL34vFP9b2BkDjKWv9iBW2JaR")
super::PublicKey::from_base58("2nV7Dv4nhTJ9dZUvRJpL34vFP9b2BkDjKWv9iBW2JaR").unwrap(); .expect("invalid pubkey");
println!("pubkey43={:?}", pubkey43.as_ref()); println!("pubkey43={:?}", pubkey43.as_ref());
assert_eq!( assert_eq!(
format!("{:?}", pubkey43), format!("{:?}", pubkey43),
...@@ -505,6 +548,7 @@ mod tests { ...@@ -505,6 +548,7 @@ mod tests {
offset: 42 offset: 42
} }
); );
Ok(())
} }
#[test] #[test]
...@@ -536,7 +580,7 @@ mod tests { ...@@ -536,7 +580,7 @@ mod tests {
signature.hash(&mut hasher); signature.hash(&mut hasher);
let hash1 = hasher.finish(); let hash1 = hasher.finish();
let mut hasher = DefaultHasher::new(); let mut hasher = DefaultHasher::new();
let signature_copy = signature.clone(); let signature_copy = signature;
signature_copy.hash(&mut hasher); signature_copy.hash(&mut hasher);
let hash2 = hasher.finish(); let hash2 = hasher.finish();
assert_eq!(hash1, hash2); assert_eq!(hash1, hash2);
......
...@@ -506,7 +506,7 @@ mod tests { ...@@ -506,7 +506,7 @@ mod tests {
} }
#[test] #[test]
fn pubkey() { fn public_key() {
let ed25519_pubkey_default = ed25519::PublicKey::default(); let ed25519_pubkey_default = ed25519::PublicKey::default();
let pubkey_default = PubKey::Ed25519(ed25519_pubkey_default); let pubkey_default = PubKey::Ed25519(ed25519_pubkey_default);
let pubkey = PubKey::Ed25519(unwrap!(ed25519::PublicKey::try_from( let pubkey = PubKey::Ed25519(unwrap!(ed25519::PublicKey::try_from(
...@@ -520,14 +520,16 @@ mod tests { ...@@ -520,14 +520,16 @@ mod tests {
); );
assert_eq!(pubkey.size_in_bytes(), ed25519::PUBKEY_SIZE_IN_BYTES + 3); assert_eq!(pubkey.size_in_bytes(), ed25519::PUBKEY_SIZE_IN_BYTES + 3);
assert_eq!("1111111111111111111111111111111", &format!("{}", pubkey)); assert_eq!("11111111111111111111111111111111", &format!("{}", pubkey));
assert_eq!(KeysAlgo::Ed25519, pubkey.algo()); assert_eq!(KeysAlgo::Ed25519, pubkey.algo());
assert_eq!(KeysAlgo::Schnorr, PubKey::Schnorr().algo()); assert_eq!(KeysAlgo::Schnorr, PubKey::Schnorr().algo());
assert_eq!([0u8; 32].to_vec(), pubkey.to_bytes_vector()); let mut expected_vec = [0u8; 32].to_vec();
expected_vec.push(32);
assert_eq!(expected_vec, pubkey.to_bytes_vector());
assert_eq!("1111111111111111111111111111111", &pubkey.to_base58()); assert_eq!("11111111111111111111111111111111", &pubkey.to_base58());
assert_eq!( assert_eq!(
Err(SigError::InvalidSig), Err(SigError::InvalidSig),
...@@ -720,11 +722,11 @@ mod tests { ...@@ -720,11 +722,11 @@ mod tests {
assert_eq!( assert_eq!(
Err(PubkeyFromBytesError::InvalidBytesLen { Err(PubkeyFromBytesError::InvalidBytesLen {
expected: ed25519::PUBKEY_SIZE_IN_BYTES, expected: ed25519::PUBKEY_SIZE_IN_BYTES,
found: 33, found: 34,
}), }),
PubKey::from_bytes(&[ PubKey::from_bytes(&[
0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 31 23, 24, 25, 26, 27, 28, 29, 30, 31, 31, 17
]), ]),
); );
} }
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
missing_copy_implementations, missing_copy_implementations,
trivial_casts, trivial_casts,
trivial_numeric_casts, trivial_numeric_casts,
unsafe_code,
unstable_features, unstable_features,
unused_import_braces, unused_import_braces,
unused_qualifications unused_qualifications
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment