diff --git a/Cargo.toml b/Cargo.toml index 829e3a5..83f6a45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lamport_sigs" -version = "0.1.1" +version = "1.0.0" authors = ["Frederic Jacobs "] description = "lamport_sigs is a Rust implementation of the Lamport one-time signature scheme." license = "BSD-3-Clause" diff --git a/docs/implementors/core/clone/trait.Clone.js b/docs/implementors/core/clone/trait.Clone.js new file mode 100644 index 0000000..cb902ec --- /dev/null +++ b/docs/implementors/core/clone/trait.Clone.js @@ -0,0 +1,10 @@ +(function() {var implementors = {}; +implementors["lamport_sigs"] = ["impl Clone for PublicKey","impl Clone for PrivateKey",]; + + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } + +})() diff --git a/docs/implementors/core/cmp/trait.PartialEq.js b/docs/implementors/core/cmp/trait.PartialEq.js index 9784f78..628bb31 100644 --- a/docs/implementors/core/cmp/trait.PartialEq.js +++ b/docs/implementors/core/cmp/trait.PartialEq.js @@ -1,5 +1,5 @@ (function() {var implementors = {}; -implementors["lamport"] = ["impl<T: Digest + Clone> PartialEq for PrivateKey<T>",]; +implementors["lamport_sigs"] = ["impl PartialEq for PrivateKey",]; if (window.register_implementors) { window.register_implementors(implementors); diff --git a/docs/implementors/core/convert/trait.From.js b/docs/implementors/core/convert/trait.From.js new file mode 100644 index 0000000..50b6ee2 --- /dev/null +++ b/docs/implementors/core/convert/trait.From.js @@ -0,0 +1,10 @@ +(function() {var implementors = {}; +implementors["lamport_sigs"] = ["impl From<PublicKey> for Vec<u8>",]; + + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } + +})() diff --git a/docs/implementors/core/fmt/trait.Debug.js b/docs/implementors/core/fmt/trait.Debug.js new file mode 100644 index 0000000..53a2b92 --- /dev/null +++ b/docs/implementors/core/fmt/trait.Debug.js @@ -0,0 +1,10 @@ +(function() {var implementors = {}; +implementors["lamport_sigs"] = ["impl Debug for PublicKey","impl Debug for PrivateKey",]; + + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } + +})() diff --git a/docs/implementors/core/ops/trait.Drop.js b/docs/implementors/core/ops/trait.Drop.js index 24f4c44..c07f090 100644 --- a/docs/implementors/core/ops/trait.Drop.js +++ b/docs/implementors/core/ops/trait.Drop.js @@ -1,5 +1,5 @@ (function() {var implementors = {}; -implementors["lamport"] = ["impl<T: Digest + Clone> Drop for PrivateKey<T>",]; +implementors["lamport_sigs"] = ["impl Drop for PrivateKey",]; if (window.register_implementors) { window.register_implementors(implementors); diff --git a/docs/lamport/sidebar-items.js b/docs/lamport/sidebar-items.js deleted file mode 100644 index fcc4914..0000000 --- a/docs/lamport/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["PrivateKey","A one-time signing private key"],["PublicKey","A one-time signing public key"]]}); \ No newline at end of file diff --git a/docs/lamport_sigs/LamportSignatureData.t.html b/docs/lamport_sigs/LamportSignatureData.t.html new file mode 100644 index 0000000..81c2d5a --- /dev/null +++ b/docs/lamport_sigs/LamportSignatureData.t.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to type.LamportSignatureData.html...

+ + + \ No newline at end of file diff --git a/docs/lamport/PrivateKey.t.html b/docs/lamport_sigs/PrivateKey.t.html similarity index 100% rename from docs/lamport/PrivateKey.t.html rename to docs/lamport_sigs/PrivateKey.t.html diff --git a/docs/lamport/PublicKey.t.html b/docs/lamport_sigs/PublicKey.t.html similarity index 100% rename from docs/lamport/PublicKey.t.html rename to docs/lamport_sigs/PublicKey.t.html diff --git a/docs/lamport/index.html b/docs/lamport_sigs/index.html similarity index 79% rename from docs/lamport/index.html rename to docs/lamport_sigs/index.html index 25a49d8..63cdba1 100644 --- a/docs/lamport/index.html +++ b/docs/lamport_sigs/index.html @@ -4,10 +4,10 @@ - - + + - lamport - Rust + lamport_sigs - Rust @@ -28,7 +28,7 @@
-

