DSA support!

This commit is contained in:
2018-12-08 10:59:14 -06:00
parent 160618cdd7
commit 62cb276888
11 changed files with 1409 additions and 23 deletions

20
src/dsa/errors.rs Normal file
View 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
View 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(&params.q);
let x = $ntype::from( (&c % (&qbig - &one)) + &one );
// 7. y = g^x mod p
let y = params.g.modexp(&$ltype::from(&x), &params.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
View 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^(N1).
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^(N1) + 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_(n1) 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
View 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
View 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
View 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
View 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]);
}

View File

@@ -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;

View File

@@ -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))
}

View File

@@ -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);