DSA support!
This commit is contained in:
20
src/dsa/errors.rs
Normal file
20
src/dsa/errors.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use simple_asn1::ASN1DecodeErr;
|
||||
use rand;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DSAError {
|
||||
RandomGenError(rand::Error),
|
||||
ASN1DecodeErr(ASN1DecodeErr)
|
||||
}
|
||||
|
||||
impl From<rand::Error> for DSAError {
|
||||
fn from(e: rand::Error) -> DSAError {
|
||||
DSAError::RandomGenError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ASN1DecodeErr> for DSAError {
|
||||
fn from(e: ASN1DecodeErr) -> DSAError {
|
||||
DSAError::ASN1DecodeErr(e)
|
||||
}
|
||||
}
|
||||
67
src/dsa/mod.rs
Normal file
67
src/dsa/mod.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
mod errors;
|
||||
mod params;
|
||||
mod private;
|
||||
mod public;
|
||||
mod rfc6979;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use self::params::*;
|
||||
pub use self::private::*;
|
||||
pub use self::public::*;
|
||||
|
||||
use cryptonum::unsigned::*;
|
||||
use rand::Rng;
|
||||
use rand::distributions::Standard;
|
||||
|
||||
pub struct DSAKeyPair<P,L,N>
|
||||
{
|
||||
pub private: DSAPrivKey<P,N>,
|
||||
pub public: DSAPubKey<P,L>
|
||||
}
|
||||
|
||||
pub trait DSAKeyGeneration<P>
|
||||
{
|
||||
fn generate<G: Rng>(params: &P, rng: &mut G) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! generate_dsa_pair {
|
||||
($ptype: ident, $ltype: ident, $ntype: ident, $nbig: ident) => {
|
||||
impl DSAKeyGeneration<$ptype> for DSAKeyPair<$ptype,$ltype,$ntype>
|
||||
where
|
||||
DSAPrivKey<$ptype,$ntype>: DSAPrivateKey<$ptype,$ltype,$ntype>,
|
||||
{
|
||||
fn generate<G: Rng>(params: &$ptype, rng: &mut G) -> Self
|
||||
{
|
||||
// 1. N = len(q); L = len(p);
|
||||
let n = $ptype::n_size();
|
||||
// 2. If the (L,N) pair is invalid, then return an ERROR indicator,
|
||||
// Invalid_x, and Invalid_y.
|
||||
// 3. requested_security_strength = the security strength associated
|
||||
// with the (L, N) pair; see SP 800-57.
|
||||
// 4. Obtain a string of N+64 returned_bits from an RBG with a security
|
||||
// strength of requested_security_strength or more. If an ERROR
|
||||
// indication is returned, then return an ERROR indication,
|
||||
// Invalid_x, and Invalid_y.
|
||||
let returned_bits: Vec<u8> = rng.sample_iter(&Standard).take(n + 8).collect();
|
||||
// 5. Convert returned_bits to the (non-negative) integer c.
|
||||
let c = $nbig::from_bytes(&returned_bits);
|
||||
// 6. x = (c mod (q-1)) + 1.
|
||||
let one = $nbig::from(1 as u64);
|
||||
let qbig = $nbig::from(¶ms.q);
|
||||
let x = $ntype::from( (&c % (&qbig - &one)) + &one );
|
||||
// 7. y = g^x mod p
|
||||
let y = params.g.modexp(&$ltype::from(&x), ¶ms.p);
|
||||
// 8. Return SUCCESS, x, and y.
|
||||
let private = DSAPrivKey::new(params.clone(), x);
|
||||
let public = DSAPubKey::new(params.clone(), y);
|
||||
DSAKeyPair { private, public }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
generate_dsa_pair!(L1024N160, U1024, U192, U256);
|
||||
generate_dsa_pair!(L2048N224, U2048, U256, U384);
|
||||
generate_dsa_pair!(L2048N256, U2048, U256, U384);
|
||||
generate_dsa_pair!(L3072N256, U3072, U256, U384);
|
||||
191
src/dsa/params.rs
Normal file
191
src/dsa/params.rs
Normal file
@@ -0,0 +1,191 @@
|
||||
use cryptonum::unsigned::{CryptoNum,Decoder,Encoder,ModExp,PrimeGen};
|
||||
use cryptonum::unsigned::{U192,U256,U1024,U2048,U3072};
|
||||
use digest::Digest;
|
||||
use sha2::Sha256;
|
||||
use rand::Rng;
|
||||
|
||||
pub trait DSAParameters<L,N>
|
||||
{
|
||||
fn new(p: L, g: L, q: N) -> Self;
|
||||
fn generate<G: Rng>(rng: &mut G) -> Self;
|
||||
fn n_size() -> usize;
|
||||
fn l_size() -> usize;
|
||||
|
||||
fn n_bits(&self) -> usize {
|
||||
Self::n_size()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! generate_parameters {
|
||||
($name: ident, $ltype: ident, $ntype: ident, $l: expr, $n: expr) => {
|
||||
#[derive(Clone)]
|
||||
pub struct $name {
|
||||
pub p: $ltype,
|
||||
pub g: $ltype,
|
||||
pub q: $ntype
|
||||
}
|
||||
|
||||
impl DSAParameters<$ltype,$ntype> for $name
|
||||
{
|
||||
fn new(p: $ltype, g: $ltype, q: $ntype) -> $name
|
||||
{
|
||||
$name{ p: p, g: g, q: q }
|
||||
}
|
||||
|
||||
fn generate<G: Rng>(rng: &mut G) -> $name
|
||||
{
|
||||
let (p, q, _, _) = $name::generate_primes(rng);
|
||||
let g = $name::generate_g(rng, &p, &q);
|
||||
$name{ p: p, g: g, q: q }
|
||||
}
|
||||
|
||||
fn l_size() -> usize {
|
||||
$l
|
||||
}
|
||||
|
||||
fn n_size() -> usize {
|
||||
$n
|
||||
}
|
||||
}
|
||||
|
||||
impl $name
|
||||
{
|
||||
fn generate_primes<G: Rng>(rng: &mut G) -> ($ltype,$ntype,U256,usize)
|
||||
{
|
||||
// This is A.1.1.2 from FIPS 186-4, with seedlen hardcoded to 256
|
||||
// (since that's guaranteed to be >= N), and with the hash
|
||||
// hardcoded as SHA-256.
|
||||
#[allow(non_snake_case)]
|
||||
let L = $ltype::bit_length();
|
||||
#[allow(non_snake_case)]
|
||||
let N = $ntype::bit_length();
|
||||
let seedlen = 256;
|
||||
let outlen = 256;
|
||||
//
|
||||
// 1. Check that the (L,N) pair is in the list of acceptable
|
||||
// (L,N) pairs (see Section 4.2). If the pair is not in the
|
||||
// list, then return INVALID.
|
||||
// [This is always true.]
|
||||
//
|
||||
// 2. If (seedlen < N), then return INVALID.
|
||||
// [This is always true.]
|
||||
//
|
||||
// 3. n = L/outlen – 1.
|
||||
let n = ((L + 255) / 256) - 1;
|
||||
// 4. b = L – 1 – (n ∗ outlen).
|
||||
let b = L - 1 - (n * outlen);
|
||||
loop {
|
||||
// 5. Get an arbitrary sequence of seedlen bits as the
|
||||
// domain_parameter_seed.
|
||||
let domain_parameter_seed: U256 = rng.gen();
|
||||
// 6. U = Hash (domain_parameter_seed) mod 2^(N–1).
|
||||
let mut ubytes = hash(&domain_parameter_seed, 32);
|
||||
while ubytes.len() > (N / 8) { ubytes.remove(0); }
|
||||
#[allow(non_snake_case)]
|
||||
let U = $ntype::from_bytes(&ubytes);
|
||||
// 7. q = 2^(N–1) + U + 1 – (U mod 2).
|
||||
let ulow = if U.is_even() { 0 } else { 1 };
|
||||
let mut q = $ntype::from(1u64) << (N - 1);
|
||||
q += U;
|
||||
q += $ntype::from(1u64 + ulow);
|
||||
// 8. Test whether or not q is prime as specified in Appendix C.3.
|
||||
let q_is_prime = q.probably_prime(rng, 40);
|
||||
// 9. If q is not a prime, then go to step 5.
|
||||
if !q_is_prime {
|
||||
continue;
|
||||
}
|
||||
// 10. offset = 1.
|
||||
let mut offset = 1;
|
||||
// 11. For counter = 0 to (4L – 1) do
|
||||
for counter in 0..(4*L)-1 {
|
||||
// 11.1 For j = 0 to n do
|
||||
// Vj = Hash ((domain_parameter_seed + offset + j) mod 2^seedlen).
|
||||
#[allow(non_snake_case)]
|
||||
let mut V = Vec::new();
|
||||
for j in 0..n {
|
||||
let val = &domain_parameter_seed + U256::from(offset + j);
|
||||
let bytes = hash(&val, 32);
|
||||
assert_eq!(seedlen, bytes.len());
|
||||
V.push(bytes);
|
||||
}
|
||||
// 11.2 W = V_0 + ( V_1 ∗ 2^outlen) + ... + ( V_(n–1) ∗ 2^(n –1) ∗ outlen) + ((V_n mod 2^b) ∗ 2^(n ∗ outlen).
|
||||
#[allow(non_snake_case)]
|
||||
let mut W = $ltype::zero();
|
||||
for (idx, val) in V.iter().enumerate() {
|
||||
if idx < n {
|
||||
let mut base = val.clone();
|
||||
let baselen = base.len();
|
||||
base.resize(baselen + (idx * (outlen / 8)), 0);
|
||||
W += $ltype::from_bytes(&base);
|
||||
} else {
|
||||
let base = $ltype::from_bytes(val);
|
||||
let twob = $ltype::from(1u64) << b;
|
||||
let val = base % twob;
|
||||
W += val << (n * outlen);
|
||||
}
|
||||
}
|
||||
// 11.3 X = W + 2^(L – 1).
|
||||
// Comment: 0 ≤ W < 2 L – 1 ; hence, 2 L – 1 ≤ X < 2 L .
|
||||
#[allow(non_snake_case)]
|
||||
let mut X = $ltype::from(1u64) << (L - 1);
|
||||
X += W;
|
||||
// 11.4 c = X mod 2q.
|
||||
let c = &X % ($ltype::from(&q) << 1);
|
||||
// 11.5 p = X – ( c – 1).
|
||||
// Comment: p ≡ 1 ( mod 2 q) .
|
||||
let p = &X - (c - $ltype::from(1u64));
|
||||
// 11.6 If ( p < 2L – 1), then go to step 11.9.
|
||||
if p >= $ltype::from((2*L) - 1) {
|
||||
// 11.7 Test whether or not p is prime as specified in Appendix C .3.
|
||||
if p.probably_prime(rng, 40) {
|
||||
// 11.8 If p is determined to be prime, then return VALID and the values of p , q and (optionally) the values of domain_parameter_seed and counter .
|
||||
return (p, q, domain_parameter_seed, counter);
|
||||
}
|
||||
}
|
||||
// 11.9 offset = offset + n + 1.
|
||||
offset = offset + n + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_g<G: Rng>(rng: &mut G, p: &$ltype, q: &$ntype) -> $ltype
|
||||
{
|
||||
let bigq = $ltype::from(q);
|
||||
let p_minus_1 = p - $ltype::from(1u64);
|
||||
// This is A.2.1 (Unverifiable Generation of g) from FIPS 186-4.
|
||||
// 1. e = (p – 1) / q.
|
||||
let e = (p - $ltype::from(1u64)) / bigq;
|
||||
loop {
|
||||
// 2. Set h = any integer satisfying 1 < h < ( p – 1), such that
|
||||
// h differs from any value previously tried. Note that h could
|
||||
// be obtained from a random number generator or from a counter
|
||||
// that changes after each use.
|
||||
let h = rng.gen_range($ltype::from(2u64), &p_minus_1);
|
||||
// 3. g = h^e mod p.
|
||||
let g = h.modexp(&e, p);
|
||||
// 4. If ( g = 1), then go to step 2.
|
||||
if g != $ltype::from(1u64) {
|
||||
// 5. Return g
|
||||
return g;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
generate_parameters!(L1024N160, U1024, U192, 1024, 160);
|
||||
generate_parameters!(L2048N224, U2048, U256, 2048, 224);
|
||||
generate_parameters!(L2048N256, U2048, U256, 2048, 256);
|
||||
generate_parameters!(L3072N256, U3072, U256, 3072, 256);
|
||||
|
||||
fn hash<T>(x: &T, len: usize) -> Vec<u8>
|
||||
where T: Encoder
|
||||
{
|
||||
let mut base = x.to_bytes();
|
||||
let bytelen = len / 8;
|
||||
while base.len() < bytelen {
|
||||
base.insert(0,0);
|
||||
}
|
||||
Sha256::digest(&base).as_slice().to_vec()
|
||||
}
|
||||
111
src/dsa/private.rs
Normal file
111
src/dsa/private.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
use cryptonum::unsigned::*;
|
||||
use cryptonum::signed::ModInv;
|
||||
use digest::{BlockInput,Digest,Input,FixedOutput,Reset};
|
||||
use dsa::params::*;
|
||||
use dsa::rfc6979::*;
|
||||
use hmac::{Hmac,Mac};
|
||||
|
||||
pub trait DSAPrivateKey<Params,L,N> {
|
||||
/// Generate a new private key using the given DSA parameters and private
|
||||
/// key value.
|
||||
fn new(params: Params, x: N) -> Self;
|
||||
/// Generate a DSA signature for the given message, using the appropriate
|
||||
/// hash included in the type invocation.
|
||||
fn sign<Hash>(&self, m: &[u8]) -> DSASignature<N>
|
||||
where
|
||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||
Hmac<Hash>: Mac;
|
||||
}
|
||||
|
||||
pub struct DSAPrivKey<Params,N>
|
||||
{
|
||||
pub(crate) params: Params,
|
||||
pub(crate) x: N
|
||||
}
|
||||
|
||||
pub enum DSAPrivate {
|
||||
DSA1024Private(DSAPrivKey<L1024N160,U192>),
|
||||
DSA2048SmallPrivate(DSAPrivKey<L2048N224,U256>),
|
||||
DSA2048Private(DSAPrivKey<L2048N256,U256>),
|
||||
DSA3072Private(DSAPrivKey<L3072N256,U256>)
|
||||
}
|
||||
|
||||
macro_rules! privkey_impls {
|
||||
($ptype: ident, $ltype: ident, $ntype: ident, $big: ident, $bigger: ident, $biggest: ident) => {
|
||||
impl DSAPrivateKey<$ptype,$ltype,$ntype> for DSAPrivKey<$ptype,$ntype>
|
||||
{
|
||||
fn new(params: $ptype, x: $ntype) -> DSAPrivKey<$ptype,$ntype>
|
||||
{
|
||||
DSAPrivKey{ params, x }
|
||||
}
|
||||
|
||||
fn sign<Hash>(&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
|
||||
// straightforward description of how to do DSA signing.
|
||||
//
|
||||
// 1. H(m) is transformed into an integer modulo q using the bits2int
|
||||
// transform and an extra modular reduction:
|
||||
//
|
||||
// h = bits2int(H(m)) mod q
|
||||
//
|
||||
// As was noted in the description of bits2octets, the extra
|
||||
// modular reduction is no more than a conditional subtraction.
|
||||
//
|
||||
let h1 = <Hash>::digest(m);
|
||||
let n = $ptype::n_size();
|
||||
let h0: $ntype = bits2int(&h1, $ptype::n_size());
|
||||
let q = &self.params.q;
|
||||
let h = h0 % q;
|
||||
|
||||
// 2. A random value modulo q, dubbed k, is generated. That value
|
||||
// shall not be 0; hence, it lies in the [1, q-1] range. Most
|
||||
// of the remainder of this document will revolve around the
|
||||
// process used to generate k. In plain DSA or ECDSA, k should
|
||||
// be selected through a random selection that chooses a value
|
||||
// among the q-1 possible values with uniform probability.
|
||||
for k in KIterator::<Hash,$ntype>::new(&h1, n, q, &self.x) {
|
||||
// 3. A value r (modulo q) is computed from k and the key
|
||||
// parameters:
|
||||
// * For DSA:
|
||||
// r = g^k mod p mod q
|
||||
//
|
||||
// (The exponentiation is performed modulo p, yielding a
|
||||
// number between 0 and p-1, which is then further reduced
|
||||
// modulo q.)
|
||||
// * For ECDSA ...
|
||||
//
|
||||
// If r turns out to be zero, a new k should be selected and r
|
||||
// computed again (this is an utterly improbable occurrence).
|
||||
let bigk = $ltype::from(&k);
|
||||
let bigr = self.params.g.modexp(&bigk, &self.params.p) % $ltype::from(q);
|
||||
if bigr.is_zero() {
|
||||
continue;
|
||||
}
|
||||
let r = $ntype::from(bigr);
|
||||
// 4. The value s (modulo q) is computed:
|
||||
//
|
||||
// s = (h+x*r)/k mod q
|
||||
//
|
||||
// The pair (r, s) is the signature.
|
||||
if let Some(kinv) = k.modinv(&q) {
|
||||
let xr = &self.x * &r;
|
||||
let top = xr + $big::from(&h);
|
||||
let left = top * $bigger::from(kinv);
|
||||
let bigs = left % $biggest::from(q);
|
||||
return DSASignature::new(r, $ntype::from(bigs));
|
||||
}
|
||||
}
|
||||
panic!("The world is broken; couldn't find a k in sign().");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
privkey_impls!(L1024N160, U1024, U192, U384, U448, U896);
|
||||
privkey_impls!(L2048N224, U2048, U256, U512, U576, U1152);
|
||||
privkey_impls!(L2048N256, U2048, U256, U512, U576, U1152);
|
||||
privkey_impls!(L3072N256, U3072, U256, U512, U576, U1152);
|
||||
87
src/dsa/public.rs
Normal file
87
src/dsa/public.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
use cryptonum::unsigned::*;
|
||||
use cryptonum::signed::ModInv;
|
||||
use digest::Digest;
|
||||
use dsa::params::*;
|
||||
use dsa::rfc6979::DSASignature;
|
||||
use num::BigInt;
|
||||
use simple_asn1::{ToASN1,ASN1Block,ASN1Class,ASN1EncodeErr};
|
||||
use std::cmp::min;
|
||||
use utils::TranslateNums;
|
||||
|
||||
pub trait DSAPublicKey<Params,L,N> {
|
||||
/// Generate a new public key given the parameters and public value.
|
||||
fn new(params: Params, y: L) -> Self;
|
||||
/// Verify the given signature against the given message, using the
|
||||
/// appropriate hash function.
|
||||
fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<N>) -> bool
|
||||
where Hash: Digest;
|
||||
}
|
||||
|
||||
pub struct DSAPubKey<Params,L> {
|
||||
pub(crate) params: Params,
|
||||
pub(crate) y: L
|
||||
}
|
||||
|
||||
macro_rules! pubkey_impls {
|
||||
($ptype: ident, $ltype: ident, $ntype: ident, $dbl: ident, $bdbl: ident) => {
|
||||
impl DSAPublicKey<$ptype,$ltype,$ntype> for DSAPubKey<$ptype,$ltype>
|
||||
{
|
||||
fn new(params: $ptype, y: $ltype) -> DSAPubKey<$ptype,$ltype>
|
||||
{
|
||||
DSAPubKey{ params, y }
|
||||
}
|
||||
|
||||
fn verify<Hash>(&self, m: &[u8], sig: &DSASignature<$ntype>) -> bool
|
||||
where Hash: Digest
|
||||
{
|
||||
if sig.r >= self.params.q {
|
||||
return false;
|
||||
}
|
||||
if sig.s >= self.params.q {
|
||||
return false;
|
||||
}
|
||||
// w = (s')^-1 mod q;
|
||||
if let Some(w) = sig.s.modinv(&self.params.q) {
|
||||
// z = the leftmost min(N, outlen) bits of Hash(M').
|
||||
let mut digest_bytes = <Hash>::digest(m).to_vec();
|
||||
let len = min(digest_bytes.len(), $ptype::n_size() / 8);
|
||||
digest_bytes.truncate(len);
|
||||
let z = $ntype::from_bytes(&digest_bytes);
|
||||
// u1 = (zw) mod q
|
||||
let qdbl = $dbl::from(&self.params.q);
|
||||
let u1 = $ltype::from( (&z * &w) % &qdbl );
|
||||
// u2 = (rw) mod q
|
||||
let u2 = $ltype::from( (&sig.r * &w) % &qdbl );
|
||||
// v = (((g)^u1(y)^u2) mod p) mod q
|
||||
let v_1 = self.params.g.modexp(&u1, &self.params.p);
|
||||
let v_2 = self.y.modexp(&u2, &self.params.p);
|
||||
let bigp = $bdbl::from(&self.params.p);
|
||||
let v_first_mod = (v_1 * v_2) % bigp;
|
||||
let v = $ltype::from(v_first_mod) % $ltype::from(&self.params.q);
|
||||
// if v = r, then the signature is verified
|
||||
return $ntype::from(v) == sig.r
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl ToASN1 for DSAPubKey<$ptype,$ltype> {
|
||||
type Error = ASN1EncodeErr;
|
||||
|
||||
fn to_asn1_class(&self, c: ASN1Class)
|
||||
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
|
||||
{
|
||||
let uinty = self.y.to_num();
|
||||
let inty = BigInt::from(uinty);
|
||||
let yblock = ASN1Block::Integer(c, 0, inty);
|
||||
Ok(vec![yblock])
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pubkey_impls!(L1024N160, U1024, U192, U384, U2048);
|
||||
pubkey_impls!(L2048N224, U2048, U256, U512, U4096);
|
||||
pubkey_impls!(L2048N256, U2048, U256, U512, U4096);
|
||||
pubkey_impls!(L3072N256, U3072, U256, U512, U6144);
|
||||
365
src/dsa/rfc6979.rs
Normal file
365
src/dsa/rfc6979.rs
Normal file
@@ -0,0 +1,365 @@
|
||||
use cryptonum::unsigned::{CryptoNum,Decoder,Encoder,U512};
|
||||
use digest::{BlockInput,Digest,FixedOutput,Input,Reset};
|
||||
use digest::generic_array::ArrayLength;
|
||||
use hmac::{Hmac,Mac};
|
||||
use num::BigInt;
|
||||
use simple_asn1::{ASN1Block,ASN1Class,ASN1DecodeErr,ASN1EncodeErr};
|
||||
use simple_asn1::{FromASN1,ToASN1};
|
||||
use utils::TranslateNums;
|
||||
|
||||
#[derive(Debug,PartialEq)]
|
||||
pub struct DSASignature<N>
|
||||
{
|
||||
pub r: N,
|
||||
pub s: N
|
||||
}
|
||||
|
||||
impl<N> DSASignature<N>
|
||||
{
|
||||
pub fn new(r: N, s: N) -> DSASignature<N>
|
||||
{
|
||||
DSASignature{ r, s }
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub struct KIterator<H,N>
|
||||
where
|
||||
H: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||
N: Clone + Encoder + From<U512> + PartialOrd,
|
||||
Hmac<H>: Mac,
|
||||
U512: From<N>
|
||||
{
|
||||
hmac_k: Hmac<H>,
|
||||
V: Vec<u8>,
|
||||
q: N,
|
||||
qlen: usize
|
||||
}
|
||||
|
||||
impl<H,N> KIterator<H,N>
|
||||
where
|
||||
H: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||
N: Clone + Encoder + From<U512> + PartialOrd,
|
||||
Hmac<H>: Mac,
|
||||
U512: From<N>
|
||||
{
|
||||
pub fn new(h1: &[u8], qlen: usize, q: &N, x: &N) -> KIterator<H,N>
|
||||
{
|
||||
// Given the input message m, the following process is applied:
|
||||
//
|
||||
// a. Process m through the hash function H, yielding:
|
||||
//
|
||||
// h1 = H(m)
|
||||
//
|
||||
// (h1 is a sequence of hlen bits).
|
||||
//
|
||||
let hlen = h1.len();
|
||||
// b. Set:
|
||||
//
|
||||
// V = 0x01 0x01 0x01 ... 0x01
|
||||
//
|
||||
// such that the length of V, in bits, is equal to 8*ceil(hlen/8).
|
||||
// For instance, on an octet-based system, if H is SHA-256, then
|
||||
// V is set to a sequence of 32 octets of value 1. Note that in
|
||||
// this step and all subsequent steps, we use the same H function
|
||||
// as the one used in step 'a' to process the input message; this
|
||||
// choice will be discussed in more detail in Section 3.6.
|
||||
//
|
||||
#[allow(non_snake_case)]
|
||||
let mut V = Vec::new();
|
||||
V.resize(hlen, 0x01);
|
||||
// c. Set:
|
||||
//
|
||||
// K = 0x00 0x00 0x00 ... 0x00
|
||||
//
|
||||
// such that the length of K, in bits, is equal to 8*ceil(hlen/8).
|
||||
#[allow(non_snake_case)]
|
||||
let mut K = Vec::new();
|
||||
K.resize(hlen, 0x00);
|
||||
// d. Set:
|
||||
//
|
||||
// K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1))
|
||||
//
|
||||
// where '||' denotes concatenation. In other words, we compute
|
||||
// HMAC with key K, over the concatenation of the following, in
|
||||
// order: the current value of V, a sequence of eight bits of value
|
||||
// 0, the encoding of the (EC)DSA private key x, and the hashed
|
||||
// message (possibly truncated and extended as specified by the
|
||||
// bits2octets transform). The HMAC result is the new value of K.
|
||||
// Note that the private key x is in the [1, q-1] range, hence a
|
||||
// proper input for int2octets, yielding rlen bits of output, i.e.,
|
||||
// an integral number of octets (rlen is a multiple of 8).
|
||||
let xbytes = int2octets(x, qlen);
|
||||
let h1bytes = bits2octets(h1, q, qlen);
|
||||
let mut input = Vec::new();
|
||||
input.extend_from_slice(&V);
|
||||
input.push(0x00);
|
||||
input.extend_from_slice(&xbytes);
|
||||
input.extend_from_slice(&h1bytes);
|
||||
K = hmac(&K, &input);
|
||||
// e. Set:
|
||||
//
|
||||
// V = HMAC_K(V)
|
||||
V = hmac(&K, &V);
|
||||
// f. Set:
|
||||
//
|
||||
// K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1))
|
||||
//
|
||||
// Note that the "internal octet" is 0x01 this time.
|
||||
input = Vec::new();
|
||||
input.extend_from_slice(&V);
|
||||
input.push(0x01);
|
||||
input.extend_from_slice(&xbytes);
|
||||
input.extend_from_slice(&h1bytes);
|
||||
K = hmac(&K, &input);
|
||||
// g. Set:
|
||||
//
|
||||
// V = HMAC_K(V)
|
||||
V = hmac(&K, &V);
|
||||
// h is for later ...
|
||||
KIterator {
|
||||
hmac_k: Hmac::<H>::new_varkey(&K).unwrap(),
|
||||
V: V,
|
||||
q: q.clone(),
|
||||
qlen: qlen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<H,N> Iterator for KIterator<H,N>
|
||||
where
|
||||
H: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||
N: Clone + CryptoNum + Encoder + From<U512> + PartialOrd,
|
||||
Hmac<H>: Mac,
|
||||
U512: From<N>
|
||||
{
|
||||
type Item = N;
|
||||
|
||||
fn next(&mut self) -> Option<N>
|
||||
{
|
||||
loop {
|
||||
// h. Apply the following algorithm until a proper value is found
|
||||
// for k:
|
||||
//
|
||||
// 1. Set T to the empty sequence. The length of T (in bits) is
|
||||
// denoted tlen; thus, at that point, tlen = 0.
|
||||
let mut t = Vec::new();
|
||||
//
|
||||
// 2. While tlen < qlen, do the following:
|
||||
//
|
||||
// V = HMAC_K(V)
|
||||
// T = T || V
|
||||
let target = (self.qlen + 7) / 8;
|
||||
while t.len() < target {
|
||||
self.V = runhmac(&self.hmac_k, &self.V);
|
||||
t.extend_from_slice(&self.V);
|
||||
}
|
||||
//
|
||||
// 3. Compute:
|
||||
//
|
||||
// k = bits2int(T)
|
||||
let resk: N = bits2int(&t, self.qlen);
|
||||
//
|
||||
// If that value of k is within the [1,q-1] range, and is
|
||||
// suitable for DSA or ECDSA (i.e., it results in an r value
|
||||
// that is not 0; see Section 3.4), then the generation of k
|
||||
// is finished. The obtained value of k is used in DSA or
|
||||
// ECDSA. Otherwise, compute:
|
||||
//
|
||||
// K = HMAC_K(V || 0x00)
|
||||
let mut input = self.V.clone();
|
||||
input.push(0x00);
|
||||
#[allow(non_snake_case)]
|
||||
let K = runhmac(&self.hmac_k, &input);
|
||||
// V = HMAC_K(V)
|
||||
self.hmac_k = Hmac::<H>::new_varkey(&K).unwrap();
|
||||
self.V = runhmac(&self.hmac_k, &self.V);
|
||||
//
|
||||
// and loop (try to generate a new T, and so on).
|
||||
//
|
||||
if !resk.is_zero() && (resk < self.q) {
|
||||
return Some(resk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bits2int<X: From<U512>>(x: &[u8], qlen: usize) -> X
|
||||
{
|
||||
let mut value = U512::from_bytes(x);
|
||||
let vlen = x.len() * 8;
|
||||
|
||||
if vlen > qlen {
|
||||
value >>= vlen - qlen;
|
||||
}
|
||||
|
||||
X::from(value)
|
||||
}
|
||||
|
||||
fn bits2octets<X>(x: &[u8], q: &X, qlen: usize) -> Vec<u8>
|
||||
where
|
||||
X: Clone + From<U512>,
|
||||
U512: From<X>
|
||||
{
|
||||
let z1: U512 = bits2int(x, qlen);
|
||||
let qbig = U512::from(q.clone());
|
||||
let res = if z1 > qbig { z1 - qbig } else { z1 };
|
||||
int2octets(&res, qlen)
|
||||
}
|
||||
|
||||
fn int2octets<X>(x: &X, qlen_bits: usize) -> Vec<u8>
|
||||
where X: Encoder
|
||||
{
|
||||
let qlen_bytes = (qlen_bits + 7) / 8;
|
||||
let mut base = x.to_bytes();
|
||||
|
||||
while base.len() < qlen_bytes {
|
||||
base.insert(0,0);
|
||||
}
|
||||
|
||||
while base.len() > qlen_bytes {
|
||||
base.remove(0);
|
||||
}
|
||||
|
||||
base
|
||||
}
|
||||
|
||||
fn runhmac<H>(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();
|
||||
runner.input(&m);
|
||||
runner.result().code().as_slice().to_vec()
|
||||
}
|
||||
|
||||
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)]
|
||||
pub enum DSADecodeError {
|
||||
ASN1Error(ASN1DecodeErr),
|
||||
NoSignatureFound,
|
||||
NegativeSigValues,
|
||||
RValueTooBig, SValueTooBig
|
||||
}
|
||||
|
||||
impl From<ASN1DecodeErr> for DSADecodeError {
|
||||
fn from(a: ASN1DecodeErr) -> DSADecodeError {
|
||||
DSADecodeError::ASN1Error(a)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> FromASN1 for DSASignature<N>
|
||||
where N: TranslateNums
|
||||
{
|
||||
type Error = DSADecodeError;
|
||||
|
||||
fn from_asn1(v: &[ASN1Block])
|
||||
-> Result<(DSASignature<N>,&[ASN1Block]),DSADecodeError>
|
||||
{
|
||||
match v.split_first() {
|
||||
Some((&ASN1Block::Sequence(_,_,ref info), rest))
|
||||
if info.len() == 2 =>
|
||||
{
|
||||
match (&info[0], &info[1]) {
|
||||
(&ASN1Block::Integer(_,_,ref rint),
|
||||
&ASN1Block::Integer(_,_,ref sint)) => {
|
||||
match (rint.to_biguint(), sint.to_biguint()) {
|
||||
(Some(rnum), Some(snum)) => {
|
||||
let r = N::from_num(rnum).ok_or(DSADecodeError::RValueTooBig)?;
|
||||
let s = N::from_num(snum).ok_or(DSADecodeError::SValueTooBig)?;
|
||||
Ok((DSASignature{ r, s }, rest))
|
||||
|
||||
}
|
||||
_ =>
|
||||
Err(DSADecodeError::NegativeSigValues)
|
||||
}
|
||||
}
|
||||
_ => Err(DSADecodeError::NoSignatureFound)
|
||||
}
|
||||
}
|
||||
_ => Err(DSADecodeError::NoSignatureFound)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> ToASN1 for DSASignature<N>
|
||||
where N: TranslateNums
|
||||
{
|
||||
type Error = ASN1EncodeErr;
|
||||
|
||||
fn to_asn1_class(&self, c: ASN1Class)
|
||||
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
|
||||
{
|
||||
let rb = ASN1Block::Integer(c, 0, BigInt::from(self.r.to_num()));
|
||||
let sb = ASN1Block::Integer(c, 0, BigInt::from(self.s.to_num()));
|
||||
Ok(vec![ASN1Block::Sequence(c, 0, vec![rb,sb])])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use cryptonum::unsigned::U192;
|
||||
use sha2::Sha256;
|
||||
use super::*;
|
||||
|
||||
const QBYTES: [u8; 21] = [0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x02, 0x01, 0x08, 0xA2, 0xE0, 0xCC,
|
||||
0x0D, 0x99, 0xF8, 0xA5, 0xEF];
|
||||
const XBYTES: [u8; 21] = [0x00, 0x9A, 0x4D, 0x67, 0x92, 0x29, 0x5A, 0x7F,
|
||||
0x73, 0x0F, 0xC3, 0xF2, 0xB4, 0x9C, 0xBC, 0x0F,
|
||||
0x62, 0xE8, 0x62, 0x27, 0x2F];
|
||||
const H1: [u8; 32] = [0xAF, 0x2B, 0xDB, 0xE1, 0xAA, 0x9B, 0x6E, 0xC1,
|
||||
0xE2, 0xAD, 0xE1, 0xD6, 0x94, 0xF4, 0x1F, 0xC7,
|
||||
0x1A, 0x83, 0x1D, 0x02, 0x68, 0xE9, 0x89, 0x15,
|
||||
0x62, 0x11, 0x3D, 0x8A, 0x62, 0xAD, 0xD1, 0xBF];
|
||||
|
||||
#[test]
|
||||
fn int2octets_example() {
|
||||
let x = U192::from_bytes(&XBYTES);
|
||||
let octets = int2octets(&x, 163);
|
||||
let target = vec![0x00, 0x9A, 0x4D, 0x67, 0x92, 0x29, 0x5A, 0x7F,
|
||||
0x73, 0x0F, 0xC3, 0xF2, 0xB4, 0x9C, 0xBC, 0x0F,
|
||||
0x62, 0xE8, 0x62, 0x27, 0x2F];
|
||||
assert_eq!(octets, target);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bits2octets_example() {
|
||||
let q = U192::from_bytes(&QBYTES);
|
||||
let octets = bits2octets(&H1, &q, 163);
|
||||
let target = vec![0x01, 0x79, 0x5E, 0xDF, 0x0D, 0x54, 0xDB, 0x76,
|
||||
0x0F, 0x15, 0x6D, 0x0D, 0xAC, 0x04, 0xC0, 0x32,
|
||||
0x2B, 0x3A, 0x20, 0x42, 0x24];
|
||||
assert_eq!(octets, target);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn k_gen_example() {
|
||||
let q = U192::from_bytes(&QBYTES);
|
||||
let x = U192::from_bytes(&XBYTES);
|
||||
let mut iter = KIterator::<Sha256,U192>::new(&H1, 163, &q, &x);
|
||||
match iter.next() {
|
||||
None =>
|
||||
assert!(false),
|
||||
Some(x) => {
|
||||
let target = vec![0x02, 0x3A, 0xF4, 0x07, 0x4C, 0x90, 0xA0,
|
||||
0x2B, 0x3F, 0xE6, 0x1D, 0x28, 0x6D, 0x5C,
|
||||
0x87, 0xF4, 0x25, 0xE6, 0xBD, 0xD8, 0x1B];
|
||||
let x2 = U192::from_bytes(&target);
|
||||
assert_eq!(x, x2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
536
src/dsa/tests.rs
Normal file
536
src/dsa/tests.rs
Normal file
@@ -0,0 +1,536 @@
|
||||
use digest::Digest;
|
||||
use sha1::Sha1;
|
||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
||||
use simple_asn1::{der_decode,der_encode};
|
||||
use super::*;
|
||||
use dsa::rfc6979::KIterator;
|
||||
|
||||
macro_rules! run_rfc6979_test {
|
||||
($hash: ty, $ntype: ident, $val: ident, $public: ident, $private: ident,
|
||||
k $k: expr,
|
||||
r $r: expr,
|
||||
s $s: expr) => ({
|
||||
let h1 = <$hash>::digest(&$val);
|
||||
let rbytes = $r;
|
||||
let sbytes = $s;
|
||||
let r = $ntype::from_bytes(&rbytes);
|
||||
let s = $ntype::from_bytes(&sbytes);
|
||||
let mut iter = KIterator::<$hash,$ntype>::new(&h1, $public.params.n_bits(),
|
||||
&$public.params.q,
|
||||
&$private.x);
|
||||
let mut k1 = iter.next().unwrap().to_bytes().to_vec();
|
||||
while k1.len() > $k.len() {
|
||||
assert_eq!(k1[0], 0);
|
||||
k1.remove(0);
|
||||
}
|
||||
assert_eq!($k, k1);
|
||||
let sig = $private.sign::<$hash>(&$val);
|
||||
assert_eq!(sig.r, r);
|
||||
assert_eq!(sig.s, s);
|
||||
assert!($public.verify::<$hash>(&$val, &sig));
|
||||
let blocks = der_encode(&sig).unwrap();
|
||||
let sig2 = der_decode(&blocks).unwrap();
|
||||
assert_eq!(sig, sig2);
|
||||
})
|
||||
}
|
||||
|
||||
// these appendix_* tests are out of RFC6979
|
||||
#[test]
|
||||
fn appendix_a21() {
|
||||
let pbytes = vec![0x86, 0xF5, 0xCA, 0x03, 0xDC, 0xFE, 0xB2, 0x25,
|
||||
0x06, 0x3F, 0xF8, 0x30, 0xA0, 0xC7, 0x69, 0xB9,
|
||||
0xDD, 0x9D, 0x61, 0x53, 0xAD, 0x91, 0xD7, 0xCE,
|
||||
0x27, 0xF7, 0x87, 0xC4, 0x32, 0x78, 0xB4, 0x47,
|
||||
0xE6, 0x53, 0x3B, 0x86, 0xB1, 0x8B, 0xED, 0x6E,
|
||||
0x8A, 0x48, 0xB7, 0x84, 0xA1, 0x4C, 0x25, 0x2C,
|
||||
0x5B, 0xE0, 0xDB, 0xF6, 0x0B, 0x86, 0xD6, 0x38,
|
||||
0x5B, 0xD2, 0xF1, 0x2F, 0xB7, 0x63, 0xED, 0x88,
|
||||
0x73, 0xAB, 0xFD, 0x3F, 0x5B, 0xA2, 0xE0, 0xA8,
|
||||
0xC0, 0xA5, 0x90, 0x82, 0xEA, 0xC0, 0x56, 0x93,
|
||||
0x5E, 0x52, 0x9D, 0xAF, 0x7C, 0x61, 0x04, 0x67,
|
||||
0x89, 0x9C, 0x77, 0xAD, 0xED, 0xFC, 0x84, 0x6C,
|
||||
0x88, 0x18, 0x70, 0xB7, 0xB1, 0x9B, 0x2B, 0x58,
|
||||
0xF9, 0xBE, 0x05, 0x21, 0xA1, 0x70, 0x02, 0xE3,
|
||||
0xBD, 0xD6, 0xB8, 0x66, 0x85, 0xEE, 0x90, 0xB3,
|
||||
0xD9, 0xA1, 0xB0, 0x2B, 0x78, 0x2B, 0x17, 0x79];
|
||||
let qbytes = vec![0x99, 0x6F, 0x96, 0x7F, 0x6C, 0x8E, 0x38, 0x8D,
|
||||
0x9E, 0x28, 0xD0, 0x1E, 0x20, 0x5F, 0xBA, 0x95,
|
||||
0x7A, 0x56, 0x98, 0xB1];
|
||||
let gbytes = vec![0x07, 0xB0, 0xF9, 0x25, 0x46, 0x15, 0x0B, 0x62,
|
||||
0x51, 0x4B, 0xB7, 0x71, 0xE2, 0xA0, 0xC0, 0xCE,
|
||||
0x38, 0x7F, 0x03, 0xBD, 0xA6, 0xC5, 0x6B, 0x50,
|
||||
0x52, 0x09, 0xFF, 0x25, 0xFD, 0x3C, 0x13, 0x3D,
|
||||
0x89, 0xBB, 0xCD, 0x97, 0xE9, 0x04, 0xE0, 0x91,
|
||||
0x14, 0xD9, 0xA7, 0xDE, 0xFD, 0xEA, 0xDF, 0xC9,
|
||||
0x07, 0x8E, 0xA5, 0x44, 0xD2, 0xE4, 0x01, 0xAE,
|
||||
0xEC, 0xC4, 0x0B, 0xB9, 0xFB, 0xBF, 0x78, 0xFD,
|
||||
0x87, 0x99, 0x5A, 0x10, 0xA1, 0xC2, 0x7C, 0xB7,
|
||||
0x78, 0x9B, 0x59, 0x4B, 0xA7, 0xEF, 0xB5, 0xC4,
|
||||
0x32, 0x6A, 0x9F, 0xE5, 0x9A, 0x07, 0x0E, 0x13,
|
||||
0x6D, 0xB7, 0x71, 0x75, 0x46, 0x4A, 0xDC, 0xA4,
|
||||
0x17, 0xBE, 0x5D, 0xCE, 0x2F, 0x40, 0xD1, 0x0A,
|
||||
0x46, 0xA3, 0xA3, 0x94, 0x3F, 0x26, 0xAB, 0x7F,
|
||||
0xD9, 0xC0, 0x39, 0x8F, 0xF8, 0xC7, 0x6E, 0xE0,
|
||||
0xA5, 0x68, 0x26, 0xA8, 0xA8, 0x8F, 0x1D, 0xBD];
|
||||
let xbytes = vec![0x41, 0x16, 0x02, 0xCB, 0x19, 0xA6, 0xCC, 0xC3,
|
||||
0x44, 0x94, 0xD7, 0x9D, 0x98, 0xEF, 0x1E, 0x7E,
|
||||
0xD5, 0xAF, 0x25, 0xF7];
|
||||
let ybytes = vec![0x5D, 0xF5, 0xE0, 0x1D, 0xED, 0x31, 0xD0, 0x29,
|
||||
0x7E, 0x27, 0x4E, 0x16, 0x91, 0xC1, 0x92, 0xFE,
|
||||
0x58, 0x68, 0xFE, 0xF9, 0xE1, 0x9A, 0x84, 0x77,
|
||||
0x64, 0x54, 0xB1, 0x00, 0xCF, 0x16, 0xF6, 0x53,
|
||||
0x92, 0x19, 0x5A, 0x38, 0xB9, 0x05, 0x23, 0xE2,
|
||||
0x54, 0x2E, 0xE6, 0x18, 0x71, 0xC0, 0x44, 0x0C,
|
||||
0xB8, 0x7C, 0x32, 0x2F, 0xC4, 0xB4, 0xD2, 0xEC,
|
||||
0x5E, 0x1E, 0x7E, 0xC7, 0x66, 0xE1, 0xBE, 0x8D,
|
||||
0x4C, 0xE9, 0x35, 0x43, 0x7D, 0xC1, 0x1C, 0x3C,
|
||||
0x8F, 0xD4, 0x26, 0x33, 0x89, 0x33, 0xEB, 0xFE,
|
||||
0x73, 0x9C, 0xB3, 0x46, 0x5F, 0x4D, 0x36, 0x68,
|
||||
0xC5, 0xE4, 0x73, 0x50, 0x82, 0x53, 0xB1, 0xE6,
|
||||
0x82, 0xF6, 0x5C, 0xBD, 0xC4, 0xFA, 0xE9, 0x3C,
|
||||
0x2E, 0xA2, 0x12, 0x39, 0x0E, 0x54, 0x90, 0x5A,
|
||||
0x86, 0xE2, 0x22, 0x31, 0x70, 0xB4, 0x4E, 0xAA,
|
||||
0x7D, 0xA5, 0xDD, 0x9F, 0xFC, 0xFB, 0x7F, 0x3B];
|
||||
//
|
||||
let p = U1024::from_bytes(&pbytes);
|
||||
let q = U192::from_bytes(&qbytes);
|
||||
let g = U1024::from_bytes(&gbytes);
|
||||
let params = L1024N160::new(p, g, q);
|
||||
let x = U192::from_bytes(&xbytes);
|
||||
let y = U1024::from_bytes(&ybytes);
|
||||
let private = DSAPrivKey::<L1024N160,U192>::new(params.clone(), x);
|
||||
let public = DSAPubKey::<L1024N160,U1024>::new(params.clone(), y);
|
||||
//
|
||||
let sample: [u8; 6] = [115, 97, 109, 112, 108, 101]; // "sample", ASCII
|
||||
let test: [u8; 4] = [116, 101, 115, 116]; // "test", ASCII
|
||||
// With SHA-1, message = "sample":
|
||||
// k = 7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B
|
||||
// r = 2E1A0C2562B2912CAAF89186FB0F42001585DA55
|
||||
// s = 29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5
|
||||
run_rfc6979_test!(Sha1, U192, sample, public, private,
|
||||
k vec![0x7B, 0xDB, 0x6B, 0x0F, 0xF7, 0x56, 0xE1, 0xBB,
|
||||
0x5D, 0x53, 0x58, 0x3E, 0xF9, 0x79, 0x08, 0x2F,
|
||||
0x9A, 0xD5, 0xBD, 0x5B],
|
||||
r vec![0x2E, 0x1A, 0x0C, 0x25, 0x62, 0xB2, 0x91, 0x2C,
|
||||
0xAA, 0xF8, 0x91, 0x86, 0xFB, 0x0F, 0x42, 0x00,
|
||||
0x15, 0x85, 0xDA, 0x55],
|
||||
s vec![0x29, 0xEF, 0xB6, 0xB0, 0xAF, 0xF2, 0xD7, 0xA6,
|
||||
0x8E, 0xB7, 0x0C, 0xA3, 0x13, 0x02, 0x22, 0x53,
|
||||
0xB9, 0xA8, 0x8D, 0xF5]);
|
||||
// With SHA-224, message = "sample":
|
||||
// k = 562097C06782D60C3037BA7BE104774344687649
|
||||
// r = 4BC3B686AEA70145856814A6F1BB53346F02101E
|
||||
// s = 410697B92295D994D21EDD2F4ADA85566F6F94C1
|
||||
run_rfc6979_test!(Sha224, U192, sample, public, private,
|
||||
k vec![0x56, 0x20, 0x97, 0xC0, 0x67, 0x82, 0xD6, 0x0C,
|
||||
0x30, 0x37, 0xBA, 0x7B, 0xE1, 0x04, 0x77, 0x43,
|
||||
0x44, 0x68, 0x76, 0x49],
|
||||
r vec![0x4B, 0xC3, 0xB6, 0x86, 0xAE, 0xA7, 0x01, 0x45,
|
||||
0x85, 0x68, 0x14, 0xA6, 0xF1, 0xBB, 0x53, 0x34,
|
||||
0x6F, 0x02, 0x10, 0x1E],
|
||||
s vec![0x41, 0x06, 0x97, 0xB9, 0x22, 0x95, 0xD9, 0x94,
|
||||
0xD2, 0x1E, 0xDD, 0x2F, 0x4A, 0xDA, 0x85, 0x56,
|
||||
0x6F, 0x6F, 0x94, 0xC1]);
|
||||
// With SHA-256, message = "sample":
|
||||
// k = 519BA0546D0C39202A7D34D7DFA5E760B318BCFB
|
||||
// r = 81F2F5850BE5BC123C43F71A3033E9384611C545
|
||||
// s = 4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89
|
||||
run_rfc6979_test!(Sha256, U192, sample, public, private,
|
||||
k vec![0x51, 0x9B, 0xA0, 0x54, 0x6D, 0x0C, 0x39, 0x20,
|
||||
0x2A, 0x7D, 0x34, 0xD7, 0xDF, 0xA5, 0xE7, 0x60,
|
||||
0xB3, 0x18, 0xBC, 0xFB],
|
||||
r vec![0x81, 0xF2, 0xF5, 0x85, 0x0B, 0xE5, 0xBC, 0x12,
|
||||
0x3C, 0x43, 0xF7, 0x1A, 0x30, 0x33, 0xE9, 0x38,
|
||||
0x46, 0x11, 0xC5, 0x45],
|
||||
s vec![0x4C, 0xDD, 0x91, 0x4B, 0x65, 0xEB, 0x6C, 0x66,
|
||||
0xA8, 0xAA, 0xAD, 0x27, 0x29, 0x9B, 0xEE, 0x6B,
|
||||
0x03, 0x5F, 0x5E, 0x89]);
|
||||
// With SHA-384, message = "sample":
|
||||
// k = 95897CD7BBB944AA932DBC579C1C09EB6FCFC595
|
||||
// r = 07F2108557EE0E3921BC1774F1CA9B410B4CE65A
|
||||
// s = 54DF70456C86FAC10FAB47C1949AB83F2C6F7595
|
||||
run_rfc6979_test!(Sha384, U192, sample, public, private,
|
||||
k vec![0x95, 0x89, 0x7C, 0xD7, 0xBB, 0xB9, 0x44, 0xAA,
|
||||
0x93, 0x2D, 0xBC, 0x57, 0x9C, 0x1C, 0x09, 0xEB,
|
||||
0x6F, 0xCF, 0xC5, 0x95],
|
||||
r vec![0x07, 0xF2, 0x10, 0x85, 0x57, 0xEE, 0x0E, 0x39,
|
||||
0x21, 0xBC, 0x17, 0x74, 0xF1, 0xCA, 0x9B, 0x41,
|
||||
0x0B, 0x4C, 0xE6, 0x5A],
|
||||
s vec![0x54, 0xDF, 0x70, 0x45, 0x6C, 0x86, 0xFA, 0xC1,
|
||||
0x0F, 0xAB, 0x47, 0xC1, 0x94, 0x9A, 0xB8, 0x3F,
|
||||
0x2C, 0x6F, 0x75, 0x95]);
|
||||
// With SHA-512, message = "sample":
|
||||
// k = 09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B
|
||||
// r = 16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B
|
||||
// s = 02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C
|
||||
run_rfc6979_test!(Sha512, U192, sample, public, private,
|
||||
k vec![0x09, 0xEC, 0xE7, 0xCA, 0x27, 0xD0, 0xF5, 0xA4,
|
||||
0xDD, 0x4E, 0x55, 0x6C, 0x9D, 0xF1, 0xD2, 0x1D,
|
||||
0x28, 0x10, 0x4F, 0x8B],
|
||||
r vec![0x16, 0xC3, 0x49, 0x1F, 0x9B, 0x8C, 0x3F, 0xBB,
|
||||
0xDD, 0x5E, 0x7A, 0x7B, 0x66, 0x70, 0x57, 0xF0,
|
||||
0xD8, 0xEE, 0x8E, 0x1B],
|
||||
s vec![0x02, 0xC3, 0x6A, 0x12, 0x7A, 0x7B, 0x89, 0xED,
|
||||
0xBB, 0x72, 0xE4, 0xFF, 0xBC, 0x71, 0xDA, 0xBC,
|
||||
0x7D, 0x4F, 0xC6, 0x9C]);
|
||||
// With SHA-1, message = "test":
|
||||
// k = 5C842DF4F9E344EE09F056838B42C7A17F4A6433
|
||||
// r = 42AB2052FD43E123F0607F115052A67DCD9C5C77
|
||||
// s = 183916B0230D45B9931491D4C6B0BD2FB4AAF088
|
||||
run_rfc6979_test!(Sha1, U192, test, public, private,
|
||||
k vec![0x5C, 0x84, 0x2D, 0xF4, 0xF9, 0xE3, 0x44, 0xEE,
|
||||
0x09, 0xF0, 0x56, 0x83, 0x8B, 0x42, 0xC7, 0xA1,
|
||||
0x7F, 0x4A, 0x64, 0x33],
|
||||
r vec![0x42, 0xAB, 0x20, 0x52, 0xFD, 0x43, 0xE1, 0x23,
|
||||
0xF0, 0x60, 0x7F, 0x11, 0x50, 0x52, 0xA6, 0x7D,
|
||||
0xCD, 0x9C, 0x5C, 0x77],
|
||||
s vec![0x18, 0x39, 0x16, 0xB0, 0x23, 0x0D, 0x45, 0xB9,
|
||||
0x93, 0x14, 0x91, 0xD4, 0xC6, 0xB0, 0xBD, 0x2F,
|
||||
0xB4, 0xAA, 0xF0, 0x88]);
|
||||
// With SHA-224, message = "test":
|
||||
// k = 4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297
|
||||
// r = 6868E9964E36C1689F6037F91F28D5F2C30610F2
|
||||
// s = 49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F
|
||||
run_rfc6979_test!(Sha224, U192, test, public, private,
|
||||
k vec![0x45, 0x98, 0xB8, 0xEF, 0xC1, 0xA5, 0x3B, 0xC8,
|
||||
0xAE, 0xCD, 0x58, 0xD1, 0xAB, 0xBB, 0x0C, 0x0C,
|
||||
0x71, 0xE6, 0x72, 0x97],
|
||||
r vec![0x68, 0x68, 0xE9, 0x96, 0x4E, 0x36, 0xC1, 0x68,
|
||||
0x9F, 0x60, 0x37, 0xF9, 0x1F, 0x28, 0xD5, 0xF2,
|
||||
0xC3, 0x06, 0x10, 0xF2],
|
||||
s vec![0x49, 0xCE, 0xC3, 0xAC, 0xDC, 0x83, 0x01, 0x8C,
|
||||
0x5B, 0xD2, 0x67, 0x4E, 0xCA, 0xAD, 0x35, 0xB8,
|
||||
0xCD, 0x22, 0x94, 0x0F]);
|
||||
// With SHA-256, message = "test":
|
||||
// k = 5A67592E8128E03A417B0484410FB72C0B630E1A
|
||||
// r = 22518C127299B0F6FDC9872B282B9E70D0790812
|
||||
// s = 6837EC18F150D55DE95B5E29BE7AF5D01E4FE160
|
||||
run_rfc6979_test!(Sha256, U192, test, public, private,
|
||||
k vec![0x5A, 0x67, 0x59, 0x2E, 0x81, 0x28, 0xE0, 0x3A,
|
||||
0x41, 0x7B, 0x04, 0x84, 0x41, 0x0F, 0xB7, 0x2C,
|
||||
0x0B, 0x63, 0x0E, 0x1A],
|
||||
r vec![0x22, 0x51, 0x8C, 0x12, 0x72, 0x99, 0xB0, 0xF6,
|
||||
0xFD, 0xC9, 0x87, 0x2B, 0x28, 0x2B, 0x9E, 0x70,
|
||||
0xD0, 0x79, 0x08, 0x12],
|
||||
s vec![0x68, 0x37, 0xEC, 0x18, 0xF1, 0x50, 0xD5, 0x5D,
|
||||
0xE9, 0x5B, 0x5E, 0x29, 0xBE, 0x7A, 0xF5, 0xD0,
|
||||
0x1E, 0x4F, 0xE1, 0x60]);
|
||||
// With SHA-384, message = "test":
|
||||
// k = 220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89
|
||||
// r = 854CF929B58D73C3CBFDC421E8D5430CD6DB5E66
|
||||
// s = 91D0E0F53E22F898D158380676A871A157CDA622
|
||||
run_rfc6979_test!(Sha384, U192, test, public, private,
|
||||
k vec![0x22, 0x01, 0x56, 0xB7, 0x61, 0xF6, 0xCA, 0x5E,
|
||||
0x6C, 0x9F, 0x1B, 0x9C, 0xF9, 0xC2, 0x4B, 0xE2,
|
||||
0x5F, 0x98, 0xCD, 0x89],
|
||||
r vec![0x85, 0x4C, 0xF9, 0x29, 0xB5, 0x8D, 0x73, 0xC3,
|
||||
0xCB, 0xFD, 0xC4, 0x21, 0xE8, 0xD5, 0x43, 0x0C,
|
||||
0xD6, 0xDB, 0x5E, 0x66],
|
||||
s vec![0x91, 0xD0, 0xE0, 0xF5, 0x3E, 0x22, 0xF8, 0x98,
|
||||
0xD1, 0x58, 0x38, 0x06, 0x76, 0xA8, 0x71, 0xA1,
|
||||
0x57, 0xCD, 0xA6, 0x22]);
|
||||
// With SHA-512, message = "test":
|
||||
// k = 65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C
|
||||
// r = 8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0
|
||||
// s = 7C670C7AD72B6C050C109E1790008097125433E8
|
||||
run_rfc6979_test!(Sha512, U192, test, public, private,
|
||||
k vec![0x65, 0xD2, 0xC2, 0xEE, 0xB1, 0x75, 0xE3, 0x70,
|
||||
0xF2, 0x8C, 0x75, 0xBF, 0xCD, 0xC0, 0x28, 0xD2,
|
||||
0x2C, 0x7D, 0xBE, 0x9C],
|
||||
r vec![0x8E, 0xA4, 0x7E, 0x47, 0x5B, 0xA8, 0xAC, 0x6F,
|
||||
0x2D, 0x82, 0x1D, 0xA3, 0xBD, 0x21, 0x2D, 0x11,
|
||||
0xA3, 0xDE, 0xB9, 0xA0],
|
||||
s vec![0x7C, 0x67, 0x0C, 0x7A, 0xD7, 0x2B, 0x6C, 0x05,
|
||||
0x0C, 0x10, 0x9E, 0x17, 0x90, 0x00, 0x80, 0x97,
|
||||
0x12, 0x54, 0x33, 0xE8]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn appendix_a22() {
|
||||
let pbytes = vec![0x9D,0xB6,0xFB,0x59,0x51,0xB6,0x6B,0xB6,
|
||||
0xFE,0x1E,0x14,0x0F,0x1D,0x2C,0xE5,0x50,
|
||||
0x23,0x74,0x16,0x1F,0xD6,0x53,0x8D,0xF1,
|
||||
0x64,0x82,0x18,0x64,0x2F,0x0B,0x5C,0x48,
|
||||
0xC8,0xF7,0xA4,0x1A,0xAD,0xFA,0x18,0x73,
|
||||
0x24,0xB8,0x76,0x74,0xFA,0x18,0x22,0xB0,
|
||||
0x0F,0x1E,0xCF,0x81,0x36,0x94,0x3D,0x7C,
|
||||
0x55,0x75,0x72,0x64,0xE5,0xA1,0xA4,0x4F,
|
||||
0xFE,0x01,0x2E,0x99,0x36,0xE0,0x0C,0x1D,
|
||||
0x3E,0x93,0x10,0xB0,0x1C,0x7D,0x17,0x98,
|
||||
0x05,0xD3,0x05,0x8B,0x2A,0x9F,0x4B,0xB6,
|
||||
0xF9,0x71,0x6B,0xFE,0x61,0x17,0xC6,0xB5,
|
||||
0xB3,0xCC,0x4D,0x9B,0xE3,0x41,0x10,0x4A,
|
||||
0xD4,0xA8,0x0A,0xD6,0xC9,0x4E,0x00,0x5F,
|
||||
0x4B,0x99,0x3E,0x14,0xF0,0x91,0xEB,0x51,
|
||||
0x74,0x3B,0xF3,0x30,0x50,0xC3,0x8D,0xE2,
|
||||
0x35,0x56,0x7E,0x1B,0x34,0xC3,0xD6,0xA5,
|
||||
0xC0,0xCE,0xAA,0x1A,0x0F,0x36,0x82,0x13,
|
||||
0xC3,0xD1,0x98,0x43,0xD0,0xB4,0xB0,0x9D,
|
||||
0xCB,0x9F,0xC7,0x2D,0x39,0xC8,0xDE,0x41,
|
||||
0xF1,0xBF,0x14,0xD4,0xBB,0x45,0x63,0xCA,
|
||||
0x28,0x37,0x16,0x21,0xCA,0xD3,0x32,0x4B,
|
||||
0x6A,0x2D,0x39,0x21,0x45,0xBE,0xBF,0xAC,
|
||||
0x74,0x88,0x05,0x23,0x6F,0x5C,0xA2,0xFE,
|
||||
0x92,0xB8,0x71,0xCD,0x8F,0x9C,0x36,0xD3,
|
||||
0x29,0x2B,0x55,0x09,0xCA,0x8C,0xAA,0x77,
|
||||
0xA2,0xAD,0xFC,0x7B,0xFD,0x77,0xDD,0xA6,
|
||||
0xF7,0x11,0x25,0xA7,0x45,0x6F,0xEA,0x15,
|
||||
0x3E,0x43,0x32,0x56,0xA2,0x26,0x1C,0x6A,
|
||||
0x06,0xED,0x36,0x93,0x79,0x7E,0x79,0x95,
|
||||
0xFA,0xD5,0xAA,0xBB,0xCF,0xBE,0x3E,0xDA,
|
||||
0x27,0x41,0xE3,0x75,0x40,0x4A,0xE2,0x5B];
|
||||
let qbytes = vec![0xF2,0xC3,0x11,0x93,0x74,0xCE,0x76,0xC9,
|
||||
0x35,0x69,0x90,0xB4,0x65,0x37,0x4A,0x17,
|
||||
0xF2,0x3F,0x9E,0xD3,0x50,0x89,0xBD,0x96,
|
||||
0x9F,0x61,0xC6,0xDD,0xE9,0x99,0x8C,0x1F];
|
||||
let gbytes = vec![0x5C,0x7F,0xF6,0xB0,0x6F,0x8F,0x14,0x3F,
|
||||
0xE8,0x28,0x84,0x33,0x49,0x3E,0x47,0x69,
|
||||
0xC4,0xD9,0x88,0xAC,0xE5,0xBE,0x25,0xA0,
|
||||
0xE2,0x48,0x09,0x67,0x07,0x16,0xC6,0x13,
|
||||
0xD7,0xB0,0xCE,0xE6,0x93,0x2F,0x8F,0xAA,
|
||||
0x7C,0x44,0xD2,0xCB,0x24,0x52,0x3D,0xA5,
|
||||
0x3F,0xBE,0x4F,0x6E,0xC3,0x59,0x58,0x92,
|
||||
0xD1,0xAA,0x58,0xC4,0x32,0x8A,0x06,0xC4,
|
||||
0x6A,0x15,0x66,0x2E,0x7E,0xAA,0x70,0x3A,
|
||||
0x1D,0xEC,0xF8,0xBB,0xB2,0xD0,0x5D,0xBE,
|
||||
0x2E,0xB9,0x56,0xC1,0x42,0xA3,0x38,0x66,
|
||||
0x1D,0x10,0x46,0x1C,0x0D,0x13,0x54,0x72,
|
||||
0x08,0x50,0x57,0xF3,0x49,0x43,0x09,0xFF,
|
||||
0xA7,0x3C,0x61,0x1F,0x78,0xB3,0x2A,0xDB,
|
||||
0xB5,0x74,0x0C,0x36,0x1C,0x9F,0x35,0xBE,
|
||||
0x90,0x99,0x7D,0xB2,0x01,0x4E,0x2E,0xF5,
|
||||
0xAA,0x61,0x78,0x2F,0x52,0xAB,0xEB,0x8B,
|
||||
0xD6,0x43,0x2C,0x4D,0xD0,0x97,0xBC,0x54,
|
||||
0x23,0xB2,0x85,0xDA,0xFB,0x60,0xDC,0x36,
|
||||
0x4E,0x81,0x61,0xF4,0xA2,0xA3,0x5A,0xCA,
|
||||
0x3A,0x10,0xB1,0xC4,0xD2,0x03,0xCC,0x76,
|
||||
0xA4,0x70,0xA3,0x3A,0xFD,0xCB,0xDD,0x92,
|
||||
0x95,0x98,0x59,0xAB,0xD8,0xB5,0x6E,0x17,
|
||||
0x25,0x25,0x2D,0x78,0xEA,0xC6,0x6E,0x71,
|
||||
0xBA,0x9A,0xE3,0xF1,0xDD,0x24,0x87,0x19,
|
||||
0x98,0x74,0x39,0x3C,0xD4,0xD8,0x32,0x18,
|
||||
0x68,0x00,0x65,0x47,0x60,0xE1,0xE3,0x4C,
|
||||
0x09,0xE4,0xD1,0x55,0x17,0x9F,0x9E,0xC0,
|
||||
0xDC,0x44,0x73,0xF9,0x96,0xBD,0xCE,0x6E,
|
||||
0xED,0x1C,0xAB,0xED,0x8B,0x6F,0x11,0x6F,
|
||||
0x7A,0xD9,0xCF,0x50,0x5D,0xF0,0xF9,0x98,
|
||||
0xE3,0x4A,0xB2,0x75,0x14,0xB0,0xFF,0xE7];
|
||||
let xbytes = vec![0x69,0xC7,0x54,0x8C,0x21,0xD0,0xDF,0xEA,
|
||||
0x6B,0x9A,0x51,0xC9,0xEA,0xD4,0xE2,0x7C,
|
||||
0x33,0xD3,0xB3,0xF1,0x80,0x31,0x6E,0x5B,
|
||||
0xCA,0xB9,0x2C,0x93,0x3F,0x0E,0x4D,0xBC];
|
||||
let ybytes = vec![0x66,0x70,0x98,0xC6,0x54,0x42,0x6C,0x78,
|
||||
0xD7,0xF8,0x20,0x1E,0xAC,0x6C,0x20,0x3E,
|
||||
0xF0,0x30,0xD4,0x36,0x05,0x03,0x2C,0x2F,
|
||||
0x1F,0xA9,0x37,0xE5,0x23,0x7D,0xBD,0x94,
|
||||
0x9F,0x34,0xA0,0xA2,0x56,0x4F,0xE1,0x26,
|
||||
0xDC,0x8B,0x71,0x5C,0x51,0x41,0x80,0x2C,
|
||||
0xE0,0x97,0x9C,0x82,0x46,0x46,0x3C,0x40,
|
||||
0xE6,0xB6,0xBD,0xAA,0x25,0x13,0xFA,0x61,
|
||||
0x17,0x28,0x71,0x6C,0x2E,0x4F,0xD5,0x3B,
|
||||
0xC9,0x5B,0x89,0xE6,0x99,0x49,0xD9,0x65,
|
||||
0x12,0xE8,0x73,0xB9,0xC8,0xF8,0xDF,0xD4,
|
||||
0x99,0xCC,0x31,0x28,0x82,0x56,0x1A,0xDE,
|
||||
0xCB,0x31,0xF6,0x58,0xE9,0x34,0xC0,0xC1,
|
||||
0x97,0xF2,0xC4,0xD9,0x6B,0x05,0xCB,0xAD,
|
||||
0x67,0x38,0x1E,0x7B,0x76,0x88,0x91,0xE4,
|
||||
0xDA,0x38,0x43,0xD2,0x4D,0x94,0xCD,0xFB,
|
||||
0x51,0x26,0xE9,0xB8,0xBF,0x21,0xE8,0x35,
|
||||
0x8E,0xE0,0xE0,0xA3,0x0E,0xF1,0x3F,0xD6,
|
||||
0xA6,0x64,0xC0,0xDC,0xE3,0x73,0x1F,0x7F,
|
||||
0xB4,0x9A,0x48,0x45,0xA4,0xFD,0x82,0x54,
|
||||
0x68,0x79,0x72,0xA2,0xD3,0x82,0x59,0x9C,
|
||||
0x9B,0xAC,0x4E,0x0E,0xD7,0x99,0x81,0x93,
|
||||
0x07,0x89,0x13,0x03,0x25,0x58,0x13,0x49,
|
||||
0x76,0x41,0x0B,0x89,0xD2,0xC1,0x71,0xD1,
|
||||
0x23,0xAC,0x35,0xFD,0x97,0x72,0x19,0x59,
|
||||
0x7A,0xA7,0xD1,0x5C,0x1A,0x9A,0x42,0x8E,
|
||||
0x59,0x19,0x4F,0x75,0xC7,0x21,0xEB,0xCB,
|
||||
0xCF,0xAE,0x44,0x69,0x6A,0x49,0x9A,0xFA,
|
||||
0x74,0xE0,0x42,0x99,0xF1,0x32,0x02,0x66,
|
||||
0x01,0x63,0x8C,0xB8,0x7A,0xB7,0x91,0x90,
|
||||
0xD4,0xA0,0x98,0x63,0x15,0xDA,0x8E,0xEC,
|
||||
0x65,0x61,0xC9,0x38,0x99,0x6B,0xEA,0xDF];
|
||||
//
|
||||
let p = U2048::from_bytes(&pbytes);
|
||||
let q = U256::from_bytes(&qbytes);
|
||||
let g = U2048::from_bytes(&gbytes);
|
||||
let params = L2048N256::new(p, g, q);
|
||||
let x = U256::from_bytes(&xbytes);
|
||||
let y = U2048::from_bytes(&ybytes);
|
||||
let private = DSAPrivKey::new(params.clone(), x);
|
||||
let public = DSAPubKey::new(params.clone(), y);
|
||||
//
|
||||
let sample: [u8; 6] = [115, 97, 109, 112, 108, 101]; // "sample", ASCII
|
||||
let test: [u8; 4] = [116, 101, 115, 116]; // "test", ASCII
|
||||
// With SHA-1, message = "sample":
|
||||
// k = 888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E
|
||||
// r = 3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A
|
||||
// s = D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF
|
||||
run_rfc6979_test!(Sha1, U256, sample, public, private,
|
||||
k vec![0x88,0x8F,0xA6,0xF7,0x73,0x8A,0x41,0xBD,
|
||||
0xC9,0x84,0x64,0x66,0xAB,0xDB,0x81,0x74,
|
||||
0xC0,0x33,0x82,0x50,0xAE,0x50,0xCE,0x95,
|
||||
0x5C,0xA1,0x62,0x30,0xF9,0xCB,0xD5,0x3E],
|
||||
r vec![0x3A,0x1B,0x2D,0xBD,0x74,0x89,0xD6,0xED,
|
||||
0x7E,0x60,0x8F,0xD0,0x36,0xC8,0x3A,0xF3,
|
||||
0x96,0xE2,0x90,0xDB,0xD6,0x02,0x40,0x8E,
|
||||
0x86,0x77,0xDA,0xAB,0xD6,0xE7,0x44,0x5A],
|
||||
s vec![0xD2,0x6F,0xCB,0xA1,0x9F,0xA3,0xE3,0x05,
|
||||
0x8F,0xFC,0x02,0xCA,0x15,0x96,0xCD,0xBB,
|
||||
0x6E,0x0D,0x20,0xCB,0x37,0xB0,0x60,0x54,
|
||||
0xF7,0xE3,0x6D,0xED,0x0C,0xDB,0xBC,0xCF]);
|
||||
// With SHA-224, message = "sample":
|
||||
// k = BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806
|
||||
// r = DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C
|
||||
// s = A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC
|
||||
run_rfc6979_test!(Sha224, U256, sample, public, private,
|
||||
k vec![0xBC,0x37,0x29,0x67,0x70,0x20,0x82,0xE1,
|
||||
0xAA,0x4F,0xCE,0x89,0x22,0x09,0xF7,0x1A,
|
||||
0xE4,0xAD,0x25,0xA6,0xDF,0xD8,0x69,0x33,
|
||||
0x4E,0x6F,0x15,0x3B,0xD0,0xC4,0xD8,0x06],
|
||||
r vec![0xDC,0x9F,0x4D,0xEA,0xDA,0x8D,0x8F,0xF5,
|
||||
0x88,0xE9,0x8F,0xED,0x0A,0xB6,0x90,0xFF,
|
||||
0xCE,0x85,0x8D,0xC8,0xC7,0x93,0x76,0x45,
|
||||
0x0E,0xB6,0xB7,0x6C,0x24,0x53,0x7E,0x2C],
|
||||
s vec![0xA6,0x5A,0x9C,0x3B,0xC7,0xBA,0xBE,0x28,
|
||||
0x6B,0x19,0x5D,0x5D,0xA6,0x86,0x16,0xDA,
|
||||
0x8D,0x47,0xFA,0x00,0x97,0xF3,0x6D,0xD1,
|
||||
0x9F,0x51,0x73,0x27,0xDC,0x84,0x8C,0xEC]);
|
||||
// With SHA-256, message = "sample":
|
||||
// k = 8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52
|
||||
// r = EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809
|
||||
// s = 7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53
|
||||
run_rfc6979_test!(Sha256, U256, sample, public, private,
|
||||
k vec![0x89,0x26,0xA2,0x7C,0x40,0x48,0x42,0x16,
|
||||
0xF0,0x52,0xF4,0x42,0x7C,0xFD,0x56,0x47,
|
||||
0x33,0x8B,0x7B,0x39,0x39,0xBC,0x65,0x73,
|
||||
0xAF,0x43,0x33,0x56,0x9D,0x59,0x7C,0x52],
|
||||
r vec![0xEA,0xCE,0x8B,0xDB,0xBE,0x35,0x3C,0x43,
|
||||
0x2A,0x79,0x5D,0x9E,0xC5,0x56,0xC6,0xD0,
|
||||
0x21,0xF7,0xA0,0x3F,0x42,0xC3,0x6E,0x9B,
|
||||
0xC8,0x7E,0x4A,0xC7,0x93,0x2C,0xC8,0x09],
|
||||
s vec![0x70,0x81,0xE1,0x75,0x45,0x5F,0x92,0x47,
|
||||
0xB8,0x12,0xB7,0x45,0x83,0xE9,0xE9,0x4F,
|
||||
0x9E,0xA7,0x9B,0xD6,0x40,0xDC,0x96,0x25,
|
||||
0x33,0xB0,0x68,0x07,0x93,0xA3,0x8D,0x53]);
|
||||
// With SHA-384, message = "sample":
|
||||
// k = C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920
|
||||
// r = B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B
|
||||
// s = 19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B
|
||||
run_rfc6979_test!(Sha384, U256, sample, public, private,
|
||||
k vec![0xC3,0x45,0xD5,0xAB,0x3D,0xA0,0xA5,0xBC,
|
||||
0xB7,0xEC,0x8F,0x8F,0xB7,0xA7,0xE9,0x60,
|
||||
0x69,0xE0,0x3B,0x20,0x63,0x71,0xEF,0x7D,
|
||||
0x83,0xE3,0x90,0x68,0xEC,0x56,0x49,0x20],
|
||||
r vec![0xB2,0xDA,0x94,0x5E,0x91,0x85,0x88,0x34,
|
||||
0xFD,0x9B,0xF6,0x16,0xEB,0xAC,0x15,0x1E,
|
||||
0xDB,0xC4,0xB4,0x5D,0x27,0xD0,0xDD,0x4A,
|
||||
0x7F,0x6A,0x22,0x73,0x9F,0x45,0xC0,0x0B],
|
||||
s vec![0x19,0x04,0x8B,0x63,0xD9,0xFD,0x6B,0xCA,
|
||||
0x1D,0x9B,0xAE,0x36,0x64,0xE1,0xBC,0xB9,
|
||||
0x7F,0x72,0x76,0xC3,0x06,0x13,0x09,0x69,
|
||||
0xF6,0x3F,0x38,0xFA,0x83,0x19,0x02,0x1B]);
|
||||
// With SHA-512, message = "sample":
|
||||
// k = 5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC
|
||||
// r = 2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E
|
||||
// s = D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351
|
||||
run_rfc6979_test!(Sha512, U256, sample, public, private,
|
||||
k vec![0x5A,0x12,0x99,0x44,0x31,0x78,0x54,0x85,
|
||||
0xB3,0xF5,0xF0,0x67,0x22,0x15,0x17,0x79,
|
||||
0x1B,0x85,0xA5,0x97,0xB7,0xA9,0x43,0x69,
|
||||
0x95,0xC8,0x9E,0xD0,0x37,0x46,0x68,0xFC],
|
||||
r vec![0x20,0x16,0xED,0x09,0x2D,0xC5,0xFB,0x66,
|
||||
0x9B,0x8E,0xFB,0x3D,0x1F,0x31,0xA9,0x1E,
|
||||
0xEC,0xB1,0x99,0x87,0x9B,0xE0,0xCF,0x78,
|
||||
0xF0,0x2B,0xA0,0x62,0xCB,0x4C,0x94,0x2E],
|
||||
s vec![0xD0,0xC7,0x6F,0x84,0xB5,0xF0,0x91,0xE1,
|
||||
0x41,0x57,0x2A,0x63,0x9A,0x4F,0xB8,0xC2,
|
||||
0x30,0x80,0x7E,0xEA,0x7D,0x55,0xC8,0xA1,
|
||||
0x54,0xA2,0x24,0x40,0x0A,0xFF,0x23,0x51]);
|
||||
// With SHA-1, message = "test":
|
||||
// k = 6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F
|
||||
// r = C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0
|
||||
// s = 414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA
|
||||
run_rfc6979_test!(Sha1, U256, test, public, private,
|
||||
k vec![0x6E,0xEA,0x48,0x6F,0x9D,0x41,0xA0,0x37,
|
||||
0xB2,0xC6,0x40,0xBC,0x56,0x45,0x69,0x4F,
|
||||
0xF8,0xFF,0x4B,0x98,0xD0,0x66,0xA2,0x5F,
|
||||
0x76,0xBE,0x64,0x1C,0xCB,0x24,0xBA,0x4F],
|
||||
r vec![0xC1,0x82,0x70,0xA9,0x3C,0xFC,0x60,0x63,
|
||||
0xF5,0x7A,0x4D,0xFA,0x86,0x02,0x4F,0x70,
|
||||
0x0D,0x98,0x0E,0x4C,0xF4,0xE2,0xCB,0x65,
|
||||
0xA5,0x04,0x39,0x72,0x73,0xD9,0x8E,0xA0],
|
||||
s vec![0x41,0x4F,0x22,0xE5,0xF3,0x1A,0x8B,0x6D,
|
||||
0x33,0x29,0x5C,0x75,0x39,0xC1,0xC1,0xBA,
|
||||
0x3A,0x61,0x60,0xD7,0xD6,0x8D,0x50,0xAC,
|
||||
0x0D,0x3A,0x5B,0xEA,0xC2,0x88,0x4F,0xAA]);
|
||||
// With SHA-224, message = "test":
|
||||
// k = 06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670
|
||||
// r = 272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3
|
||||
// s = E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806
|
||||
run_rfc6979_test!(Sha224, U256, test, public, private,
|
||||
k vec![0x06,0xBD,0x4C,0x05,0xED,0x74,0x71,0x91,
|
||||
0x06,0x22,0x3B,0xE3,0x3F,0x2D,0x95,0xDA,
|
||||
0x6B,0x3B,0x54,0x1D,0xAD,0x7B,0xFB,0xD7,
|
||||
0xAC,0x50,0x82,0x13,0xB6,0xDA,0x66,0x70],
|
||||
r vec![0x27,0x2A,0xBA,0x31,0x57,0x2F,0x6C,0xC5,
|
||||
0x5E,0x30,0xBF,0x61,0x6B,0x7A,0x26,0x53,
|
||||
0x12,0x01,0x8D,0xD3,0x25,0xBE,0x03,0x1B,
|
||||
0xE0,0xCC,0x82,0xAA,0x17,0x87,0x0E,0xA3],
|
||||
s vec![0xE9,0xCC,0x28,0x6A,0x52,0xCC,0xE2,0x01,
|
||||
0x58,0x67,0x22,0xD3,0x6D,0x1E,0x91,0x7E,
|
||||
0xB9,0x6A,0x4E,0xBD,0xB4,0x79,0x32,0xF9,
|
||||
0x57,0x6A,0xC6,0x45,0xB3,0xA6,0x08,0x06]);
|
||||
// With SHA-256, message = "test":
|
||||
// k = 1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7
|
||||
// r = 8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0
|
||||
// s = 7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E
|
||||
run_rfc6979_test!(Sha256, U256, test, public, private,
|
||||
k vec![0x1D,0x6C,0xE6,0xDD,0xA1,0xC5,0xD3,0x73,
|
||||
0x07,0x83,0x9C,0xD0,0x3A,0xB0,0xA5,0xCB,
|
||||
0xB1,0x8E,0x60,0xD8,0x00,0x93,0x7D,0x67,
|
||||
0xDF,0xB4,0x47,0x9A,0xAC,0x8D,0xEA,0xD7],
|
||||
r vec![0x81,0x90,0x01,0x2A,0x19,0x69,0xF9,0x95,
|
||||
0x7D,0x56,0xFC,0xCA,0xAD,0x22,0x31,0x86,
|
||||
0xF4,0x23,0x39,0x8D,0x58,0xEF,0x5B,0x3C,
|
||||
0xEF,0xD5,0xA4,0x14,0x6A,0x44,0x76,0xF0],
|
||||
s vec![0x74,0x52,0xA5,0x3F,0x70,0x75,0xD4,0x17,
|
||||
0xB4,0xB0,0x13,0xB2,0x78,0xD1,0xBB,0x8B,
|
||||
0xBD,0x21,0x86,0x3F,0x5E,0x7B,0x1C,0xEE,
|
||||
0x67,0x9C,0xF2,0x18,0x8E,0x1A,0xB1,0x9E]);
|
||||
// With SHA-384, message = "test":
|
||||
// k = 206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C
|
||||
// r = 239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE
|
||||
// s = 6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961
|
||||
run_rfc6979_test!(Sha384, U256, test, public, private,
|
||||
k vec![0x20,0x6E,0x61,0xF7,0x3D,0xBE,0x1B,0x2D,
|
||||
0xC8,0xBE,0x73,0x6B,0x22,0xB0,0x79,0xE9,
|
||||
0xDA,0xCD,0x97,0x4D,0xB0,0x0E,0xEB,0xBC,
|
||||
0x5B,0x64,0xCA,0xD3,0x9C,0xF9,0xF9,0x1C],
|
||||
r vec![0x23,0x9E,0x66,0xDD,0xBE,0x8F,0x8C,0x23,
|
||||
0x0A,0x3D,0x07,0x1D,0x60,0x1B,0x6F,0xFB,
|
||||
0xDF,0xB5,0x90,0x1F,0x94,0xD4,0x44,0xC6,
|
||||
0xAF,0x56,0xF7,0x32,0xBE,0xB9,0x54,0xBE],
|
||||
s vec![0x6B,0xD7,0x37,0x51,0x3D,0x5E,0x72,0xFE,
|
||||
0x85,0xD1,0xC7,0x50,0xE0,0xF7,0x39,0x21,
|
||||
0xFE,0x29,0x9B,0x94,0x5A,0xAD,0x1C,0x80,
|
||||
0x2F,0x15,0xC2,0x6A,0x43,0xD3,0x49,0x61]);
|
||||
// With SHA-512, message = "test":
|
||||
// k = AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA
|
||||
// r = 89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307
|
||||
// s = C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1
|
||||
run_rfc6979_test!(Sha512, U256, test, public, private,
|
||||
k vec![0xAF,0xF1,0x65,0x1E,0x4C,0xD6,0x03,0x6D,
|
||||
0x57,0xAA,0x8B,0x2A,0x05,0xCC,0xF1,0xA9,
|
||||
0xD5,0xA4,0x01,0x66,0x34,0x0E,0xCB,0xBD,
|
||||
0xC5,0x5B,0xE1,0x0B,0x56,0x8A,0xA0,0xAA],
|
||||
r vec![0x89,0xEC,0x4B,0xB1,0x40,0x0E,0xCC,0xFF,
|
||||
0x8E,0x7D,0x9A,0xA5,0x15,0xCD,0x1D,0xE7,
|
||||
0x80,0x3F,0x2D,0xAF,0xF0,0x96,0x93,0xEE,
|
||||
0x7F,0xD1,0x35,0x3E,0x90,0xA6,0x83,0x07],
|
||||
s vec![0xC9,0xF0,0xBD,0xAB,0xCC,0x0D,0x88,0x0B,
|
||||
0xB1,0x37,0xA9,0x94,0xCC,0x7F,0x39,0x80,
|
||||
0xCE,0x91,0xCC,0x10,0xFA,0xF5,0x29,0xFC,
|
||||
0x46,0x56,0x5B,0x15,0xCE,0xA8,0x54,0xE1]);
|
||||
}
|
||||
@@ -12,10 +12,11 @@
|
||||
extern crate byteorder;
|
||||
extern crate cryptonum;
|
||||
extern crate digest;
|
||||
extern crate hmac;
|
||||
extern crate num;
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate quickcheck;
|
||||
extern crate num;
|
||||
extern crate rand;
|
||||
extern crate sha1;
|
||||
extern crate sha2;
|
||||
@@ -24,6 +25,11 @@ extern crate simple_asn1;
|
||||
/// The `rsa` module provides bare-bones support for RSA signing, verification,
|
||||
/// encryption, decryption, and key generation.
|
||||
pub mod rsa;
|
||||
/// The `dsa` module provides bare-bones support for DSA signing, verification,
|
||||
/// and key generation. You shouldn't need to use these if you're building a
|
||||
/// new system, but might need to use them to interact with legacy systems or
|
||||
/// protocols.
|
||||
pub mod dsa;
|
||||
|
||||
#[cfg(test)]
|
||||
mod testing;
|
||||
|
||||
@@ -95,44 +95,44 @@ impl FromASN1 for RSAPublic {
|
||||
}
|
||||
match rsa_size {
|
||||
512 => {
|
||||
let n2 = U512::from_num(n);
|
||||
let e2 = U512::from_num(e);
|
||||
let n2 = U512::from_num(n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U512::from_num(e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA512Public::new(n2, e2);
|
||||
Ok((RSAPublic::Key512(res), rest))
|
||||
}
|
||||
1024 => {
|
||||
let n2 = U1024::from_num(n);
|
||||
let e2 = U1024::from_num(e);
|
||||
let n2 = U1024::from_num(n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U1024::from_num(e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA1024Public::new(n2, e2);
|
||||
Ok((RSAPublic::Key1024(res), rest))
|
||||
}
|
||||
2048 => {
|
||||
let n2 = U2048::from_num(n);
|
||||
let e2 = U2048::from_num(e);
|
||||
let n2 = U2048::from_num(n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U2048::from_num(e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA2048Public::new(n2, e2);
|
||||
Ok((RSAPublic::Key2048(res), rest))
|
||||
}
|
||||
3072 => {
|
||||
let n2 = U3072::from_num(n);
|
||||
let e2 = U3072::from_num(e);
|
||||
let n2 = U3072::from_num(n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U3072::from_num(e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA3072Public::new(n2, e2);
|
||||
Ok((RSAPublic::Key3072(res), rest))
|
||||
}
|
||||
4096 => {
|
||||
let n2 = U4096::from_num(n);
|
||||
let e2 = U4096::from_num(e);
|
||||
let n2 = U4096::from_num(n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U4096::from_num(e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA4096Public::new(n2, e2);
|
||||
Ok((RSAPublic::Key4096(res), rest))
|
||||
}
|
||||
8192 => {
|
||||
let n2 = U8192::from_num(n);
|
||||
let e2 = U8192::from_num(e);
|
||||
let n2 = U8192::from_num(n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U8192::from_num(e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA8192Public::new(n2, e2);
|
||||
Ok((RSAPublic::Key8192(res), rest))
|
||||
}
|
||||
15360 => {
|
||||
let n2 = U15360::from_num(n);
|
||||
let e2 = U15360::from_num(e);
|
||||
let n2 = U15360::from_num(n).ok_or(RSAError::InvalidKey)?;
|
||||
let e2 = U15360::from_num(e).ok_or(RSAError::InvalidKey)?;
|
||||
let res = RSA15360Public::new(n2, e2);
|
||||
Ok((RSAPublic::Key15360(res), rest))
|
||||
}
|
||||
|
||||
18
src/utils.rs
18
src/utils.rs
@@ -1,27 +1,27 @@
|
||||
use cryptonum::unsigned::*;
|
||||
use num::BigUint;
|
||||
|
||||
pub trait TranslateNums {
|
||||
fn from_num(x: BigUint) -> Self;
|
||||
pub trait TranslateNums: Sized {
|
||||
fn from_num(x: BigUint) -> Option<Self>;
|
||||
fn to_num(&self) -> BigUint;
|
||||
}
|
||||
|
||||
macro_rules! from_biguint {
|
||||
($uname: ident, $size: expr) => {
|
||||
impl TranslateNums for $uname {
|
||||
fn from_num(x: BigUint) -> $uname {
|
||||
fn from_num(x: BigUint) -> Option<$uname> {
|
||||
let mut base_vec = x.to_bytes_be();
|
||||
let target_bytes = $size / 8;
|
||||
|
||||
if target_bytes < base_vec.len() {
|
||||
return None;
|
||||
|
||||
}
|
||||
while target_bytes > base_vec.len() {
|
||||
base_vec.insert(0,0);
|
||||
}
|
||||
|
||||
while base_vec.len() > target_bytes {
|
||||
base_vec.remove(0);
|
||||
}
|
||||
|
||||
$uname::from_bytes(&base_vec)
|
||||
Some($uname::from_bytes(&base_vec))
|
||||
}
|
||||
|
||||
fn to_num(&self) -> BigUint {
|
||||
@@ -32,6 +32,8 @@ macro_rules! from_biguint {
|
||||
};
|
||||
}
|
||||
|
||||
from_biguint!(U192, 192);
|
||||
from_biguint!(U256, 256);
|
||||
from_biguint!(U512, 512);
|
||||
from_biguint!(U1024, 1024);
|
||||
from_biguint!(U2048, 2048);
|
||||
|
||||
Reference in New Issue
Block a user