Crate lamport +

Crate lamport_sigs [] - [src]

+
[src]

lamport implements one-time hash-based signatures using the Lamport signature scheme.

Structs

+ title='lamport_sigs::PrivateKey'>PrivateKey + title='lamport_sigs::PublicKey'>PublicKey +
PrivateKey

A one-time signing private key

PublicKey

A one-time signing public key

Type Definitions

+ + + +
LamportSignatureData +

A type alias defining a Lamport signature

+
@@ -119,10 +127,12 @@ + \ No newline at end of file diff --git a/docs/lamport_sigs/sidebar-items.js b/docs/lamport_sigs/sidebar-items.js new file mode 100644 index 0000000..99d609f --- /dev/null +++ b/docs/lamport_sigs/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["PrivateKey","A one-time signing private key"],["PublicKey","A one-time signing public key"]],"type":[["LamportSignatureData","A type alias defining a Lamport signature"]]}); \ No newline at end of file diff --git a/docs/lamport/struct.PrivateKey.html b/docs/lamport_sigs/struct.PrivateKey.html similarity index 51% rename from docs/lamport/struct.PrivateKey.html rename to docs/lamport_sigs/struct.PrivateKey.html index 5450827..63de697 100644 --- a/docs/lamport/struct.PrivateKey.html +++ b/docs/lamport_sigs/struct.PrivateKey.html @@ -4,10 +4,10 @@ - + - lamport::PrivateKey - Rust + lamport_sigs::PrivateKey - Rust @@ -28,7 +28,7 @@
-

Struct lamport::PrivateKey +

Struct lamport_sigs::PrivateKey [] - [src]

-
pub struct PrivateKey<T: Digest + Clone> { /* fields omitted */ }

A one-time signing private key

-

Methods

impl<T: Digest + Clone> PrivateKey<T>
[src]

-

+ [src]

+
pub struct PrivateKey { /* fields omitted */ }

A one-time signing private key

+

Methods

impl PrivateKey
[src]

+

Generates a new random one-time signing key. This method can panic if OS RNG fails

-

+

Returns the public key associated with this private key

-

+

Signs the data with the private key and returns the result if successful. If unsuccesful, an explanation string is returned

-

Trait Implementations

impl<T: Digest + Clone> Drop for PrivateKey<T>
[src]

+

Trait Implementations

impl Clone for PrivateKey
[src]

+

+

Returns a copy of the value. Read more

+

+

Performs copy-assignment from source. Read more

+

impl Debug for PrivateKey
[src]

+

+

Formats the value using the given formatter.

+

impl Drop for PrivateKey
[src]

A method called when the value goes out of scope. Read more

-

impl<T: Digest + Clone> PartialEq for PrivateKey<T>
[src]

-

+

impl PartialEq for PrivateKey
[src]

+

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

@@ -120,10 +128,12 @@ If unsuccesful, an explanation string is returned

+ \ No newline at end of file diff --git a/docs/lamport_sigs/struct.PublicKey.html b/docs/lamport_sigs/struct.PublicKey.html new file mode 100644 index 0000000..ce56e2b --- /dev/null +++ b/docs/lamport_sigs/struct.PublicKey.html @@ -0,0 +1,131 @@ + + + + + + + + + + lamport_sigs::PublicKey - Rust + + + + + + + + + + + + + + + + + +
+

Struct lamport_sigs::PublicKey + + [] + + [src]

+
pub struct PublicKey { /* fields omitted */ }

A one-time signing public key

+

Methods

impl PublicKey
[src]

+

+

Intializes a public key with a byte vector. +Returns None if it couldn't parse the provided data

+

+

Serializes a public key into a byte vector

+

+

Verifies that the signature of the data is correctly signed with the given key

+

Trait Implementations

impl Clone for PublicKey
[src]

+

+

Returns a copy of the value. Read more

+

+

Performs copy-assignment from source. Read more

+

