Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82bb499be3 | |||
| 20c65b93bf | |||
| 7c45f898ab | |||
| c675aaa5f6 | |||
| 6d4c9c4f50 | |||
| a34d8dc88b | |||
| b59653de57 | |||
| 3eee154fe1 |
@@ -13,12 +13,8 @@ base64 = "^0.10.1"
|
|||||||
byteorder = "^1.3.1"
|
byteorder = "^1.3.1"
|
||||||
chrono = "^0.4.6"
|
chrono = "^0.4.6"
|
||||||
cryptonum = { path = "cryptonum" }
|
cryptonum = { path = "cryptonum" }
|
||||||
digest = "^0.8.0"
|
|
||||||
hmac = "^0.7.0"
|
|
||||||
num = "^0.2.0"
|
num = "^0.2.0"
|
||||||
rand = "^0.6.5"
|
rand = "^0.6.5"
|
||||||
sha-1 = "^0.8.1"
|
|
||||||
sha2 = "^0.8.0"
|
|
||||||
simple_asn1 = "^0.2.0"
|
simple_asn1 = "^0.2.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@@ -5,10 +5,8 @@
|
|||||||
//! random number generator.
|
//! random number generator.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! extern crate sha2;
|
|
||||||
//!
|
|
||||||
//! use simple_crypto::dsa::{DSAKeyPair,DSAParameters,L2048N256};
|
//! use simple_crypto::dsa::{DSAKeyPair,DSAParameters,L2048N256};
|
||||||
//! use sha2::Sha224;
|
//! use simple_crypto::sha::SHA224;
|
||||||
//!
|
//!
|
||||||
//! // Generate a set of DSA parameters, assuming you don't have
|
//! // Generate a set of DSA parameters, assuming you don't have
|
||||||
//! // them already
|
//! // them already
|
||||||
@@ -25,8 +23,8 @@
|
|||||||
//! // using it. For example, to sign the vector [0,1,2,3,4] with SHA224
|
//! // using it. For example, to sign the vector [0,1,2,3,4] with SHA224
|
||||||
//! // and then verify that signature, we would write:
|
//! // and then verify that signature, we would write:
|
||||||
//! let msg = vec![0,1,2,3,4];
|
//! let msg = vec![0,1,2,3,4];
|
||||||
//! let sig = kp.private.sign::<Sha224>(&msg);
|
//! let sig = kp.private.sign::<SHA224>(&msg);
|
||||||
//! assert!( kp.public.verify::<Sha224>(&msg, &sig) );
|
//! assert!( kp.public.verify::<SHA224>(&msg, &sig) );
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use cryptonum::unsigned::{CryptoNum,Decoder,Encoder,ModExp,PrimeGen};
|
use cryptonum::unsigned::{CryptoNum,Decoder,Encoder,ModExp,PrimeGen};
|
||||||
use cryptonum::unsigned::{U192,U256,U1024,U2048,U3072};
|
use cryptonum::unsigned::{U192,U256,U1024,U2048,U3072};
|
||||||
use digest::Digest;
|
use sha::{Hash,SHA256};
|
||||||
use sha2::Sha256;
|
|
||||||
use simple_asn1::{ToASN1,ASN1Block,ASN1Class,ASN1EncodeErr};
|
use simple_asn1::{ToASN1,ASN1Block,ASN1Class,ASN1EncodeErr};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use utils::TranslateNums;
|
use utils::TranslateNums;
|
||||||
@@ -222,5 +221,5 @@ fn hash<T>(x: &T, len: usize) -> Vec<u8>
|
|||||||
while base.len() < bytelen {
|
while base.len() < bytelen {
|
||||||
base.insert(0,0);
|
base.insert(0,0);
|
||||||
}
|
}
|
||||||
Sha256::digest(&base).as_slice().to_vec()
|
SHA256::hash(&base)
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
use cryptonum::unsigned::*;
|
use cryptonum::unsigned::*;
|
||||||
use cryptonum::signed::ModInv;
|
use cryptonum::signed::ModInv;
|
||||||
use digest::{BlockInput,Digest,Input,FixedOutput,Reset};
|
|
||||||
use dsa::params::*;
|
use dsa::params::*;
|
||||||
use dsa::rfc6979::*;
|
use dsa::rfc6979::*;
|
||||||
use hmac::{Hmac,Mac};
|
use sha::Hash;
|
||||||
|
|
||||||
/// A DSA private key, parameterized by its DSA parameters (so that you don't
|
/// A DSA private key, parameterized by its DSA parameters (so that you don't
|
||||||
/// accidentally pass the wrong key to the wrong routine).
|
/// accidentally pass the wrong key to the wrong routine).
|
||||||
@@ -31,10 +30,7 @@ macro_rules! privkey_impls {
|
|||||||
DSAPrivateKey{ params, x }
|
DSAPrivateKey{ params, x }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sign<Hash>(&self, m: &[u8]) -> DSASignature<$ntype>
|
pub fn sign<H: Hash + Clone>(&self, m: &[u8]) -> DSASignature<$ntype>
|
||||||
where
|
|
||||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
|
||||||
Hmac<Hash>: Mac
|
|
||||||
{
|
{
|
||||||
// This algorithm is per RFC 6979, which has a nice, relatively
|
// This algorithm is per RFC 6979, which has a nice, relatively
|
||||||
// straightforward description of how to do DSA signing.
|
// straightforward description of how to do DSA signing.
|
||||||
@@ -47,7 +43,7 @@ macro_rules! privkey_impls {
|
|||||||
// As was noted in the description of bits2octets, the extra
|
// As was noted in the description of bits2octets, the extra
|
||||||
// modular reduction is no more than a conditional subtraction.
|
// modular reduction is no more than a conditional subtraction.
|
||||||
//
|
//
|
||||||
let h1 = <Hash>::digest(m);
|
let h1 = <H>::hash(m);
|
||||||
let n = $ptype::n_size();
|
let n = $ptype::n_size();
|
||||||
let h0: $ntype = bits2int(&h1, $ptype::n_size());
|
let h0: $ntype = bits2int(&h1, $ptype::n_size());
|
||||||
let q = &self.params.q;
|
let q = &self.params.q;
|
||||||
@@ -59,7 +55,7 @@ macro_rules! privkey_impls {
|
|||||||
// process used to generate k. In plain DSA or ECDSA, k should
|
// process used to generate k. In plain DSA or ECDSA, k should
|
||||||
// be selected through a random selection that chooses a value
|
// be selected through a random selection that chooses a value
|
||||||
// among the q-1 possible values with uniform probability.
|
// among the q-1 possible values with uniform probability.
|
||||||
for k in KIterator::<Hash,$ntype>::new(&h1, n, q, &self.x) {
|
for k in KIterator::<H,$ntype>::new(&h1, n, q, &self.x) {
|
||||||
// 3. A value r (modulo q) is computed from k and the key
|
// 3. A value r (modulo q) is computed from k and the key
|
||||||
// parameters:
|
// parameters:
|
||||||
// * For DSA:
|
// * For DSA:
|
||||||
@@ -111,7 +107,7 @@ macro_rules! generate_tests {
|
|||||||
use cryptonum::unsigned::Decoder;
|
use cryptonum::unsigned::Decoder;
|
||||||
use super::*;
|
use super::*;
|
||||||
use testing::run_test;
|
use testing::run_test;
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn verify() {
|
fn verify() {
|
||||||
@@ -141,10 +137,10 @@ macro_rules! generate_tests {
|
|||||||
let params = $params::new(p,g,q);
|
let params = $params::new(p,g,q);
|
||||||
let private = DSAPrivateKey::<$params>::new(params, x);
|
let private = DSAPrivateKey::<$params>::new(params, x);
|
||||||
let sig = match h {
|
let sig = match h {
|
||||||
224 => private.sign::<Sha224>(mbytes),
|
224 => private.sign::<SHA224>(mbytes),
|
||||||
256 => private.sign::<Sha256>(mbytes),
|
256 => private.sign::<SHA256>(mbytes),
|
||||||
384 => private.sign::<Sha384>(mbytes),
|
384 => private.sign::<SHA384>(mbytes),
|
||||||
512 => private.sign::<Sha512>(mbytes),
|
512 => private.sign::<SHA512>(mbytes),
|
||||||
_ => panic!("Unexpected hash {}", h)
|
_ => panic!("Unexpected hash {}", h)
|
||||||
};
|
};
|
||||||
assert_eq!(r, sig.r);
|
assert_eq!(r, sig.r);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use cryptonum::unsigned::*;
|
use cryptonum::unsigned::*;
|
||||||
use cryptonum::signed::ModInv;
|
use cryptonum::signed::ModInv;
|
||||||
use digest::Digest;
|
|
||||||
use dsa::params::*;
|
use dsa::params::*;
|
||||||
use dsa::rfc6979::DSASignature;
|
use dsa::rfc6979::DSASignature;
|
||||||
use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,ToASN1};
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,ToASN1};
|
||||||
|
use sha::Hash;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use utils::TranslateNums;
|
use utils::TranslateNums;
|
||||||
|
|
||||||
@@ -32,8 +32,7 @@ macro_rules! pubkey_impls {
|
|||||||
DSAPublicKey{ params, y }
|
DSAPublicKey{ params, y }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<$ntype>) -> bool
|
pub fn verify<H: Hash>(&self, m: &[u8], sig: &DSASignature<$ntype>) -> bool
|
||||||
where Hash: Digest
|
|
||||||
{
|
{
|
||||||
if sig.r >= self.params.q {
|
if sig.r >= self.params.q {
|
||||||
return false;
|
return false;
|
||||||
@@ -44,7 +43,7 @@ macro_rules! pubkey_impls {
|
|||||||
// w = (s')^-1 mod q;
|
// w = (s')^-1 mod q;
|
||||||
if let Some(w) = sig.s.modinv(&self.params.q) {
|
if let Some(w) = sig.s.modinv(&self.params.q) {
|
||||||
// z = the leftmost min(N, outlen) bits of Hash(M').
|
// z = the leftmost min(N, outlen) bits of Hash(M').
|
||||||
let mut digest_bytes = <Hash>::digest(m).to_vec();
|
let mut digest_bytes = <H>::hash(m);
|
||||||
let len = min(digest_bytes.len(), $ptype::n_size() / 8);
|
let len = min(digest_bytes.len(), $ptype::n_size() / 8);
|
||||||
digest_bytes.truncate(len);
|
digest_bytes.truncate(len);
|
||||||
let z = $ntype::from_bytes(&digest_bytes);
|
let z = $ntype::from_bytes(&digest_bytes);
|
||||||
@@ -95,7 +94,7 @@ macro_rules! generate_tests {
|
|||||||
use cryptonum::unsigned::Decoder;
|
use cryptonum::unsigned::Decoder;
|
||||||
use super::*;
|
use super::*;
|
||||||
use testing::run_test;
|
use testing::run_test;
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn verify() {
|
fn verify() {
|
||||||
@@ -126,10 +125,10 @@ macro_rules! generate_tests {
|
|||||||
let public = DSAPublicKey::<$params>::new(params, y);
|
let public = DSAPublicKey::<$params>::new(params, y);
|
||||||
let sig = DSASignature::<$nt>::new(r, s);
|
let sig = DSASignature::<$nt>::new(r, s);
|
||||||
match h {
|
match h {
|
||||||
224 => assert!(public.verify::<Sha224>(mbytes, &sig)),
|
224 => assert!(public.verify::<SHA224>(mbytes, &sig)),
|
||||||
256 => assert!(public.verify::<Sha256>(mbytes, &sig)),
|
256 => assert!(public.verify::<SHA256>(mbytes, &sig)),
|
||||||
384 => assert!(public.verify::<Sha384>(mbytes, &sig)),
|
384 => assert!(public.verify::<SHA384>(mbytes, &sig)),
|
||||||
512 => assert!(public.verify::<Sha512>(mbytes, &sig)),
|
512 => assert!(public.verify::<SHA512>(mbytes, &sig)),
|
||||||
_ => panic!("Unexpected hash {}", h)
|
_ => panic!("Unexpected hash {}", h)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use cryptonum::unsigned::{CryptoNum,Decoder,Encoder};
|
use cryptonum::unsigned::{CryptoNum,Decoder,Encoder};
|
||||||
use digest::{BlockInput,Digest,FixedOutput,Input,Reset};
|
use hmac::HMAC;
|
||||||
use digest::generic_array::ArrayLength;
|
use sha::Hash;
|
||||||
use hmac::{Hmac,Mac};
|
|
||||||
use num::BigInt;
|
use num::BigInt;
|
||||||
use simple_asn1::{ASN1Block,ASN1Class,ASN1DecodeErr,ASN1EncodeErr};
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1DecodeErr,ASN1EncodeErr};
|
||||||
use simple_asn1::{FromASN1,ToASN1};
|
use simple_asn1::{FromASN1,ToASN1};
|
||||||
@@ -26,11 +25,10 @@ impl<N> DSASignature<N>
|
|||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub struct KIterator<H,N>
|
pub struct KIterator<H,N>
|
||||||
where
|
where
|
||||||
H: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
H: Hash + Clone,
|
||||||
N: Clone + Decoder + Encoder + PartialOrd + Shr<usize,Output=N>,
|
N: Clone + Decoder + Encoder + PartialOrd + Shr<usize,Output=N>,
|
||||||
Hmac<H>: Mac
|
|
||||||
{
|
{
|
||||||
hmac_k: Hmac<H>,
|
hmac_k: HMAC<H>,
|
||||||
V: Vec<u8>,
|
V: Vec<u8>,
|
||||||
q: N,
|
q: N,
|
||||||
qlen: usize
|
qlen: usize
|
||||||
@@ -38,9 +36,8 @@ pub struct KIterator<H,N>
|
|||||||
|
|
||||||
impl<H,N> KIterator<H,N>
|
impl<H,N> KIterator<H,N>
|
||||||
where
|
where
|
||||||
H: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
H: Hash + Clone,
|
||||||
N: Clone + Decoder + Encoder + PartialOrd + Shr<usize,Output=N> + Sub<Output=N>,
|
N: Clone + Decoder + Encoder + PartialOrd + Shr<usize,Output=N> + Sub<Output=N>,
|
||||||
Hmac<H>: Mac
|
|
||||||
{
|
{
|
||||||
pub fn new(h1: &[u8], qlen: usize, q: &N, x: &N) -> KIterator<H,N>
|
pub fn new(h1: &[u8], qlen: usize, q: &N, x: &N) -> KIterator<H,N>
|
||||||
{
|
{
|
||||||
@@ -95,11 +92,11 @@ impl<H,N> KIterator<H,N>
|
|||||||
input.push(0x00);
|
input.push(0x00);
|
||||||
input.extend_from_slice(&xbytes);
|
input.extend_from_slice(&xbytes);
|
||||||
input.extend_from_slice(&h1bytes);
|
input.extend_from_slice(&h1bytes);
|
||||||
K = hmac(&K, &input);
|
K = HMAC::<H>::hmac(&K, &input);
|
||||||
// e. Set:
|
// e. Set:
|
||||||
//
|
//
|
||||||
// V = HMAC_K(V)
|
// V = HMAC_K(V)
|
||||||
V = hmac(&K, &V);
|
V = HMAC::<H>::hmac(&K, &V);
|
||||||
// f. Set:
|
// f. Set:
|
||||||
//
|
//
|
||||||
// K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1))
|
// K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1))
|
||||||
@@ -110,14 +107,14 @@ impl<H,N> KIterator<H,N>
|
|||||||
input.push(0x01);
|
input.push(0x01);
|
||||||
input.extend_from_slice(&xbytes);
|
input.extend_from_slice(&xbytes);
|
||||||
input.extend_from_slice(&h1bytes);
|
input.extend_from_slice(&h1bytes);
|
||||||
K = hmac(&K, &input);
|
K = HMAC::<H>::hmac(&K, &input);
|
||||||
// g. Set:
|
// g. Set:
|
||||||
//
|
//
|
||||||
// V = HMAC_K(V)
|
// V = HMAC_K(V)
|
||||||
V = hmac(&K, &V);
|
V = HMAC::<H>::hmac(&K, &V);
|
||||||
// h is for later ...
|
// h is for later ...
|
||||||
KIterator {
|
KIterator {
|
||||||
hmac_k: Hmac::<H>::new_varkey(&K).unwrap(),
|
hmac_k: HMAC::<H>::new(&K),
|
||||||
V: V,
|
V: V,
|
||||||
q: q.clone(),
|
q: q.clone(),
|
||||||
qlen: qlen
|
qlen: qlen
|
||||||
@@ -127,9 +124,8 @@ impl<H,N> KIterator<H,N>
|
|||||||
|
|
||||||
impl<H,N> Iterator for KIterator<H,N>
|
impl<H,N> Iterator for KIterator<H,N>
|
||||||
where
|
where
|
||||||
H: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
H: Hash + Clone,
|
||||||
N: Clone + CryptoNum + Decoder + Encoder + PartialOrd + Shr<usize,Output=N>,
|
N: Clone + CryptoNum + Decoder + Encoder + PartialOrd + Shr<usize,Output=N>,
|
||||||
Hmac<H>: Mac
|
|
||||||
{
|
{
|
||||||
type Item = N;
|
type Item = N;
|
||||||
|
|
||||||
@@ -170,7 +166,7 @@ impl<H,N> Iterator for KIterator<H,N>
|
|||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
let K = runhmac(&self.hmac_k, &input);
|
let K = runhmac(&self.hmac_k, &input);
|
||||||
// V = HMAC_K(V)
|
// V = HMAC_K(V)
|
||||||
self.hmac_k = Hmac::<H>::new_varkey(&K).unwrap();
|
self.hmac_k = HMAC::<H>::new(&K);
|
||||||
self.V = runhmac(&self.hmac_k, &self.V);
|
self.V = runhmac(&self.hmac_k, &self.V);
|
||||||
//
|
//
|
||||||
// and loop (try to generate a new T, and so on).
|
// and loop (try to generate a new T, and so on).
|
||||||
@@ -224,26 +220,11 @@ fn int2octets<X>(x: &X, qlen_bits: usize) -> Vec<u8>
|
|||||||
base
|
base
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runhmac<H>(base: &Hmac<H>, m: &[u8]) -> Vec<u8>
|
fn runhmac<H: Hash + Clone>(base: &HMAC<H>, m: &[u8]) -> Vec<u8>
|
||||||
where
|
|
||||||
H: Clone + BlockInput + Default + Input + FixedOutput + Reset,
|
|
||||||
Hmac<H>: Clone + Mac,
|
|
||||||
H::BlockSize : ArrayLength<u8>
|
|
||||||
{
|
{
|
||||||
let mut runner = base.clone();
|
let mut runner = base.clone();
|
||||||
runner.input(&m);
|
runner.update(&m);
|
||||||
runner.result().code().as_slice().to_vec()
|
runner.finalize()
|
||||||
}
|
|
||||||
|
|
||||||
fn hmac<H>(k: &[u8], m: &[u8]) -> Vec<u8>
|
|
||||||
where
|
|
||||||
H: BlockInput + Clone + Default + Input + FixedOutput + Reset,
|
|
||||||
Hmac<H>: Clone + Mac,
|
|
||||||
H::BlockSize : ArrayLength<u8>
|
|
||||||
{
|
|
||||||
let mut runner = Hmac::<H>::new_varkey(&k).unwrap();
|
|
||||||
runner.input(&m);
|
|
||||||
runner.result().code().as_slice().to_vec()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone,Debug,PartialEq)]
|
#[derive(Clone,Debug,PartialEq)]
|
||||||
@@ -304,7 +285,7 @@ impl<N> ToASN1 for DSASignature<N>
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use cryptonum::unsigned::U192;
|
use cryptonum::unsigned::U192;
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
use super::*;
|
use super::*;
|
||||||
use testing::*;
|
use testing::*;
|
||||||
|
|
||||||
@@ -343,7 +324,7 @@ mod tests {
|
|||||||
fn k_gen_example() {
|
fn k_gen_example() {
|
||||||
let q = U192::from_bytes(&QBYTES);
|
let q = U192::from_bytes(&QBYTES);
|
||||||
let x = U192::from_bytes(&XBYTES);
|
let x = U192::from_bytes(&XBYTES);
|
||||||
let mut iter = KIterator::<Sha256,U192>::new(&H1, 163, &q, &x);
|
let mut iter = KIterator::<SHA256,U192>::new(&H1, 163, &q, &x);
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
None =>
|
None =>
|
||||||
assert!(false),
|
assert!(false),
|
||||||
@@ -428,9 +409,9 @@ mod tests {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
k_generator_tests!(kgen_sha224, Sha224, "SHA224");
|
k_generator_tests!(kgen_sha224, SHA224, "SHA224");
|
||||||
k_generator_tests!(kgen_sha256, Sha256, "SHA256");
|
k_generator_tests!(kgen_sha256, SHA256, "SHA256");
|
||||||
k_generator_tests!(kgen_sha384, Sha384, "SHA384");
|
k_generator_tests!(kgen_sha384, SHA384, "SHA384");
|
||||||
k_generator_tests!(kgen_sha512, Sha512, "SHA512");
|
k_generator_tests!(kgen_sha512, SHA512, "SHA512");
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
use cryptonum::unsigned::*;
|
use cryptonum::unsigned::*;
|
||||||
use digest::Digest;
|
use sha::{Hash,SHA1,SHA224,SHA256,SHA384,SHA512};
|
||||||
use sha1::Sha1;
|
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
|
||||||
use simple_asn1::{der_decode,der_encode};
|
use simple_asn1::{der_decode,der_encode};
|
||||||
use dsa::params::{DSAParameters,L1024N160,L2048N256};
|
use dsa::params::{DSAParameters,L1024N160,L2048N256};
|
||||||
use dsa::private::DSAPrivateKey;
|
use dsa::private::DSAPrivateKey;
|
||||||
@@ -13,7 +11,7 @@ macro_rules! run_rfc6979_test {
|
|||||||
k $k: expr,
|
k $k: expr,
|
||||||
r $r: expr,
|
r $r: expr,
|
||||||
s $s: expr) => ({
|
s $s: expr) => ({
|
||||||
let h1 = <$hash>::digest(&$val);
|
let h1 = <$hash>::hash(&$val);
|
||||||
let rbytes = $r;
|
let rbytes = $r;
|
||||||
let sbytes = $s;
|
let sbytes = $s;
|
||||||
let r = $ntype::from_bytes(&rbytes);
|
let r = $ntype::from_bytes(&rbytes);
|
||||||
@@ -108,7 +106,7 @@ fn appendix_a21() {
|
|||||||
// k = 7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B
|
// k = 7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B
|
||||||
// r = 2E1A0C2562B2912CAAF89186FB0F42001585DA55
|
// r = 2E1A0C2562B2912CAAF89186FB0F42001585DA55
|
||||||
// s = 29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5
|
// s = 29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5
|
||||||
run_rfc6979_test!(Sha1, U192, sample, params, public, private,
|
run_rfc6979_test!(SHA1, U192, sample, params, public, private,
|
||||||
k vec![0x7B, 0xDB, 0x6B, 0x0F, 0xF7, 0x56, 0xE1, 0xBB,
|
k vec![0x7B, 0xDB, 0x6B, 0x0F, 0xF7, 0x56, 0xE1, 0xBB,
|
||||||
0x5D, 0x53, 0x58, 0x3E, 0xF9, 0x79, 0x08, 0x2F,
|
0x5D, 0x53, 0x58, 0x3E, 0xF9, 0x79, 0x08, 0x2F,
|
||||||
0x9A, 0xD5, 0xBD, 0x5B],
|
0x9A, 0xD5, 0xBD, 0x5B],
|
||||||
@@ -122,7 +120,7 @@ fn appendix_a21() {
|
|||||||
// k = 562097C06782D60C3037BA7BE104774344687649
|
// k = 562097C06782D60C3037BA7BE104774344687649
|
||||||
// r = 4BC3B686AEA70145856814A6F1BB53346F02101E
|
// r = 4BC3B686AEA70145856814A6F1BB53346F02101E
|
||||||
// s = 410697B92295D994D21EDD2F4ADA85566F6F94C1
|
// s = 410697B92295D994D21EDD2F4ADA85566F6F94C1
|
||||||
run_rfc6979_test!(Sha224, U192, sample, params, public, private,
|
run_rfc6979_test!(SHA224, U192, sample, params, public, private,
|
||||||
k vec![0x56, 0x20, 0x97, 0xC0, 0x67, 0x82, 0xD6, 0x0C,
|
k vec![0x56, 0x20, 0x97, 0xC0, 0x67, 0x82, 0xD6, 0x0C,
|
||||||
0x30, 0x37, 0xBA, 0x7B, 0xE1, 0x04, 0x77, 0x43,
|
0x30, 0x37, 0xBA, 0x7B, 0xE1, 0x04, 0x77, 0x43,
|
||||||
0x44, 0x68, 0x76, 0x49],
|
0x44, 0x68, 0x76, 0x49],
|
||||||
@@ -136,7 +134,7 @@ fn appendix_a21() {
|
|||||||
// k = 519BA0546D0C39202A7D34D7DFA5E760B318BCFB
|
// k = 519BA0546D0C39202A7D34D7DFA5E760B318BCFB
|
||||||
// r = 81F2F5850BE5BC123C43F71A3033E9384611C545
|
// r = 81F2F5850BE5BC123C43F71A3033E9384611C545
|
||||||
// s = 4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89
|
// s = 4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89
|
||||||
run_rfc6979_test!(Sha256, U192, sample, params, public, private,
|
run_rfc6979_test!(SHA256, U192, sample, params, public, private,
|
||||||
k vec![0x51, 0x9B, 0xA0, 0x54, 0x6D, 0x0C, 0x39, 0x20,
|
k vec![0x51, 0x9B, 0xA0, 0x54, 0x6D, 0x0C, 0x39, 0x20,
|
||||||
0x2A, 0x7D, 0x34, 0xD7, 0xDF, 0xA5, 0xE7, 0x60,
|
0x2A, 0x7D, 0x34, 0xD7, 0xDF, 0xA5, 0xE7, 0x60,
|
||||||
0xB3, 0x18, 0xBC, 0xFB],
|
0xB3, 0x18, 0xBC, 0xFB],
|
||||||
@@ -150,7 +148,7 @@ fn appendix_a21() {
|
|||||||
// k = 95897CD7BBB944AA932DBC579C1C09EB6FCFC595
|
// k = 95897CD7BBB944AA932DBC579C1C09EB6FCFC595
|
||||||
// r = 07F2108557EE0E3921BC1774F1CA9B410B4CE65A
|
// r = 07F2108557EE0E3921BC1774F1CA9B410B4CE65A
|
||||||
// s = 54DF70456C86FAC10FAB47C1949AB83F2C6F7595
|
// s = 54DF70456C86FAC10FAB47C1949AB83F2C6F7595
|
||||||
run_rfc6979_test!(Sha384, U192, sample, params, public, private,
|
run_rfc6979_test!(SHA384, U192, sample, params, public, private,
|
||||||
k vec![0x95, 0x89, 0x7C, 0xD7, 0xBB, 0xB9, 0x44, 0xAA,
|
k vec![0x95, 0x89, 0x7C, 0xD7, 0xBB, 0xB9, 0x44, 0xAA,
|
||||||
0x93, 0x2D, 0xBC, 0x57, 0x9C, 0x1C, 0x09, 0xEB,
|
0x93, 0x2D, 0xBC, 0x57, 0x9C, 0x1C, 0x09, 0xEB,
|
||||||
0x6F, 0xCF, 0xC5, 0x95],
|
0x6F, 0xCF, 0xC5, 0x95],
|
||||||
@@ -164,7 +162,7 @@ fn appendix_a21() {
|
|||||||
// k = 09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B
|
// k = 09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B
|
||||||
// r = 16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B
|
// r = 16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B
|
||||||
// s = 02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C
|
// s = 02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C
|
||||||
run_rfc6979_test!(Sha512, U192, sample, params, public, private,
|
run_rfc6979_test!(SHA512, U192, sample, params, public, private,
|
||||||
k vec![0x09, 0xEC, 0xE7, 0xCA, 0x27, 0xD0, 0xF5, 0xA4,
|
k vec![0x09, 0xEC, 0xE7, 0xCA, 0x27, 0xD0, 0xF5, 0xA4,
|
||||||
0xDD, 0x4E, 0x55, 0x6C, 0x9D, 0xF1, 0xD2, 0x1D,
|
0xDD, 0x4E, 0x55, 0x6C, 0x9D, 0xF1, 0xD2, 0x1D,
|
||||||
0x28, 0x10, 0x4F, 0x8B],
|
0x28, 0x10, 0x4F, 0x8B],
|
||||||
@@ -178,7 +176,7 @@ fn appendix_a21() {
|
|||||||
// k = 5C842DF4F9E344EE09F056838B42C7A17F4A6433
|
// k = 5C842DF4F9E344EE09F056838B42C7A17F4A6433
|
||||||
// r = 42AB2052FD43E123F0607F115052A67DCD9C5C77
|
// r = 42AB2052FD43E123F0607F115052A67DCD9C5C77
|
||||||
// s = 183916B0230D45B9931491D4C6B0BD2FB4AAF088
|
// s = 183916B0230D45B9931491D4C6B0BD2FB4AAF088
|
||||||
run_rfc6979_test!(Sha1, U192, test, params, public, private,
|
run_rfc6979_test!(SHA1, U192, test, params, public, private,
|
||||||
k vec![0x5C, 0x84, 0x2D, 0xF4, 0xF9, 0xE3, 0x44, 0xEE,
|
k vec![0x5C, 0x84, 0x2D, 0xF4, 0xF9, 0xE3, 0x44, 0xEE,
|
||||||
0x09, 0xF0, 0x56, 0x83, 0x8B, 0x42, 0xC7, 0xA1,
|
0x09, 0xF0, 0x56, 0x83, 0x8B, 0x42, 0xC7, 0xA1,
|
||||||
0x7F, 0x4A, 0x64, 0x33],
|
0x7F, 0x4A, 0x64, 0x33],
|
||||||
@@ -192,7 +190,7 @@ fn appendix_a21() {
|
|||||||
// k = 4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297
|
// k = 4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297
|
||||||
// r = 6868E9964E36C1689F6037F91F28D5F2C30610F2
|
// r = 6868E9964E36C1689F6037F91F28D5F2C30610F2
|
||||||
// s = 49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F
|
// s = 49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F
|
||||||
run_rfc6979_test!(Sha224, U192, test, params, public, private,
|
run_rfc6979_test!(SHA224, U192, test, params, public, private,
|
||||||
k vec![0x45, 0x98, 0xB8, 0xEF, 0xC1, 0xA5, 0x3B, 0xC8,
|
k vec![0x45, 0x98, 0xB8, 0xEF, 0xC1, 0xA5, 0x3B, 0xC8,
|
||||||
0xAE, 0xCD, 0x58, 0xD1, 0xAB, 0xBB, 0x0C, 0x0C,
|
0xAE, 0xCD, 0x58, 0xD1, 0xAB, 0xBB, 0x0C, 0x0C,
|
||||||
0x71, 0xE6, 0x72, 0x97],
|
0x71, 0xE6, 0x72, 0x97],
|
||||||
@@ -206,7 +204,7 @@ fn appendix_a21() {
|
|||||||
// k = 5A67592E8128E03A417B0484410FB72C0B630E1A
|
// k = 5A67592E8128E03A417B0484410FB72C0B630E1A
|
||||||
// r = 22518C127299B0F6FDC9872B282B9E70D0790812
|
// r = 22518C127299B0F6FDC9872B282B9E70D0790812
|
||||||
// s = 6837EC18F150D55DE95B5E29BE7AF5D01E4FE160
|
// s = 6837EC18F150D55DE95B5E29BE7AF5D01E4FE160
|
||||||
run_rfc6979_test!(Sha256, U192, test, params, public, private,
|
run_rfc6979_test!(SHA256, U192, test, params, public, private,
|
||||||
k vec![0x5A, 0x67, 0x59, 0x2E, 0x81, 0x28, 0xE0, 0x3A,
|
k vec![0x5A, 0x67, 0x59, 0x2E, 0x81, 0x28, 0xE0, 0x3A,
|
||||||
0x41, 0x7B, 0x04, 0x84, 0x41, 0x0F, 0xB7, 0x2C,
|
0x41, 0x7B, 0x04, 0x84, 0x41, 0x0F, 0xB7, 0x2C,
|
||||||
0x0B, 0x63, 0x0E, 0x1A],
|
0x0B, 0x63, 0x0E, 0x1A],
|
||||||
@@ -220,7 +218,7 @@ fn appendix_a21() {
|
|||||||
// k = 220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89
|
// k = 220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89
|
||||||
// r = 854CF929B58D73C3CBFDC421E8D5430CD6DB5E66
|
// r = 854CF929B58D73C3CBFDC421E8D5430CD6DB5E66
|
||||||
// s = 91D0E0F53E22F898D158380676A871A157CDA622
|
// s = 91D0E0F53E22F898D158380676A871A157CDA622
|
||||||
run_rfc6979_test!(Sha384, U192, test, params, public, private,
|
run_rfc6979_test!(SHA384, U192, test, params, public, private,
|
||||||
k vec![0x22, 0x01, 0x56, 0xB7, 0x61, 0xF6, 0xCA, 0x5E,
|
k vec![0x22, 0x01, 0x56, 0xB7, 0x61, 0xF6, 0xCA, 0x5E,
|
||||||
0x6C, 0x9F, 0x1B, 0x9C, 0xF9, 0xC2, 0x4B, 0xE2,
|
0x6C, 0x9F, 0x1B, 0x9C, 0xF9, 0xC2, 0x4B, 0xE2,
|
||||||
0x5F, 0x98, 0xCD, 0x89],
|
0x5F, 0x98, 0xCD, 0x89],
|
||||||
@@ -234,7 +232,7 @@ fn appendix_a21() {
|
|||||||
// k = 65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C
|
// k = 65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C
|
||||||
// r = 8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0
|
// r = 8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0
|
||||||
// s = 7C670C7AD72B6C050C109E1790008097125433E8
|
// s = 7C670C7AD72B6C050C109E1790008097125433E8
|
||||||
run_rfc6979_test!(Sha512, U192, test, params, public, private,
|
run_rfc6979_test!(SHA512, U192, test, params, public, private,
|
||||||
k vec![0x65, 0xD2, 0xC2, 0xEE, 0xB1, 0x75, 0xE3, 0x70,
|
k vec![0x65, 0xD2, 0xC2, 0xEE, 0xB1, 0x75, 0xE3, 0x70,
|
||||||
0xF2, 0x8C, 0x75, 0xBF, 0xCD, 0xC0, 0x28, 0xD2,
|
0xF2, 0x8C, 0x75, 0xBF, 0xCD, 0xC0, 0x28, 0xD2,
|
||||||
0x2C, 0x7D, 0xBE, 0x9C],
|
0x2C, 0x7D, 0xBE, 0x9C],
|
||||||
@@ -368,7 +366,7 @@ fn appendix_a22() {
|
|||||||
// k = 888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E
|
// k = 888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E
|
||||||
// r = 3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A
|
// r = 3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A
|
||||||
// s = D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF
|
// s = D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF
|
||||||
run_rfc6979_test!(Sha1, U256, sample, params, public, private,
|
run_rfc6979_test!(SHA1, U256, sample, params, public, private,
|
||||||
k vec![0x88,0x8F,0xA6,0xF7,0x73,0x8A,0x41,0xBD,
|
k vec![0x88,0x8F,0xA6,0xF7,0x73,0x8A,0x41,0xBD,
|
||||||
0xC9,0x84,0x64,0x66,0xAB,0xDB,0x81,0x74,
|
0xC9,0x84,0x64,0x66,0xAB,0xDB,0x81,0x74,
|
||||||
0xC0,0x33,0x82,0x50,0xAE,0x50,0xCE,0x95,
|
0xC0,0x33,0x82,0x50,0xAE,0x50,0xCE,0x95,
|
||||||
@@ -385,7 +383,7 @@ fn appendix_a22() {
|
|||||||
// k = BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806
|
// k = BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806
|
||||||
// r = DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C
|
// r = DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C
|
||||||
// s = A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC
|
// s = A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC
|
||||||
run_rfc6979_test!(Sha224, U256, sample, params, public, private,
|
run_rfc6979_test!(SHA224, U256, sample, params, public, private,
|
||||||
k vec![0xBC,0x37,0x29,0x67,0x70,0x20,0x82,0xE1,
|
k vec![0xBC,0x37,0x29,0x67,0x70,0x20,0x82,0xE1,
|
||||||
0xAA,0x4F,0xCE,0x89,0x22,0x09,0xF7,0x1A,
|
0xAA,0x4F,0xCE,0x89,0x22,0x09,0xF7,0x1A,
|
||||||
0xE4,0xAD,0x25,0xA6,0xDF,0xD8,0x69,0x33,
|
0xE4,0xAD,0x25,0xA6,0xDF,0xD8,0x69,0x33,
|
||||||
@@ -402,7 +400,7 @@ fn appendix_a22() {
|
|||||||
// k = 8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52
|
// k = 8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52
|
||||||
// r = EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809
|
// r = EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809
|
||||||
// s = 7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53
|
// s = 7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53
|
||||||
run_rfc6979_test!(Sha256, U256, sample, params, public, private,
|
run_rfc6979_test!(SHA256, U256, sample, params, public, private,
|
||||||
k vec![0x89,0x26,0xA2,0x7C,0x40,0x48,0x42,0x16,
|
k vec![0x89,0x26,0xA2,0x7C,0x40,0x48,0x42,0x16,
|
||||||
0xF0,0x52,0xF4,0x42,0x7C,0xFD,0x56,0x47,
|
0xF0,0x52,0xF4,0x42,0x7C,0xFD,0x56,0x47,
|
||||||
0x33,0x8B,0x7B,0x39,0x39,0xBC,0x65,0x73,
|
0x33,0x8B,0x7B,0x39,0x39,0xBC,0x65,0x73,
|
||||||
@@ -419,7 +417,7 @@ fn appendix_a22() {
|
|||||||
// k = C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920
|
// k = C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920
|
||||||
// r = B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B
|
// r = B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B
|
||||||
// s = 19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B
|
// s = 19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B
|
||||||
run_rfc6979_test!(Sha384, U256, sample, params, public, private,
|
run_rfc6979_test!(SHA384, U256, sample, params, public, private,
|
||||||
k vec![0xC3,0x45,0xD5,0xAB,0x3D,0xA0,0xA5,0xBC,
|
k vec![0xC3,0x45,0xD5,0xAB,0x3D,0xA0,0xA5,0xBC,
|
||||||
0xB7,0xEC,0x8F,0x8F,0xB7,0xA7,0xE9,0x60,
|
0xB7,0xEC,0x8F,0x8F,0xB7,0xA7,0xE9,0x60,
|
||||||
0x69,0xE0,0x3B,0x20,0x63,0x71,0xEF,0x7D,
|
0x69,0xE0,0x3B,0x20,0x63,0x71,0xEF,0x7D,
|
||||||
@@ -436,7 +434,7 @@ fn appendix_a22() {
|
|||||||
// k = 5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC
|
// k = 5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC
|
||||||
// r = 2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E
|
// r = 2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E
|
||||||
// s = D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351
|
// s = D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351
|
||||||
run_rfc6979_test!(Sha512, U256, sample, params, public, private,
|
run_rfc6979_test!(SHA512, U256, sample, params, public, private,
|
||||||
k vec![0x5A,0x12,0x99,0x44,0x31,0x78,0x54,0x85,
|
k vec![0x5A,0x12,0x99,0x44,0x31,0x78,0x54,0x85,
|
||||||
0xB3,0xF5,0xF0,0x67,0x22,0x15,0x17,0x79,
|
0xB3,0xF5,0xF0,0x67,0x22,0x15,0x17,0x79,
|
||||||
0x1B,0x85,0xA5,0x97,0xB7,0xA9,0x43,0x69,
|
0x1B,0x85,0xA5,0x97,0xB7,0xA9,0x43,0x69,
|
||||||
@@ -453,7 +451,7 @@ fn appendix_a22() {
|
|||||||
// k = 6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F
|
// k = 6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F
|
||||||
// r = C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0
|
// r = C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0
|
||||||
// s = 414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA
|
// s = 414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA
|
||||||
run_rfc6979_test!(Sha1, U256, test, params, public, private,
|
run_rfc6979_test!(SHA1, U256, test, params, public, private,
|
||||||
k vec![0x6E,0xEA,0x48,0x6F,0x9D,0x41,0xA0,0x37,
|
k vec![0x6E,0xEA,0x48,0x6F,0x9D,0x41,0xA0,0x37,
|
||||||
0xB2,0xC6,0x40,0xBC,0x56,0x45,0x69,0x4F,
|
0xB2,0xC6,0x40,0xBC,0x56,0x45,0x69,0x4F,
|
||||||
0xF8,0xFF,0x4B,0x98,0xD0,0x66,0xA2,0x5F,
|
0xF8,0xFF,0x4B,0x98,0xD0,0x66,0xA2,0x5F,
|
||||||
@@ -470,7 +468,7 @@ fn appendix_a22() {
|
|||||||
// k = 06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670
|
// k = 06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670
|
||||||
// r = 272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3
|
// r = 272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3
|
||||||
// s = E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806
|
// s = E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806
|
||||||
run_rfc6979_test!(Sha224, U256, test, params, public, private,
|
run_rfc6979_test!(SHA224, U256, test, params, public, private,
|
||||||
k vec![0x06,0xBD,0x4C,0x05,0xED,0x74,0x71,0x91,
|
k vec![0x06,0xBD,0x4C,0x05,0xED,0x74,0x71,0x91,
|
||||||
0x06,0x22,0x3B,0xE3,0x3F,0x2D,0x95,0xDA,
|
0x06,0x22,0x3B,0xE3,0x3F,0x2D,0x95,0xDA,
|
||||||
0x6B,0x3B,0x54,0x1D,0xAD,0x7B,0xFB,0xD7,
|
0x6B,0x3B,0x54,0x1D,0xAD,0x7B,0xFB,0xD7,
|
||||||
@@ -487,7 +485,7 @@ fn appendix_a22() {
|
|||||||
// k = 1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7
|
// k = 1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7
|
||||||
// r = 8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0
|
// r = 8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0
|
||||||
// s = 7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E
|
// s = 7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E
|
||||||
run_rfc6979_test!(Sha256, U256, test, params, public, private,
|
run_rfc6979_test!(SHA256, U256, test, params, public, private,
|
||||||
k vec![0x1D,0x6C,0xE6,0xDD,0xA1,0xC5,0xD3,0x73,
|
k vec![0x1D,0x6C,0xE6,0xDD,0xA1,0xC5,0xD3,0x73,
|
||||||
0x07,0x83,0x9C,0xD0,0x3A,0xB0,0xA5,0xCB,
|
0x07,0x83,0x9C,0xD0,0x3A,0xB0,0xA5,0xCB,
|
||||||
0xB1,0x8E,0x60,0xD8,0x00,0x93,0x7D,0x67,
|
0xB1,0x8E,0x60,0xD8,0x00,0x93,0x7D,0x67,
|
||||||
@@ -504,7 +502,7 @@ fn appendix_a22() {
|
|||||||
// k = 206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C
|
// k = 206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C
|
||||||
// r = 239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE
|
// r = 239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE
|
||||||
// s = 6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961
|
// s = 6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961
|
||||||
run_rfc6979_test!(Sha384, U256, test, params, public, private,
|
run_rfc6979_test!(SHA384, U256, test, params, public, private,
|
||||||
k vec![0x20,0x6E,0x61,0xF7,0x3D,0xBE,0x1B,0x2D,
|
k vec![0x20,0x6E,0x61,0xF7,0x3D,0xBE,0x1B,0x2D,
|
||||||
0xC8,0xBE,0x73,0x6B,0x22,0xB0,0x79,0xE9,
|
0xC8,0xBE,0x73,0x6B,0x22,0xB0,0x79,0xE9,
|
||||||
0xDA,0xCD,0x97,0x4D,0xB0,0x0E,0xEB,0xBC,
|
0xDA,0xCD,0x97,0x4D,0xB0,0x0E,0xEB,0xBC,
|
||||||
@@ -521,7 +519,7 @@ fn appendix_a22() {
|
|||||||
// k = AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA
|
// k = AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA
|
||||||
// r = 89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307
|
// r = 89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307
|
||||||
// s = C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1
|
// s = C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1
|
||||||
run_rfc6979_test!(Sha512, U256, test, params, public, private,
|
run_rfc6979_test!(SHA512, U256, test, params, public, private,
|
||||||
k vec![0xAF,0xF1,0x65,0x1E,0x4C,0xD6,0x03,0x6D,
|
k vec![0xAF,0xF1,0x65,0x1E,0x4C,0xD6,0x03,0x6D,
|
||||||
0x57,0xAA,0x8B,0x2A,0x05,0xCC,0xF1,0xA9,
|
0x57,0xAA,0x8B,0x2A,0x05,0xCC,0xF1,0xA9,
|
||||||
0xD5,0xA4,0x01,0x66,0x34,0x0E,0xCB,0xBD,
|
0xD5,0xA4,0x01,0x66,0x34,0x0E,0xCB,0xBD,
|
||||||
|
|||||||
@@ -3,10 +3,8 @@
|
|||||||
//! following code snippet, as an example:
|
//! following code snippet, as an example:
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! extern crate sha2;
|
|
||||||
//!
|
|
||||||
//! use simple_crypto::ecdsa::{ECDSAKeyPair,P384};
|
//! use simple_crypto::ecdsa::{ECDSAKeyPair,P384};
|
||||||
//! use sha2::Sha256;
|
//! use simple_crypto::sha::SHA256;
|
||||||
//!
|
//!
|
||||||
//! // Generate a new ECDSA key for curve P384 (this is a good choice, by
|
//! // Generate a new ECDSA key for curve P384 (this is a good choice, by
|
||||||
//! // the way, if you're wondering which curve to use).
|
//! // the way, if you're wondering which curve to use).
|
||||||
@@ -17,8 +15,8 @@
|
|||||||
//! // using it. For example, to sign the vector [0,1,2,3,4] with SHA256
|
//! // using it. For example, to sign the vector [0,1,2,3,4] with SHA256
|
||||||
//! // and then verify that signature, we would write:
|
//! // and then verify that signature, we would write:
|
||||||
//! let msg = vec![0,1,2,3,4];
|
//! let msg = vec![0,1,2,3,4];
|
||||||
//! let sig = kp.private.sign::<Sha256>(&msg);
|
//! let sig = kp.private.sign::<SHA256>(&msg);
|
||||||
//! assert!( kp.public.verify::<Sha256>(&msg, &sig) );
|
//! assert!( kp.public.verify::<SHA256>(&msg, &sig) );
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
mod curve;
|
mod curve;
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
use cryptonum::signed::*;
|
use cryptonum::signed::*;
|
||||||
use cryptonum::unsigned::*;
|
use cryptonum::unsigned::*;
|
||||||
use digest::{BlockInput,Digest,Input,FixedOutput,Reset};
|
|
||||||
use dsa::rfc6979::{DSASignature,KIterator,bits2int};
|
use dsa::rfc6979::{DSASignature,KIterator,bits2int};
|
||||||
use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
||||||
use ecdsa::point::{ECCPoint,Point};
|
use ecdsa::point::{ECCPoint,Point};
|
||||||
use hmac::{Hmac,Mac};
|
use sha::Hash;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// A private key for the given curve.
|
/// A private key for the given curve.
|
||||||
@@ -42,10 +41,7 @@ macro_rules! generate_privates
|
|||||||
|
|
||||||
/// Sign the given message with the current key, using the hash provided
|
/// Sign the given message with the current key, using the hash provided
|
||||||
/// in the type.
|
/// in the type.
|
||||||
pub fn sign<Hash>(&self, m: &[u8]) -> DSASignature<$base>
|
pub fn sign<H: Hash + Clone>(&self, m: &[u8]) -> DSASignature<$base>
|
||||||
where
|
|
||||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
|
||||||
Hmac<Hash>: Mac
|
|
||||||
{
|
{
|
||||||
// This algorithm is per RFC 6979, which has a nice, relatively
|
// This algorithm is per RFC 6979, which has a nice, relatively
|
||||||
// straightforward description of how to do DSA signing.
|
// straightforward description of how to do DSA signing.
|
||||||
@@ -58,7 +54,7 @@ macro_rules! generate_privates
|
|||||||
// As was noted in the description of bits2octets, the extra
|
// As was noted in the description of bits2octets, the extra
|
||||||
// modular reduction is no more than a conditional subtraction.
|
// modular reduction is no more than a conditional subtraction.
|
||||||
//
|
//
|
||||||
let h1 = <Hash>::digest(m);
|
let h1 = <H>::hash(m);
|
||||||
let size = <$curve>::size();
|
let size = <$curve>::size();
|
||||||
let h0: $base = bits2int(&h1, size);
|
let h0: $base = bits2int(&h1, size);
|
||||||
let n = <$curve>::n();
|
let n = <$curve>::n();
|
||||||
@@ -70,7 +66,7 @@ macro_rules! generate_privates
|
|||||||
// process used to generate k. In plain DSA or ECDSA, k should
|
// process used to generate k. In plain DSA or ECDSA, k should
|
||||||
// be selected through a random selection that chooses a value
|
// be selected through a random selection that chooses a value
|
||||||
// among the q-1 possible values with uniform probability.
|
// among the q-1 possible values with uniform probability.
|
||||||
for k in KIterator::<Hash,$base>::new(&h1, size, &n, &self.d) {
|
for k in KIterator::<H,$base>::new(&h1, size, &n, &self.d) {
|
||||||
// 3. A value r (modulo q) is computed from k and the key
|
// 3. A value r (modulo q) is computed from k and the key
|
||||||
// parameters:
|
// parameters:
|
||||||
// * For DSA ...
|
// * For DSA ...
|
||||||
@@ -118,7 +114,7 @@ generate_privates!(P521, U576, I576, U1152, U2304);
|
|||||||
/************* TESTING ********************************************************/
|
/************* TESTING ********************************************************/
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use testing::*;
|
use testing::*;
|
||||||
|
|
||||||
@@ -148,10 +144,10 @@ macro_rules! sign_test_body
|
|||||||
|
|
||||||
let private = ECCPrivateKey::<$curve>::new(d);
|
let private = ECCPrivateKey::<$curve>::new(d);
|
||||||
let sig = match usize::from(h) {
|
let sig = match usize::from(h) {
|
||||||
224 => private.sign::<Sha224>(mbytes),
|
224 => private.sign::<SHA224>(mbytes),
|
||||||
256 => private.sign::<Sha256>(mbytes),
|
256 => private.sign::<SHA256>(mbytes),
|
||||||
384 => private.sign::<Sha384>(mbytes),
|
384 => private.sign::<SHA384>(mbytes),
|
||||||
512 => private.sign::<Sha512>(mbytes),
|
512 => private.sign::<SHA512>(mbytes),
|
||||||
x => panic!("Unknown hash algorithm {}", x)
|
x => panic!("Unknown hash algorithm {}", x)
|
||||||
};
|
};
|
||||||
assert_eq!(r, sig.r, "r signature check");
|
assert_eq!(r, sig.r, "r signature check");
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
use cryptonum::signed::*;
|
use cryptonum::signed::*;
|
||||||
use cryptonum::unsigned::*;
|
use cryptonum::unsigned::*;
|
||||||
use digest::{BlockInput,Digest,Input,FixedOutput,Reset};
|
|
||||||
use dsa::rfc6979::DSASignature;
|
use dsa::rfc6979::DSASignature;
|
||||||
use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
||||||
use ecdsa::point::{ECCPoint,Point};
|
use ecdsa::point::{ECCPoint,Point};
|
||||||
use hmac::{Hmac,Mac};
|
use sha::Hash;
|
||||||
use simple_asn1::{ASN1Block,ASN1Class,ASN1DecodeErr,ASN1EncodeErr,FromASN1,ToASN1};
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1DecodeErr,ASN1EncodeErr,FromASN1,ToASN1};
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
@@ -65,10 +64,7 @@ macro_rules! public_impl {
|
|||||||
|
|
||||||
/// Returns true if the given message matches the given signature,
|
/// Returns true if the given message matches the given signature,
|
||||||
/// assuming the provided hash function.
|
/// assuming the provided hash function.
|
||||||
pub fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<$un>) -> bool
|
pub fn verify<H: Hash>(&self, m: &[u8], sig: &DSASignature<$un>) -> bool
|
||||||
where
|
|
||||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
|
||||||
Hmac<Hash>: Mac
|
|
||||||
{
|
{
|
||||||
let n = <$curve>::n();
|
let n = <$curve>::n();
|
||||||
|
|
||||||
@@ -81,7 +77,7 @@ macro_rules! public_impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// e = the leftmost min(N, outlen) bits of Hash(M').
|
// e = the leftmost min(N, outlen) bits of Hash(M').
|
||||||
let mut digest_bytes = <Hash>::digest(m).to_vec();
|
let mut digest_bytes = <H>::hash(m);
|
||||||
let len = min(digest_bytes.len(), $curve::size() / 8);
|
let len = min(digest_bytes.len(), $curve::size() / 8);
|
||||||
digest_bytes.truncate(len);
|
digest_bytes.truncate(len);
|
||||||
|
|
||||||
@@ -169,7 +165,7 @@ public_impl!(P384, U384, I384);
|
|||||||
public_impl!(P521, U576, I576);
|
public_impl!(P521, U576, I576);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use testing::*;
|
use testing::*;
|
||||||
|
|
||||||
@@ -201,10 +197,10 @@ macro_rules! verify_test_body
|
|||||||
let public = ECCPublicKey::<$curve>::new(point);
|
let public = ECCPublicKey::<$curve>::new(point);
|
||||||
let sig = DSASignature::new(r, s);
|
let sig = DSASignature::new(r, s);
|
||||||
match usize::from(h) {
|
match usize::from(h) {
|
||||||
224 => assert!(public.verify::<Sha224>(mbytes, &sig)),
|
224 => assert!(public.verify::<SHA224>(mbytes, &sig)),
|
||||||
256 => assert!(public.verify::<Sha256>(mbytes, &sig)),
|
256 => assert!(public.verify::<SHA256>(mbytes, &sig)),
|
||||||
384 => assert!(public.verify::<Sha384>(mbytes, &sig)),
|
384 => assert!(public.verify::<SHA384>(mbytes, &sig)),
|
||||||
512 => assert!(public.verify::<Sha512>(mbytes, &sig)),
|
512 => assert!(public.verify::<SHA512>(mbytes, &sig)),
|
||||||
x => panic!("Unknown hash algorithm {}", x)
|
x => panic!("Unknown hash algorithm {}", x)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,9 +25,8 @@ mod loads;
|
|||||||
mod point;
|
mod point;
|
||||||
mod scalars;
|
mod scalars;
|
||||||
|
|
||||||
use digest::Digest;
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use sha2::Sha512;
|
use sha::{Hash,SHA512};
|
||||||
use self::scalars::{curve25519_scalar_mask,x25519_sc_muladd,x25519_sc_reduce};
|
use self::scalars::{curve25519_scalar_mask,x25519_sc_muladd,x25519_sc_reduce};
|
||||||
use self::point::{Point,Point2};
|
use self::point::{Point,Point2};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -103,7 +102,7 @@ impl ED25519Private {
|
|||||||
public: [0; 32]
|
public: [0; 32]
|
||||||
};
|
};
|
||||||
result.seed.copy_from_slice(seed);
|
result.seed.copy_from_slice(seed);
|
||||||
let mut expanded = Sha512::digest(seed);
|
let mut expanded = SHA512::hash(seed);
|
||||||
let (private, prefix) = expanded.split_at_mut(32);
|
let (private, prefix) = expanded.split_at_mut(32);
|
||||||
result.private.copy_from_slice(private);
|
result.private.copy_from_slice(private);
|
||||||
result.prefix.copy_from_slice(prefix);
|
result.prefix.copy_from_slice(prefix);
|
||||||
@@ -120,10 +119,10 @@ impl ED25519Private {
|
|||||||
{
|
{
|
||||||
let mut signature_s = [0u8; 32];
|
let mut signature_s = [0u8; 32];
|
||||||
|
|
||||||
let mut ctx = Sha512::new();
|
let mut ctx = SHA512::new();
|
||||||
ctx.input(&self.prefix);
|
ctx.update(&self.prefix);
|
||||||
ctx.input(&msg);
|
ctx.update(&msg);
|
||||||
let nonce = digest_scalar(ctx.result().as_slice());
|
let nonce = digest_scalar(&ctx.finalize());
|
||||||
let r = Point::scalarmult_base(&nonce);
|
let r = Point::scalarmult_base(&nonce);
|
||||||
let signature_r = r.encode();
|
let signature_r = r.encode();
|
||||||
let hram_digest = eddsa_digest(&signature_r, &self.public, &msg);
|
let hram_digest = eddsa_digest(&signature_r, &self.public, &msg);
|
||||||
@@ -218,11 +217,11 @@ impl ED25519Public {
|
|||||||
|
|
||||||
fn eddsa_digest(signature_r: &[u8], public_key: &[u8], msg: &[u8]) -> Vec<u8>
|
fn eddsa_digest(signature_r: &[u8], public_key: &[u8], msg: &[u8]) -> Vec<u8>
|
||||||
{
|
{
|
||||||
let mut ctx = Sha512::new();
|
let mut ctx = SHA512::new();
|
||||||
ctx.input(signature_r);
|
ctx.update(signature_r);
|
||||||
ctx.input(public_key);
|
ctx.update(public_key);
|
||||||
ctx.input(msg);
|
ctx.update(msg);
|
||||||
ctx.result().as_slice().to_vec()
|
ctx.finalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn digest_scalar(digest: &[u8]) -> Vec<u8> {
|
fn digest_scalar(digest: &[u8]) -> Vec<u8> {
|
||||||
|
|||||||
196
src/hmac.rs
Normal file
196
src/hmac.rs
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
//! This module implements the Keyed-Hash Message Authentication Code, or HMAC,
|
||||||
|
//! as defined by NIST 198-1. Now, you might have questions, like:
|
||||||
|
//! * *Where did the 'K' go in the acronym?* I don't know. Maybe we should
|
||||||
|
//! always be saying Keyed-HMAC? It's a mystery.
|
||||||
|
//! * *What is this good for?* I do know the answer to that! HMACs are
|
||||||
|
//! useful when you want to extend the ability of a hash to tell you if
|
||||||
|
//! a message has been modified with the ability to determine if the
|
||||||
|
//! person that sent it had hold of a key. It's thus a version of the
|
||||||
|
//! message signing capability used in asymmetric crypto (`DSA`, `RSA`,
|
||||||
|
//! `ECDSA`, and `ED25519`, as implemented in this crate), but with a
|
||||||
|
//! symmetric key, instead.
|
||||||
|
//!
|
||||||
|
//! Because HMAC can be used with a variety of hash functions, this module
|
||||||
|
//! implements it as a generic structure that takes the associated hash as
|
||||||
|
//! a type argument. This should provide a reasonable level of flexibility,
|
||||||
|
//! while allowing the type system from preventing us from making any number
|
||||||
|
//! of really annoying mistakes. You can specify which of the hash functions
|
||||||
|
//! you want to use by using your standard turbofish:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::hmac::HMAC;
|
||||||
|
//! use simple_crypto::sha::SHA256;
|
||||||
|
//!
|
||||||
|
//! let key = [0,1,2,3,4]; // very secure
|
||||||
|
//! let msg = [5,6,7,8];
|
||||||
|
//! let hmac = HMAC::<SHA256>::hmac(&key, &msg);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Much like with `SHAKE128` and `SHAKE256` the interface for HMAC is
|
||||||
|
//! similar to, but not quite, the interface for `Hash`. We thus try to
|
||||||
|
//! copy as much of the standard `Hash` interface as we can, but extend
|
||||||
|
//! `new` with a key, rename `hash` to `hmac`, and extend `hmac` with a
|
||||||
|
//! key as well. This provides a similar ability to use HMACs both in an
|
||||||
|
//! incremental mode as well as just do it all at once, as follows:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::hmac::HMAC;
|
||||||
|
//! use simple_crypto::sha::SHA256;
|
||||||
|
//!
|
||||||
|
//! let key = [0,1,2,3,4]; // like my suitcase
|
||||||
|
//! let msg = [5,6,7,8];
|
||||||
|
//!
|
||||||
|
//! // Compute the HMAC incrementally
|
||||||
|
//! let mut hmacinc = HMAC::<SHA256>::new(&key);
|
||||||
|
//! hmacinc.update(&[5,6]);
|
||||||
|
//! hmacinc.update(&[7,8]);
|
||||||
|
//! let hmac_incremental = hmacinc.finalize();
|
||||||
|
//!
|
||||||
|
//! // Compute the HMAC all at once
|
||||||
|
//! let hmac_once = HMAC::<SHA256>::hmac(&key, &msg);
|
||||||
|
//!
|
||||||
|
//! // ... which should be the same thing
|
||||||
|
//! assert_eq!(hmac_incremental, hmac_once);
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
/// The HMAC structure, parameterized by its hash function.
|
||||||
|
///
|
||||||
|
/// Much like with `SHAKE128` and `SHAKE256` the interface for HMAC is
|
||||||
|
/// similar to, but not quite, the interface for `Hash`. We thus try to
|
||||||
|
/// copy as much of the standard `Hash` interface as we can, but extend
|
||||||
|
/// `new` with a key, rename `hash` to `hmac`, and extend `hmac` with a
|
||||||
|
/// key as well. This provides a similar ability to use HMACs both in an
|
||||||
|
/// incremental mode as well as just do it all at once, as follows:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::hmac::HMAC;
|
||||||
|
/// use simple_crypto::sha::SHA256;
|
||||||
|
///
|
||||||
|
/// let key = [0,1,2,3,4]; // like my suitcase
|
||||||
|
/// let msg = [5,6,7,8];
|
||||||
|
///
|
||||||
|
/// // Compute the HMAC incrementally
|
||||||
|
/// let mut hmacinc = HMAC::<SHA256>::new(&key);
|
||||||
|
/// hmacinc.update(&[5,6]);
|
||||||
|
/// hmacinc.update(&[7,8]);
|
||||||
|
/// let hmac_incremental = hmacinc.finalize();
|
||||||
|
///
|
||||||
|
/// // Compute the HMAC all at once
|
||||||
|
/// let hmac_once = HMAC::<SHA256>::hmac(&key, &msg);
|
||||||
|
///
|
||||||
|
/// // ... which should be the same thing
|
||||||
|
/// assert_eq!(hmac_incremental, hmac_once);
|
||||||
|
/// ```
|
||||||
|
use super::Hash;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct HMAC<H: Hash + Clone> {
|
||||||
|
ipad_hash: H,
|
||||||
|
opad_hash: H,
|
||||||
|
result: Option<Vec<u8>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: Hash + Clone> HMAC<H> {
|
||||||
|
/// Generate a new HMAC construction for the provide underlying hash
|
||||||
|
/// function, and prep it to start taking input via the `update`
|
||||||
|
/// method.
|
||||||
|
pub fn new(inkey: &[u8]) -> Self {
|
||||||
|
let hash_blocklen_bytes = H::block_size() / 8;
|
||||||
|
|
||||||
|
// If the input key is longer than the hash block length, then we
|
||||||
|
// immediately hash it down to be the block length. Otherwise, we
|
||||||
|
// leave it be.
|
||||||
|
let mut key = if inkey.len() > hash_blocklen_bytes { H::hash(inkey) }
|
||||||
|
else { inkey.to_vec() };
|
||||||
|
// It may now be too small, or have started too small, in which case
|
||||||
|
// we pad it out with zeros.
|
||||||
|
key.resize(hash_blocklen_bytes, 0);
|
||||||
|
// Generate the inner and outer key pad from this key.
|
||||||
|
let o_key_pad: Vec<u8> = key.iter().map(|x| *x ^ 0x5c).collect();
|
||||||
|
let i_key_pad: Vec<u8> = key.iter().map(|x| *x ^ 0x36).collect();
|
||||||
|
// Now we can start the hashes; obviously we'll have to wait
|
||||||
|
// until we get the rest of the message to complete them.
|
||||||
|
let mut ipad_hash = H::new();
|
||||||
|
ipad_hash.update(&i_key_pad);
|
||||||
|
let mut opad_hash = H::new();
|
||||||
|
opad_hash.update(&o_key_pad);
|
||||||
|
let result = None;
|
||||||
|
HMAC { ipad_hash, opad_hash, result }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add more data as part of the HMAC computation. This can be called
|
||||||
|
/// zero or more times over the lifetime of the HMAC structure. That
|
||||||
|
/// being said, once you call `finalize`, this structure is done, and
|
||||||
|
/// it will ignore further calls to `update`.
|
||||||
|
pub fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
if self.result.is_none() {
|
||||||
|
self.ipad_hash.update(&buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provide the final HMAC value for the bitrstream as read. This shifts
|
||||||
|
/// this structure into a final mode, in which it will ignore any more
|
||||||
|
/// data provided to it from `update`. You can, however, call `finalize`
|
||||||
|
/// more than once; the HMAC structure caches the return value and will
|
||||||
|
/// return it as many times as you like.
|
||||||
|
pub fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if let Some(ref res) = self.result {
|
||||||
|
res.clone()
|
||||||
|
} else {
|
||||||
|
self.opad_hash.update(&self.ipad_hash.finalize());
|
||||||
|
let res = self.opad_hash.finalize();
|
||||||
|
self.result = Some(res.clone());
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A useful method for those situations in which you have only one block
|
||||||
|
/// of data to generate an HMAC for. Runs `new`, `update`, and `finalize`
|
||||||
|
/// for you, in order.
|
||||||
|
pub fn hmac(key: &[u8], val: &[u8]) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut h = Self::new(key);
|
||||||
|
h.update(val);
|
||||||
|
h.finalize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use sha::{SHA1,SHA224,SHA256,SHA384,SHA512};
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
#[cfg(test)]
|
||||||
|
use cryptonum::unsigned::{Decoder,U192};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_vectors() {
|
||||||
|
let fname = "testdata/sha/hmac.test";
|
||||||
|
run_test(fname.to_string(), 6, |case| {
|
||||||
|
let (negh, hbytes) = case.get("h").unwrap();
|
||||||
|
let (negr, rbytes) = case.get("r").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negk, kbytes) = case.get("k").unwrap();
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negt, tbytes) = case.get("t").unwrap();
|
||||||
|
|
||||||
|
assert!(!negh && !negr && !negm && !negk && !negl && !negt);
|
||||||
|
let l = usize::from(U192::from_bytes(lbytes));
|
||||||
|
let h = usize::from(U192::from_bytes(hbytes));
|
||||||
|
assert_eq!(l, kbytes.len());
|
||||||
|
let mut res = match h {
|
||||||
|
160 => HMAC::<SHA1>::hmac(&kbytes, &mbytes),
|
||||||
|
224 => HMAC::<SHA224>::hmac(&kbytes, &mbytes),
|
||||||
|
256 => HMAC::<SHA256>::hmac(&kbytes, &mbytes),
|
||||||
|
384 => HMAC::<SHA384>::hmac(&kbytes, &mbytes),
|
||||||
|
512 => HMAC::<SHA512>::hmac(&kbytes, &mbytes),
|
||||||
|
_ => panic!("Weird hash size in HMAC test file")
|
||||||
|
};
|
||||||
|
let t = usize::from(U192::from_bytes(tbytes));
|
||||||
|
res.resize(t, 0);
|
||||||
|
assert_eq!(rbytes, &res);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
44
src/lib.rs
44
src/lib.rs
@@ -13,15 +13,11 @@ extern crate base64;
|
|||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
extern crate chrono;
|
extern crate chrono;
|
||||||
extern crate cryptonum;
|
extern crate cryptonum;
|
||||||
extern crate digest;
|
|
||||||
extern crate hmac;
|
|
||||||
extern crate num;
|
extern crate num;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate quickcheck;
|
extern crate quickcheck;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate sha1;
|
|
||||||
extern crate sha2;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate simple_asn1;
|
extern crate simple_asn1;
|
||||||
|
|
||||||
@@ -41,9 +37,20 @@ pub mod ed25519;
|
|||||||
/// The `ssh` module provides support for parsing OpenSSH-formatted SSH keys,
|
/// The `ssh` module provides support for parsing OpenSSH-formatted SSH keys,
|
||||||
/// both public and private.
|
/// both public and private.
|
||||||
pub mod ssh;
|
pub mod ssh;
|
||||||
|
/// The `shake` module provides support for SHAKE128 and SHAKE256, two
|
||||||
|
/// variable-length hash functions that derive from the same core hash
|
||||||
|
/// as SHA3.
|
||||||
|
pub mod shake;
|
||||||
|
/// The `hmac` module provides support for keyed-hash message authentication,
|
||||||
|
/// or HMAC, based on any of the hash functions defined in this module.
|
||||||
|
pub mod hmac;
|
||||||
/// The `x509` module supports parsing and generating x.509 certificates, as
|
/// The `x509` module supports parsing and generating x.509 certificates, as
|
||||||
/// used by TLS and others.
|
/// used by TLS and others.
|
||||||
pub mod x509;
|
pub mod x509;
|
||||||
|
/// An implementation of the SHA family of hashes, including the relatively
|
||||||
|
/// weak SHA1 and a bunch of hashes you should use, like the SHA2 and SHA3
|
||||||
|
/// hashes.
|
||||||
|
pub mod sha;
|
||||||
|
|
||||||
/// A generic trait for defining what a key pair looks like. This is useful
|
/// A generic trait for defining what a key pair looks like. This is useful
|
||||||
/// in a couple places in which we want to define code regardless of the
|
/// in a couple places in which we want to define code regardless of the
|
||||||
@@ -59,6 +66,35 @@ pub trait KeyPair {
|
|||||||
fn new(pbl: Self::Public, prv: Self::Private) -> Self;
|
fn new(pbl: Self::Public, prv: Self::Private) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A generic trait for defining a hash function.
|
||||||
|
pub trait Hash: Sized
|
||||||
|
{
|
||||||
|
/// Generate a fresh instance of this hash function, set to the
|
||||||
|
/// appropriate initial state.
|
||||||
|
fn new() -> Self;
|
||||||
|
/// Update the hash function with some more data for it to chew on.
|
||||||
|
/// Nom nom nom. If you give it more information after calling
|
||||||
|
/// `finalize`, the implementation is welcome to do anything it
|
||||||
|
/// wants; mostly they will just ignore additional data, but
|
||||||
|
/// maybe just don't do that.
|
||||||
|
fn update(&mut self, data: &[u8]);
|
||||||
|
/// Finalize the hash function, returning the hash value.
|
||||||
|
fn finalize(&mut self) -> Vec<u8>;
|
||||||
|
/// Return the block size of the underlying hash function, in
|
||||||
|
/// bits. This is mostly useful internally to this crate.
|
||||||
|
fn block_size() -> usize;
|
||||||
|
|
||||||
|
/// This is a convenience routine that runs new(), update(), and
|
||||||
|
/// finalize() on a piece of data all at once. Because that's
|
||||||
|
/// mostly what people want to do.
|
||||||
|
fn hash(data: &[u8]) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut x = Self::new();
|
||||||
|
x.update(&data);
|
||||||
|
x.finalize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod testing;
|
mod testing;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|||||||
@@ -22,12 +22,11 @@
|
|||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! extern crate cryptonum;
|
//! extern crate cryptonum;
|
||||||
//! extern crate sha2;
|
|
||||||
//!
|
//!
|
||||||
//! use simple_crypto::rsa::RSAKeyPair;
|
//! use simple_crypto::rsa::RSAKeyPair;
|
||||||
//! use simple_crypto::rsa::SIGNING_HASH_SHA256;
|
//! use simple_crypto::rsa::SIGNING_HASH_SHA256;
|
||||||
//! use simple_crypto::rsa::OAEPParams;
|
//! use simple_crypto::rsa::OAEPParams;
|
||||||
//! use sha2::Sha256;
|
//! use simple_crypto::sha::SHA256;
|
||||||
//! use cryptonum::unsigned::U2048;
|
//! use cryptonum::unsigned::U2048;
|
||||||
//!
|
//!
|
||||||
//! // Generate a new RSA with key size 2048. (This is an acceptable but
|
//! // Generate a new RSA with key size 2048. (This is an acceptable but
|
||||||
@@ -45,7 +44,7 @@
|
|||||||
//!
|
//!
|
||||||
//! // We can also use RSA public keys to encrypt data, which can then be
|
//! // We can also use RSA public keys to encrypt data, which can then be
|
||||||
//! // decrypted by the private key.
|
//! // decrypted by the private key.
|
||||||
//! let params = OAEPParams::<Sha256>::new(String::from("example!"));
|
//! let params = OAEPParams::<SHA256>::new(String::from("example!"));
|
||||||
//! let cipher = kp.public.encrypt(¶ms, &msg).expect("Encryption error");
|
//! let cipher = kp.public.encrypt(¶ms, &msg).expect("Encryption error");
|
||||||
//! let msg2 = kp.private.decrypt(¶ms, &cipher).expect("Decryption error");
|
//! let msg2 = kp.private.decrypt(¶ms, &cipher).expect("Decryption error");
|
||||||
//! assert_eq!(msg, msg2);
|
//! assert_eq!(msg, msg2);
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
use byteorder::{BigEndian,ByteOrder};
|
use byteorder::{BigEndian,ByteOrder};
|
||||||
use digest::{Digest,FixedOutput};
|
use sha::Hash;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
/// Parameters for OAEP encryption and decryption: a hash function to use as
|
/// Parameters for OAEP encryption and decryption: a hash function to use as
|
||||||
/// part of the message generation function (MGF1, if you're curious),
|
/// part of the message generation function (MGF1, if you're curious),
|
||||||
/// and any labels you want to include as part of the encryption.
|
/// and any labels you want to include as part of the encryption.
|
||||||
pub struct OAEPParams<H: Default + Digest + FixedOutput> {
|
pub struct OAEPParams<H: Hash> {
|
||||||
pub label: String,
|
pub label: String,
|
||||||
phantom: PhantomData<H>
|
phantom: PhantomData<H>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: Default + Digest + FixedOutput> OAEPParams<H> {
|
impl<H: Hash> OAEPParams<H> {
|
||||||
pub fn new(label: String)
|
pub fn new(label: String)
|
||||||
-> OAEPParams<H>
|
-> OAEPParams<H>
|
||||||
{
|
{
|
||||||
@@ -18,11 +18,11 @@ impl<H: Default + Digest + FixedOutput> OAEPParams<H> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash_len(&self) -> usize {
|
pub fn hash_len(&self) -> usize {
|
||||||
H::default().fixed_result().as_slice().len()
|
H::hash(&[]).len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash(&self, input: &[u8]) -> Vec<u8> {
|
pub fn hash(&self, input: &[u8]) -> Vec<u8> {
|
||||||
H::digest(input).as_slice().to_vec()
|
H::hash(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mgf1(&self, input: &[u8], len: usize) -> Vec<u8> {
|
pub fn mgf1(&self, input: &[u8], len: usize) -> Vec<u8> {
|
||||||
@@ -32,10 +32,10 @@ impl<H: Default + Digest + FixedOutput> OAEPParams<H> {
|
|||||||
while res.len() < len {
|
while res.len() < len {
|
||||||
let mut buffer = [0; 4];
|
let mut buffer = [0; 4];
|
||||||
BigEndian::write_u32(&mut buffer, counter);
|
BigEndian::write_u32(&mut buffer, counter);
|
||||||
let mut digest = H::default();
|
let mut digest = H::new();
|
||||||
digest.input(input);
|
digest.update(input);
|
||||||
digest.input(&buffer);
|
digest.update(&buffer);
|
||||||
let chunk = digest.fixed_result();
|
let chunk = digest.finalize();
|
||||||
res.extend_from_slice(chunk.as_slice());
|
res.extend_from_slice(chunk.as_slice());
|
||||||
counter = counter + 1;
|
counter = counter + 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use cryptonum::unsigned::*;
|
use cryptonum::unsigned::*;
|
||||||
use digest::{Digest,FixedOutput};
|
|
||||||
use rsa::core::{RSAMode,drop0s,pkcs1_pad,xor_vecs};
|
use rsa::core::{RSAMode,drop0s,pkcs1_pad,xor_vecs};
|
||||||
use rsa::errors::RSAError;
|
use rsa::errors::RSAError;
|
||||||
use rsa::oaep::OAEPParams;
|
use rsa::oaep::OAEPParams;
|
||||||
use rsa::signing_hashes::SigningHash;
|
use rsa::signing_hashes::SigningHash;
|
||||||
|
use sha::Hash;
|
||||||
|
|
||||||
/// An RSA private key. Useful for signing messages and decrypting encrypted
|
/// An RSA private key. Useful for signing messages and decrypting encrypted
|
||||||
/// content.
|
/// content.
|
||||||
@@ -61,9 +61,8 @@ macro_rules! generate_rsa_private
|
|||||||
/// method to encrypt/decrypt a shared symmetric key, like an
|
/// method to encrypt/decrypt a shared symmetric key, like an
|
||||||
/// AES key. That way, you only do this operation (which is
|
/// AES key. That way, you only do this operation (which is
|
||||||
/// SO SLOW) for a relatively small amount of data.
|
/// SO SLOW) for a relatively small amount of data.
|
||||||
pub fn decrypt<H>(&self, oaep: &OAEPParams<H>, msg: &[u8])
|
pub fn decrypt<H: Hash>(&self, oaep: &OAEPParams<H>, msg: &[u8])
|
||||||
-> Result<Vec<u8>,RSAError>
|
-> Result<Vec<u8>,RSAError>
|
||||||
where H: Default + Digest + FixedOutput
|
|
||||||
{
|
{
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
|
|
||||||
@@ -83,10 +82,8 @@ macro_rules! generate_rsa_private
|
|||||||
c.modexp(&self.d, &self.nu)
|
c.modexp(&self.d, &self.nu)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn oaep_decrypt<H>(&self, oaep: &OAEPParams<H>, c: &[u8])
|
fn oaep_decrypt<H: Hash>(&self, oaep: &OAEPParams<H>, c: &[u8])
|
||||||
-> Result<Vec<u8>,RSAError>
|
-> Result<Vec<u8>,RSAError>
|
||||||
where
|
|
||||||
H: Default + Digest + FixedOutput
|
|
||||||
{
|
{
|
||||||
let byte_len = $size / 8;
|
let byte_len = $size / 8;
|
||||||
// Step 1b
|
// Step 1b
|
||||||
@@ -204,10 +201,10 @@ macro_rules! decrypt_test_body {
|
|||||||
let privkey = RSAPrivateKey{ nu: nu, d: d };
|
let privkey = RSAPrivateKey{ nu: nu, d: d };
|
||||||
let lstr = String::from_utf8(lbytes.clone()).unwrap();
|
let lstr = String::from_utf8(lbytes.clone()).unwrap();
|
||||||
let message = match usize::from($num::from_bytes(hbytes)) {
|
let message = match usize::from($num::from_bytes(hbytes)) {
|
||||||
224 => privkey.decrypt(&OAEPParams::<Sha224>::new(lstr), &cbytes),
|
224 => privkey.decrypt(&OAEPParams::<SHA224>::new(lstr), &cbytes),
|
||||||
256 => privkey.decrypt(&OAEPParams::<Sha256>::new(lstr), &cbytes),
|
256 => privkey.decrypt(&OAEPParams::<SHA256>::new(lstr), &cbytes),
|
||||||
384 => privkey.decrypt(&OAEPParams::<Sha384>::new(lstr), &cbytes),
|
384 => privkey.decrypt(&OAEPParams::<SHA384>::new(lstr), &cbytes),
|
||||||
512 => privkey.decrypt(&OAEPParams::<Sha512>::new(lstr), &cbytes),
|
512 => privkey.decrypt(&OAEPParams::<SHA512>::new(lstr), &cbytes),
|
||||||
x => panic!("Unknown hash number: {}", x)
|
x => panic!("Unknown hash number: {}", x)
|
||||||
};
|
};
|
||||||
assert!(message.is_ok());
|
assert!(message.is_ok());
|
||||||
@@ -225,7 +222,7 @@ macro_rules! generate_tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use testing::run_test;
|
use testing::run_test;
|
||||||
use rsa::signing_hashes::*;
|
use rsa::signing_hashes::*;
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sign() {
|
fn sign() {
|
||||||
@@ -246,7 +243,7 @@ macro_rules! generate_tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use testing::run_test;
|
use testing::run_test;
|
||||||
use rsa::signing_hashes::*;
|
use rsa::signing_hashes::*;
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
#[ignore]
|
#[ignore]
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use cryptonum::unsigned::*;
|
use cryptonum::unsigned::*;
|
||||||
use digest::{Digest,FixedOutput};
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use rsa::core::{RSAMode,decode_biguint,pkcs1_pad,xor_vecs};
|
use rsa::core::{RSAMode,decode_biguint,pkcs1_pad,xor_vecs};
|
||||||
use rsa::errors::RSAError;
|
use rsa::errors::RSAError;
|
||||||
use rsa::oaep::OAEPParams;
|
use rsa::oaep::OAEPParams;
|
||||||
use rsa::signing_hashes::SigningHash;
|
use rsa::signing_hashes::SigningHash;
|
||||||
|
use sha::Hash;
|
||||||
use simple_asn1::{ASN1Block,ASN1DecodeErr,ASN1EncodeErr,
|
use simple_asn1::{ASN1Block,ASN1DecodeErr,ASN1EncodeErr,
|
||||||
ASN1Class,FromASN1,ToASN1};
|
ASN1Class,FromASN1,ToASN1};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -200,7 +200,7 @@ macro_rules! generate_rsa_public
|
|||||||
-> Result<Vec<u8>,RSAError>
|
-> Result<Vec<u8>,RSAError>
|
||||||
where
|
where
|
||||||
G: Rng,
|
G: Rng,
|
||||||
H: Default + Digest + FixedOutput
|
H: Hash
|
||||||
{
|
{
|
||||||
let byte_len = $size / 8;
|
let byte_len = $size / 8;
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
@@ -224,10 +224,8 @@ macro_rules! generate_rsa_public
|
|||||||
/// with that symmetric key.
|
/// with that symmetric key.
|
||||||
///
|
///
|
||||||
/// This variant will just use the system RNG for its randomness.
|
/// This variant will just use the system RNG for its randomness.
|
||||||
pub fn encrypt<H>(&self,oaep:&OAEPParams<H>,msg:&[u8])
|
pub fn encrypt<H: Hash>(&self,oaep:&OAEPParams<H>,msg:&[u8])
|
||||||
-> Result<Vec<u8>,RSAError>
|
-> Result<Vec<u8>,RSAError>
|
||||||
where
|
|
||||||
H: Default + Digest + FixedOutput
|
|
||||||
{
|
{
|
||||||
let mut g = OsRng::new()?;
|
let mut g = OsRng::new()?;
|
||||||
self.encrypt_rng(&mut g, oaep, msg)
|
self.encrypt_rng(&mut g, oaep, msg)
|
||||||
@@ -245,7 +243,7 @@ macro_rules! generate_rsa_public
|
|||||||
-> Result<Vec<u8>,RSAError>
|
-> Result<Vec<u8>,RSAError>
|
||||||
where
|
where
|
||||||
G: Rng,
|
G: Rng,
|
||||||
H: Default + Digest + FixedOutput
|
H: Hash
|
||||||
{
|
{
|
||||||
let byte_len = $size / 8;
|
let byte_len = $size / 8;
|
||||||
// Step 1b
|
// Step 1b
|
||||||
@@ -450,18 +448,18 @@ macro_rules! encrypt_test_body {
|
|||||||
let privkey = RSAPrivateKey{ nu: nu, d: d };
|
let privkey = RSAPrivateKey{ nu: nu, d: d };
|
||||||
let lstr = String::from_utf8(lbytes.clone()).unwrap();
|
let lstr = String::from_utf8(lbytes.clone()).unwrap();
|
||||||
let cipher = match usize::from($num::from_bytes(hbytes)) {
|
let cipher = match usize::from($num::from_bytes(hbytes)) {
|
||||||
224 => pubkey.encrypt(&OAEPParams::<Sha224>::new(lstr.clone()), mbytes),
|
224 => pubkey.encrypt(&OAEPParams::<SHA224>::new(lstr.clone()), mbytes),
|
||||||
256 => pubkey.encrypt(&OAEPParams::<Sha256>::new(lstr.clone()), mbytes),
|
256 => pubkey.encrypt(&OAEPParams::<SHA256>::new(lstr.clone()), mbytes),
|
||||||
384 => pubkey.encrypt(&OAEPParams::<Sha384>::new(lstr.clone()), mbytes),
|
384 => pubkey.encrypt(&OAEPParams::<SHA384>::new(lstr.clone()), mbytes),
|
||||||
512 => pubkey.encrypt(&OAEPParams::<Sha512>::new(lstr.clone()), mbytes),
|
512 => pubkey.encrypt(&OAEPParams::<SHA512>::new(lstr.clone()), mbytes),
|
||||||
x => panic!("Unknown hash number: {}", x)
|
x => panic!("Unknown hash number: {}", x)
|
||||||
};
|
};
|
||||||
assert!(cipher.is_ok());
|
assert!(cipher.is_ok());
|
||||||
let message = match usize::from($num::from_bytes(hbytes)) {
|
let message = match usize::from($num::from_bytes(hbytes)) {
|
||||||
224 => privkey.decrypt(&OAEPParams::<Sha224>::new(lstr), &cipher.unwrap()),
|
224 => privkey.decrypt(&OAEPParams::<SHA224>::new(lstr), &cipher.unwrap()),
|
||||||
256 => privkey.decrypt(&OAEPParams::<Sha256>::new(lstr), &cipher.unwrap()),
|
256 => privkey.decrypt(&OAEPParams::<SHA256>::new(lstr), &cipher.unwrap()),
|
||||||
384 => privkey.decrypt(&OAEPParams::<Sha384>::new(lstr), &cipher.unwrap()),
|
384 => privkey.decrypt(&OAEPParams::<SHA384>::new(lstr), &cipher.unwrap()),
|
||||||
512 => privkey.decrypt(&OAEPParams::<Sha512>::new(lstr), &cipher.unwrap()),
|
512 => privkey.decrypt(&OAEPParams::<SHA512>::new(lstr), &cipher.unwrap()),
|
||||||
x => panic!("Unknown hash number: {}", x)
|
x => panic!("Unknown hash number: {}", x)
|
||||||
};
|
};
|
||||||
assert!(message.is_ok());
|
assert!(message.is_ok());
|
||||||
@@ -480,7 +478,7 @@ macro_rules! generate_tests {
|
|||||||
use testing::run_test;
|
use testing::run_test;
|
||||||
use rsa::private::*;
|
use rsa::private::*;
|
||||||
use rsa::signing_hashes::*;
|
use rsa::signing_hashes::*;
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn new() { new_test_body!($mod, $num, $bar, $num64, $size); }
|
fn new() { new_test_body!($mod, $num, $bar, $num64, $size); }
|
||||||
@@ -501,7 +499,7 @@ macro_rules! generate_tests {
|
|||||||
use testing::run_test;
|
use testing::run_test;
|
||||||
use rsa::private::*;
|
use rsa::private::*;
|
||||||
use rsa::signing_hashes::*;
|
use rsa::signing_hashes::*;
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
#[ignore]
|
#[ignore]
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
use digest::Digest;
|
use sha::{Hash,SHA1,SHA224,SHA256,SHA384,SHA512};
|
||||||
use sha1::Sha1;
|
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// A hash that can be used to sign a message.
|
/// A hash that can be used to sign a message.
|
||||||
@@ -28,13 +26,9 @@ impl fmt::Debug for SigningHash {
|
|||||||
pub static SIGNING_HASH_NULL: SigningHash = SigningHash {
|
pub static SIGNING_HASH_NULL: SigningHash = SigningHash {
|
||||||
name: "NULL",
|
name: "NULL",
|
||||||
ident: &[],
|
ident: &[],
|
||||||
run: nohash
|
run: |x| { x.to_vec() }
|
||||||
};
|
};
|
||||||
|
|
||||||
fn nohash(i: &[u8]) -> Vec<u8> {
|
|
||||||
i.to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sign a hash based on SHA1. You shouldn't use this unless you're using
|
/// Sign a hash based on SHA1. You shouldn't use this unless you're using
|
||||||
/// very small keys, and this is the only one available to you. Even then,
|
/// very small keys, and this is the only one available to you. Even then,
|
||||||
/// why are you using such small keys?!
|
/// why are you using such small keys?!
|
||||||
@@ -42,13 +36,9 @@ pub static SIGNING_HASH_SHA1: SigningHash = SigningHash {
|
|||||||
name: "SHA1",
|
name: "SHA1",
|
||||||
ident: &[0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,
|
ident: &[0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,
|
||||||
0x02,0x1a,0x05,0x00,0x04,0x14],
|
0x02,0x1a,0x05,0x00,0x04,0x14],
|
||||||
run: runsha1
|
run: |x| { SHA1::hash(x) }
|
||||||
};
|
};
|
||||||
|
|
||||||
fn runsha1(i: &[u8]) -> Vec<u8> {
|
|
||||||
Sha1::digest(i).as_slice().to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sign a hash based on SHA2-224. This is the first reasonable choice
|
/// Sign a hash based on SHA2-224. This is the first reasonable choice
|
||||||
/// we've come across, and is useful when you have smaller RSA key sizes.
|
/// we've come across, and is useful when you have smaller RSA key sizes.
|
||||||
/// I wouldn't recommend it, though.
|
/// I wouldn't recommend it, though.
|
||||||
@@ -57,26 +47,18 @@ pub static SIGNING_HASH_SHA224: SigningHash = SigningHash {
|
|||||||
ident: &[0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
ident: &[0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
||||||
0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,
|
0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,
|
||||||
0x1c],
|
0x1c],
|
||||||
run: runsha224
|
run: |x| { SHA224::hash(x) }
|
||||||
};
|
};
|
||||||
|
|
||||||
fn runsha224(i: &[u8]) -> Vec<u8> {
|
|
||||||
Sha224::digest(i).as_slice().to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sign a hash based on SHA2-256. The first one I'd recommend!
|
/// Sign a hash based on SHA2-256. The first one I'd recommend!
|
||||||
pub static SIGNING_HASH_SHA256: SigningHash = SigningHash {
|
pub static SIGNING_HASH_SHA256: SigningHash = SigningHash {
|
||||||
name: "SHA256",
|
name: "SHA256",
|
||||||
ident: &[0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
ident: &[0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
||||||
0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,
|
0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,
|
||||||
0x20],
|
0x20],
|
||||||
run: runsha256
|
run: |x| { SHA256::hash(x) }
|
||||||
};
|
};
|
||||||
|
|
||||||
fn runsha256(i: &[u8]) -> Vec<u8> {
|
|
||||||
Sha256::digest(i).as_slice().to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sign a hash based on SHA2-384. Approximately 50% better than
|
/// Sign a hash based on SHA2-384. Approximately 50% better than
|
||||||
/// SHA-256.
|
/// SHA-256.
|
||||||
pub static SIGNING_HASH_SHA384: SigningHash = SigningHash {
|
pub static SIGNING_HASH_SHA384: SigningHash = SigningHash {
|
||||||
@@ -84,13 +66,9 @@ pub static SIGNING_HASH_SHA384: SigningHash = SigningHash {
|
|||||||
ident: &[0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
ident: &[0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
||||||
0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,
|
0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,
|
||||||
0x30],
|
0x30],
|
||||||
run: runsha384
|
run: |x| { SHA384::hash(x) }
|
||||||
};
|
};
|
||||||
|
|
||||||
fn runsha384(i: &[u8]) -> Vec<u8> {
|
|
||||||
Sha384::digest(i).as_slice().to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sign a hash based on SHA2-512. At this point, you're getting a bit
|
/// Sign a hash based on SHA2-512. At this point, you're getting a bit
|
||||||
/// silly. But if you want to through 8kbit RSA keys with a 512 bit SHA2
|
/// silly. But if you want to through 8kbit RSA keys with a 512 bit SHA2
|
||||||
/// signing hash, we're totally behind you.
|
/// signing hash, we're totally behind you.
|
||||||
@@ -99,11 +77,5 @@ pub static SIGNING_HASH_SHA512: SigningHash = SigningHash {
|
|||||||
ident: &[0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
ident: &[0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
||||||
0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,
|
0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,
|
||||||
0x40],
|
0x40],
|
||||||
run: runsha512
|
run: |x| { SHA512::hash(x) }
|
||||||
};
|
};
|
||||||
|
|
||||||
fn runsha512(i: &[u8]) -> Vec<u8> {
|
|
||||||
Sha512::digest(i).as_slice().to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
64
src/sha/mod.rs
Normal file
64
src/sha/mod.rs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
//! The SHA family of hash functions, as defined by NIST; specifically, from
|
||||||
|
//! NIST 180-4 (for SHA1 and SHA2) and NIST 202 (for SHA3).
|
||||||
|
//!
|
||||||
|
//! These hash functions are used through their instantiation of the `Hash`
|
||||||
|
//! trait, located in the parent `simple_crypto` module and re-exported
|
||||||
|
//! here for convenience. Thus, you're not going to see a lot of functions
|
||||||
|
//! or macros, here, just the type declarations.
|
||||||
|
//!
|
||||||
|
//! To use SHA2-384, as an example, you could run the following code:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::sha::{Hash,SHA384};
|
||||||
|
//!
|
||||||
|
//! let empty: [u8; 0] = [0; 0];
|
||||||
|
//! let mut digest_incremental = SHA384::new();
|
||||||
|
//! digest_incremental.update(&empty);
|
||||||
|
//! digest_incremental.update(&empty);
|
||||||
|
//! digest_incremental.update(&empty);
|
||||||
|
//! let result = digest_incremental.finalize();
|
||||||
|
//!
|
||||||
|
//! assert_eq!(result, vec![0x38,0xb0,0x60,0xa7,0x51,0xac,0x96,0x38,
|
||||||
|
//! 0x4c,0xd9,0x32,0x7e,0xb1,0xb1,0xe3,0x6a,
|
||||||
|
//! 0x21,0xfd,0xb7,0x11,0x14,0xbe,0x07,0x43,
|
||||||
|
//! 0x4c,0x0c,0xc7,0xbf,0x63,0xf6,0xe1,0xda,
|
||||||
|
//! 0x27,0x4e,0xde,0xbf,0xe7,0x6f,0x65,0xfb,
|
||||||
|
//! 0xd5,0x1a,0xd2,0xf1,0x48,0x98,0xb9,0x5b]);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! For other hashes, just substitute the appropriate hash structure for
|
||||||
|
//! `SHA384`. The `Hash` trait also includes a do-it-all-at-once built-in
|
||||||
|
//! function for those cases when you just have a single blob of data
|
||||||
|
//! you want to hash, rather than an incremental set of data:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::sha::{Hash,SHA3_256};
|
||||||
|
//!
|
||||||
|
//! let empty: [u8; 0] = [0; 0];
|
||||||
|
//! let result = SHA3_256::hash(&empty);
|
||||||
|
//!
|
||||||
|
//! assert_eq!(result, vec![0xa7,0xff,0xc6,0xf8,0xbf,0x1e,0xd7,0x66,
|
||||||
|
//! 0x51,0xc1,0x47,0x56,0xa0,0x61,0xd6,0x62,
|
||||||
|
//! 0xf5,0x80,0xff,0x4d,0xe4,0x3b,0x49,0xfa,
|
||||||
|
//! 0x82,0xd8,0x0a,0x4b,0x80,0xf8,0x43,0x4a]);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! In general, you should not use SHA1 for anything but supporting legacy
|
||||||
|
//! systems. We recommend either SHA2 or SHA3 at their 256-, 384-, or 512-bit
|
||||||
|
//! sizes. NIST claims (in FIPS 202, page 23-24) that SHA2 and SHA3 are
|
||||||
|
//! approximately equivalent in terms of security for collision, preimate,
|
||||||
|
//! and second preimage attacks, but that SHA3 improves upon SHA2 against
|
||||||
|
//! length-extension and other attacks. On the other hand, SHA2 has been
|
||||||
|
//! banged on for a little longer, and there's some claims that it's more
|
||||||
|
//! resistant to quantum attacks. So ... make your own decisions.
|
||||||
|
#[macro_use]
|
||||||
|
mod shared;
|
||||||
|
mod sha1;
|
||||||
|
mod sha2;
|
||||||
|
mod sha3;
|
||||||
|
|
||||||
|
pub use super::Hash;
|
||||||
|
pub use self::sha1::SHA1;
|
||||||
|
pub use self::sha2::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
pub use self::sha3::{SHA3_224,SHA3_256,SHA3_384,SHA3_512};
|
||||||
|
pub(crate) use self::sha3::Keccak;
|
||||||
306
src/sha/sha1.rs
Normal file
306
src/sha/sha1.rs
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
use byteorder::{BigEndian,WriteBytesExt};
|
||||||
|
use super::super::Hash;
|
||||||
|
use sha::shared::calculate_k;
|
||||||
|
|
||||||
|
/// The SHA1 hash. Don't use this except to support legacy systems.
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA1};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA1::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA1::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA1 {
|
||||||
|
state: [u32; 5],
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
done: bool,
|
||||||
|
l: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! sha1_step {
|
||||||
|
($op: ident, $out: ident, $ins: expr, $k: expr, $w: ident) => {
|
||||||
|
let $out = {
|
||||||
|
let [a,b,c,d,e] = $ins;
|
||||||
|
let ap = a.rotate_left(5) + $op!(b,c,d) + e + $k + $w;
|
||||||
|
let bp = a;
|
||||||
|
let cp = b.rotate_left(30);
|
||||||
|
let dp = c;
|
||||||
|
let ep = d;
|
||||||
|
[ap, bp, cp, dp, ep]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SHA1 {
|
||||||
|
fn process(&mut self, w00: u32, w01: u32, w02: u32, w03: u32,
|
||||||
|
w04: u32, w05: u32, w06: u32, w07: u32,
|
||||||
|
w08: u32, w09: u32, w10: u32, w11: u32,
|
||||||
|
w12: u32, w13: u32, w14: u32, w15: u32)
|
||||||
|
{
|
||||||
|
let w16 = (w13 ^ w08 ^ w02 ^ w00).rotate_left(1);
|
||||||
|
let w17 = (w14 ^ w09 ^ w03 ^ w01).rotate_left(1);
|
||||||
|
let w18 = (w15 ^ w10 ^ w04 ^ w02).rotate_left(1);
|
||||||
|
let w19 = (w16 ^ w11 ^ w05 ^ w03).rotate_left(1);
|
||||||
|
let w20 = (w17 ^ w12 ^ w06 ^ w04).rotate_left(1);
|
||||||
|
let w21 = (w18 ^ w13 ^ w07 ^ w05).rotate_left(1);
|
||||||
|
let w22 = (w19 ^ w14 ^ w08 ^ w06).rotate_left(1);
|
||||||
|
let w23 = (w20 ^ w15 ^ w09 ^ w07).rotate_left(1);
|
||||||
|
let w24 = (w21 ^ w16 ^ w10 ^ w08).rotate_left(1);
|
||||||
|
let w25 = (w22 ^ w17 ^ w11 ^ w09).rotate_left(1);
|
||||||
|
let w26 = (w23 ^ w18 ^ w12 ^ w10).rotate_left(1);
|
||||||
|
let w27 = (w24 ^ w19 ^ w13 ^ w11).rotate_left(1);
|
||||||
|
let w28 = (w25 ^ w20 ^ w14 ^ w12).rotate_left(1);
|
||||||
|
let w29 = (w26 ^ w21 ^ w15 ^ w13).rotate_left(1);
|
||||||
|
let w30 = (w27 ^ w22 ^ w16 ^ w14).rotate_left(1);
|
||||||
|
let w31 = (w28 ^ w23 ^ w17 ^ w15).rotate_left(1);
|
||||||
|
let w32 = (w29 ^ w24 ^ w18 ^ w16).rotate_left(1);
|
||||||
|
let w33 = (w30 ^ w25 ^ w19 ^ w17).rotate_left(1);
|
||||||
|
let w34 = (w31 ^ w26 ^ w20 ^ w18).rotate_left(1);
|
||||||
|
let w35 = (w32 ^ w27 ^ w21 ^ w19).rotate_left(1);
|
||||||
|
let w36 = (w33 ^ w28 ^ w22 ^ w20).rotate_left(1);
|
||||||
|
let w37 = (w34 ^ w29 ^ w23 ^ w21).rotate_left(1);
|
||||||
|
let w38 = (w35 ^ w30 ^ w24 ^ w22).rotate_left(1);
|
||||||
|
let w39 = (w36 ^ w31 ^ w25 ^ w23).rotate_left(1);
|
||||||
|
let w40 = (w37 ^ w32 ^ w26 ^ w24).rotate_left(1);
|
||||||
|
let w41 = (w38 ^ w33 ^ w27 ^ w25).rotate_left(1);
|
||||||
|
let w42 = (w39 ^ w34 ^ w28 ^ w26).rotate_left(1);
|
||||||
|
let w43 = (w40 ^ w35 ^ w29 ^ w27).rotate_left(1);
|
||||||
|
let w44 = (w41 ^ w36 ^ w30 ^ w28).rotate_left(1);
|
||||||
|
let w45 = (w42 ^ w37 ^ w31 ^ w29).rotate_left(1);
|
||||||
|
let w46 = (w43 ^ w38 ^ w32 ^ w30).rotate_left(1);
|
||||||
|
let w47 = (w44 ^ w39 ^ w33 ^ w31).rotate_left(1);
|
||||||
|
let w48 = (w45 ^ w40 ^ w34 ^ w32).rotate_left(1);
|
||||||
|
let w49 = (w46 ^ w41 ^ w35 ^ w33).rotate_left(1);
|
||||||
|
let w50 = (w47 ^ w42 ^ w36 ^ w34).rotate_left(1);
|
||||||
|
let w51 = (w48 ^ w43 ^ w37 ^ w35).rotate_left(1);
|
||||||
|
let w52 = (w49 ^ w44 ^ w38 ^ w36).rotate_left(1);
|
||||||
|
let w53 = (w50 ^ w45 ^ w39 ^ w37).rotate_left(1);
|
||||||
|
let w54 = (w51 ^ w46 ^ w40 ^ w38).rotate_left(1);
|
||||||
|
let w55 = (w52 ^ w47 ^ w41 ^ w39).rotate_left(1);
|
||||||
|
let w56 = (w53 ^ w48 ^ w42 ^ w40).rotate_left(1);
|
||||||
|
let w57 = (w54 ^ w49 ^ w43 ^ w41).rotate_left(1);
|
||||||
|
let w58 = (w55 ^ w50 ^ w44 ^ w42).rotate_left(1);
|
||||||
|
let w59 = (w56 ^ w51 ^ w45 ^ w43).rotate_left(1);
|
||||||
|
let w60 = (w57 ^ w52 ^ w46 ^ w44).rotate_left(1);
|
||||||
|
let w61 = (w58 ^ w53 ^ w47 ^ w45).rotate_left(1);
|
||||||
|
let w62 = (w59 ^ w54 ^ w48 ^ w46).rotate_left(1);
|
||||||
|
let w63 = (w60 ^ w55 ^ w49 ^ w47).rotate_left(1);
|
||||||
|
let w64 = (w61 ^ w56 ^ w50 ^ w48).rotate_left(1);
|
||||||
|
let w65 = (w62 ^ w57 ^ w51 ^ w49).rotate_left(1);
|
||||||
|
let w66 = (w63 ^ w58 ^ w52 ^ w50).rotate_left(1);
|
||||||
|
let w67 = (w64 ^ w59 ^ w53 ^ w51).rotate_left(1);
|
||||||
|
let w68 = (w65 ^ w60 ^ w54 ^ w52).rotate_left(1);
|
||||||
|
let w69 = (w66 ^ w61 ^ w55 ^ w53).rotate_left(1);
|
||||||
|
let w70 = (w67 ^ w62 ^ w56 ^ w54).rotate_left(1);
|
||||||
|
let w71 = (w68 ^ w63 ^ w57 ^ w55).rotate_left(1);
|
||||||
|
let w72 = (w69 ^ w64 ^ w58 ^ w56).rotate_left(1);
|
||||||
|
let w73 = (w70 ^ w65 ^ w59 ^ w57).rotate_left(1);
|
||||||
|
let w74 = (w71 ^ w66 ^ w60 ^ w58).rotate_left(1);
|
||||||
|
let w75 = (w72 ^ w67 ^ w61 ^ w59).rotate_left(1);
|
||||||
|
let w76 = (w73 ^ w68 ^ w62 ^ w60).rotate_left(1);
|
||||||
|
let w77 = (w74 ^ w69 ^ w63 ^ w61).rotate_left(1);
|
||||||
|
let w78 = (w75 ^ w70 ^ w64 ^ w62).rotate_left(1);
|
||||||
|
let w79 = (w76 ^ w71 ^ w65 ^ w63).rotate_left(1);
|
||||||
|
sha1_step!(ch, s01, self.state, 0x5a827999, w00);
|
||||||
|
sha1_step!(ch, s02, s01, 0x5a827999, w01);
|
||||||
|
sha1_step!(ch, s03, s02, 0x5a827999, w02);
|
||||||
|
sha1_step!(ch, s04, s03, 0x5a827999, w03);
|
||||||
|
sha1_step!(ch, s05, s04, 0x5a827999, w04);
|
||||||
|
sha1_step!(ch, s06, s05, 0x5a827999, w05);
|
||||||
|
sha1_step!(ch, s07, s06, 0x5a827999, w06);
|
||||||
|
sha1_step!(ch, s08, s07, 0x5a827999, w07);
|
||||||
|
sha1_step!(ch, s09, s08, 0x5a827999, w08);
|
||||||
|
sha1_step!(ch, s10, s09, 0x5a827999, w09);
|
||||||
|
sha1_step!(ch, s11, s10, 0x5a827999, w10);
|
||||||
|
sha1_step!(ch, s12, s11, 0x5a827999, w11);
|
||||||
|
sha1_step!(ch, s13, s12, 0x5a827999, w12);
|
||||||
|
sha1_step!(ch, s14, s13, 0x5a827999, w13);
|
||||||
|
sha1_step!(ch, s15, s14, 0x5a827999, w14);
|
||||||
|
sha1_step!(ch, s16, s15, 0x5a827999, w15);
|
||||||
|
sha1_step!(ch, s17, s16, 0x5a827999, w16);
|
||||||
|
sha1_step!(ch, s18, s17, 0x5a827999, w17);
|
||||||
|
sha1_step!(ch, s19, s18, 0x5a827999, w18);
|
||||||
|
sha1_step!(ch, s20, s19, 0x5a827999, w19);
|
||||||
|
sha1_step!(parity, s21, s20, 0x6ed9eba1, w20);
|
||||||
|
sha1_step!(parity, s22, s21, 0x6ed9eba1, w21);
|
||||||
|
sha1_step!(parity, s23, s22, 0x6ed9eba1, w22);
|
||||||
|
sha1_step!(parity, s24, s23, 0x6ed9eba1, w23);
|
||||||
|
sha1_step!(parity, s25, s24, 0x6ed9eba1, w24);
|
||||||
|
sha1_step!(parity, s26, s25, 0x6ed9eba1, w25);
|
||||||
|
sha1_step!(parity, s27, s26, 0x6ed9eba1, w26);
|
||||||
|
sha1_step!(parity, s28, s27, 0x6ed9eba1, w27);
|
||||||
|
sha1_step!(parity, s29, s28, 0x6ed9eba1, w28);
|
||||||
|
sha1_step!(parity, s30, s29, 0x6ed9eba1, w29);
|
||||||
|
sha1_step!(parity, s31, s30, 0x6ed9eba1, w30);
|
||||||
|
sha1_step!(parity, s32, s31, 0x6ed9eba1, w31);
|
||||||
|
sha1_step!(parity, s33, s32, 0x6ed9eba1, w32);
|
||||||
|
sha1_step!(parity, s34, s33, 0x6ed9eba1, w33);
|
||||||
|
sha1_step!(parity, s35, s34, 0x6ed9eba1, w34);
|
||||||
|
sha1_step!(parity, s36, s35, 0x6ed9eba1, w35);
|
||||||
|
sha1_step!(parity, s37, s36, 0x6ed9eba1, w36);
|
||||||
|
sha1_step!(parity, s38, s37, 0x6ed9eba1, w37);
|
||||||
|
sha1_step!(parity, s39, s38, 0x6ed9eba1, w38);
|
||||||
|
sha1_step!(parity, s40, s39, 0x6ed9eba1, w39);
|
||||||
|
sha1_step!(maj, s41, s40, 0x8f1bbcdc, w40);
|
||||||
|
sha1_step!(maj, s42, s41, 0x8f1bbcdc, w41);
|
||||||
|
sha1_step!(maj, s43, s42, 0x8f1bbcdc, w42);
|
||||||
|
sha1_step!(maj, s44, s43, 0x8f1bbcdc, w43);
|
||||||
|
sha1_step!(maj, s45, s44, 0x8f1bbcdc, w44);
|
||||||
|
sha1_step!(maj, s46, s45, 0x8f1bbcdc, w45);
|
||||||
|
sha1_step!(maj, s47, s46, 0x8f1bbcdc, w46);
|
||||||
|
sha1_step!(maj, s48, s47, 0x8f1bbcdc, w47);
|
||||||
|
sha1_step!(maj, s49, s48, 0x8f1bbcdc, w48);
|
||||||
|
sha1_step!(maj, s50, s49, 0x8f1bbcdc, w49);
|
||||||
|
sha1_step!(maj, s51, s50, 0x8f1bbcdc, w50);
|
||||||
|
sha1_step!(maj, s52, s51, 0x8f1bbcdc, w51);
|
||||||
|
sha1_step!(maj, s53, s52, 0x8f1bbcdc, w52);
|
||||||
|
sha1_step!(maj, s54, s53, 0x8f1bbcdc, w53);
|
||||||
|
sha1_step!(maj, s55, s54, 0x8f1bbcdc, w54);
|
||||||
|
sha1_step!(maj, s56, s55, 0x8f1bbcdc, w55);
|
||||||
|
sha1_step!(maj, s57, s56, 0x8f1bbcdc, w56);
|
||||||
|
sha1_step!(maj, s58, s57, 0x8f1bbcdc, w57);
|
||||||
|
sha1_step!(maj, s59, s58, 0x8f1bbcdc, w58);
|
||||||
|
sha1_step!(maj, s60, s59, 0x8f1bbcdc, w59);
|
||||||
|
sha1_step!(parity, s61, s60, 0xca62c1d6, w60);
|
||||||
|
sha1_step!(parity, s62, s61, 0xca62c1d6, w61);
|
||||||
|
sha1_step!(parity, s63, s62, 0xca62c1d6, w62);
|
||||||
|
sha1_step!(parity, s64, s63, 0xca62c1d6, w63);
|
||||||
|
sha1_step!(parity, s65, s64, 0xca62c1d6, w64);
|
||||||
|
sha1_step!(parity, s66, s65, 0xca62c1d6, w65);
|
||||||
|
sha1_step!(parity, s67, s66, 0xca62c1d6, w66);
|
||||||
|
sha1_step!(parity, s68, s67, 0xca62c1d6, w67);
|
||||||
|
sha1_step!(parity, s69, s68, 0xca62c1d6, w68);
|
||||||
|
sha1_step!(parity, s70, s69, 0xca62c1d6, w69);
|
||||||
|
sha1_step!(parity, s71, s70, 0xca62c1d6, w70);
|
||||||
|
sha1_step!(parity, s72, s71, 0xca62c1d6, w71);
|
||||||
|
sha1_step!(parity, s73, s72, 0xca62c1d6, w72);
|
||||||
|
sha1_step!(parity, s74, s73, 0xca62c1d6, w73);
|
||||||
|
sha1_step!(parity, s75, s74, 0xca62c1d6, w74);
|
||||||
|
sha1_step!(parity, s76, s75, 0xca62c1d6, w75);
|
||||||
|
sha1_step!(parity, s77, s76, 0xca62c1d6, w76);
|
||||||
|
sha1_step!(parity, s78, s77, 0xca62c1d6, w77);
|
||||||
|
sha1_step!(parity, s79, s78, 0xca62c1d6, w78);
|
||||||
|
sha1_step!(parity, s80, s79, 0xca62c1d6, w79);
|
||||||
|
self.state[0] += s80[0];
|
||||||
|
self.state[1] += s80[1];
|
||||||
|
self.state[2] += s80[2];
|
||||||
|
self.state[3] += s80[3];
|
||||||
|
self.state[4] += s80[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(&mut self)
|
||||||
|
{
|
||||||
|
let bitlen = self.l * 8;
|
||||||
|
let k = calculate_k(448, 512, bitlen);
|
||||||
|
// INVARIANT: k is necessarily > 0, and (k + 1) is a multiple of 8
|
||||||
|
let bytes_to_add = (k + 1) / 8;
|
||||||
|
let mut padvec = Vec::with_capacity(bytes_to_add + 8);
|
||||||
|
padvec.push(0x80); // Set the high bit, since the first bit after the data
|
||||||
|
// should be set
|
||||||
|
padvec.resize(bytes_to_add, 0);
|
||||||
|
padvec.write_u64::<BigEndian>(bitlen as u64).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
self.update(&padvec);
|
||||||
|
self.done = true;
|
||||||
|
assert_eq!(self.buffer.len(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA1
|
||||||
|
{
|
||||||
|
fn new() -> SHA1
|
||||||
|
{
|
||||||
|
SHA1 {
|
||||||
|
state: [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ],
|
||||||
|
buffer: Vec::with_capacity(64),
|
||||||
|
done: false,
|
||||||
|
l: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, block: &[u8])
|
||||||
|
{
|
||||||
|
if !self.done {
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
self.l += block.len();
|
||||||
|
|
||||||
|
if self.buffer.len() + block.len() < 64 {
|
||||||
|
self.buffer.extend_from_slice(block);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.buffer.len() > 0 {
|
||||||
|
// We must be able to build up a 64 byte chunk, at this point, otherwise
|
||||||
|
// the math above would've been wrong.
|
||||||
|
while self.buffer.len() < 64 {
|
||||||
|
self.buffer.push(block[offset]);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
process_u32_block!(self.buffer, 0, self);
|
||||||
|
// Reset the buffer now, we're done with that nonsense for the moment
|
||||||
|
self.buffer.resize(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset + 64) <= block.len() {
|
||||||
|
process_u32_block!(block, offset, self);
|
||||||
|
offset += 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset < block.len() {
|
||||||
|
self.buffer.extend_from_slice(&block[offset..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if !self.done {
|
||||||
|
self.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(20);
|
||||||
|
output.write_u32::<BigEndian>(self.state[0]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state[1]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state[2]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state[3]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state[4]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist() {
|
||||||
|
let fname = "testdata/sha/nist_sha1.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA1::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
842
src/sha/sha2.rs
Normal file
842
src/sha/sha2.rs
Normal file
@@ -0,0 +1,842 @@
|
|||||||
|
use byteorder::{BigEndian,ByteOrder,WriteBytesExt};
|
||||||
|
use sha::shared::calculate_k;
|
||||||
|
use super::super::Hash;
|
||||||
|
|
||||||
|
/// The SHA2-224 hash.
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA224};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA224::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA224::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA224 {
|
||||||
|
state: SHA256State
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA224 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
let state = SHA256State::new([0xc1059ed8,0x367cd507,0x3070dd17,0xf70e5939,
|
||||||
|
0xffc00b31,0x68581511,0x64f98fa7,0xbefa4fa4]);
|
||||||
|
SHA224{ state }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, data: &[u8])
|
||||||
|
{
|
||||||
|
self.state.update(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if !self.state.done {
|
||||||
|
self.state.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(28);
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[0]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[1]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[2]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[3]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[4]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[5]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[6]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA2-256 hash. [GOOD]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA256};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA256::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA256::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA256 {
|
||||||
|
state: SHA256State
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA256 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
let state = SHA256State::new([0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,
|
||||||
|
0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19]);
|
||||||
|
SHA256{ state }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, data: &[u8])
|
||||||
|
{
|
||||||
|
self.state.update(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if !self.state.done {
|
||||||
|
self.state.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(28);
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[0]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[1]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[2]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[3]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[4]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[5]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[6]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[7]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA2-384 hash. [BETTER]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA384};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA384::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA384::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA384 {
|
||||||
|
state: SHA512State
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA384 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
let state = SHA512State::new([0xcbbb9d5dc1059ed8,0x629a292a367cd507,
|
||||||
|
0x9159015a3070dd17,0x152fecd8f70e5939,
|
||||||
|
0x67332667ffc00b31,0x8eb44a8768581511,
|
||||||
|
0xdb0c2e0d64f98fa7,0x47b5481dbefa4fa4]);
|
||||||
|
SHA384{ state }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, data: &[u8])
|
||||||
|
{
|
||||||
|
self.state.update(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if !self.state.done {
|
||||||
|
self.state.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(64);
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[0]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[1]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[2]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[3]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[4]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[5]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA2-512 hash. [BEST]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA512};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA512::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA512::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA512 {
|
||||||
|
state: SHA512State
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA512 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
let state = SHA512State::new([0x6a09e667f3bcc908,0xbb67ae8584caa73b,
|
||||||
|
0x3c6ef372fe94f82b,0xa54ff53a5f1d36f1,
|
||||||
|
0x510e527fade682d1,0x9b05688c2b3e6c1f,
|
||||||
|
0x1f83d9abfb41bd6b,0x5be0cd19137e2179]);
|
||||||
|
SHA512{ state }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, data: &[u8])
|
||||||
|
{
|
||||||
|
self.state.update(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if !self.state.done {
|
||||||
|
self.state.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(64);
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[0]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[1]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[2]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[3]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[4]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[5]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[6]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[7]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! bsig256_0 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(2) ^ $x.rotate_right(13) ^ $x.rotate_right(22)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! bsig256_1 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(6) ^ $x.rotate_right(11) ^ $x.rotate_right(25)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! lsig256_0 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(7) ^ $x.rotate_right(18) ^ ($x >> 3)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! lsig256_1 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(17) ^ $x.rotate_right(19) ^ ($x >> 10)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct SHA256State {
|
||||||
|
state: [u32; 8],
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
done: bool,
|
||||||
|
l: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SHA256State {
|
||||||
|
fn new(values: [u32; 8]) -> Self {
|
||||||
|
SHA256State {
|
||||||
|
state: values,
|
||||||
|
buffer: Vec::with_capacity(64),
|
||||||
|
done: false,
|
||||||
|
l: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, w00: u32, w01: u32, w02: u32, w03: u32,
|
||||||
|
w04: u32, w05: u32, w06: u32, w07: u32,
|
||||||
|
w08: u32, w09: u32, w10: u32, w11: u32,
|
||||||
|
w12: u32, w13: u32, w14: u32, w15: u32)
|
||||||
|
{
|
||||||
|
let w16 = lsig256_1!(w14) + w09 + lsig256_0!(w01) + w00;
|
||||||
|
let w17 = lsig256_1!(w15) + w10 + lsig256_0!(w02) + w01;
|
||||||
|
let w18 = lsig256_1!(w16) + w11 + lsig256_0!(w03) + w02;
|
||||||
|
let w19 = lsig256_1!(w17) + w12 + lsig256_0!(w04) + w03;
|
||||||
|
let w20 = lsig256_1!(w18) + w13 + lsig256_0!(w05) + w04;
|
||||||
|
let w21 = lsig256_1!(w19) + w14 + lsig256_0!(w06) + w05;
|
||||||
|
let w22 = lsig256_1!(w20) + w15 + lsig256_0!(w07) + w06;
|
||||||
|
let w23 = lsig256_1!(w21) + w16 + lsig256_0!(w08) + w07;
|
||||||
|
let w24 = lsig256_1!(w22) + w17 + lsig256_0!(w09) + w08;
|
||||||
|
let w25 = lsig256_1!(w23) + w18 + lsig256_0!(w10) + w09;
|
||||||
|
let w26 = lsig256_1!(w24) + w19 + lsig256_0!(w11) + w10;
|
||||||
|
let w27 = lsig256_1!(w25) + w20 + lsig256_0!(w12) + w11;
|
||||||
|
let w28 = lsig256_1!(w26) + w21 + lsig256_0!(w13) + w12;
|
||||||
|
let w29 = lsig256_1!(w27) + w22 + lsig256_0!(w14) + w13;
|
||||||
|
let w30 = lsig256_1!(w28) + w23 + lsig256_0!(w15) + w14;
|
||||||
|
let w31 = lsig256_1!(w29) + w24 + lsig256_0!(w16) + w15;
|
||||||
|
let w32 = lsig256_1!(w30) + w25 + lsig256_0!(w17) + w16;
|
||||||
|
let w33 = lsig256_1!(w31) + w26 + lsig256_0!(w18) + w17;
|
||||||
|
let w34 = lsig256_1!(w32) + w27 + lsig256_0!(w19) + w18;
|
||||||
|
let w35 = lsig256_1!(w33) + w28 + lsig256_0!(w20) + w19;
|
||||||
|
let w36 = lsig256_1!(w34) + w29 + lsig256_0!(w21) + w20;
|
||||||
|
let w37 = lsig256_1!(w35) + w30 + lsig256_0!(w22) + w21;
|
||||||
|
let w38 = lsig256_1!(w36) + w31 + lsig256_0!(w23) + w22;
|
||||||
|
let w39 = lsig256_1!(w37) + w32 + lsig256_0!(w24) + w23;
|
||||||
|
let w40 = lsig256_1!(w38) + w33 + lsig256_0!(w25) + w24;
|
||||||
|
let w41 = lsig256_1!(w39) + w34 + lsig256_0!(w26) + w25;
|
||||||
|
let w42 = lsig256_1!(w40) + w35 + lsig256_0!(w27) + w26;
|
||||||
|
let w43 = lsig256_1!(w41) + w36 + lsig256_0!(w28) + w27;
|
||||||
|
let w44 = lsig256_1!(w42) + w37 + lsig256_0!(w29) + w28;
|
||||||
|
let w45 = lsig256_1!(w43) + w38 + lsig256_0!(w30) + w29;
|
||||||
|
let w46 = lsig256_1!(w44) + w39 + lsig256_0!(w31) + w30;
|
||||||
|
let w47 = lsig256_1!(w45) + w40 + lsig256_0!(w32) + w31;
|
||||||
|
let w48 = lsig256_1!(w46) + w41 + lsig256_0!(w33) + w32;
|
||||||
|
let w49 = lsig256_1!(w47) + w42 + lsig256_0!(w34) + w33;
|
||||||
|
let w50 = lsig256_1!(w48) + w43 + lsig256_0!(w35) + w34;
|
||||||
|
let w51 = lsig256_1!(w49) + w44 + lsig256_0!(w36) + w35;
|
||||||
|
let w52 = lsig256_1!(w50) + w45 + lsig256_0!(w37) + w36;
|
||||||
|
let w53 = lsig256_1!(w51) + w46 + lsig256_0!(w38) + w37;
|
||||||
|
let w54 = lsig256_1!(w52) + w47 + lsig256_0!(w39) + w38;
|
||||||
|
let w55 = lsig256_1!(w53) + w48 + lsig256_0!(w40) + w39;
|
||||||
|
let w56 = lsig256_1!(w54) + w49 + lsig256_0!(w41) + w40;
|
||||||
|
let w57 = lsig256_1!(w55) + w50 + lsig256_0!(w42) + w41;
|
||||||
|
let w58 = lsig256_1!(w56) + w51 + lsig256_0!(w43) + w42;
|
||||||
|
let w59 = lsig256_1!(w57) + w52 + lsig256_0!(w44) + w43;
|
||||||
|
let w60 = lsig256_1!(w58) + w53 + lsig256_0!(w45) + w44;
|
||||||
|
let w61 = lsig256_1!(w59) + w54 + lsig256_0!(w46) + w45;
|
||||||
|
let w62 = lsig256_1!(w60) + w55 + lsig256_0!(w47) + w46;
|
||||||
|
let w63 = lsig256_1!(w61) + w56 + lsig256_0!(w48) + w47;
|
||||||
|
let s01 = step256(self.state,0x428a2f98,w00);
|
||||||
|
let s02 = step256(s01,0x71374491,w01);
|
||||||
|
let s03 = step256(s02,0xb5c0fbcf,w02);
|
||||||
|
let s04 = step256(s03,0xe9b5dba5,w03);
|
||||||
|
let s05 = step256(s04,0x3956c25b,w04);
|
||||||
|
let s06 = step256(s05,0x59f111f1,w05);
|
||||||
|
let s07 = step256(s06,0x923f82a4,w06);
|
||||||
|
let s08 = step256(s07,0xab1c5ed5,w07);
|
||||||
|
let s09 = step256(s08,0xd807aa98,w08);
|
||||||
|
let s10 = step256(s09,0x12835b01,w09);
|
||||||
|
let s11 = step256(s10,0x243185be,w10);
|
||||||
|
let s12 = step256(s11,0x550c7dc3,w11);
|
||||||
|
let s13 = step256(s12,0x72be5d74,w12);
|
||||||
|
let s14 = step256(s13,0x80deb1fe,w13);
|
||||||
|
let s15 = step256(s14,0x9bdc06a7,w14);
|
||||||
|
let s16 = step256(s15,0xc19bf174,w15);
|
||||||
|
let s17 = step256(s16,0xe49b69c1,w16);
|
||||||
|
let s18 = step256(s17,0xefbe4786,w17);
|
||||||
|
let s19 = step256(s18,0x0fc19dc6,w18);
|
||||||
|
let s20 = step256(s19,0x240ca1cc,w19);
|
||||||
|
let s21 = step256(s20,0x2de92c6f,w20);
|
||||||
|
let s22 = step256(s21,0x4a7484aa,w21);
|
||||||
|
let s23 = step256(s22,0x5cb0a9dc,w22);
|
||||||
|
let s24 = step256(s23,0x76f988da,w23);
|
||||||
|
let s25 = step256(s24,0x983e5152,w24);
|
||||||
|
let s26 = step256(s25,0xa831c66d,w25);
|
||||||
|
let s27 = step256(s26,0xb00327c8,w26);
|
||||||
|
let s28 = step256(s27,0xbf597fc7,w27);
|
||||||
|
let s29 = step256(s28,0xc6e00bf3,w28);
|
||||||
|
let s30 = step256(s29,0xd5a79147,w29);
|
||||||
|
let s31 = step256(s30,0x06ca6351,w30);
|
||||||
|
let s32 = step256(s31,0x14292967,w31);
|
||||||
|
let s33 = step256(s32,0x27b70a85,w32);
|
||||||
|
let s34 = step256(s33,0x2e1b2138,w33);
|
||||||
|
let s35 = step256(s34,0x4d2c6dfc,w34);
|
||||||
|
let s36 = step256(s35,0x53380d13,w35);
|
||||||
|
let s37 = step256(s36,0x650a7354,w36);
|
||||||
|
let s38 = step256(s37,0x766a0abb,w37);
|
||||||
|
let s39 = step256(s38,0x81c2c92e,w38);
|
||||||
|
let s40 = step256(s39,0x92722c85,w39);
|
||||||
|
let s41 = step256(s40,0xa2bfe8a1,w40);
|
||||||
|
let s42 = step256(s41,0xa81a664b,w41);
|
||||||
|
let s43 = step256(s42,0xc24b8b70,w42);
|
||||||
|
let s44 = step256(s43,0xc76c51a3,w43);
|
||||||
|
let s45 = step256(s44,0xd192e819,w44);
|
||||||
|
let s46 = step256(s45,0xd6990624,w45);
|
||||||
|
let s47 = step256(s46,0xf40e3585,w46);
|
||||||
|
let s48 = step256(s47,0x106aa070,w47);
|
||||||
|
let s49 = step256(s48,0x19a4c116,w48);
|
||||||
|
let s50 = step256(s49,0x1e376c08,w49);
|
||||||
|
let s51 = step256(s50,0x2748774c,w50);
|
||||||
|
let s52 = step256(s51,0x34b0bcb5,w51);
|
||||||
|
let s53 = step256(s52,0x391c0cb3,w52);
|
||||||
|
let s54 = step256(s53,0x4ed8aa4a,w53);
|
||||||
|
let s55 = step256(s54,0x5b9cca4f,w54);
|
||||||
|
let s56 = step256(s55,0x682e6ff3,w55);
|
||||||
|
let s57 = step256(s56,0x748f82ee,w56);
|
||||||
|
let s58 = step256(s57,0x78a5636f,w57);
|
||||||
|
let s59 = step256(s58,0x84c87814,w58);
|
||||||
|
let s60 = step256(s59,0x8cc70208,w59);
|
||||||
|
let s61 = step256(s60,0x90befffa,w60);
|
||||||
|
let s62 = step256(s61,0xa4506ceb,w61);
|
||||||
|
let s63 = step256(s62,0xbef9a3f7,w62);
|
||||||
|
let s64 = step256(s63,0xc67178f2,w63);
|
||||||
|
self.state[0] += s64[0];
|
||||||
|
self.state[1] += s64[1];
|
||||||
|
self.state[2] += s64[2];
|
||||||
|
self.state[3] += s64[3];
|
||||||
|
self.state[4] += s64[4];
|
||||||
|
self.state[5] += s64[5];
|
||||||
|
self.state[6] += s64[6];
|
||||||
|
self.state[7] += s64[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, block: &[u8]) {
|
||||||
|
if !self.done {
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
self.l += block.len();
|
||||||
|
|
||||||
|
if self.buffer.len() + block.len() < 64 {
|
||||||
|
self.buffer.extend_from_slice(block);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.buffer.len() > 0 {
|
||||||
|
// We must be able to build up a 64 byte chunk, at this point, otherwise
|
||||||
|
// the math above would've been wrong.
|
||||||
|
while self.buffer.len() < 64 {
|
||||||
|
self.buffer.push(block[offset]);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
process_u32_block!(self.buffer, 0, self);
|
||||||
|
// Reset the buffer now, we're done with that nonsense for the moment
|
||||||
|
self.buffer.resize(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset + 64) <= block.len() {
|
||||||
|
process_u32_block!(block, offset, self);
|
||||||
|
offset += 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset < block.len() {
|
||||||
|
self.buffer.extend_from_slice(&block[offset..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(&mut self) {
|
||||||
|
let bitlen = self.l * 8;
|
||||||
|
let k = calculate_k(448, 512, bitlen);
|
||||||
|
// INVARIANT: k is necessarily > 0, and (k + 1) is a multiple of 8
|
||||||
|
let bytes_to_add = (k + 1) / 8;
|
||||||
|
let mut padvec = Vec::with_capacity(bytes_to_add + 8);
|
||||||
|
padvec.push(0x80); // Set the high bit, since the first bit after the data
|
||||||
|
// should be set
|
||||||
|
padvec.resize(bytes_to_add, 0);
|
||||||
|
padvec.write_u64::<BigEndian>(bitlen as u64).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
self.update(&padvec);
|
||||||
|
self.done = true;
|
||||||
|
assert_eq!(self.buffer.len(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn step256(state0: [u32; 8], k: u32, w: u32) -> [u32; 8]
|
||||||
|
{
|
||||||
|
let [a,b,c,d,e,f,g,h] = state0;
|
||||||
|
let t1 = h + bsig256_1!(e) + ch!(e,f,g) + k + w;
|
||||||
|
let t2 = bsig256_0!(a) + maj!(a,b,c);
|
||||||
|
let hp = g;
|
||||||
|
let gp = f;
|
||||||
|
let fp = e;
|
||||||
|
let ep = d + t1;
|
||||||
|
let dp = c;
|
||||||
|
let cp = b;
|
||||||
|
let bp = a;
|
||||||
|
let ap = t1 + t2;
|
||||||
|
[ap,bp,cp,dp,ep,fp,gp,hp]
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! bsig512_0 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(28) ^ $x.rotate_right(34) ^ $x.rotate_right(39)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! bsig512_1 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(14) ^ $x.rotate_right(18) ^ $x.rotate_right(41)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! lsig512_0 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(1) ^ $x.rotate_right(8) ^ ($x >> 7)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! lsig512_1 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(19) ^ $x.rotate_right(61) ^ ($x >> 6)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! process_u64_block {
|
||||||
|
($buf: expr, $off: expr, $self: ident) => {{
|
||||||
|
let w00 = BigEndian::read_u64(&$buf[$off+0..]);
|
||||||
|
let w01 = BigEndian::read_u64(&$buf[$off+8..]);
|
||||||
|
let w02 = BigEndian::read_u64(&$buf[$off+16..]);
|
||||||
|
let w03 = BigEndian::read_u64(&$buf[$off+24..]);
|
||||||
|
let w04 = BigEndian::read_u64(&$buf[$off+32..]);
|
||||||
|
let w05 = BigEndian::read_u64(&$buf[$off+40..]);
|
||||||
|
let w06 = BigEndian::read_u64(&$buf[$off+48..]);
|
||||||
|
let w07 = BigEndian::read_u64(&$buf[$off+56..]);
|
||||||
|
let w08 = BigEndian::read_u64(&$buf[$off+64..]);
|
||||||
|
let w09 = BigEndian::read_u64(&$buf[$off+72..]);
|
||||||
|
let w10 = BigEndian::read_u64(&$buf[$off+80..]);
|
||||||
|
let w11 = BigEndian::read_u64(&$buf[$off+88..]);
|
||||||
|
let w12 = BigEndian::read_u64(&$buf[$off+96..]);
|
||||||
|
let w13 = BigEndian::read_u64(&$buf[$off+104..]);
|
||||||
|
let w14 = BigEndian::read_u64(&$buf[$off+112..]);
|
||||||
|
let w15 = BigEndian::read_u64(&$buf[$off+120..]);
|
||||||
|
$self.process(w00, w01, w02, w03, w04, w05, w06, w07,
|
||||||
|
w08, w09, w10, w11, w12, w13, w14, w15);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct SHA512State {
|
||||||
|
state: [u64; 8],
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
done: bool,
|
||||||
|
l: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SHA512State {
|
||||||
|
fn new(values: [u64; 8]) -> Self {
|
||||||
|
SHA512State {
|
||||||
|
state: values,
|
||||||
|
buffer: Vec::with_capacity(128),
|
||||||
|
done: false,
|
||||||
|
l: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, w00: u64, w01: u64, w02: u64, w03: u64,
|
||||||
|
w04: u64, w05: u64, w06: u64, w07: u64,
|
||||||
|
w08: u64, w09: u64, w10: u64, w11: u64,
|
||||||
|
w12: u64, w13: u64, w14: u64, w15: u64)
|
||||||
|
{
|
||||||
|
let w16 = lsig512_1!(w14) + w09 + lsig512_0!(w01) + w00;
|
||||||
|
let w17 = lsig512_1!(w15) + w10 + lsig512_0!(w02) + w01;
|
||||||
|
let w18 = lsig512_1!(w16) + w11 + lsig512_0!(w03) + w02;
|
||||||
|
let w19 = lsig512_1!(w17) + w12 + lsig512_0!(w04) + w03;
|
||||||
|
let w20 = lsig512_1!(w18) + w13 + lsig512_0!(w05) + w04;
|
||||||
|
let w21 = lsig512_1!(w19) + w14 + lsig512_0!(w06) + w05;
|
||||||
|
let w22 = lsig512_1!(w20) + w15 + lsig512_0!(w07) + w06;
|
||||||
|
let w23 = lsig512_1!(w21) + w16 + lsig512_0!(w08) + w07;
|
||||||
|
let w24 = lsig512_1!(w22) + w17 + lsig512_0!(w09) + w08;
|
||||||
|
let w25 = lsig512_1!(w23) + w18 + lsig512_0!(w10) + w09;
|
||||||
|
let w26 = lsig512_1!(w24) + w19 + lsig512_0!(w11) + w10;
|
||||||
|
let w27 = lsig512_1!(w25) + w20 + lsig512_0!(w12) + w11;
|
||||||
|
let w28 = lsig512_1!(w26) + w21 + lsig512_0!(w13) + w12;
|
||||||
|
let w29 = lsig512_1!(w27) + w22 + lsig512_0!(w14) + w13;
|
||||||
|
let w30 = lsig512_1!(w28) + w23 + lsig512_0!(w15) + w14;
|
||||||
|
let w31 = lsig512_1!(w29) + w24 + lsig512_0!(w16) + w15;
|
||||||
|
let w32 = lsig512_1!(w30) + w25 + lsig512_0!(w17) + w16;
|
||||||
|
let w33 = lsig512_1!(w31) + w26 + lsig512_0!(w18) + w17;
|
||||||
|
let w34 = lsig512_1!(w32) + w27 + lsig512_0!(w19) + w18;
|
||||||
|
let w35 = lsig512_1!(w33) + w28 + lsig512_0!(w20) + w19;
|
||||||
|
let w36 = lsig512_1!(w34) + w29 + lsig512_0!(w21) + w20;
|
||||||
|
let w37 = lsig512_1!(w35) + w30 + lsig512_0!(w22) + w21;
|
||||||
|
let w38 = lsig512_1!(w36) + w31 + lsig512_0!(w23) + w22;
|
||||||
|
let w39 = lsig512_1!(w37) + w32 + lsig512_0!(w24) + w23;
|
||||||
|
let w40 = lsig512_1!(w38) + w33 + lsig512_0!(w25) + w24;
|
||||||
|
let w41 = lsig512_1!(w39) + w34 + lsig512_0!(w26) + w25;
|
||||||
|
let w42 = lsig512_1!(w40) + w35 + lsig512_0!(w27) + w26;
|
||||||
|
let w43 = lsig512_1!(w41) + w36 + lsig512_0!(w28) + w27;
|
||||||
|
let w44 = lsig512_1!(w42) + w37 + lsig512_0!(w29) + w28;
|
||||||
|
let w45 = lsig512_1!(w43) + w38 + lsig512_0!(w30) + w29;
|
||||||
|
let w46 = lsig512_1!(w44) + w39 + lsig512_0!(w31) + w30;
|
||||||
|
let w47 = lsig512_1!(w45) + w40 + lsig512_0!(w32) + w31;
|
||||||
|
let w48 = lsig512_1!(w46) + w41 + lsig512_0!(w33) + w32;
|
||||||
|
let w49 = lsig512_1!(w47) + w42 + lsig512_0!(w34) + w33;
|
||||||
|
let w50 = lsig512_1!(w48) + w43 + lsig512_0!(w35) + w34;
|
||||||
|
let w51 = lsig512_1!(w49) + w44 + lsig512_0!(w36) + w35;
|
||||||
|
let w52 = lsig512_1!(w50) + w45 + lsig512_0!(w37) + w36;
|
||||||
|
let w53 = lsig512_1!(w51) + w46 + lsig512_0!(w38) + w37;
|
||||||
|
let w54 = lsig512_1!(w52) + w47 + lsig512_0!(w39) + w38;
|
||||||
|
let w55 = lsig512_1!(w53) + w48 + lsig512_0!(w40) + w39;
|
||||||
|
let w56 = lsig512_1!(w54) + w49 + lsig512_0!(w41) + w40;
|
||||||
|
let w57 = lsig512_1!(w55) + w50 + lsig512_0!(w42) + w41;
|
||||||
|
let w58 = lsig512_1!(w56) + w51 + lsig512_0!(w43) + w42;
|
||||||
|
let w59 = lsig512_1!(w57) + w52 + lsig512_0!(w44) + w43;
|
||||||
|
let w60 = lsig512_1!(w58) + w53 + lsig512_0!(w45) + w44;
|
||||||
|
let w61 = lsig512_1!(w59) + w54 + lsig512_0!(w46) + w45;
|
||||||
|
let w62 = lsig512_1!(w60) + w55 + lsig512_0!(w47) + w46;
|
||||||
|
let w63 = lsig512_1!(w61) + w56 + lsig512_0!(w48) + w47;
|
||||||
|
let w64 = lsig512_1!(w62) + w57 + lsig512_0!(w49) + w48;
|
||||||
|
let w65 = lsig512_1!(w63) + w58 + lsig512_0!(w50) + w49;
|
||||||
|
let w66 = lsig512_1!(w64) + w59 + lsig512_0!(w51) + w50;
|
||||||
|
let w67 = lsig512_1!(w65) + w60 + lsig512_0!(w52) + w51;
|
||||||
|
let w68 = lsig512_1!(w66) + w61 + lsig512_0!(w53) + w52;
|
||||||
|
let w69 = lsig512_1!(w67) + w62 + lsig512_0!(w54) + w53;
|
||||||
|
let w70 = lsig512_1!(w68) + w63 + lsig512_0!(w55) + w54;
|
||||||
|
let w71 = lsig512_1!(w69) + w64 + lsig512_0!(w56) + w55;
|
||||||
|
let w72 = lsig512_1!(w70) + w65 + lsig512_0!(w57) + w56;
|
||||||
|
let w73 = lsig512_1!(w71) + w66 + lsig512_0!(w58) + w57;
|
||||||
|
let w74 = lsig512_1!(w72) + w67 + lsig512_0!(w59) + w58;
|
||||||
|
let w75 = lsig512_1!(w73) + w68 + lsig512_0!(w60) + w59;
|
||||||
|
let w76 = lsig512_1!(w74) + w69 + lsig512_0!(w61) + w60;
|
||||||
|
let w77 = lsig512_1!(w75) + w70 + lsig512_0!(w62) + w61;
|
||||||
|
let w78 = lsig512_1!(w76) + w71 + lsig512_0!(w63) + w62;
|
||||||
|
let w79 = lsig512_1!(w77) + w72 + lsig512_0!(w64) + w63;
|
||||||
|
let s01 = step512(self.state,0x428a2f98d728ae22,w00);
|
||||||
|
let s02 = step512(s01,0x7137449123ef65cd,w01);
|
||||||
|
let s03 = step512(s02,0xb5c0fbcfec4d3b2f,w02);
|
||||||
|
let s04 = step512(s03,0xe9b5dba58189dbbc,w03);
|
||||||
|
let s05 = step512(s04,0x3956c25bf348b538,w04);
|
||||||
|
let s06 = step512(s05,0x59f111f1b605d019,w05);
|
||||||
|
let s07 = step512(s06,0x923f82a4af194f9b,w06);
|
||||||
|
let s08 = step512(s07,0xab1c5ed5da6d8118,w07);
|
||||||
|
let s09 = step512(s08,0xd807aa98a3030242,w08);
|
||||||
|
let s10 = step512(s09,0x12835b0145706fbe,w09);
|
||||||
|
let s11 = step512(s10,0x243185be4ee4b28c,w10);
|
||||||
|
let s12 = step512(s11,0x550c7dc3d5ffb4e2,w11);
|
||||||
|
let s13 = step512(s12,0x72be5d74f27b896f,w12);
|
||||||
|
let s14 = step512(s13,0x80deb1fe3b1696b1,w13);
|
||||||
|
let s15 = step512(s14,0x9bdc06a725c71235,w14);
|
||||||
|
let s16 = step512(s15,0xc19bf174cf692694,w15);
|
||||||
|
let s17 = step512(s16,0xe49b69c19ef14ad2,w16);
|
||||||
|
let s18 = step512(s17,0xefbe4786384f25e3,w17);
|
||||||
|
let s19 = step512(s18,0x0fc19dc68b8cd5b5,w18);
|
||||||
|
let s20 = step512(s19,0x240ca1cc77ac9c65,w19);
|
||||||
|
let s21 = step512(s20,0x2de92c6f592b0275,w20);
|
||||||
|
let s22 = step512(s21,0x4a7484aa6ea6e483,w21);
|
||||||
|
let s23 = step512(s22,0x5cb0a9dcbd41fbd4,w22);
|
||||||
|
let s24 = step512(s23,0x76f988da831153b5,w23);
|
||||||
|
let s25 = step512(s24,0x983e5152ee66dfab,w24);
|
||||||
|
let s26 = step512(s25,0xa831c66d2db43210,w25);
|
||||||
|
let s27 = step512(s26,0xb00327c898fb213f,w26);
|
||||||
|
let s28 = step512(s27,0xbf597fc7beef0ee4,w27);
|
||||||
|
let s29 = step512(s28,0xc6e00bf33da88fc2,w28);
|
||||||
|
let s30 = step512(s29,0xd5a79147930aa725,w29);
|
||||||
|
let s31 = step512(s30,0x06ca6351e003826f,w30);
|
||||||
|
let s32 = step512(s31,0x142929670a0e6e70,w31);
|
||||||
|
let s33 = step512(s32,0x27b70a8546d22ffc,w32);
|
||||||
|
let s34 = step512(s33,0x2e1b21385c26c926,w33);
|
||||||
|
let s35 = step512(s34,0x4d2c6dfc5ac42aed,w34);
|
||||||
|
let s36 = step512(s35,0x53380d139d95b3df,w35);
|
||||||
|
let s37 = step512(s36,0x650a73548baf63de,w36);
|
||||||
|
let s38 = step512(s37,0x766a0abb3c77b2a8,w37);
|
||||||
|
let s39 = step512(s38,0x81c2c92e47edaee6,w38);
|
||||||
|
let s40 = step512(s39,0x92722c851482353b,w39);
|
||||||
|
let s41 = step512(s40,0xa2bfe8a14cf10364,w40);
|
||||||
|
let s42 = step512(s41,0xa81a664bbc423001,w41);
|
||||||
|
let s43 = step512(s42,0xc24b8b70d0f89791,w42);
|
||||||
|
let s44 = step512(s43,0xc76c51a30654be30,w43);
|
||||||
|
let s45 = step512(s44,0xd192e819d6ef5218,w44);
|
||||||
|
let s46 = step512(s45,0xd69906245565a910,w45);
|
||||||
|
let s47 = step512(s46,0xf40e35855771202a,w46);
|
||||||
|
let s48 = step512(s47,0x106aa07032bbd1b8,w47);
|
||||||
|
let s49 = step512(s48,0x19a4c116b8d2d0c8,w48);
|
||||||
|
let s50 = step512(s49,0x1e376c085141ab53,w49);
|
||||||
|
let s51 = step512(s50,0x2748774cdf8eeb99,w50);
|
||||||
|
let s52 = step512(s51,0x34b0bcb5e19b48a8,w51);
|
||||||
|
let s53 = step512(s52,0x391c0cb3c5c95a63,w52);
|
||||||
|
let s54 = step512(s53,0x4ed8aa4ae3418acb,w53);
|
||||||
|
let s55 = step512(s54,0x5b9cca4f7763e373,w54);
|
||||||
|
let s56 = step512(s55,0x682e6ff3d6b2b8a3,w55);
|
||||||
|
let s57 = step512(s56,0x748f82ee5defb2fc,w56);
|
||||||
|
let s58 = step512(s57,0x78a5636f43172f60,w57);
|
||||||
|
let s59 = step512(s58,0x84c87814a1f0ab72,w58);
|
||||||
|
let s60 = step512(s59,0x8cc702081a6439ec,w59);
|
||||||
|
let s61 = step512(s60,0x90befffa23631e28,w60);
|
||||||
|
let s62 = step512(s61,0xa4506cebde82bde9,w61);
|
||||||
|
let s63 = step512(s62,0xbef9a3f7b2c67915,w62);
|
||||||
|
let s64 = step512(s63,0xc67178f2e372532b,w63);
|
||||||
|
let s65 = step512(s64,0xca273eceea26619c,w64);
|
||||||
|
let s66 = step512(s65,0xd186b8c721c0c207,w65);
|
||||||
|
let s67 = step512(s66,0xeada7dd6cde0eb1e,w66);
|
||||||
|
let s68 = step512(s67,0xf57d4f7fee6ed178,w67);
|
||||||
|
let s69 = step512(s68,0x06f067aa72176fba,w68);
|
||||||
|
let s70 = step512(s69,0x0a637dc5a2c898a6,w69);
|
||||||
|
let s71 = step512(s70,0x113f9804bef90dae,w70);
|
||||||
|
let s72 = step512(s71,0x1b710b35131c471b,w71);
|
||||||
|
let s73 = step512(s72,0x28db77f523047d84,w72);
|
||||||
|
let s74 = step512(s73,0x32caab7b40c72493,w73);
|
||||||
|
let s75 = step512(s74,0x3c9ebe0a15c9bebc,w74);
|
||||||
|
let s76 = step512(s75,0x431d67c49c100d4c,w75);
|
||||||
|
let s77 = step512(s76,0x4cc5d4becb3e42b6,w76);
|
||||||
|
let s78 = step512(s77,0x597f299cfc657e2a,w77);
|
||||||
|
let s79 = step512(s78,0x5fcb6fab3ad6faec,w78);
|
||||||
|
let s80 = step512(s79,0x6c44198c4a475817,w79);
|
||||||
|
self.state[0] += s80[0];
|
||||||
|
self.state[1] += s80[1];
|
||||||
|
self.state[2] += s80[2];
|
||||||
|
self.state[3] += s80[3];
|
||||||
|
self.state[4] += s80[4];
|
||||||
|
self.state[5] += s80[5];
|
||||||
|
self.state[6] += s80[6];
|
||||||
|
self.state[7] += s80[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, block: &[u8]) {
|
||||||
|
if !self.done {
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
self.l += block.len();
|
||||||
|
|
||||||
|
if self.buffer.len() + block.len() < 128 {
|
||||||
|
self.buffer.extend_from_slice(block);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.buffer.len() > 0 {
|
||||||
|
// We must be able to build up a 128 byte chunk, at this point, otherwise
|
||||||
|
// the math above would've been wrong.
|
||||||
|
while self.buffer.len() < 128 {
|
||||||
|
self.buffer.push(block[offset]);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
process_u64_block!(self.buffer, 0, self);
|
||||||
|
// Reset the buffer now, we're done with that nonsense for the moment
|
||||||
|
self.buffer.resize(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset + 128) <= block.len() {
|
||||||
|
process_u64_block!(block, offset, self);
|
||||||
|
offset += 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset < block.len() {
|
||||||
|
self.buffer.extend_from_slice(&block[offset..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(&mut self) {
|
||||||
|
let bitlen = self.l * 8;
|
||||||
|
let k = calculate_k(896, 1024, bitlen);
|
||||||
|
// INVARIANT: k is necessarily > 0, and (k + 1) is a multiple of 8
|
||||||
|
let bytes_to_add = (k + 1) / 8;
|
||||||
|
let mut padvec = Vec::with_capacity(bytes_to_add + 16);
|
||||||
|
padvec.push(0x80); // Set the high bit, since the first bit after the data
|
||||||
|
// should be set
|
||||||
|
padvec.resize(bytes_to_add, 0);
|
||||||
|
padvec.write_u128::<BigEndian>(bitlen as u128).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
self.update(&padvec);
|
||||||
|
self.done = true;
|
||||||
|
assert_eq!(self.buffer.len(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn step512(state0: [u64; 8], k: u64, w: u64) -> [u64; 8]
|
||||||
|
{
|
||||||
|
let [a,b,c,d,e,f,g,h] = state0;
|
||||||
|
let t1 = h + bsig512_1!(e) + ch!(e,f,g) + k + w;
|
||||||
|
let t2 = bsig512_0!(a) + maj!(a,b,c);
|
||||||
|
let hp = g;
|
||||||
|
let gp = f;
|
||||||
|
let fp = e;
|
||||||
|
let ep = d + t1;
|
||||||
|
let dp = c;
|
||||||
|
let cp = b;
|
||||||
|
let bp = a;
|
||||||
|
let ap = t1 + t2;
|
||||||
|
[ap,bp,cp,dp,ep,fp,gp,hp]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_sha224() {
|
||||||
|
let fname = "testdata/sha/nist_sha224.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA224::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_sha256() {
|
||||||
|
let fname = "testdata/sha/nist_sha256.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA256::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_sha384() {
|
||||||
|
let fname = "testdata/sha/nist_sha384.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA384::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_sha512() {
|
||||||
|
let fname = "testdata/sha/nist_sha512.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA512::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
610
src/sha/sha3.rs
Normal file
610
src/sha/sha3.rs
Normal file
@@ -0,0 +1,610 @@
|
|||||||
|
use super::super::Hash;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) struct Keccak {
|
||||||
|
rate_in_bytes: usize,
|
||||||
|
rate_in_longs: usize,
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
state: [u64; 25], // This is Keccak-f[1600]
|
||||||
|
output: Option<Vec<u8>>
|
||||||
|
}
|
||||||
|
|
||||||
|
const KECCAK_ROUND_CONSTANTS: [u64; 24] =
|
||||||
|
[ 0x0000000000000001u64, 0x0000000000008082u64,
|
||||||
|
0x800000000000808au64, 0x8000000080008000u64,
|
||||||
|
0x000000000000808bu64, 0x0000000080000001u64,
|
||||||
|
0x8000000080008081u64, 0x8000000000008009u64,
|
||||||
|
0x000000000000008au64, 0x0000000000000088u64,
|
||||||
|
0x0000000080008009u64, 0x000000008000000au64,
|
||||||
|
0x000000008000808bu64, 0x800000000000008bu64,
|
||||||
|
0x8000000000008089u64, 0x8000000000008003u64,
|
||||||
|
0x8000000000008002u64, 0x8000000000000080u64,
|
||||||
|
0x000000000000800au64, 0x800000008000000au64,
|
||||||
|
0x8000000080008081u64, 0x8000000000008080u64,
|
||||||
|
0x0000000080000001u64, 0x8000000080008008u64,
|
||||||
|
];
|
||||||
|
|
||||||
|
macro_rules! absorb {
|
||||||
|
($self: ident, $block: expr, $sidx: expr) => {{
|
||||||
|
let mut i = 0;
|
||||||
|
let mut off = 0;
|
||||||
|
|
||||||
|
while i < $self.rate_in_longs {
|
||||||
|
let word = ($block[$sidx+off+0] as u64) << 00 |
|
||||||
|
($block[$sidx+off+1] as u64) << 08 |
|
||||||
|
($block[$sidx+off+2] as u64) << 16 |
|
||||||
|
($block[$sidx+off+3] as u64) << 24 |
|
||||||
|
($block[$sidx+off+4] as u64) << 32 |
|
||||||
|
($block[$sidx+off+5] as u64) << 40 |
|
||||||
|
($block[$sidx+off+6] as u64) << 48 |
|
||||||
|
($block[$sidx+off+7] as u64) << 56;
|
||||||
|
$self.state[i] ^= word;
|
||||||
|
off += 8;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self.permute();
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Keccak {
|
||||||
|
pub fn new(rate: usize) -> Self
|
||||||
|
{
|
||||||
|
assert_eq!(rate % 64, 0);
|
||||||
|
Keccak {
|
||||||
|
rate_in_bytes: rate / 8,
|
||||||
|
rate_in_longs: rate / 64,
|
||||||
|
buffer: Vec::with_capacity(rate),
|
||||||
|
state: [0; 25],
|
||||||
|
output: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn permute(&mut self)
|
||||||
|
{
|
||||||
|
// This is a translation of the very easy-to-read implementation in BouncyCastle
|
||||||
|
for i in 0..24 {
|
||||||
|
// Theta!
|
||||||
|
let c0 = self.state[0] ^ self.state[5] ^ self.state[10] ^ self.state[15] ^ self.state[20];
|
||||||
|
let c1 = self.state[1] ^ self.state[6] ^ self.state[11] ^ self.state[16] ^ self.state[21];
|
||||||
|
let c2 = self.state[2] ^ self.state[7] ^ self.state[12] ^ self.state[17] ^ self.state[22];
|
||||||
|
let c3 = self.state[3] ^ self.state[8] ^ self.state[13] ^ self.state[18] ^ self.state[23];
|
||||||
|
let c4 = self.state[4] ^ self.state[9] ^ self.state[14] ^ self.state[19] ^ self.state[24];
|
||||||
|
let d0 = c0.rotate_left(1) ^ c3;
|
||||||
|
let d1 = c1.rotate_left(1) ^ c4;
|
||||||
|
let d2 = c2.rotate_left(1) ^ c0;
|
||||||
|
let d3 = c3.rotate_left(1) ^ c1;
|
||||||
|
let d4 = c4.rotate_left(1) ^ c2;
|
||||||
|
self.state[0] ^= d1; self.state[5] ^= d1; self.state[10] ^= d1; self.state[15] ^= d1; self.state[20] ^= d1;
|
||||||
|
self.state[1] ^= d2; self.state[6] ^= d2; self.state[11] ^= d2; self.state[16] ^= d2; self.state[21] ^= d2;
|
||||||
|
self.state[2] ^= d3; self.state[7] ^= d3; self.state[12] ^= d3; self.state[17] ^= d3; self.state[22] ^= d3;
|
||||||
|
self.state[3] ^= d4; self.state[8] ^= d4; self.state[13] ^= d4; self.state[18] ^= d4; self.state[23] ^= d4;
|
||||||
|
self.state[4] ^= d0; self.state[9] ^= d0; self.state[14] ^= d0; self.state[19] ^= d0; self.state[24] ^= d0;
|
||||||
|
// Rho & Pi!
|
||||||
|
let t1 = self.state[01].rotate_left(1);
|
||||||
|
self.state[01] = self.state[06].rotate_left(44);
|
||||||
|
self.state[06] = self.state[09].rotate_left(20);
|
||||||
|
self.state[09] = self.state[22].rotate_left(61);
|
||||||
|
self.state[22] = self.state[14].rotate_left(39);
|
||||||
|
self.state[14] = self.state[20].rotate_left(18);
|
||||||
|
self.state[20] = self.state[02].rotate_left(62);
|
||||||
|
self.state[02] = self.state[12].rotate_left(43);
|
||||||
|
self.state[12] = self.state[13].rotate_left(25);
|
||||||
|
self.state[13] = self.state[19].rotate_left(8);
|
||||||
|
self.state[19] = self.state[23].rotate_left(56);
|
||||||
|
self.state[23] = self.state[15].rotate_left(41);
|
||||||
|
self.state[15] = self.state[04].rotate_left(27);
|
||||||
|
self.state[04] = self.state[24].rotate_left(14);
|
||||||
|
self.state[24] = self.state[21].rotate_left(2);
|
||||||
|
self.state[21] = self.state[08].rotate_left(55);
|
||||||
|
self.state[08] = self.state[16].rotate_left(45);
|
||||||
|
self.state[16] = self.state[05].rotate_left(36);
|
||||||
|
self.state[05] = self.state[03].rotate_left(28);
|
||||||
|
self.state[03] = self.state[18].rotate_left(21);
|
||||||
|
self.state[18] = self.state[17].rotate_left(15);
|
||||||
|
self.state[17] = self.state[11].rotate_left(10);
|
||||||
|
self.state[11] = self.state[07].rotate_left(6);
|
||||||
|
self.state[07] = self.state[10].rotate_left(3);
|
||||||
|
self.state[10] = t1;
|
||||||
|
// Chi!
|
||||||
|
let t2 = self.state[00] ^ (!self.state[01] & self.state[02]);
|
||||||
|
let t3 = self.state[01] ^ (!self.state[02] & self.state[03]);
|
||||||
|
self.state[02] ^= !self.state[03] & self.state[04];
|
||||||
|
self.state[03] ^= !self.state[04] & self.state[00];
|
||||||
|
self.state[04] ^= !self.state[00] & self.state[01];
|
||||||
|
self.state[00] = t2;
|
||||||
|
self.state[01] = t3;
|
||||||
|
|
||||||
|
let t4 = self.state[05] ^ (!self.state[06] & self.state[07]);
|
||||||
|
let t5 = self.state[06] ^ (!self.state[07] & self.state[08]);
|
||||||
|
self.state[07] ^= !self.state[08] & self.state[09];
|
||||||
|
self.state[08] ^= !self.state[09] & self.state[05];
|
||||||
|
self.state[09] ^= !self.state[05] & self.state[06];
|
||||||
|
self.state[05] = t4;
|
||||||
|
self.state[06] = t5;
|
||||||
|
|
||||||
|
let t6 = self.state[10] ^ (!self.state[11] & self.state[12]);
|
||||||
|
let t7 = self.state[11] ^ (!self.state[12] & self.state[13]);
|
||||||
|
self.state[12] ^= !self.state[13] & self.state[14];
|
||||||
|
self.state[13] ^= !self.state[14] & self.state[10];
|
||||||
|
self.state[14] ^= !self.state[10] & self.state[11];
|
||||||
|
self.state[10] = t6;
|
||||||
|
self.state[11] = t7;
|
||||||
|
|
||||||
|
let t8 = self.state[15] ^ (!self.state[16] & self.state[17]);
|
||||||
|
let t9 = self.state[16] ^ (!self.state[17] & self.state[18]);
|
||||||
|
self.state[17] ^= !self.state[18] & self.state[19];
|
||||||
|
self.state[18] ^= !self.state[19] & self.state[15];
|
||||||
|
self.state[19] ^= !self.state[15] & self.state[16];
|
||||||
|
self.state[15] = t8;
|
||||||
|
self.state[16] = t9;
|
||||||
|
|
||||||
|
let ta = self.state[20] ^ (!self.state[21] & self.state[22]);
|
||||||
|
let tb = self.state[21] ^ (!self.state[22] & self.state[23]);
|
||||||
|
self.state[22] ^= !self.state[23] & self.state[24];
|
||||||
|
self.state[23] ^= !self.state[24] & self.state[20];
|
||||||
|
self.state[24] ^= !self.state[20] & self.state[21];
|
||||||
|
self.state[20] = ta;
|
||||||
|
self.state[21] = tb;
|
||||||
|
|
||||||
|
// iota
|
||||||
|
self.state[00] ^= KECCAK_ROUND_CONSTANTS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process(&mut self, bytes: &[u8])
|
||||||
|
{
|
||||||
|
if self.output.is_none() {
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
if self.buffer.len() + bytes.len() < self.rate_in_bytes {
|
||||||
|
self.buffer.extend_from_slice(bytes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.buffer.len() > 0 {
|
||||||
|
// We must be able to build up a chunk at our absorbtion rate, at this
|
||||||
|
// point, otherwise the math above would've been wrong.
|
||||||
|
while self.buffer.len() < self.rate_in_bytes {
|
||||||
|
self.buffer.push(bytes[offset]);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
absorb!(self, self.buffer, 0);
|
||||||
|
// Reset the buffer now, we're done with that nonsense for the moment
|
||||||
|
self.buffer.resize(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset + self.rate_in_bytes) <= bytes.len() {
|
||||||
|
absorb!(self, bytes, offset);
|
||||||
|
offset += self.rate_in_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset < bytes.len() {
|
||||||
|
self.buffer.extend_from_slice(&bytes[offset..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tag_and_pad(&mut self, tag_byte: u8)
|
||||||
|
{
|
||||||
|
if self.output.is_none() {
|
||||||
|
assert!(self.buffer.len() < self.rate_in_bytes);
|
||||||
|
// what we need to do here is tag on a final 01, to tag that as SHA3,
|
||||||
|
// and then pad it out, with an 0x80 at the end.
|
||||||
|
self.buffer.push(tag_byte);
|
||||||
|
self.buffer.resize(self.rate_in_bytes, 0);
|
||||||
|
self.buffer[self.rate_in_bytes-1] |= 0x80;
|
||||||
|
absorb!(self, self.buffer, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn squeeze(&mut self, output_len: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if let Some(ref result) = self.output {
|
||||||
|
result.clone()
|
||||||
|
} else {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
|
||||||
|
while res.len() < output_len {
|
||||||
|
for i in 0..self.rate_in_longs {
|
||||||
|
res.push( (self.state[i] >> 00) as u8 );
|
||||||
|
res.push( (self.state[i] >> 08) as u8 );
|
||||||
|
res.push( (self.state[i] >> 16) as u8 );
|
||||||
|
res.push( (self.state[i] >> 24) as u8 );
|
||||||
|
res.push( (self.state[i] >> 32) as u8 );
|
||||||
|
res.push( (self.state[i] >> 40) as u8 );
|
||||||
|
res.push( (self.state[i] >> 48) as u8 );
|
||||||
|
res.push( (self.state[i] >> 56) as u8 );
|
||||||
|
}
|
||||||
|
self.permute();
|
||||||
|
}
|
||||||
|
|
||||||
|
res.resize(output_len, 0);
|
||||||
|
self.output = Some(res.clone());
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA3-224 hash.
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA3_224};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA3_224::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA3_224::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA3_224 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA3_224 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
SHA3_224{ state: Keccak::new(1600 - 448) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
self.state.tag_and_pad(0x06);
|
||||||
|
self.state.squeeze(224 / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
1152
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod sha224 {
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-224_Msg0.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_empty_example() {
|
||||||
|
let empty = [0; 0];
|
||||||
|
let hashres = [0x6B,0x4E,0x03,0x42,0x36,0x67,0xDB,0xB7,0x3B,0x6E,0x15,
|
||||||
|
0x45,0x4F,0x0E,0xB1,0xAB,0xD4,0x59,0x7F,0x9A,0x1B,0x07,
|
||||||
|
0x8E,0x3F,0x5B,0x5A,0x6B,0xC7];
|
||||||
|
let mine = SHA3_224::hash(&empty);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-224_1600.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_1600_example() {
|
||||||
|
let example = [0xA3; 200];
|
||||||
|
let hashres = [0x93,0x76,0x81,0x6A,0xBA,0x50,0x3F,0x72,
|
||||||
|
0xF9,0x6C,0xE7,0xEB,0x65,0xAC,0x09,0x5D,
|
||||||
|
0xEE,0xE3,0xBE,0x4B,0xF9,0xBB,0xC2,0xA1,
|
||||||
|
0xCB,0x7E,0x11,0xE0];
|
||||||
|
let mine = SHA3_224::hash(&example);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_test_vectors() {
|
||||||
|
let fname = "testdata/sha/nist_sha3_224.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA3_224::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA3-256 hash. [GOOD]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA3_256};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA3_256::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA3_256::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA3_256 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA3_256 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
SHA3_256{ state: Keccak::new(1600 - 512) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
self.state.tag_and_pad(0x06);
|
||||||
|
self.state.squeeze(256 / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
1088
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod sha256 {
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-256.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_empty_example() {
|
||||||
|
let empty = [0; 0];
|
||||||
|
let hashres = [0xA7,0xFF,0xC6,0xF8,0xBF,0x1E,0xD7,0x66,
|
||||||
|
0x51,0xC1,0x47,0x56,0xA0,0x61,0xD6,0x62,
|
||||||
|
0xF5,0x80,0xFF,0x4D,0xE4,0x3B,0x49,0xFA,
|
||||||
|
0x82,0xD8,0x0A,0x4B,0x80,0xF8,0x43,0x4A];
|
||||||
|
let mine = SHA3_256::hash(&empty);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-256_1600.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_1600_example() {
|
||||||
|
let example = [0xA3; 200];
|
||||||
|
let hashres = [0x79,0xF3,0x8A,0xDE,0xC5,0xC2,0x03,0x07,
|
||||||
|
0xA9,0x8E,0xF7,0x6E,0x83,0x24,0xAF,0xBF,
|
||||||
|
0xD4,0x6C,0xFD,0x81,0xB2,0x2E,0x39,0x73,
|
||||||
|
0xC6,0x5F,0xA1,0xBD,0x9D,0xE3,0x17,0x87];
|
||||||
|
let mine = SHA3_256::hash(&example);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_test_vectors() {
|
||||||
|
let fname = "testdata/sha/nist_sha3_256.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA3_256::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA3-384 hash. [BETTER]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA3_384};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA3_384::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA3_384::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA3_384 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA3_384 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
SHA3_384{ state: Keccak::new(1600 - 768) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
self.state.tag_and_pad(0x06);
|
||||||
|
self.state.squeeze(384 / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
832
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod sha384 {
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-384_Msg0.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_empty_example() {
|
||||||
|
let empty = [0; 0];
|
||||||
|
let hashres = [0x0C,0x63,0xA7,0x5B,0x84,0x5E,0x4F,0x7D,
|
||||||
|
0x01,0x10,0x7D,0x85,0x2E,0x4C,0x24,0x85,
|
||||||
|
0xC5,0x1A,0x50,0xAA,0xAA,0x94,0xFC,0x61,
|
||||||
|
0x99,0x5E,0x71,0xBB,0xEE,0x98,0x3A,0x2A,
|
||||||
|
0xC3,0x71,0x38,0x31,0x26,0x4A,0xDB,0x47,
|
||||||
|
0xFB,0x6B,0xD1,0xE0,0x58,0xD5,0xF0,0x04];
|
||||||
|
let mine = SHA3_384::hash(&empty);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-384_1600.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_1600_example() {
|
||||||
|
let example = [0xA3; 200];
|
||||||
|
let hashres = [0x18,0x81,0xDE,0x2C,0xA7,0xE4,0x1E,0xF9,
|
||||||
|
0x5D,0xC4,0x73,0x2B,0x8F,0x5F,0x00,0x2B,
|
||||||
|
0x18,0x9C,0xC1,0xE4,0x2B,0x74,0x16,0x8E,
|
||||||
|
0xD1,0x73,0x26,0x49,0xCE,0x1D,0xBC,0xDD,
|
||||||
|
0x76,0x19,0x7A,0x31,0xFD,0x55,0xEE,0x98,
|
||||||
|
0x9F,0x2D,0x70,0x50,0xDD,0x47,0x3E,0x8F];
|
||||||
|
let mine = SHA3_384::hash(&example);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_test_vectors() {
|
||||||
|
let fname = "testdata/sha/nist_sha3_384.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA3_384::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA3-512 hash. [BEST]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA3_512};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA3_512::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA3_512::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA3_512 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA3_512 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
SHA3_512{ state: Keccak::new(1600 - 1024) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
self.state.tag_and_pad(0x06);
|
||||||
|
self.state.squeeze(512 / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
576
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod sha512 {
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-512_Msg0.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_empty_example() {
|
||||||
|
let empty = [0; 0];
|
||||||
|
let hashres = [0xA6,0x9F,0x73,0xCC,0xA2,0x3A,0x9A,0xC5,
|
||||||
|
0xC8,0xB5,0x67,0xDC,0x18,0x5A,0x75,0x6E,
|
||||||
|
0x97,0xC9,0x82,0x16,0x4F,0xE2,0x58,0x59,
|
||||||
|
0xE0,0xD1,0xDC,0xC1,0x47,0x5C,0x80,0xA6,
|
||||||
|
0x15,0xB2,0x12,0x3A,0xF1,0xF5,0xF9,0x4C,
|
||||||
|
0x11,0xE3,0xE9,0x40,0x2C,0x3A,0xC5,0x58,
|
||||||
|
0xF5,0x00,0x19,0x9D,0x95,0xB6,0xD3,0xE3,
|
||||||
|
0x01,0x75,0x85,0x86,0x28,0x1D,0xCD,0x26];
|
||||||
|
let mine = SHA3_512::hash(&empty);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-512_1600.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_1600_example() {
|
||||||
|
let example = [0xA3; 200];
|
||||||
|
let hashres = [0xE7,0x6D,0xFA,0xD2,0x20,0x84,0xA8,0xB1,
|
||||||
|
0x46,0x7F,0xCF,0x2F,0xFA,0x58,0x36,0x1B,
|
||||||
|
0xEC,0x76,0x28,0xED,0xF5,0xF3,0xFD,0xC0,
|
||||||
|
0xE4,0x80,0x5D,0xC4,0x8C,0xAE,0xEC,0xA8,
|
||||||
|
0x1B,0x7C,0x13,0xC3,0x0A,0xDF,0x52,0xA3,
|
||||||
|
0x65,0x95,0x84,0x73,0x9A,0x2D,0xF4,0x6B,
|
||||||
|
0xE5,0x89,0xC5,0x1C,0xA1,0xA4,0xA8,0x41,
|
||||||
|
0x6D,0xF6,0x54,0x5A,0x1C,0xE8,0xBA,0x00];
|
||||||
|
let mine = SHA3_512::hash(&example);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_test_vectors() {
|
||||||
|
let fname = "testdata/sha/nist_sha3_512.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA3_512::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
101
src/sha/shared.rs
Normal file
101
src/sha/shared.rs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
macro_rules! ch {
|
||||||
|
($x: expr, $y: expr, $z: expr) => {{
|
||||||
|
let xval = $x;
|
||||||
|
(xval & $y) ^ (!xval & $z)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! parity {
|
||||||
|
($x: expr, $y: expr, $z: expr) => {
|
||||||
|
$x ^ $y ^ $z
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! maj {
|
||||||
|
($x: expr, $y: expr, $z: expr) => {{
|
||||||
|
/* the original function is (x & y) ^ (x & z) ^ (y & z).
|
||||||
|
if you fire off truth tables, this is equivalent to
|
||||||
|
(x & y) | (x & z) | (y & z)
|
||||||
|
which you can then use distribution on:
|
||||||
|
(x & (y | z)) | (y & z)
|
||||||
|
which saves one operation */
|
||||||
|
let yval = $y;
|
||||||
|
let zval = $z;
|
||||||
|
($x & (yval | zval)) | (yval & zval)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! process_u32_block {
|
||||||
|
($buf: expr, $off: expr, $self: ident) => {{
|
||||||
|
let w00 = ($buf[$off+0] as u32) << 24 | ($buf[$off+1] as u32) << 16 |
|
||||||
|
($buf[$off+2] as u32) << 8 | ($buf[$off+3] as u32);
|
||||||
|
let w01 = ($buf[$off+4] as u32) << 24 | ($buf[$off+5] as u32) << 16 |
|
||||||
|
($buf[$off+6] as u32) << 8 | ($buf[$off+7] as u32);
|
||||||
|
let w02 = ($buf[$off+8] as u32) << 24 | ($buf[$off+9] as u32) << 16 |
|
||||||
|
($buf[$off+10] as u32) << 8 | ($buf[$off+11] as u32);
|
||||||
|
let w03 = ($buf[$off+12] as u32) << 24 | ($buf[$off+13] as u32) << 16 |
|
||||||
|
($buf[$off+14] as u32) << 8 | ($buf[$off+15] as u32);
|
||||||
|
let w04 = ($buf[$off+16] as u32) << 24 | ($buf[$off+17] as u32) << 16 |
|
||||||
|
($buf[$off+18] as u32) << 8 | ($buf[$off+19] as u32);
|
||||||
|
let w05 = ($buf[$off+20] as u32) << 24 | ($buf[$off+21] as u32) << 16 |
|
||||||
|
($buf[$off+22] as u32) << 8 | ($buf[$off+23] as u32);
|
||||||
|
let w06 = ($buf[$off+24] as u32) << 24 | ($buf[$off+25] as u32) << 16 |
|
||||||
|
($buf[$off+26] as u32) << 8 | ($buf[$off+27] as u32);
|
||||||
|
let w07 = ($buf[$off+28] as u32) << 24 | ($buf[$off+29] as u32) << 16 |
|
||||||
|
($buf[$off+30] as u32) << 8 | ($buf[$off+31] as u32);
|
||||||
|
let w08 = ($buf[$off+32] as u32) << 24 | ($buf[$off+33] as u32) << 16 |
|
||||||
|
($buf[$off+34] as u32) << 8 | ($buf[$off+35] as u32);
|
||||||
|
let w09 = ($buf[$off+36] as u32) << 24 | ($buf[$off+37] as u32) << 16 |
|
||||||
|
($buf[$off+38] as u32) << 8 | ($buf[$off+39] as u32);
|
||||||
|
let w10 = ($buf[$off+40] as u32) << 24 | ($buf[$off+41] as u32) << 16 |
|
||||||
|
($buf[$off+42] as u32) << 8 | ($buf[$off+43] as u32);
|
||||||
|
let w11 = ($buf[$off+44] as u32) << 24 | ($buf[$off+45] as u32) << 16 |
|
||||||
|
($buf[$off+46] as u32) << 8 | ($buf[$off+47] as u32);
|
||||||
|
let w12 = ($buf[$off+48] as u32) << 24 | ($buf[$off+49] as u32) << 16 |
|
||||||
|
($buf[$off+50] as u32) << 8 | ($buf[$off+51] as u32);
|
||||||
|
let w13 = ($buf[$off+52] as u32) << 24 | ($buf[$off+53] as u32) << 16 |
|
||||||
|
($buf[$off+54] as u32) << 8 | ($buf[$off+55] as u32);
|
||||||
|
let w14 = ($buf[$off+56] as u32) << 24 | ($buf[$off+57] as u32) << 16 |
|
||||||
|
($buf[$off+58] as u32) << 8 | ($buf[$off+59] as u32);
|
||||||
|
let w15 = ($buf[$off+60] as u32) << 24 | ($buf[$off+61] as u32) << 16 |
|
||||||
|
($buf[$off+62] as u32) << 8 | ($buf[$off+63] as u32);
|
||||||
|
$self.process(w00, w01, w02, w03, w04, w05, w06, w07,
|
||||||
|
w08, w09, w10, w11, w12, w13, w14, w15);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate the value `k` used in the padding for all the hashes, solving the
|
||||||
|
// equation (l + 1 + k) mod b = a.
|
||||||
|
pub fn calculate_k(a: usize, b: usize, l: usize) -> usize
|
||||||
|
{
|
||||||
|
(a - (l + 1)) % b
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
quickcheck!
|
||||||
|
{
|
||||||
|
fn maj_rewrite_ok(x: u64, y: u64, z: u64) -> bool
|
||||||
|
{
|
||||||
|
let orig = (x & y) ^ (x & z) ^ (y & z);
|
||||||
|
maj!(x, y, z) == orig
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, these two laws hold because we hash with bytes as the atomic size,
|
||||||
|
// not bits. If we hashed true bit streams, we'd be in trouble.
|
||||||
|
fn sha1_k_plus_1_multiple_of_8(lbytes: usize) -> bool
|
||||||
|
{
|
||||||
|
let l = lbytes * 8;
|
||||||
|
(calculate_k(448,512,l) + 1) % 8 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, these two laws hold because we hash with bytes as the atomic size,
|
||||||
|
// not bits. If we hashed true bit streams, we'd be in trouble.
|
||||||
|
fn sha2_k_plus_1_multiple_of_8(lbytes: usize) -> bool
|
||||||
|
{
|
||||||
|
let l = lbytes * 8;
|
||||||
|
(calculate_k(896,1024,l) + 1) % 8 == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
215
src/shake.rs
Normal file
215
src/shake.rs
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
//! This module implements the SHAKE family of variable-length hash functions,
|
||||||
|
//! which NIST also referes to as Extendable-Output Functions (XOFs). They are
|
||||||
|
//! based on the same underlying hashing mechanism used in SHA3, but can be
|
||||||
|
//! tuned to output a variety of different hash lengths. One trick is that the
|
||||||
|
//! security of the hash is the minimum of the defined bit size (128 for
|
||||||
|
//! SHAKE128, or 256 for SHAKE256) and the output hash length, so if you use
|
||||||
|
//! shorter hashes you lose some amount of collision protection.
|
||||||
|
//!
|
||||||
|
//! Because the output is variable length, these don't quite fit into the
|
||||||
|
//! normal `Hash` trait. Instead, they implement the same basic functions,
|
||||||
|
//! but with `hash` and `finalize` functions extended with an additional
|
||||||
|
//! output length function. Usage is thus in the analagous way to normal
|
||||||
|
//! hashing:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::shake::SHAKE128;
|
||||||
|
//!
|
||||||
|
//! // Use SHAKE incrementally
|
||||||
|
//! let empty = [0; 0];
|
||||||
|
//! let mut shakef = SHAKE128::new();
|
||||||
|
//! shakef.update(&empty);
|
||||||
|
//! let result_inc = shakef.finalize(384);
|
||||||
|
//! // Use SHAKE directly
|
||||||
|
//! let result_dir = SHAKE128::hash(&empty, 384);
|
||||||
|
//! // ... and the answers should be the same.
|
||||||
|
//! assert_eq!(result_inc, result_dir);
|
||||||
|
//! ```
|
||||||
|
use sha::Keccak;
|
||||||
|
|
||||||
|
/// The SHAKE128 variable-length hash.
|
||||||
|
///
|
||||||
|
/// This generates a variable-length hash value, although it's not necessarily as
|
||||||
|
/// strong as a hash of the same value. My understanding (which is admittedly
|
||||||
|
/// limited; I've never seen these used) is that this is more for convenience
|
||||||
|
/// when you want to fit into particularly-sized regions. The 128 is the
|
||||||
|
/// approximate maximum bit strength of the hash in bits; the true strength is
|
||||||
|
/// the minimum of the length of the output hash and 128.
|
||||||
|
///
|
||||||
|
/// `SHAKE128` does not implement `Hash`, because it is finalized differently,
|
||||||
|
/// but we've kept something of the flavor of the `Hash` interface for
|
||||||
|
/// familiarity.
|
||||||
|
///
|
||||||
|
/// Like the SHA3 variants, this can be used incrementally or directly, as per
|
||||||
|
/// usual:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::shake::SHAKE128;
|
||||||
|
///
|
||||||
|
/// // Use SHAKE incrementally
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// let mut shakef = SHAKE128::new();
|
||||||
|
/// shakef.update(&empty);
|
||||||
|
/// let result_inc = shakef.finalize(384);
|
||||||
|
/// // Use SHAKE directly
|
||||||
|
/// let result_dir = SHAKE128::hash(&empty, 384);
|
||||||
|
/// // ... and the answers should be the same.
|
||||||
|
/// assert_eq!(result_inc, result_dir);
|
||||||
|
/// ```
|
||||||
|
pub struct SHAKE128 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SHAKE128 {
|
||||||
|
/// Create a fresh, new SHAKE128 instance for incremental use.
|
||||||
|
pub fn new() -> Self
|
||||||
|
{
|
||||||
|
SHAKE128{
|
||||||
|
state: Keccak::new(1600 - 256)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add more data into the hash function for processing.
|
||||||
|
pub fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate the final hash. Because this is a variable-length hash,
|
||||||
|
/// you will need to provide the output size in bits. Note that this
|
||||||
|
/// output size *must* be a multiple of 8, and that the security
|
||||||
|
/// strength of the whole hash is approximately the minimum of this
|
||||||
|
/// length and 128 bits.
|
||||||
|
pub fn finalize(&mut self, outsize: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
assert_eq!(outsize % 8, 0);
|
||||||
|
self.state.tag_and_pad(0x1F);
|
||||||
|
self.state.squeeze(outsize / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Directly generate the SHAKE128 hash of the given buffer, returning
|
||||||
|
/// a hash value of the given size (in bits). Presently, the output
|
||||||
|
/// size *must* be a multiple of 8, although this may change in the
|
||||||
|
/// future.
|
||||||
|
pub fn hash(buffer: &[u8], outsize: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut x = Self::new();
|
||||||
|
x.update(&buffer);
|
||||||
|
x.finalize(outsize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
#[cfg(test)]
|
||||||
|
use cryptonum::unsigned::{Decoder,U192};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn shake128() {
|
||||||
|
let fname = "testdata/sha/shake128.test";
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
let (nego, obytes) = case.get("o").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd && !nego);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let osize = usize::from(U192::from_bytes(obytes));
|
||||||
|
let digest = SHAKE128::hash(&msg, osize);;
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHAKE256 variable-length hash.
|
||||||
|
///
|
||||||
|
/// This generates a variable-length hash value, although it's not necessarily as
|
||||||
|
/// strong as a hash of the same value. My understanding (which is admittedly
|
||||||
|
/// limited; I've never seen these used) is that this is more for convenience
|
||||||
|
/// when you want to fit into particularly-sized regions. The 256 is the
|
||||||
|
/// approximate maximum bit strength of the hash in bits; the true strength is
|
||||||
|
/// the minimum of the length of the output hash and 256.
|
||||||
|
///
|
||||||
|
/// `SHAKE256` does not implement `Hash`, because it is finalized differently,
|
||||||
|
/// but we've kept something of the flavor of the `Hash` interface for
|
||||||
|
/// familiarity.
|
||||||
|
///
|
||||||
|
/// Like the SHA3 variants, this can be used incrementally or directly, as per
|
||||||
|
/// usual:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::shake::SHAKE256;
|
||||||
|
///
|
||||||
|
/// // Use SHAKE incrementally
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// let mut shakef = SHAKE256::new();
|
||||||
|
/// shakef.update(&empty);
|
||||||
|
/// let result_inc = shakef.finalize(384);
|
||||||
|
/// // Use SHAKE directly
|
||||||
|
/// let result_dir = SHAKE256::hash(&empty, 384);
|
||||||
|
/// // ... and the answers should be the same.
|
||||||
|
/// assert_eq!(result_inc, result_dir);
|
||||||
|
/// ```
|
||||||
|
pub struct SHAKE256 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SHAKE256 {
|
||||||
|
/// Create a fresh, new SHAKE256 instance for incremental use.
|
||||||
|
pub fn new() -> Self
|
||||||
|
{
|
||||||
|
SHAKE256{
|
||||||
|
state: Keccak::new(1600 - 512)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add more data into the hash function for processing.
|
||||||
|
pub fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate the final hash. Because this is a variable-length hash,
|
||||||
|
/// you will need to provide the output size in bits. Note that this
|
||||||
|
/// output size *must* be a multiple of 8, and that the security
|
||||||
|
/// strength of the whole hash is approximately the minimum of this
|
||||||
|
/// length and 256 bits.
|
||||||
|
pub fn finalize(&mut self, outsize: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
assert_eq!(outsize % 8, 0);
|
||||||
|
self.state.tag_and_pad(0x1F);
|
||||||
|
self.state.squeeze(outsize / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Directly generate the SHAKE256 hash of the given buffer, returning
|
||||||
|
/// a hash value of the given size (in bits). Presently, the output
|
||||||
|
/// size *must* be a multiple of 8, although this may change in the
|
||||||
|
/// future.
|
||||||
|
pub fn hash(buffer: &[u8], outsize: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut x = Self::new();
|
||||||
|
x.update(&buffer);
|
||||||
|
x.finalize(outsize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn shake256() {
|
||||||
|
let fname = "testdata/sha/shake256.test";
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
let (nego, obytes) = case.get("o").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd && !nego);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let osize = usize::from(U192::from_bytes(obytes));
|
||||||
|
let digest = SHAKE256::hash(&msg, osize);;
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ use std::io::Read;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::iter::Iterator;
|
use std::iter::Iterator;
|
||||||
|
|
||||||
const OPENER: &'static str = "-----BEGIN OPENSSH PRIVATE KEY-----\n";
|
const OPENER: &'static str = "-----BEGIN OPENSSH PRIVATE KEY-----";
|
||||||
const CLOSER: &'static str = "-----END OPENSSH PRIVATE KEY-----";
|
const CLOSER: &'static str = "-----END OPENSSH PRIVATE KEY-----";
|
||||||
|
|
||||||
/// Given a string defining an ASCII SSH key blob (one that starts with
|
/// Given a string defining an ASCII SSH key blob (one that starts with
|
||||||
@@ -20,7 +20,7 @@ pub fn parse_ssh_private_key_data(s: &str) -> Result<Vec<u8>,SSHKeyParseError>
|
|||||||
{
|
{
|
||||||
if s.starts_with(OPENER) {
|
if s.starts_with(OPENER) {
|
||||||
if let Some(endidx) = s.find(CLOSER) {
|
if let Some(endidx) = s.find(CLOSER) {
|
||||||
let b64str: String = s[OPENER.len()..endidx].chars().filter(|x| *x != '\n').collect();
|
let b64str: String = s[OPENER.len()..endidx].chars().filter(|x| !x.is_whitespace()).collect();
|
||||||
let bytes = decode(&b64str)?;
|
let bytes = decode(&b64str)?;
|
||||||
Ok(bytes)
|
Ok(bytes)
|
||||||
} else {
|
} else {
|
||||||
@@ -39,13 +39,20 @@ pub fn render_ssh_private_key_data(bytes: &[u8]) -> String
|
|||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
||||||
output.push_str(OPENER);
|
output.push_str(OPENER);
|
||||||
|
#[cfg(target_os="windows")]
|
||||||
|
output.push_str("\r");
|
||||||
|
output.push_str("\n");
|
||||||
while bytestr.len() > 70 {
|
while bytestr.len() > 70 {
|
||||||
let rest = bytestr.split_off(70);
|
let rest = bytestr.split_off(70);
|
||||||
output.push_str(&bytestr);
|
output.push_str(&bytestr);
|
||||||
|
#[cfg(target_os="windows")]
|
||||||
|
output.push_str("\r");
|
||||||
output.push_str("\n");
|
output.push_str("\n");
|
||||||
bytestr = rest;
|
bytestr = rest;
|
||||||
}
|
}
|
||||||
output.push_str(&bytestr);
|
output.push_str(&bytestr);
|
||||||
|
#[cfg(target_os="windows")]
|
||||||
|
output.push_str("\r");
|
||||||
output.push_str("\n");
|
output.push_str("\n");
|
||||||
output.push_str(CLOSER);
|
output.push_str(CLOSER);
|
||||||
|
|
||||||
@@ -197,7 +204,8 @@ quickcheck! {
|
|||||||
let mut is_ok = true;
|
let mut is_ok = true;
|
||||||
|
|
||||||
for line in rendered.lines() {
|
for line in rendered.lines() {
|
||||||
is_ok &= line.len() <= 70;
|
let clean_line: String = line.chars().filter(|x| *x != '\r').collect();
|
||||||
|
is_ok &= clean_line.len() <= 70;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_ok
|
is_ok
|
||||||
@@ -293,8 +301,12 @@ fn pregenerated_reencode() {
|
|||||||
fd.read_to_string(&mut contents).unwrap();
|
fd.read_to_string(&mut contents).unwrap();
|
||||||
let parsed = parse_ssh_private_key_data(&contents).unwrap();
|
let parsed = parse_ssh_private_key_data(&contents).unwrap();
|
||||||
let rendered = render_ssh_private_key_data(&parsed);
|
let rendered = render_ssh_private_key_data(&parsed);
|
||||||
// starts_with() avoids newline unpleasantness
|
// we remove white space in this to avoid a couple issues with files
|
||||||
assert!(contents.starts_with(&rendered));
|
// generated in Windows or not, as well as trailing white space that
|
||||||
|
// doesn't really matter.
|
||||||
|
let cleaned_orig: String = contents.chars().filter(|x| !x.is_whitespace()).collect();
|
||||||
|
let cleaned_rend: String = rendered.chars().filter(|x| !x.is_whitespace()).collect();
|
||||||
|
assert_eq!(cleaned_orig, cleaned_rend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ use ed25519::ED25519KeyPair;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use rsa::{RSAPair,RSAPublic,SIGNING_HASH_SHA256};
|
use rsa::{RSAPair,RSAPublic,SIGNING_HASH_SHA256};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use sha2::Sha256;
|
use sha::SHA256;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[test]
|
#[test]
|
||||||
@@ -235,10 +235,10 @@ fn dsa_examples() {
|
|||||||
Ok((keypair, comment)) => {
|
Ok((keypair, comment)) => {
|
||||||
let buffer = [0,1,2,3,4,6,2];
|
let buffer = [0,1,2,3,4,6,2];
|
||||||
let _ : DSAKeyPair<L1024N160> = keypair;
|
let _ : DSAKeyPair<L1024N160> = keypair;
|
||||||
let sig = keypair.private.sign::<Sha256>(&buffer);
|
let sig = keypair.private.sign::<SHA256>(&buffer);
|
||||||
assert!(keypair.public.verify::<Sha256>(&buffer, &sig));
|
assert!(keypair.public.verify::<SHA256>(&buffer, &sig));
|
||||||
let buffer2 = [0,1,2,3,4,6,5];
|
let buffer2 = [0,1,2,3,4,6,5];
|
||||||
assert!(!keypair.public.verify::<Sha256>(&buffer2, &sig));
|
assert!(!keypair.public.verify::<SHA256>(&buffer2, &sig));
|
||||||
match encode_ssh(&keypair, &comment) {
|
match encode_ssh(&keypair, &comment) {
|
||||||
Err(e2) => assert!(false, format!("render error: {:?}", e2)),
|
Err(e2) => assert!(false, format!("render error: {:?}", e2)),
|
||||||
Ok(encodedstr) => {
|
Ok(encodedstr) => {
|
||||||
@@ -345,16 +345,16 @@ fn ecdsa_examples() {
|
|||||||
ECDSAPair::P224(_,_) =>
|
ECDSAPair::P224(_,_) =>
|
||||||
assert!(false, "Somehow got a P224 in read test"),
|
assert!(false, "Somehow got a P224 in read test"),
|
||||||
ECDSAPair::P256(ref pu, ref pr) => {
|
ECDSAPair::P256(ref pu, ref pr) => {
|
||||||
let sig = pr.sign::<Sha256>(&buffer);
|
let sig = pr.sign::<SHA256>(&buffer);
|
||||||
assert!(pu.verify::<Sha256>(&buffer, &sig));
|
assert!(pu.verify::<SHA256>(&buffer, &sig));
|
||||||
}
|
}
|
||||||
ECDSAPair::P384(ref pu, ref pr) => {
|
ECDSAPair::P384(ref pu, ref pr) => {
|
||||||
let sig = pr.sign::<Sha256>(&buffer);
|
let sig = pr.sign::<SHA256>(&buffer);
|
||||||
assert!(pu.verify::<Sha256>(&buffer, &sig));
|
assert!(pu.verify::<SHA256>(&buffer, &sig));
|
||||||
}
|
}
|
||||||
ECDSAPair::P521(ref pu, ref pr) => {
|
ECDSAPair::P521(ref pu, ref pr) => {
|
||||||
let sig = pr.sign::<Sha256>(&buffer);
|
let sig = pr.sign::<SHA256>(&buffer);
|
||||||
assert!(pu.verify::<Sha256>(&buffer, &sig));
|
assert!(pu.verify::<SHA256>(&buffer, &sig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// encode this, parse it again
|
// encode this, parse it again
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ mod validity;
|
|||||||
use dsa::DSAPublic;
|
use dsa::DSAPublic;
|
||||||
use ecdsa::ECDSAPublic;
|
use ecdsa::ECDSAPublic;
|
||||||
use rsa::{SIGNING_HASH_SHA1,SIGNING_HASH_SHA224,SIGNING_HASH_SHA256,SIGNING_HASH_SHA384,SIGNING_HASH_SHA512};
|
use rsa::{SIGNING_HASH_SHA1,SIGNING_HASH_SHA224,SIGNING_HASH_SHA256,SIGNING_HASH_SHA384,SIGNING_HASH_SHA512};
|
||||||
use sha1::Sha1;
|
use sha::{SHA1,SHA224,SHA256,SHA384,SHA512};
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
|
||||||
use simple_asn1::{ASN1Block,FromASN1,der_decode,from_der};
|
use simple_asn1::{ASN1Block,FromASN1,der_decode,from_der};
|
||||||
pub use x509::validity::Validity;
|
pub use x509::validity::Validity;
|
||||||
pub use x509::algident::{AlgorithmIdentifier,HashAlgorithm,PublicKeyInfo};
|
pub use x509::algident::{AlgorithmIdentifier,HashAlgorithm,PublicKeyInfo};
|
||||||
@@ -137,10 +136,10 @@ fn check_signature(alg: &AlgorithmIdentifier,
|
|||||||
let dsa_sig = der_decode(&sig)?;
|
let dsa_sig = der_decode(&sig)?;
|
||||||
match alg.hash {
|
match alg.hash {
|
||||||
HashAlgorithm::SHA1
|
HashAlgorithm::SHA1
|
||||||
if key.verify::<Sha1>(block, &dsa_sig) => Ok(()),
|
if key.verify::<SHA1>(block, &dsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA224
|
HashAlgorithm::SHA224
|
||||||
if key.verify::<Sha224>(block, &dsa_sig) => Ok(()),
|
if key.verify::<SHA224>(block, &dsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA256 if key.verify::<Sha256>(block, &dsa_sig) =>
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &dsa_sig) =>
|
||||||
Ok(()),
|
Ok(()),
|
||||||
_ =>
|
_ =>
|
||||||
Err(X509ParseError::InvalidSignatureHash)
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
@@ -150,10 +149,10 @@ fn check_signature(alg: &AlgorithmIdentifier,
|
|||||||
let dsa_sig = der_decode(&sig)?;
|
let dsa_sig = der_decode(&sig)?;
|
||||||
match alg.hash {
|
match alg.hash {
|
||||||
HashAlgorithm::SHA1
|
HashAlgorithm::SHA1
|
||||||
if key.verify::<Sha1>(block, &dsa_sig) => Ok(()),
|
if key.verify::<SHA1>(block, &dsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA224
|
HashAlgorithm::SHA224
|
||||||
if key.verify::<Sha224>(block, &dsa_sig) => Ok(()),
|
if key.verify::<SHA224>(block, &dsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA256 if key.verify::<Sha256>(block, &dsa_sig) =>
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &dsa_sig) =>
|
||||||
Ok(()),
|
Ok(()),
|
||||||
_ =>
|
_ =>
|
||||||
Err(X509ParseError::InvalidSignatureHash)
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
@@ -163,10 +162,10 @@ fn check_signature(alg: &AlgorithmIdentifier,
|
|||||||
let dsa_sig = der_decode(&sig)?;
|
let dsa_sig = der_decode(&sig)?;
|
||||||
match alg.hash {
|
match alg.hash {
|
||||||
HashAlgorithm::SHA1
|
HashAlgorithm::SHA1
|
||||||
if key.verify::<Sha1>(block, &dsa_sig) => Ok(()),
|
if key.verify::<SHA1>(block, &dsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA224
|
HashAlgorithm::SHA224
|
||||||
if key.verify::<Sha224>(block, &dsa_sig) => Ok(()),
|
if key.verify::<SHA224>(block, &dsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA256 if key.verify::<Sha256>(block, &dsa_sig) =>
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &dsa_sig) =>
|
||||||
Ok(()),
|
Ok(()),
|
||||||
_ =>
|
_ =>
|
||||||
Err(X509ParseError::InvalidSignatureHash)
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
@@ -176,10 +175,10 @@ fn check_signature(alg: &AlgorithmIdentifier,
|
|||||||
let dsa_sig = der_decode(&sig)?;
|
let dsa_sig = der_decode(&sig)?;
|
||||||
match alg.hash {
|
match alg.hash {
|
||||||
HashAlgorithm::SHA1
|
HashAlgorithm::SHA1
|
||||||
if key.verify::<Sha1>(block, &dsa_sig) => Ok(()),
|
if key.verify::<SHA1>(block, &dsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA224
|
HashAlgorithm::SHA224
|
||||||
if key.verify::<Sha224>(block, &dsa_sig) => Ok(()),
|
if key.verify::<SHA224>(block, &dsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA256 if key.verify::<Sha256>(block, &dsa_sig) =>
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &dsa_sig) =>
|
||||||
Ok(()),
|
Ok(()),
|
||||||
_ =>
|
_ =>
|
||||||
Err(X509ParseError::InvalidSignatureHash)
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
@@ -188,11 +187,11 @@ fn check_signature(alg: &AlgorithmIdentifier,
|
|||||||
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P192(ref key))) => {
|
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P192(ref key))) => {
|
||||||
let ecdsa_sig = der_decode(&sig)?;
|
let ecdsa_sig = der_decode(&sig)?;
|
||||||
match alg.hash {
|
match alg.hash {
|
||||||
HashAlgorithm::SHA1 if key.verify::<Sha1>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA1 if key.verify::<SHA1>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA224 if key.verify::<Sha224>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA224 if key.verify::<SHA224>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA256 if key.verify::<Sha256>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA384 if key.verify::<Sha384>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA384 if key.verify::<SHA384>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA512 if key.verify::<Sha512>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA512 if key.verify::<SHA512>(block, &ecdsa_sig) => Ok(()),
|
||||||
_ =>
|
_ =>
|
||||||
Err(X509ParseError::InvalidSignatureHash)
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
}
|
}
|
||||||
@@ -200,11 +199,11 @@ fn check_signature(alg: &AlgorithmIdentifier,
|
|||||||
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P224(ref key))) => {
|
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P224(ref key))) => {
|
||||||
let ecdsa_sig = der_decode(&sig)?;
|
let ecdsa_sig = der_decode(&sig)?;
|
||||||
match alg.hash {
|
match alg.hash {
|
||||||
HashAlgorithm::SHA1 if key.verify::<Sha1>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA1 if key.verify::<SHA1>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA224 if key.verify::<Sha224>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA224 if key.verify::<SHA224>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA256 if key.verify::<Sha256>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA384 if key.verify::<Sha384>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA384 if key.verify::<SHA384>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA512 if key.verify::<Sha512>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA512 if key.verify::<SHA512>(block, &ecdsa_sig) => Ok(()),
|
||||||
_ =>
|
_ =>
|
||||||
Err(X509ParseError::InvalidSignatureHash)
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
}
|
}
|
||||||
@@ -212,11 +211,11 @@ fn check_signature(alg: &AlgorithmIdentifier,
|
|||||||
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P256(ref key))) => {
|
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P256(ref key))) => {
|
||||||
let ecdsa_sig = der_decode(&sig)?;
|
let ecdsa_sig = der_decode(&sig)?;
|
||||||
match alg.hash {
|
match alg.hash {
|
||||||
HashAlgorithm::SHA1 if key.verify::<Sha1>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA1 if key.verify::<SHA1>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA224 if key.verify::<Sha224>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA224 if key.verify::<SHA224>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA256 if key.verify::<Sha256>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA384 if key.verify::<Sha384>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA384 if key.verify::<SHA384>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA512 if key.verify::<Sha512>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA512 if key.verify::<SHA512>(block, &ecdsa_sig) => Ok(()),
|
||||||
_ =>
|
_ =>
|
||||||
Err(X509ParseError::InvalidSignatureHash)
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
}
|
}
|
||||||
@@ -224,11 +223,11 @@ fn check_signature(alg: &AlgorithmIdentifier,
|
|||||||
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P384(ref key))) => {
|
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P384(ref key))) => {
|
||||||
let ecdsa_sig = der_decode(&sig)?;
|
let ecdsa_sig = der_decode(&sig)?;
|
||||||
match alg.hash {
|
match alg.hash {
|
||||||
HashAlgorithm::SHA1 if key.verify::<Sha1>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA1 if key.verify::<SHA1>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA224 if key.verify::<Sha224>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA224 if key.verify::<SHA224>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA256 if key.verify::<Sha256>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA384 if key.verify::<Sha384>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA384 if key.verify::<SHA384>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA512 if key.verify::<Sha512>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA512 if key.verify::<SHA512>(block, &ecdsa_sig) => Ok(()),
|
||||||
_ =>
|
_ =>
|
||||||
Err(X509ParseError::InvalidSignatureHash)
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
}
|
}
|
||||||
@@ -236,11 +235,11 @@ fn check_signature(alg: &AlgorithmIdentifier,
|
|||||||
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P521(ref key))) => {
|
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P521(ref key))) => {
|
||||||
let ecdsa_sig = der_decode(&sig)?;
|
let ecdsa_sig = der_decode(&sig)?;
|
||||||
match alg.hash {
|
match alg.hash {
|
||||||
HashAlgorithm::SHA1 if key.verify::<Sha1>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA1 if key.verify::<SHA1>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA224 if key.verify::<Sha224>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA224 if key.verify::<SHA224>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA256 if key.verify::<Sha256>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA384 if key.verify::<Sha384>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA384 if key.verify::<SHA384>(block, &ecdsa_sig) => Ok(()),
|
||||||
HashAlgorithm::SHA512 if key.verify::<Sha512>(block, &ecdsa_sig) => Ok(()),
|
HashAlgorithm::SHA512 if key.verify::<SHA512>(block, &ecdsa_sig) => Ok(()),
|
||||||
_ =>
|
_ =>
|
||||||
Err(X509ParseError::InvalidSignatureHash)
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
}
|
}
|
||||||
|
|||||||
2880
testdata/sha/hmac.test
vendored
Normal file
2880
testdata/sha/hmac.test
vendored
Normal file
File diff suppressed because it is too large
Load Diff
387
testdata/sha/nist_sha1.test
vendored
Normal file
387
testdata/sha/nist_sha1.test
vendored
Normal file
File diff suppressed because one or more lines are too long
387
testdata/sha/nist_sha224.test
vendored
Normal file
387
testdata/sha/nist_sha224.test
vendored
Normal file
File diff suppressed because one or more lines are too long
387
testdata/sha/nist_sha256.test
vendored
Normal file
387
testdata/sha/nist_sha256.test
vendored
Normal file
File diff suppressed because one or more lines are too long
771
testdata/sha/nist_sha384.test
vendored
Normal file
771
testdata/sha/nist_sha384.test
vendored
Normal file
File diff suppressed because one or more lines are too long
735
testdata/sha/nist_sha3_224.test
vendored
Normal file
735
testdata/sha/nist_sha3_224.test
vendored
Normal file
File diff suppressed because one or more lines are too long
711
testdata/sha/nist_sha3_256.test
vendored
Normal file
711
testdata/sha/nist_sha3_256.test
vendored
Normal file
File diff suppressed because one or more lines are too long
615
testdata/sha/nist_sha3_384.test
vendored
Normal file
615
testdata/sha/nist_sha3_384.test
vendored
Normal file
File diff suppressed because one or more lines are too long
519
testdata/sha/nist_sha3_512.test
vendored
Normal file
519
testdata/sha/nist_sha3_512.test
vendored
Normal file
File diff suppressed because one or more lines are too long
771
testdata/sha/nist_sha512.test
vendored
Normal file
771
testdata/sha/nist_sha512.test
vendored
Normal file
File diff suppressed because one or more lines are too long
6252
testdata/sha/shake128.test
vendored
Normal file
6252
testdata/sha/shake128.test
vendored
Normal file
File diff suppressed because one or more lines are too long
6476
testdata/sha/shake256.test
vendored
Normal file
6476
testdata/sha/shake256.test
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user