Fix PartialEq for PrivateKey

- If `one_values: Vec<Vec<u8>>` is different in `len()` than `zero_values`, the
  code can either panic, or it's possible different `PrivateKey`s are evaluated
  as equal.  In both these examples, at least one key would be of invalid
  structure, but there's nothing about the `PrivateKey` struct that enforces
  valid structure in this sense. Perhaps this is an argument to create
  key-length-specific types*.
- Algorithm equality is now checked.

* E.g.,

```rust
pub struct PrivateKey512 {
    zero_values: [[u8; 512 / 8]; 512],
    one_values: [[u8; 512 / 8]; 512],
    // ...
}
```
This commit is contained in:
Noah Vesely
2018-03-17 23:31:23 -06:00
committed by Romain Ruetschi
parent 86bc30fe56
commit e27418c384
2 changed files with 37 additions and 6 deletions

View File

@ -271,17 +271,24 @@ impl Drop for PrivateKey {
impl PartialEq for PrivateKey { impl PartialEq for PrivateKey {
// ⚠️ This is not a constant-time implementation // ⚠️ This is not a constant-time implementation
fn eq(&self, other: &PrivateKey) -> bool { fn eq(&self, other: &PrivateKey) -> bool {
if self.one_values.len() != other.one_values.len() { if self.algorithm != other.algorithm {
return false; return false;
} }
if self.zero_values.len() != other.zero_values.len() { // NOTE: The `zero_values` and `one_values` need not be of the
// the same length (and maybe this should change).
let zero_size = self.zero_values.len();
let one_size = self.one_values.len();
if zero_size != other.zero_values.len() || one_size != other.one_values.len() {
return false; return false;
} }
for i in 0..self.zero_values.len() { for i in 0..zero_size {
if self.zero_values[i] != other.zero_values[i] || if self.zero_values[i] != other.zero_values[i] {
self.one_values[i] != other.one_values[i] return false;
{ }
}
for i in 0..one_size {
if self.one_values[i] != other.one_values[i] {
return false; return false;
} }
} }

View File

@ -88,3 +88,27 @@ fn test_serialization_panic() {
assert_eq!(pub_key.one_values, recovered_pub_key.one_values); assert_eq!(pub_key.one_values, recovered_pub_key.one_values);
assert_eq!(pub_key.zero_values, recovered_pub_key.zero_values); assert_eq!(pub_key.zero_values, recovered_pub_key.zero_values);
} }
#[test]
fn test_private_key_equality() {
let mut pub_key = PrivateKey::new(digest_512);
let pub_key_2 = pub_key.clone();
assert!(pub_key == pub_key_2);
pub_key.one_values.push(vec![0]);
assert!(pub_key != pub_key_2);
let mut pub_key = PrivateKey::new(digest_512);
let pub_key_2 = pub_key.clone();
pub_key.one_values.pop();
assert!(pub_key != pub_key_2);
let mut pub_key = PrivateKey::new(digest_512);
let pub_key_2 = pub_key.clone();
pub_key.algorithm = digest_256;
assert!(pub_key != pub_key_2);
}