impl Debug for PublicKey
[src]

+

+

Formats the value using the given formatter.

+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/lamport/struct.PublicKey.html b/docs/lamport_sigs/type.LamportSignatureData.html similarity index 54% rename from docs/lamport/struct.PublicKey.html rename to docs/lamport_sigs/type.LamportSignatureData.html index 622d44a..79b0623 100644 --- a/docs/lamport/struct.PublicKey.html +++ b/docs/lamport_sigs/type.LamportSignatureData.html @@ -4,10 +4,10 @@ - - + + - lamport::PublicKey - Rust + lamport_sigs::LamportSignatureData - Rust @@ -28,7 +28,7 @@ -
-

Struct lamport::PublicKey +
+

Type Definition lamport_sigs::LamportSignatureData [] - [src]

-
pub struct PublicKey<T: Digest + Clone> { /* fields omitted */ }

A one-time signing public key

-

Methods

impl<T: Digest + Clone> PublicKey<T>
[src]

-

-

Verifies that the signature of the data is correctly signed with the given key

-
+
[src]

+
type LamportSignatureData = Vec<Vec<u8>>;

A type alias defining a Lamport signature

+
@@ -107,10 +104,12 @@ + \ No newline at end of file diff --git a/docs/playpen.js b/docs/playpen.js new file mode 100644 index 0000000..cad97c0 --- /dev/null +++ b/docs/playpen.js @@ -0,0 +1,43 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*jslint browser: true, es5: true */ +/*globals $: true, rootPath: true */ + +document.addEventListener('DOMContentLoaded', function() { + 'use strict'; + + if (!window.playgroundUrl) { + return; + } + + var featureRegexp = new RegExp('^\s*#!\\[feature\\(\.*?\\)\\]'); + var elements = document.querySelectorAll('pre.rust-example-rendered'); + + Array.prototype.forEach.call(elements, function(el) { + el.onmouseover = function(e) { + if (el.contains(e.relatedTarget)) { + return; + } + + var a = el.querySelectorAll('a.test-arrow')[0]; + + var code = el.previousElementSibling.textContent; + + var channel = ''; + if (featureRegexp.test(code)) { + channel = '&version=nightly'; + } + + a.setAttribute('href', window.playgroundUrl + '?code=' + + encodeURIComponent(code) + channel); + }; + }); +}); diff --git a/docs/rustdoc.css b/docs/rustdoc.css index f49b855..cad5fae 100644 --- a/docs/rustdoc.css +++ b/docs/rustdoc.css @@ -570,11 +570,8 @@ pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val, pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; } pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } pre.rust .lifetime { color: #B76514; } -pre.rust .question-mark { - color: #ff9011; - font-weight: bold; -} +.rusttest { display: none; } pre.rust { position: relative; } a.test-arrow { background-color: rgba(78, 139, 202, 0.2); @@ -588,7 +585,6 @@ a.test-arrow { } a.test-arrow:hover{ background-color: #4e8bca; - text-decoration: none; } .section-header:hover a:after { diff --git a/docs/search-index.js b/docs/search-index.js index 1f5a363..4378332 100644 --- a/docs/search-index.js +++ b/docs/search-index.js @@ -1,3 +1,3 @@ var searchIndex = {}; -searchIndex["lamport"] = {"doc":"*lamport* implements one-time hash-based signatures using the Lamport signature scheme.","items":[[3,"PublicKey","lamport","A one-time signing public key",null,null],[3,"PrivateKey","","A one-time signing private key",null,null],[11,"verify_signature","","Verifies that the signature of the data is correctly signed with the given key",0,null],[11,"new","","Generates a new random one-time signing key. This method can panic if OS RNG fails",1,{"inputs":[{"name":"t"}],"output":{"name":"privatekey"}}],[11,"public_key","","Returns the public key associated with this private key",1,null],[11,"sign","","Signs the data with the private key and returns the result if successful.\nIf unsuccesful, an explanation string is returned",1,null],[11,"drop","","",1,null],[11,"eq","","",1,null]],"paths":[[3,"PublicKey"],[3,"PrivateKey"]]}; +searchIndex["lamport_sigs"] = {"doc":"*lamport* implements one-time hash-based signatures using the Lamport signature scheme.","items":[[3,"PublicKey","lamport_sigs","A one-time signing public key",null,null],[3,"PrivateKey","","A one-time signing private key",null,null],[6,"LamportSignatureData","","A type alias defining a Lamport signature",null,null],[11,"clone","","",0,null],[11,"fmt","","",0,null],[11,"clone","","",1,null],[11,"fmt","","",1,null],[11,"from_vec","","Intializes a public key with a byte vector.\nReturns `None` if it couldn't parse the provided data",0,{"inputs":[{"name":"vec"},{"name":"algorithm"}],"output":{"name":"option"}}],[11,"to_bytes","","Serializes a public key into a byte vector",0,null],[11,"verify_signature","","Verifies that the signature of the data is correctly signed with the given key",0,null],[11,"new","","Generates a new random one-time signing key. This method can panic if OS RNG fails",1,{"inputs":[{"name":"algorithm"}],"output":{"name":"privatekey"}}],[11,"public_key","","Returns the public key associated with this private key",1,null],[11,"sign","","Signs the data with the private key and returns the result if successful.\nIf unsuccesful, an explanation string is returned",1,null],[11,"drop","","",1,null],[11,"eq","","",1,null]],"paths":[[3,"PublicKey"],[3,"PrivateKey"]]}; initSearch(searchIndex); diff --git a/docs/src/lamport/src/lib.rs.html b/docs/src/lamport_sigs/src/lib.rs.html similarity index 52% rename from docs/src/lamport/src/lib.rs.html rename to docs/src/lamport_sigs/src/lib.rs.html index 5015ee0..2635751 100644 --- a/docs/src/lamport/src/lib.rs.html +++ b/docs/src/lamport_sigs/src/lib.rs.html @@ -243,61 +243,168 @@ 199 200 201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248
 //! *lamport* implements one-time hash-based signatures using the Lamport signature scheme.
 
-extern crate crypto;
+#![deny(
+    missing_docs,
+    missing_debug_implementations, missing_copy_implementations,
+    trivial_casts, trivial_numeric_casts,
+    unsafe_code, unstable_features,
+    unused_import_braces, unused_qualifications
+)]
+
+extern crate ring;
 extern crate rand;
 
 use rand::OsRng;
 use rand::Rng;
-use crypto::digest::Digest;
+use ring::digest::{ Algorithm, Context };
+
+/// A type alias defining a Lamport signature
+pub type LamportSignatureData = Vec<Vec<u8>>;
 
 /// A one-time signing public key
-pub struct PublicKey<T: Digest + Clone> {
+#[derive(Clone, Debug)]
+pub struct PublicKey {
     zero_values: Vec<Vec<u8>>,
-    one_values:  Vec<Vec<u8>>,
-    digest: T
+    one_values: Vec<Vec<u8>>,
+    algorithm: &'static Algorithm,
 }
 
 /// A one-time signing private key
-pub struct PrivateKey<T: Digest + Clone> {
-    zero_values: Vec<Vec<u8>>, // For a n bits hash function: (n * n/8 bytes) for zero_values and one_values
-    one_values:  Vec<Vec<u8>>,
-    digest: T,
-    used: bool
+#[derive(Clone, Debug)]
+pub struct PrivateKey {
+    // For a n bits hash function: (n * n/8 bytes) for zero_values and one_values
+    zero_values: Vec<Vec<u8>>,
+    one_values: Vec<Vec<u8>>,
+    algorithm: &'static Algorithm,
+    used: bool,
 }
 
-impl<T: Digest + Clone> PublicKey<T> {
-    /// Verifies that the signature of the data is correctly signed with the given key
-    pub fn verify_signature(    &self,
-                                signature: &Vec<Vec<u8>>,
-                                data:&[u8],
-                                ) -> bool
-    {
-        let mut digest = self.digest.clone();
-        digest.input(data);
-        let mut data_hash = vec![0 as u8; digest.output_bytes()];
-        digest.result(data_hash.as_mut_slice());
-        digest.reset();
+impl From<PublicKey> for Vec<u8> {
+    fn from(original: PublicKey) -> Vec<u8> {
+        original.to_bytes()
+    }
+}
 
-        for i in 0..data_hash.len() {
-            let byte = data_hash[i];
+impl PublicKey {
+    /// Intializes a public key with a byte vector.
+    /// Returns `None` if it couldn't parse the provided data
+    pub fn from_vec(vec: Vec<u8>, algorithm: &'static Algorithm) -> Option<PublicKey> {
+        let size = vec.len();
+        let hash_output_size = algorithm.output_len;
+
+        let mut zero_values_merged = vec;
+        let one_values_merged = zero_values_merged.split_off(size / 2);
+
+        let mut zero_values = Vec::new();
+        for i in (0..zero_values_merged.len()).filter(|x| x % hash_output_size == 0) {
+            // indexes for heads
+            let mut sub_vec = Vec::new();
+            for j in 0..hash_output_size {
+                sub_vec.push(zero_values_merged[i + j]);
+            }
+
+            zero_values.push(sub_vec);
+        }
+
+        let mut one_values = Vec::new();
+        for i in (0..one_values_merged.len()).filter(|x| x % hash_output_size == 0) {
+            // indexes for heads
+            let mut sub_vec = Vec::new();
+            for j in 0..hash_output_size {
+                sub_vec.push(one_values_merged[i + j]);
+            }
+
+            one_values.push(sub_vec);
+        }
+
+        Some(PublicKey {
+            zero_values: zero_values,
+            one_values: one_values,
+            algorithm: algorithm,
+        })
+    }
+
+    /// Serializes a public key into a byte vector
+    pub fn to_bytes(&self) -> Vec<u8> {
+        self.zero_values.iter().chain(self.one_values.iter()).fold(Vec::new(), |mut acc, i| {
+            acc.append(&mut i.clone());
+            acc
+        })
+    }
+
+    /// Verifies that the signature of the data is correctly signed with the given key
+    pub fn verify_signature(&self, signature: &LamportSignatureData, data: &[u8]) -> bool {
+        let mut context = Context::new(self.algorithm);
+        context.update(data);
+        let result = context.finish();
+        let data_hash = result.as_ref();
+
+        for (i, byte) in data_hash.iter().enumerate() {
             for j in 0..8 {
-                let offset = i*8 + j;
-                if (byte & (1<<j)) > 0 {
-                    digest.input(signature[offset].as_slice());
-                    let mut hashed_value = vec![0 as u8; digest.output_bytes()];
-                    digest.result(hashed_value.as_mut_slice());
-                    digest.reset();
+                let offset = i * 8 + j;
+                if (byte & (1 << j)) > 0 {
+                    let mut context = Context::new(self.algorithm);
+                    context.update(signature[offset].as_slice());
+                    let hashed_value = Vec::from(context.finish().as_ref());
+
                     if hashed_value != self.one_values[offset] {
                         return false;
                     }
                 } else {
-                    digest.input(signature[offset].as_slice());
-                    let mut hashed_value = vec![0 as u8; digest.output_bytes()];
-                    digest.result(hashed_value.as_mut_slice());
-                    digest.reset();
+                    let mut context = Context::new(self.algorithm);
+                    context.update(signature[offset].as_slice());
+                    let hashed_value = Vec::from(context.finish().as_ref());
+
                     if hashed_value != self.zero_values[offset] {
                         return false;
                     }
@@ -305,81 +412,83 @@
             }
         }
 
-        return true;
+        true
     }
 }
 
-impl <T: Digest + Clone> PrivateKey<T> {
+impl PrivateKey {
     /// Generates a new random one-time signing key. This method can panic if OS RNG fails
-    pub fn new(digest: T) -> PrivateKey<T> {
-        let generate_bit_hash_values = |hasher: &T| -> Vec<Vec<u8>> {
+    pub fn new(algorithm: &'static Algorithm) -> PrivateKey {
+        let generate_bit_hash_values = || -> Vec<Vec<u8>> {
             let mut rng = match OsRng::new() {
                 Ok(g) => g,
-                Err(e) => panic!("Failed to obtain OS RNG: {}", e)
+                Err(e) => panic!("Failed to obtain OS RNG: {}", e),
             };
-            let buffer_byte = vec![0 as u8; hasher.output_bytes()];
-            let mut buffer  = vec![buffer_byte; hasher.output_bits()];
+            let buffer_byte = vec![0u8; algorithm.output_len];
+            let mut buffer = vec![buffer_byte; algorithm.output_len * 8];
 
-            for hash in buffer.iter_mut() {
+            for hash in &mut buffer {
                 rng.fill_bytes(hash)
             }
 
-            return buffer;
+            buffer
         };
 
-        let zero_values = generate_bit_hash_values(&digest);
-        let one_values  = generate_bit_hash_values(&digest);
+        let zero_values = generate_bit_hash_values();
+        let one_values  = generate_bit_hash_values();
 
-        return PrivateKey { zero_values: zero_values,
-                            one_values: one_values,
-                            digest: digest,
-                            used: false }
+        PrivateKey {
+            zero_values: zero_values,
+            one_values: one_values,
+            algorithm: algorithm,
+            used: false,
+        }
     }
 
     /// Returns the public key associated with this private key
-    pub fn public_key(&self) -> PublicKey<T> {
-        let mut digest = self.digest.clone();
+    pub fn public_key(&self) -> PublicKey {
+        let hash_values = |x: &Vec<Vec<u8>>| -> Vec<Vec<u8>> {
+            let buffer_byte = vec![0u8; self.algorithm.output_len];
+            let mut buffer  = vec![buffer_byte; self.algorithm.output_len * 8];
 
-        let hash_values = |x: &Vec<Vec<u8>>, hash_func: &mut Digest | -> Vec<Vec<u8>> {
-            let buffer_byte = vec![0 as u8; hash_func.output_bytes()];
-            let mut buffer  = vec![buffer_byte; hash_func.output_bits()];
-
-            for i in 0..hash_func.output_bits(){
-                hash_func.input(x[i].as_slice());
-                hash_func.result(buffer[i].as_mut_slice());
-                hash_func.reset();
+            for i in 0 .. self.algorithm.output_len * 8 {
+                let mut context = Context::new(self.algorithm);
+                context.update(x[i].as_slice());
+                buffer[i] = Vec::from(context.finish().as_ref());
             }
 
-            return buffer;
+            buffer
         };
 
-        let hashed_zero_values = hash_values(&self.zero_values, &mut digest);
-        let hashed_one_values  = hash_values(&self.one_values, &mut digest);
+        let hashed_zero_values = hash_values(&self.zero_values);
+        let hashed_one_values  = hash_values(&self.one_values);
 
-        return PublicKey { zero_values: hashed_zero_values,
-                            one_values: hashed_one_values,
-                            digest: digest }
+        PublicKey {
+            zero_values: hashed_zero_values,
+            one_values: hashed_one_values,
+            algorithm: self.algorithm,
+        }
     }
 
     /// Signs the data with the private key and returns the result if successful.
     /// If unsuccesful, an explanation string is returned
-    pub fn sign(&mut self, data: &[u8]) ->  Result<Vec<Vec<u8>>, &'static str> {
+    pub fn sign(&mut self, data: &[u8]) -> Result<LamportSignatureData, &'static str> {
         if self.used {
             return Err("Attempting to sign more than once.");
         }
-        self.digest.input(data);
-        let mut data_hash = vec![0 as u8; self.digest.output_bytes()];
-        self.digest.result(data_hash.as_mut_slice());
-        self.digest.reset();
+
+        let mut context = Context::new(self.algorithm);
+        context.update(data);
+        let result    = context.finish();
+        let data_hash = result.as_ref();
 
         let signature_len = data_hash.len() * 8;
         let mut signature = Vec::with_capacity(signature_len);
 
-        for i in 0..data_hash.len() {
-            let byte = data_hash[i];
+        for (i, byte) in data_hash.iter().enumerate() {
             for j in 0..8 {
-                let offset = i*8 + j;
-                if (byte & (1<<j)) > 0 {
+                let offset = i * 8 + j;
+                if (byte & (1 << j)) > 0 {
                     // Bit is 1
                     signature.push(self.one_values[offset].clone());
                 } else {
@@ -389,11 +498,11 @@
             }
         }
         self.used = true;
-        return Ok(signature);
+        Ok(signature)
     }
 }
 
-impl <T: Digest + Clone> Drop for PrivateKey<T> {
+impl Drop for PrivateKey {
     fn drop(&mut self) {
         let zeroize_vector = |vector: &mut Vec<Vec<u8>>| {
             for v2 in vector.iter_mut() {
@@ -408,9 +517,9 @@
     }
 }
 
-impl<T: Digest + Clone> PartialEq for PrivateKey<T> {
+impl PartialEq for PrivateKey {
     // ⚠️ This is not a constant-time implementation
-    fn eq(&self, other: &PrivateKey<T>) -> bool {
+    fn eq(&self, other: &PrivateKey) -> bool {
         if self.one_values.len() != other.one_values.len() {
             return false;
         }
@@ -419,32 +528,17 @@
         }
 
         for i in 0..self.zero_values.len() {
-            if self.zero_values[i] != other.zero_values[i] || self.one_values[i] != other.one_values[i] {
-                return false
+            if self.zero_values[i] != other.zero_values[i] ||
+               self.one_values[i] != other.one_values[i] {
+                return false;
             }
         }
-        return true;
+        true
     }
 }
 
 #[cfg(test)]
-use crypto::sha3::Sha3;
-#[test]
-fn test_public_key_length_256() {
-    let pk = PrivateKey::new(Sha3::sha3_256());
-    assert!(    pk.public_key().one_values.len() == 256 &&
-                pk.public_key().zero_values.len() == 256);
-}
-#[test]
-fn test_public_key_length_512() {
-    let pk = PrivateKey::new(Sha3::sha3_512());
-    assert!(    pk.public_key().one_values.len() == 512 &&
-                pk.public_key().zero_values.len() == 512);
-}
-
-
-#[cfg(test)]
-pub mod test;
+pub mod tests;
 
@@ -501,10 +595,12 @@ + \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index cbbf64b..e212357 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,13 @@ //! *lamport* implements one-time hash-based signatures using the Lamport signature scheme. +#![deny( + missing_docs, + missing_debug_implementations, missing_copy_implementations, + trivial_casts, trivial_numeric_casts, + unsafe_code, unstable_features, + unused_import_braces, unused_qualifications +)] + extern crate ring; extern crate rand; @@ -7,10 +15,11 @@ use rand::OsRng; use rand::Rng; use ring::digest::{ Algorithm, Context }; +/// A type alias defining a Lamport signature pub type LamportSignatureData = Vec>; /// A one-time signing public key -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct PublicKey { zero_values: Vec>, one_values: Vec>, @@ -18,7 +27,7 @@ pub struct PublicKey { } /// A one-time signing private key -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct PrivateKey { // For a n bits hash function: (n * n/8 bytes) for zero_values and one_values zero_values: Vec>, @@ -34,10 +43,8 @@ impl From for Vec { } impl PublicKey { - pub fn values(&self) -> (Vec>, Vec>) { - (self.zero_values.clone(), self.one_values.clone()) - } - + /// Intializes a public key with a byte vector. + /// Returns `None` if it couldn't parse the provided data pub fn from_vec(vec: Vec, algorithm: &'static Algorithm) -> Option { let size = vec.len(); let hash_output_size = algorithm.output_len; @@ -74,6 +81,7 @@ impl PublicKey { }) } + /// Serializes a public key into a byte vector pub fn to_bytes(&self) -> Vec { self.zero_values.iter().chain(self.one_values.iter()).fold(Vec::new(), |mut acc, i| { acc.append(&mut i.clone()); @@ -130,8 +138,6 @@ impl PrivateKey { rng.fill_bytes(hash) } - println!("{:?}", buffer); - buffer }; @@ -149,7 +155,7 @@ impl PrivateKey { /// Returns the public key associated with this private key pub fn public_key(&self) -> PublicKey { let hash_values = |x: &Vec>| -> Vec> { - let buffer_byte = vec![0 as u8; self.algorithm.output_len]; + let buffer_byte = vec![0u8; self.algorithm.output_len]; let mut buffer = vec![buffer_byte; self.algorithm.output_len * 8]; for i in 0 .. self.algorithm.output_len * 8 {