Compare commits
129 Commits
variable_c
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 82bb499be3 | |||
| 20c65b93bf | |||
| 7c45f898ab | |||
| c675aaa5f6 | |||
| 6d4c9c4f50 | |||
| a34d8dc88b | |||
| b59653de57 | |||
| 3eee154fe1 | |||
| 0b4d84b038 | |||
| 54687cb602 | |||
| 1bac2010b1 | |||
| 818b006521 | |||
| bae1c93c54 | |||
| ef3174f224 | |||
| 89c8705779 | |||
| 080c8f18e2 | |||
| 060b82b351 | |||
| ba2ceee725 | |||
| 4d2e43620a | |||
| c5850b4d01 | |||
| a19c1ee124 | |||
| 2145fb47fa | |||
| 2912c72a07 | |||
| 23a79300c8 | |||
| 0e6664f232 | |||
| 4ce8797da2 | |||
| 7f2b509640 | |||
| b0885722a8 | |||
| 83cdd8ef4c | |||
| 2f395721bc | |||
| 2b63dfa376 | |||
| fc09ff48a2 | |||
| c9f418feff | |||
| ac380d08af | |||
| 25746af626 | |||
| 16cf6172ce | |||
| d2bdbd37fe | |||
| e6e3789127 | |||
| 8bca480e47 | |||
| b42902e6ab | |||
| 44618c2e2f | |||
| 4c03ab6648 | |||
| 1b2d7db1e0 | |||
| 9cf0b587b2 | |||
| d459850c54 | |||
| 6c61e1c56c | |||
| aaa8dc3497 | |||
| ad484877cf | |||
| 1eba2d1709 | |||
| 29872fa47a | |||
| 031b4be14e | |||
| 8c87f945a1 | |||
| 6d2c803f2b | |||
| 8a7e604fbd | |||
| cfc06c3b56 | |||
| 40a5793089 | |||
| 026b321f7c | |||
| 887c90202a | |||
| 6613f85ff3 | |||
| 22b4fcbd94 | |||
| e4f67f0918 | |||
| 68ddc7096b | |||
| 54c5244bc5 | |||
| 06d3391748 | |||
| 3a0d08d572 | |||
| 1d1ca3d817 | |||
| 69cef498f2 | |||
| 47fae77a4f | |||
| 06400cc7a5 | |||
| 3a6ae61707 | |||
| 5a69795fdf | |||
| 40254014d3 | |||
| 9d2e56ad06 | |||
| 95c3dc94df | |||
| cc83b239cc | |||
| b3276ce2f6 | |||
| 91d595ee4b | |||
| f1f39f8b5f | |||
| 038db66c2f | |||
| bf13f4a1e6 | |||
| 15ec3c5c9b | |||
| 8d8351e833 | |||
| 4559b80d2f | |||
| 293a93c6d4 | |||
| a3b0ef8d98 | |||
| 9ce976bb6e | |||
| 94defc4e77 | |||
| a426ca3901 | |||
| 3716dba87c | |||
| a390a7bb53 | |||
| 71cb38ca30 | |||
| 322701ad6c | |||
| 8a771c05a4 | |||
| a8174ac47e | |||
| 00b944e30a | |||
| 63bfda9073 | |||
| 4529562cb8 | |||
| 4af5446e80 | |||
| 04b4c79f7a | |||
| 89deea0337 | |||
| f60a492a0b | |||
| c5e9d4be25 | |||
| f4e47154c2 | |||
| cdcfd9a3a3 | |||
| f3494d8524 | |||
| eb82edea7e | |||
| 62cb276888 | |||
| 160618cdd7 | |||
| 9d87916cc5 | |||
| ef54ed4cda | |||
| 43b73139cd | |||
| b30fe6a75f | |||
| 011ebc0c99 | |||
| a6def22bd1 | |||
| c49cd29c43 | |||
| 65d7b7e93f | |||
| b93286fe60 | |||
| 5a5b48569b | |||
| b5afa8fdf9 | |||
| 26eb05ceeb | |||
| fee68cca18 | |||
| 11c951d29b | |||
| 72a5c4568e | |||
| eae2ea49a9 | |||
| 69596c83ec | |||
| bebb5b2861 | |||
| a5f0179d77 | |||
| 041f824caf | |||
| f088f0f9a5 |
13
.gitignore
vendored
13
.gitignore
vendored
@@ -11,3 +11,16 @@ Cargo.lock
|
|||||||
|
|
||||||
# And these are just annoying
|
# And these are just annoying
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# Ignore testing files
|
||||||
|
**/*.o
|
||||||
|
**/*.hi
|
||||||
|
**/gen
|
||||||
|
**/.cabal-sandbox
|
||||||
|
**/cabal.sandbox.config
|
||||||
|
FlameGraph
|
||||||
|
*.user_stacks
|
||||||
|
**/.ghc.environment.*
|
||||||
|
|
||||||
|
test.ed25519
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "cryptonum"]
|
||||||
|
path = cryptonum
|
||||||
|
url = https://github.com/acw/cryptonum.git
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
language: rust
|
language: rust
|
||||||
rust:
|
rust:
|
||||||
|
- stable
|
||||||
|
- beta
|
||||||
- nightly
|
- nightly
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- nightly
|
||||||
|
fast_finish: true
|
||||||
|
|||||||
16
Cargo.toml
16
Cargo.toml
@@ -9,13 +9,23 @@ license-file = "LICENSE"
|
|||||||
repository = "https://github.com/acw/simple_crypto"
|
repository = "https://github.com/acw/simple_crypto"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "^0.3"
|
base64 = "^0.10.1"
|
||||||
|
byteorder = "^1.3.1"
|
||||||
|
chrono = "^0.4.6"
|
||||||
|
cryptonum = { path = "cryptonum" }
|
||||||
|
num = "^0.2.0"
|
||||||
|
rand = "^0.6.5"
|
||||||
|
simple_asn1 = "^0.2.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
quickcheck = "^0.4.1"
|
quickcheck = "^0.7.2"
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
opt-level = 1
|
||||||
|
overflow-checks = false
|
||||||
|
|
||||||
[profile.test]
|
[profile.test]
|
||||||
opt-level = 2
|
opt-level = 2
|
||||||
debug = true
|
debug = true
|
||||||
debug-assertions = true
|
debug-assertions = true
|
||||||
|
overflow-checks = false
|
||||||
|
|||||||
11
TECHNICAL_DEBT
Normal file
11
TECHNICAL_DEBT
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
- Add negative test cases (RSA, DSA, ECDSA)
|
||||||
|
- Make Point::double_scalar_mult() not truly awful
|
||||||
|
- Use std::Default instead of the bespoke default() in Point?
|
||||||
|
- Run rustfmt on this stuff
|
||||||
|
- Run clippy on this stuff
|
||||||
|
- De-macro. Surely some of this stuff could be turned into trait invocations?
|
||||||
|
- Test cases for key generation
|
||||||
|
- Better, timing-resistant ECC point math
|
||||||
|
- Make the x.509 library not terrible
|
||||||
|
- Ability to generate a SSH public key line / file
|
||||||
|
- Extend SSH examples with public key reading/writing
|
||||||
1
cryptonum
Submodule
1
cryptonum
Submodule
Submodule cryptonum added at 666378b14b
File diff suppressed because it is too large
Load Diff
@@ -1,332 +0,0 @@
|
|||||||
use std::cmp::Ordering;
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_cmp(a: &[u64], b: &[u64]) -> Ordering {
|
|
||||||
let mut i = a.len() - 1;
|
|
||||||
|
|
||||||
assert!(a.len() == b.len());
|
|
||||||
loop {
|
|
||||||
match a[i].cmp(&b[i]) {
|
|
||||||
Ordering::Equal if i == 0 =>
|
|
||||||
return Ordering::Equal,
|
|
||||||
Ordering::Equal =>
|
|
||||||
i -= 1,
|
|
||||||
res =>
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn le(a: &[u64], b: &[u64]) -> bool {
|
|
||||||
generic_cmp(a, b) != Ordering::Greater
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ge(a: &[u64], b: &[u64]) -> bool {
|
|
||||||
generic_cmp(a, b) != Ordering::Less
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_bitand(a: &mut [u64], b: &[u64]) {
|
|
||||||
let mut i = 0;
|
|
||||||
|
|
||||||
assert!(a.len() == b.len());
|
|
||||||
while i < a.len() {
|
|
||||||
a[i] &= b[i];
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_bitor(a: &mut [u64], b: &[u64]) {
|
|
||||||
let mut i = 0;
|
|
||||||
|
|
||||||
assert!(a.len() == b.len());
|
|
||||||
while i < a.len() {
|
|
||||||
a[i] |= b[i];
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_bitxor(a: &mut [u64], b: &[u64]) {
|
|
||||||
let mut i = 0;
|
|
||||||
|
|
||||||
assert!(a.len() == b.len());
|
|
||||||
while i < a.len() {
|
|
||||||
a[i] ^= b[i];
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_not(a: &mut [u64]) {
|
|
||||||
for x in a.iter_mut() {
|
|
||||||
*x = !*x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_shl(a: &mut [u64], orig: &[u64], amount: usize) {
|
|
||||||
let digits = amount / 64;
|
|
||||||
let bits = amount % 64;
|
|
||||||
|
|
||||||
assert!(a.len() == orig.len());
|
|
||||||
for i in 0..a.len() {
|
|
||||||
if i < digits {
|
|
||||||
a[i] = 0;
|
|
||||||
} else {
|
|
||||||
let origidx = i - digits;
|
|
||||||
let prev = if origidx == 0 { 0 } else { orig[origidx - 1] };
|
|
||||||
let (carry,_) = if bits == 0 { (0, false) }
|
|
||||||
else { prev.overflowing_shr(64 - bits as u32) };
|
|
||||||
a[i] = (orig[origidx] << bits) | carry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_shr(a: &mut [u64], orig: &[u64], amount: usize) {
|
|
||||||
let digits = amount / 64;
|
|
||||||
let bits = amount % 64;
|
|
||||||
|
|
||||||
assert!(a.len() == orig.len());
|
|
||||||
for i in 0..a.len() {
|
|
||||||
let oldidx = i + digits;
|
|
||||||
let caridx = i + digits + 1;
|
|
||||||
let old = if oldidx >= a.len() { 0 } else { orig[oldidx] };
|
|
||||||
let carry = if caridx >= a.len() { 0 } else { orig[caridx] };
|
|
||||||
let cb = if bits == 0 { 0 } else { carry << (64 - bits) };
|
|
||||||
a[i] = (old >> bits) | cb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_add(a: &mut [u64], b: &[u64]) {
|
|
||||||
let mut carry = 0;
|
|
||||||
|
|
||||||
assert!(a.len() == b.len());
|
|
||||||
for i in 0..a.len() {
|
|
||||||
let x = a[i] as u128;
|
|
||||||
let y = b[i] as u128;
|
|
||||||
let total = x + y + carry;
|
|
||||||
a[i] = total as u64;
|
|
||||||
carry = total >> 64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_sub(a: &mut [u64], b: &[u64]) {
|
|
||||||
let mut negated_rhs = b.to_vec();
|
|
||||||
generic_not(&mut negated_rhs);
|
|
||||||
let mut one = Vec::with_capacity(a.len());
|
|
||||||
one.resize(a.len(), 0);
|
|
||||||
one[0] = 1;
|
|
||||||
generic_add(&mut negated_rhs, &one);
|
|
||||||
generic_add(a, &negated_rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_mul(a: &mut [u64], orig: &[u64], b: &[u64]) {
|
|
||||||
assert!(a.len() == orig.len());
|
|
||||||
assert!(a.len() == b.len());
|
|
||||||
assert!(a == orig);
|
|
||||||
|
|
||||||
// Build the output table. This is a little bit awkward because we don't
|
|
||||||
// know how big we're running, but hopefully the compiler is smart enough
|
|
||||||
// to work all this out.
|
|
||||||
let mut table = Vec::with_capacity(a.len());
|
|
||||||
for _ in 0..a.len() {
|
|
||||||
let mut row = Vec::with_capacity(a.len());
|
|
||||||
row.resize(a.len(), 0);
|
|
||||||
table.push(row);
|
|
||||||
}
|
|
||||||
// This uses "simple" grade school techniques to work things out. But,
|
|
||||||
// for reference, consider two 4 digit numbers:
|
|
||||||
//
|
|
||||||
// l0c3 l0c2 l0c1 l0c0 [orig]
|
|
||||||
// x l1c3 l1c2 l1c1 l1c0 [b]
|
|
||||||
// ------------------------------------------------------------
|
|
||||||
// (l0c3*l1c0) (l0c2*l1c0) (l0c1*l1c0) (l0c0*l1c0)
|
|
||||||
// (l0c2*l1c1) (l0c1*l1c1) (l0c0*l1c1)
|
|
||||||
// (l0c1*l1c2) (l0c0*l1c2)
|
|
||||||
// (l0c0*l1c3)
|
|
||||||
// ------------------------------------------------------------
|
|
||||||
// AAAAA BBBBB CCCCC DDDDD
|
|
||||||
for line in 0..a.len() {
|
|
||||||
let maxcol = a.len() - line;
|
|
||||||
for col in 0..maxcol {
|
|
||||||
let left = orig[col] as u128;
|
|
||||||
let right = b[line] as u128;
|
|
||||||
table[line][col + line] = left * right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ripple the carry across each line, ensuring that each entry in the
|
|
||||||
// table is 64-bits
|
|
||||||
for line in 0..a.len() {
|
|
||||||
let mut carry = 0;
|
|
||||||
for col in 0..a.len() {
|
|
||||||
table[line][col] = table[line][col] + carry;
|
|
||||||
carry = table[line][col] >> 64;
|
|
||||||
table[line][col] &= 0xFFFFFFFFFFFFFFFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// now do the final addition across the lines, rippling the carry as
|
|
||||||
// normal
|
|
||||||
let mut carry = 0;
|
|
||||||
for col in 0..a.len() {
|
|
||||||
let mut total = carry;
|
|
||||||
for line in 0..a.len() {
|
|
||||||
total += table[line][col];
|
|
||||||
}
|
|
||||||
a[col] = total as u64;
|
|
||||||
carry = total >> 64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn expanding_mul(a: &[u64], b: &[u64]) -> Vec<u64> {
|
|
||||||
assert!(a.len() == b.len());
|
|
||||||
// The maximum size of an n x n digit multiplication is 2n digits, so
|
|
||||||
// here's our output array.
|
|
||||||
let mut result = Vec::with_capacity(a.len() * 2);
|
|
||||||
result.resize(a.len() * 2, 0);
|
|
||||||
|
|
||||||
for (base_idx, digit) in b.iter().enumerate() {
|
|
||||||
let mut myrow = Vec::with_capacity(a.len() * 2);
|
|
||||||
let mut carry = 0;
|
|
||||||
|
|
||||||
myrow.resize(a.len() * 2, 0);
|
|
||||||
for (col_idx, digit2) in a.iter().enumerate() {
|
|
||||||
let left = *digit2 as u128;
|
|
||||||
let right = *digit as u128;
|
|
||||||
let combo = (left * right) + carry;
|
|
||||||
|
|
||||||
myrow[base_idx + col_idx] = combo as u64;
|
|
||||||
carry = combo >> 64;
|
|
||||||
}
|
|
||||||
generic_add(&mut result, &myrow);
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn generic_div(inx: &[u64], iny: &[u64],
|
|
||||||
outq: &mut [u64], outr: &mut [u64])
|
|
||||||
{
|
|
||||||
assert!(inx.len() == inx.len());
|
|
||||||
assert!(inx.len() == iny.len());
|
|
||||||
assert!(inx.len() == outq.len());
|
|
||||||
assert!(inx.len() == outr.len());
|
|
||||||
// This algorithm is from the Handbook of Applied Cryptography, Chapter 14,
|
|
||||||
// algorithm 14.20. It has a couple assumptions about the inputs, namely that
|
|
||||||
// n >= t >= 1 and y[t] != 0, where n and t refer to the number of digits in
|
|
||||||
// the numbers. Which means that if we used the inputs unmodified, we can't
|
|
||||||
// divide by single-digit numbers.
|
|
||||||
//
|
|
||||||
// To deal with this, we multiply inx and iny by 2^64, so that we push out
|
|
||||||
// t by one.
|
|
||||||
//
|
|
||||||
// In addition, this algorithm starts to go badly when y[t] is very small
|
|
||||||
// and x[n] is very large. Really, really badly. This can be fixed by
|
|
||||||
// insuring that the top bit is set in y[t], which we can achieve by
|
|
||||||
// shifting everyone over a maxiumum of 63 bits.
|
|
||||||
//
|
|
||||||
// What this means is, just for safety, we add a 0 at the beginning and
|
|
||||||
// end of each number.
|
|
||||||
let mut y = iny.to_vec();
|
|
||||||
let mut x = inx.to_vec();
|
|
||||||
y.insert(0,0); y.push(0);
|
|
||||||
x.insert(0,0); x.push(0);
|
|
||||||
// 0. Compute 'n' and 't'
|
|
||||||
let n = x.len() - 1;
|
|
||||||
let mut t = y.len() - 1;
|
|
||||||
while (t > 0) && (y[t] == 0) { t -= 1 }
|
|
||||||
assert!(y[t] != 0); // this is where division by zero will fire
|
|
||||||
// 0.5. Figure out a shift we can do such that the high bit of y[t] is
|
|
||||||
// set, and then shift x and y left by that much.
|
|
||||||
let additional_shift: usize = y[t].leading_zeros() as usize;
|
|
||||||
let origx = x.clone();
|
|
||||||
let origy = y.clone();
|
|
||||||
generic_shl(&mut x, &origx, additional_shift);
|
|
||||||
generic_shl(&mut y, &origy, additional_shift);
|
|
||||||
// 1. For j from 0 to (n - 1) do: q_j <- 0
|
|
||||||
let mut q = Vec::with_capacity(y.len());
|
|
||||||
q.resize(y.len(), 0);
|
|
||||||
for qj in q.iter_mut() { *qj = 0 }
|
|
||||||
// 2. While (x >= yb^(n-t)) do the following:
|
|
||||||
// q_(n-t) <- q_(n-t) + 1
|
|
||||||
// x <- x - yb^(n-t)
|
|
||||||
let mut ybnt = y.clone();
|
|
||||||
generic_shl(&mut ybnt, &y, 64 * (n - t));
|
|
||||||
while ge(&x, &ybnt) {
|
|
||||||
q[n-t] = q[n-t] + 1;
|
|
||||||
generic_sub(&mut x, &ybnt);
|
|
||||||
}
|
|
||||||
// 3. For i from n down to (t + 1) do the following:
|
|
||||||
let mut i = n;
|
|
||||||
while i >= (t + 1) {
|
|
||||||
// 3.1. if x_i = y_t, then set q_(i-t-1) <- b - 1; otherwise set
|
|
||||||
// q_(i-t-1) <- floor((x_i * b + x_(i-1)) / y_t).
|
|
||||||
if x[i] == y[t] {
|
|
||||||
q[i-t-1] = 0xFFFFFFFFFFFFFFFF;
|
|
||||||
} else {
|
|
||||||
let top = ((x[i] as u128) << 64) + (x[i-1] as u128);
|
|
||||||
let bot = y[t] as u128;
|
|
||||||
let solution = top / bot;
|
|
||||||
q[i-t-1] = solution as u64;
|
|
||||||
}
|
|
||||||
// 3.2. While (q_(i-t-1)(y_t * b + y_(t-1)) > x_i(b2) + x_(i-1)b +
|
|
||||||
// x_(i-2)) do:
|
|
||||||
// q_(i - t - 1) <- q_(i - t 1) - 1.
|
|
||||||
loop {
|
|
||||||
let mut left = Vec::with_capacity(x.len());
|
|
||||||
left.resize(x.len(), 0);
|
|
||||||
left[0] = q[i - t - 1];
|
|
||||||
let mut leftright = Vec::with_capacity(x.len());
|
|
||||||
leftright.resize(x.len(), 0);
|
|
||||||
leftright[0] = y[t-1];
|
|
||||||
|
|
||||||
let copy = left.clone();
|
|
||||||
generic_mul(&mut left, ©, &leftright);
|
|
||||||
let mut right = Vec::with_capacity(x.len());
|
|
||||||
right.resize(x.len(), 0);
|
|
||||||
right[0] = x[i-2];
|
|
||||||
right[1] = x[i-1];
|
|
||||||
right[2] = x[i];
|
|
||||||
|
|
||||||
if le(&left, &right) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
q[i - t - 1] -= 1;
|
|
||||||
}
|
|
||||||
// 3.3. x <- x - q_(i - t - 1) * y * b^(i-t-1)
|
|
||||||
let mut right = Vec::with_capacity(y.len());
|
|
||||||
right.resize(y.len(), 0);
|
|
||||||
right[i - t - 1] = q[i - t - 1];
|
|
||||||
let rightclone = right.clone();
|
|
||||||
generic_mul(&mut right, &rightclone, &y);
|
|
||||||
let wentnegative = generic_cmp(&x, &right) == Ordering::Less;
|
|
||||||
generic_sub(&mut x, &right);
|
|
||||||
// 3.4. if x < 0 then set x <- x + yb^(i-t-1) and
|
|
||||||
// q_(i-t-1) <- q_(i-t-1) - 1
|
|
||||||
if wentnegative {
|
|
||||||
let mut ybit1 = y.to_vec();
|
|
||||||
generic_shl(&mut ybit1, &y, 64 * (i - t - 1));
|
|
||||||
generic_add(&mut x, &ybit1);
|
|
||||||
q[i - t - 1] -= 1;
|
|
||||||
}
|
|
||||||
i -= 1;
|
|
||||||
}
|
|
||||||
// 4. r <- x
|
|
||||||
let finalx = x.clone();
|
|
||||||
generic_shr(&mut x, &finalx, additional_shift);
|
|
||||||
for i in 0..outr.len() {
|
|
||||||
outr[i] = x[i + 1]; // note that for the remainder, we're dividing by
|
|
||||||
// our normalization value.
|
|
||||||
}
|
|
||||||
// 5. return (q,r)
|
|
||||||
for i in 0..outq.len() {
|
|
||||||
outq[i] = q[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
use cryptonum::signed::Signed;
|
|
||||||
use cryptonum::traits::*;
|
|
||||||
use std::ops::*;
|
|
||||||
|
|
||||||
pub fn modinv<'a,T>(e: &T, phi: &T) -> T
|
|
||||||
where
|
|
||||||
T: Clone + CryptoNumBase + Ord,
|
|
||||||
T: AddAssign + SubAssign + MulAssign + DivAssign,
|
|
||||||
T: Add<Output=T> + Sub<Output=T> + Mul<Output=T> + Div<Output=T>,
|
|
||||||
&'a T: Sub<Output=T>,
|
|
||||||
T: 'a
|
|
||||||
{
|
|
||||||
let (_, mut x, _) = extended_euclidean(e, phi);
|
|
||||||
let int_phi = Signed::<T>::new(phi.clone());
|
|
||||||
while x.is_negative() {
|
|
||||||
x += &int_phi;
|
|
||||||
}
|
|
||||||
x.abs()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modexp<T>(b: &T, e: &T, m: &T) -> T
|
|
||||||
{
|
|
||||||
panic!("modexp")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn extended_euclidean<T>(a: &T, b: &T) -> (Signed<T>, Signed<T>, Signed<T>)
|
|
||||||
where
|
|
||||||
T: Clone + CryptoNumBase + Div + Mul + Sub
|
|
||||||
{
|
|
||||||
let posinta = Signed::<T>::new(a.clone());
|
|
||||||
let posintb = Signed::<T>::new(b.clone());
|
|
||||||
let (mut d, mut x, mut y) = egcd(&posinta, &posintb);
|
|
||||||
|
|
||||||
if d.is_negative() {
|
|
||||||
d.negate();
|
|
||||||
x.negate();
|
|
||||||
y.negate();
|
|
||||||
}
|
|
||||||
|
|
||||||
(d, x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn egcd<T>(a: &Signed<T>, b: &Signed<T>) -> (Signed<T>,Signed<T>,Signed<T>)
|
|
||||||
where
|
|
||||||
T: Clone + CryptoNumBase + Div + Mul + Sub
|
|
||||||
{
|
|
||||||
let mut s = Signed::<T>::zero();
|
|
||||||
let mut old_s = Signed::<T>::from_u8(1);
|
|
||||||
let mut t = Signed::<T>::from_u8(1);
|
|
||||||
let mut old_t = Signed::<T>::zero();
|
|
||||||
let mut r = b.clone();
|
|
||||||
let mut old_r = a.clone();
|
|
||||||
|
|
||||||
while !r.is_zero() {
|
|
||||||
let quotient = old_r.clone() / r.clone();
|
|
||||||
|
|
||||||
let prov_r = r.clone();
|
|
||||||
let prov_s = s.clone();
|
|
||||||
let prov_t = t.clone();
|
|
||||||
|
|
||||||
r = old_r - (r * "ient);
|
|
||||||
s = old_s - (s * "ient);
|
|
||||||
t = old_t - (t * "ient);
|
|
||||||
|
|
||||||
old_r = prov_r;
|
|
||||||
old_s = prov_s;
|
|
||||||
old_t = prov_t;
|
|
||||||
}
|
|
||||||
|
|
||||||
(old_r, old_s, old_t)
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
//! # Simple-Crypto CryptoNum
|
|
||||||
//!
|
|
||||||
//! This module is designed to provide large, fixed-width number support for
|
|
||||||
//! the rest of the Simple-Crypto libraries. Feel free to use it other places,
|
|
||||||
//! of course, but that's its origin.
|
|
||||||
mod core;
|
|
||||||
#[macro_use]
|
|
||||||
mod builder;
|
|
||||||
//mod extended_math;
|
|
||||||
// mod primes;
|
|
||||||
mod signed;
|
|
||||||
mod traits;
|
|
||||||
mod unsigned;
|
|
||||||
|
|
||||||
// pub use self::extended_math::{modexp,modinv,extended_euclidean,egcd};
|
|
||||||
// pub use self::primes::{probably_prime};
|
|
||||||
pub use self::signed::{Signed};
|
|
||||||
pub use self::unsigned::{U512,U1024,U2048,U3072,U4096,U7680,U8192,U15360};
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
use cryptonum::extended_math::modexp;
|
|
||||||
use cryptonum::traits::*;
|
|
||||||
use rand::Rng;
|
|
||||||
use std::ops::*;
|
|
||||||
|
|
||||||
static SMALL_PRIMES: [u64; 310] = [
|
|
||||||
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
|
|
||||||
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
|
|
||||||
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
|
|
||||||
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
|
|
||||||
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
|
|
||||||
233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
|
|
||||||
283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
|
|
||||||
353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
|
|
||||||
419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
|
|
||||||
467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
|
|
||||||
547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
|
|
||||||
607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
|
|
||||||
661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
|
|
||||||
739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
|
|
||||||
811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
|
|
||||||
877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
|
|
||||||
947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
|
|
||||||
1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
|
|
||||||
1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
|
|
||||||
1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
|
|
||||||
1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
|
|
||||||
1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
|
|
||||||
1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
|
|
||||||
1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
|
|
||||||
1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
|
|
||||||
1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
|
|
||||||
1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
|
|
||||||
1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
|
|
||||||
1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
|
|
||||||
1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
|
|
||||||
1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053];
|
|
||||||
|
|
||||||
|
|
||||||
pub fn probably_prime<G,T>(x: &T, g: &mut G, iters: usize) -> bool
|
|
||||||
where
|
|
||||||
G: Rng,
|
|
||||||
T: Clone + PartialOrd + Rem + Sub,
|
|
||||||
T: CryptoNumBase + CryptoNumSerialization,
|
|
||||||
{
|
|
||||||
for tester in SMALL_PRIMES.iter() {
|
|
||||||
if (x % T::from_u64(*tester)) == T::zero() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
miller_rabin(g, x, iters)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn miller_rabin<G,T>(g: &mut G, n: T, iters: usize) -> bool
|
|
||||||
where
|
|
||||||
G: Rng,
|
|
||||||
T: Clone + PartialEq + PartialOrd + Sub,
|
|
||||||
T: CryptoNumBase + CryptoNumSerialization,
|
|
||||||
{
|
|
||||||
let one = T::from_u8(1);
|
|
||||||
let two = T::from_u8(2);
|
|
||||||
let nm1 = n - one;
|
|
||||||
// Quoth Wikipedia:
|
|
||||||
// write n - 1 as 2^r*d with d odd by factoring powers of 2 from n - 1
|
|
||||||
let mut d = nm1.clone();
|
|
||||||
let mut r = 0;
|
|
||||||
while d.is_even() {
|
|
||||||
d >>= 1;
|
|
||||||
r += 1;
|
|
||||||
assert!(r < n.bit_size());
|
|
||||||
}
|
|
||||||
// WitnessLoop: repeat k times
|
|
||||||
'WitnessLoop: for _k in 0..iters {
|
|
||||||
// pick a random integer a in the range [2, n - 2]
|
|
||||||
let a = random_in_range(g, &two, &nm1);
|
|
||||||
// x <- a^d mod n
|
|
||||||
let mut x = modexp(&a, &d, &n);
|
|
||||||
// if x = 1 or x = n - 1 then
|
|
||||||
if (&x == &one) || (&x == &nm1) {
|
|
||||||
// continue WitnessLoop
|
|
||||||
continue 'WitnessLoop;
|
|
||||||
}
|
|
||||||
// repeat r - 1 times:
|
|
||||||
for _i in 0..r {
|
|
||||||
// x <- x^2 mod n
|
|
||||||
x = modexp(&x, &two, &n);
|
|
||||||
// if x = 1 then
|
|
||||||
if &x == &one {
|
|
||||||
// return composite
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// if x = n - 1 then
|
|
||||||
if &x == &nm1 {
|
|
||||||
// continue WitnessLoop
|
|
||||||
continue 'WitnessLoop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// return composite
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// return probably prime
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn random_in_range<G,T>(rng: &mut G, min: &T, max: &T) -> T
|
|
||||||
where
|
|
||||||
G: Rng,
|
|
||||||
T: CryptoNumSerialization + PartialOrd
|
|
||||||
{
|
|
||||||
assert_eq!(min.byte_size(), max.byte_size());
|
|
||||||
loop {
|
|
||||||
let candidate = random_number(rng, min.byte_size());
|
|
||||||
|
|
||||||
if (&candidate >= min) && (&candidate < max) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn random_number<G,T>(rng: &mut G, bytelen: usize) -> T
|
|
||||||
where
|
|
||||||
G: Rng,
|
|
||||||
T: CryptoNumSerialization
|
|
||||||
{
|
|
||||||
let components: Vec<u8> = rng.gen_iter().take(bytelen).collect();
|
|
||||||
T::from_bytes(&components)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,431 +0,0 @@
|
|||||||
use cryptonum::traits::*;
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::fmt::{Debug,Error,Formatter};
|
|
||||||
use std::ops::*;
|
|
||||||
|
|
||||||
pub struct Signed<T: Sized> {
|
|
||||||
positive: bool,
|
|
||||||
value: T
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Signed<T> {
|
|
||||||
pub fn new(v: T) -> Signed<T> {
|
|
||||||
Signed{ positive: true, value: v }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn abs(&self) -> T
|
|
||||||
where T: Clone
|
|
||||||
{
|
|
||||||
self.value.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_positive(&self) -> bool
|
|
||||||
where T: CryptoNumBase
|
|
||||||
{
|
|
||||||
self.positive && !self.value.is_zero()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_negative(&self) -> bool
|
|
||||||
where T: CryptoNumBase
|
|
||||||
{
|
|
||||||
!self.positive && !self.value.is_zero()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn negate(&mut self)
|
|
||||||
{
|
|
||||||
self.positive = !self.positive;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: CryptoNumBase> CryptoNumBase for Signed<T> {
|
|
||||||
fn zero() -> Signed<T> {
|
|
||||||
Signed{ positive: true, value: T::zero() }
|
|
||||||
}
|
|
||||||
fn max_value() -> Signed<T> {
|
|
||||||
Signed{ positive: true, value: T::max_value() }
|
|
||||||
}
|
|
||||||
fn is_zero(&self) -> bool {
|
|
||||||
self.value.is_zero()
|
|
||||||
}
|
|
||||||
fn is_odd(&self) -> bool {
|
|
||||||
self.value.is_odd()
|
|
||||||
}
|
|
||||||
fn is_even(&self) -> bool {
|
|
||||||
self.value.is_even()
|
|
||||||
}
|
|
||||||
fn from_u8(x: u8) -> Signed<T> {
|
|
||||||
Signed{ positive: true, value: T::from_u8(x) }
|
|
||||||
}
|
|
||||||
fn to_u8(&self) -> u8 {
|
|
||||||
self.value.to_u8()
|
|
||||||
}
|
|
||||||
fn from_u16(x: u16) -> Signed<T> {
|
|
||||||
Signed{ positive: true, value: T::from_u16(x) }
|
|
||||||
}
|
|
||||||
fn to_u16(&self) -> u16 {
|
|
||||||
self.value.to_u16()
|
|
||||||
}
|
|
||||||
fn from_u32(x: u32) -> Signed<T> {
|
|
||||||
Signed{ positive: true, value: T::from_u32(x) }
|
|
||||||
}
|
|
||||||
fn to_u32(&self) -> u32 {
|
|
||||||
self.value.to_u32()
|
|
||||||
}
|
|
||||||
fn from_u64(x: u64) -> Signed<T> {
|
|
||||||
Signed{ positive: true, value: T::from_u64(x) }
|
|
||||||
}
|
|
||||||
fn to_u64(&self) -> u64 {
|
|
||||||
self.value.to_u64()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: CryptoNumFastMod> CryptoNumFastMod for Signed<T> {
|
|
||||||
type BarrettMu = T::BarrettMu;
|
|
||||||
|
|
||||||
fn barrett_mu(&self) -> Option<T::BarrettMu> {
|
|
||||||
if self.positive {
|
|
||||||
self.value.barrett_mu()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fastmod(&self, mu: &T::BarrettMu) -> Signed<T> {
|
|
||||||
Signed{ positive: self.positive, value: self.value.fastmod(&mu) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone> Clone for Signed<T> {
|
|
||||||
fn clone(&self) -> Signed<T> {
|
|
||||||
Signed{ positive: self.positive, value: self.value.clone() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,T: PartialEq> PartialEq<&'a Signed<T>> for Signed<T> {
|
|
||||||
fn eq(&self, other: &&Signed<T>) -> bool {
|
|
||||||
(self.positive == other.positive) && (self.value == other.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,T: PartialEq> PartialEq<Signed<T>> for &'a Signed<T> {
|
|
||||||
fn eq(&self, other: &Signed<T>) -> bool {
|
|
||||||
(self.positive == other.positive) && (self.value == other.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialEq> PartialEq for Signed<T> {
|
|
||||||
fn eq(&self, other: &Signed<T>) -> bool {
|
|
||||||
(self.positive == other.positive) && (self.value == other.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Eq> Eq for Signed<T> {}
|
|
||||||
|
|
||||||
impl<T: Debug> Debug for Signed<T> {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
|
||||||
if self.positive {
|
|
||||||
f.write_str("+")?;
|
|
||||||
} else {
|
|
||||||
f.write_str("-")?;
|
|
||||||
}
|
|
||||||
self.value.fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Ord> Ord for Signed<T> {
|
|
||||||
fn cmp(&self, other: &Signed<T>) -> Ordering {
|
|
||||||
match (self.positive, other.positive) {
|
|
||||||
(true, true) => self.value.cmp(&other.value),
|
|
||||||
(true, false) => Ordering::Greater,
|
|
||||||
(false, true) => Ordering::Less,
|
|
||||||
(false, false) =>
|
|
||||||
self.value.cmp(&other.value).reverse()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Ord> PartialOrd for Signed<T> {
|
|
||||||
fn partial_cmp(&self, other: &Signed<T>) -> Option<Ordering>{
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
impl<T: Clone> Neg for Signed<T> {
|
|
||||||
type Output = Signed<T>;
|
|
||||||
|
|
||||||
fn neg(self) -> Signed<T> {
|
|
||||||
Signed {
|
|
||||||
positive: !self.positive,
|
|
||||||
value: self.value.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,T: Clone> Neg for &'a Signed<T> {
|
|
||||||
type Output = Signed<T>;
|
|
||||||
|
|
||||||
fn neg(self) -> Signed<T> {
|
|
||||||
Signed {
|
|
||||||
positive: !self.positive,
|
|
||||||
value: self.value.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
impl<T> AddAssign for Signed<T>
|
|
||||||
where
|
|
||||||
T: Clone + Ord,
|
|
||||||
T: AddAssign + SubAssign,
|
|
||||||
{
|
|
||||||
fn add_assign(&mut self, other: Signed<T>) {
|
|
||||||
match (self.positive, other.positive, self.value.cmp(&other.value)) {
|
|
||||||
// if the signs are the same, we maintain the sign and just increase
|
|
||||||
// the magnitude
|
|
||||||
(x, y, _) if x == y =>
|
|
||||||
self.value.add_assign(other.value),
|
|
||||||
// if the signs are different and the numbers are equal, we just set
|
|
||||||
// this to zero. However, we actually do the subtraction to make the
|
|
||||||
// timing roughly similar.
|
|
||||||
(_, _, Ordering::Equal) => {
|
|
||||||
self.positive = true;
|
|
||||||
self.value.sub_assign(other.value);
|
|
||||||
}
|
|
||||||
// if the signs are different and the first one is less than the
|
|
||||||
// second, then we flip the sign and subtract.
|
|
||||||
(_, _, Ordering::Less) => {
|
|
||||||
self.positive = !self.positive;
|
|
||||||
let temp = self.value.clone();
|
|
||||||
self.value = other.value.clone();
|
|
||||||
self.value.sub_assign(temp);
|
|
||||||
}
|
|
||||||
// if the signs are different and the first one is greater than the
|
|
||||||
// second, then we leave the sign and subtract.
|
|
||||||
(_, _, Ordering::Greater) => {
|
|
||||||
self.value.sub_assign(other.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,T> AddAssign<&'a Signed<T>> for Signed<T>
|
|
||||||
where
|
|
||||||
T: Clone + Ord,
|
|
||||||
T: AddAssign + SubAssign,
|
|
||||||
T: AddAssign<&'a T> + SubAssign<&'a T>
|
|
||||||
{
|
|
||||||
fn add_assign(&mut self, other: &'a Signed<T>) {
|
|
||||||
match (self.positive, other.positive, self.value.cmp(&other.value)) {
|
|
||||||
// if the signs are the same, we maintain the sign and just increase
|
|
||||||
// the magnitude
|
|
||||||
(x, y, _) if x == y =>
|
|
||||||
self.value.add_assign(&other.value),
|
|
||||||
// if the signs are different and the numbers are equal, we just set
|
|
||||||
// this to zero. However, we actually do the subtraction to make the
|
|
||||||
// timing roughly similar.
|
|
||||||
(_, _, Ordering::Equal) => {
|
|
||||||
self.positive = true;
|
|
||||||
self.value.sub_assign(&other.value);
|
|
||||||
}
|
|
||||||
// if the signs are different and the first one is less than the
|
|
||||||
// second, then we flip the sign and subtract.
|
|
||||||
(_, _, Ordering::Less) => {
|
|
||||||
self.positive = !self.positive;
|
|
||||||
let temp = self.value.clone();
|
|
||||||
self.value = other.value.clone();
|
|
||||||
self.value.sub_assign(temp);
|
|
||||||
}
|
|
||||||
// if the signs are different and the first one is greater than the
|
|
||||||
// second, then we leave the sign and subtract.
|
|
||||||
(_, _, Ordering::Greater) => {
|
|
||||||
self.value.sub_assign(&other.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
math_operator!(Add,add,add_assign);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
impl<T> SubAssign for Signed<T>
|
|
||||||
where
|
|
||||||
T: Clone + Ord,
|
|
||||||
T: AddAssign + SubAssign,
|
|
||||||
{
|
|
||||||
fn sub_assign(&mut self, other: Signed<T>) {
|
|
||||||
let mut other2 = other.clone();
|
|
||||||
other2.positive = !other.positive;
|
|
||||||
self.add_assign(other2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,T> SubAssign<&'a Signed<T>> for Signed<T>
|
|
||||||
where
|
|
||||||
T: Clone + Ord,
|
|
||||||
T: AddAssign + SubAssign,
|
|
||||||
T: AddAssign<&'a T> + SubAssign<&'a T>
|
|
||||||
{
|
|
||||||
fn sub_assign(&mut self, other: &'a Signed<T>) {
|
|
||||||
let mut other2 = other.clone();
|
|
||||||
other2.positive = !other.positive;
|
|
||||||
self.add_assign(other2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
math_operator!(Sub,sub,sub_assign);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
impl<T> MulAssign for Signed<T>
|
|
||||||
where
|
|
||||||
T: MulAssign
|
|
||||||
{
|
|
||||||
fn mul_assign(&mut self, other: Signed<T>) {
|
|
||||||
self.positive = !(self.positive ^ other.positive);
|
|
||||||
self.value *= other.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,T> MulAssign<&'a Signed<T>> for Signed<T>
|
|
||||||
where
|
|
||||||
T: MulAssign + MulAssign<&'a T>
|
|
||||||
{
|
|
||||||
fn mul_assign(&mut self, other: &'a Signed<T>) {
|
|
||||||
self.positive = !(self.positive ^ other.positive);
|
|
||||||
self.value *= &other.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
math_operator!(Mul,mul,mul_assign);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
impl<T> DivAssign for Signed<T>
|
|
||||||
where
|
|
||||||
T: DivAssign
|
|
||||||
{
|
|
||||||
fn div_assign(&mut self, other: Signed<T>) {
|
|
||||||
self.positive = !(self.positive ^ other.positive);
|
|
||||||
self.value /= other.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a,T> DivAssign<&'a Signed<T>> for Signed<T>
|
|
||||||
where
|
|
||||||
T: DivAssign + DivAssign<&'a T>
|
|
||||||
{
|
|
||||||
fn div_assign(&mut self, other: &'a Signed<T>) {
|
|
||||||
self.positive = !(self.positive ^ other.positive);
|
|
||||||
self.value /= &other.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
math_operator!(Div,div,div_assign);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use cryptonum::unsigned::U512;
|
|
||||||
use quickcheck::{Arbitrary,Gen};
|
|
||||||
use std::cmp::{max,min};
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
impl<T: Arbitrary + CryptoNumBase> Arbitrary for Signed<T> {
|
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> Signed<T> {
|
|
||||||
let value = T::arbitrary(g);
|
|
||||||
if value.is_zero() {
|
|
||||||
Signed {
|
|
||||||
positive: true,
|
|
||||||
value: value
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Signed {
|
|
||||||
positive: g.gen_weighted_bool(2),
|
|
||||||
value: value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn double_negation(x: Signed<U512>) -> bool {
|
|
||||||
&x == (- (- &x))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn add_associates(x: Signed<U512>, y: Signed<U512>, z: Signed<U512>)
|
|
||||||
-> bool
|
|
||||||
{
|
|
||||||
let mut a = x.clone();
|
|
||||||
let mut b = y.clone();
|
|
||||||
let mut c = z.clone();
|
|
||||||
|
|
||||||
// we shift these right because rollover makes for weird behavior
|
|
||||||
a.value >>= 2;
|
|
||||||
b.value >>= 2;
|
|
||||||
c.value >>= 2;
|
|
||||||
|
|
||||||
(&a + (&b + &c)) == ((&a + &b) + &c)
|
|
||||||
}
|
|
||||||
fn add_commutes(x: Signed<U512>, y: Signed<U512>) -> bool {
|
|
||||||
(&x + &y) == (&y + &x)
|
|
||||||
}
|
|
||||||
fn add_identity(x: Signed<U512>) -> bool {
|
|
||||||
let zero = Signed{ positive: true, value: U512::zero() };
|
|
||||||
(&x + &zero) == &x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn sub_is_add_negation(x: Signed<U512>, y: Signed<U512>) -> bool {
|
|
||||||
(&x - &y) == (&x + (- &y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn mul_associates(x: Signed<U512>, y: Signed<U512>, z: Signed<U512>)
|
|
||||||
-> bool
|
|
||||||
{
|
|
||||||
let mut a = x.clone();
|
|
||||||
let mut b = y.clone();
|
|
||||||
let mut c = z.clone();
|
|
||||||
|
|
||||||
// we shift these right because rollover makes for weird behavior
|
|
||||||
a.value >>= 258;
|
|
||||||
b.value >>= 258;
|
|
||||||
c.value >>= 258;
|
|
||||||
|
|
||||||
(&a * (&b * &c)) == ((&a * &b) * &c)
|
|
||||||
}
|
|
||||||
fn mul_commutes(x: Signed<U512>, y: Signed<U512>) -> bool {
|
|
||||||
(&x * &y) == (&y * &x)
|
|
||||||
}
|
|
||||||
fn mul_identity(x: Signed<U512>) -> bool {
|
|
||||||
let one = Signed{ positive: true, value: U512::from_u8(1) };
|
|
||||||
(&x * &one) == &x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quickcheck! {
|
|
||||||
fn add_mul_distribution(x:Signed<U512>,y:Signed<U512>,z:Signed<U512>)
|
|
||||||
-> bool
|
|
||||||
{
|
|
||||||
let mut a = x.clone();
|
|
||||||
let mut b = y.clone();
|
|
||||||
let mut c = z.clone();
|
|
||||||
|
|
||||||
// we shift these right because rollover makes for weird behavior
|
|
||||||
a.value >>= 258;
|
|
||||||
b.value >>= 258;
|
|
||||||
c.value >>= 258;
|
|
||||||
|
|
||||||
(&a * (&b + &c)) == ((&a * &b) + (&a * &c))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
pub trait CryptoNumBase {
|
|
||||||
/// Generate the zero value for this type.
|
|
||||||
fn zero() -> Self;
|
|
||||||
/// Generate the maximum possible value for this type.
|
|
||||||
fn max_value() -> Self;
|
|
||||||
/// Test if the number is zero.
|
|
||||||
fn is_zero(&self) -> bool;
|
|
||||||
/// Test if the number is odd (a.k.a., the low bit is set)
|
|
||||||
fn is_odd(&self) -> bool;
|
|
||||||
/// Test if the number is even (a.k.a., the low bit is clear)
|
|
||||||
fn is_even(&self) -> bool;
|
|
||||||
/// Translate a `u8` to this type. This must be safe.
|
|
||||||
fn from_u8(x: u8) -> Self;
|
|
||||||
/// Convert this back into a `u8`. This is the equivalent of masking off
|
|
||||||
/// the lowest 8 bits and then casting to a `u8`.
|
|
||||||
fn to_u8(&self) -> u8;
|
|
||||||
/// Translate a `u16` to this type. This must be safe.
|
|
||||||
fn from_u16(x: u16) -> Self;
|
|
||||||
/// Convert this back into a `u16`. This is the equivalent of masking off
|
|
||||||
/// the lowest 16 bits and then casting to a `u16`.
|
|
||||||
fn to_u16(&self) -> u16;
|
|
||||||
/// Translate a `u32` to this type. This must be safe.
|
|
||||||
fn from_u32(x: u32) -> Self;
|
|
||||||
/// Convert this back into a `u32`. This is the equivalent of masking off
|
|
||||||
/// the lowest 32 bits and then casting to a `u32`.
|
|
||||||
fn to_u32(&self) -> u32;
|
|
||||||
/// Translate a `u64` to this type. This must be safe.
|
|
||||||
fn from_u64(x: u64) -> Self;
|
|
||||||
/// Convert this back into a `u64`. This is the equivalent of masking off
|
|
||||||
/// the lowest 64 bits and then casting to a `u64`.
|
|
||||||
fn to_u64(&self) -> u64;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait CryptoNumSerialization {
|
|
||||||
/// The number of bits used when this number is serialized.
|
|
||||||
fn bit_size(&self) -> usize;
|
|
||||||
/// The number of bytes used when this number is serialized.
|
|
||||||
fn byte_size(&self) -> usize;
|
|
||||||
/// Convert a number to a series of bytes, in standard order (most to
|
|
||||||
/// least significant)
|
|
||||||
fn to_bytes(&self) -> Vec<u8>;
|
|
||||||
/// Convert a series of bytes into the number. The size of the given slice
|
|
||||||
/// must be greater than or equal to the size of the number, and must be
|
|
||||||
/// a multiple of 8 bytes long. Unused bytes should be ignored.
|
|
||||||
fn from_bytes(&[u8]) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait CryptoNumFastMod {
|
|
||||||
/// A related type that can hold the constant required for Barrett
|
|
||||||
/// reduction.
|
|
||||||
type BarrettMu;
|
|
||||||
|
|
||||||
/// Compute the Barett constant mu, using this as a modulus, which we can
|
|
||||||
/// use later to perform faster mod operations.
|
|
||||||
fn barrett_mu(&self) -> Option<Self::BarrettMu>;
|
|
||||||
/// Faster modulo through the use of the Barrett constant, above.
|
|
||||||
fn fastmod(&self, &Self::BarrettMu) -> Self;
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
use cryptonum::core::*;
|
|
||||||
use cryptonum::traits::*;
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::fmt::{Debug,Error,Formatter};
|
|
||||||
use std::ops::*;
|
|
||||||
|
|
||||||
construct_unsigned!(U512, BarretMu512, u512, 8);
|
|
||||||
construct_unsigned!(U1024, BarretMu1024, u1024, 16);
|
|
||||||
construct_unsigned!(U2048, BarretMu2048, u2048, 32);
|
|
||||||
construct_unsigned!(U3072, BarretMu3072, u3072, 48);
|
|
||||||
construct_unsigned!(U4096, BarretMu4096, u4096, 64);
|
|
||||||
construct_unsigned!(U7680, BarretMu7680, u7680, 120);
|
|
||||||
construct_unsigned!(U8192, BarretMu8192, u8192, 128);
|
|
||||||
construct_unsigned!(U15360, BarretMu15360, u15360, 240);
|
|
||||||
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
118
src/dsa/mod.rs
Normal file
118
src/dsa/mod.rs
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
//! If you want to use this module to generate keys, which you really
|
||||||
|
//! really shouldn't, there are two ways to do so, depending on whether
|
||||||
|
//! you've previously agreed on a set of DSA parameters for this key
|
||||||
|
//! pair. If you haven't, you can generate the parameters using a good
|
||||||
|
//! random number generator.
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::dsa::{DSAKeyPair,DSAParameters,L2048N256};
|
||||||
|
//! use simple_crypto::sha::SHA224;
|
||||||
|
//!
|
||||||
|
//! // Generate a set of DSA parameters, assuming you don't have
|
||||||
|
//! // them already
|
||||||
|
//! let mut rng = rand::rngs::OsRng::new().unwrap();
|
||||||
|
//! let params = L2048N256::generate(&mut rng);
|
||||||
|
//!
|
||||||
|
//! // Given those parameters, you can generate a key pair like so:
|
||||||
|
//! let kp = DSAKeyPair::<L2048N256>::generate(¶ms, &mut rng);
|
||||||
|
//! // Keeping in mind that you can re-use the parameters across multiple
|
||||||
|
//! // keys, and that their secrecy isn't paramout for the security of the
|
||||||
|
//! // algorithm.
|
||||||
|
//!
|
||||||
|
//! // Now that you have this key pair, you can sign and verify messages
|
||||||
|
//! // using it. For example, to sign the vector [0,1,2,3,4] with SHA224
|
||||||
|
//! // and then verify that signature, we would write:
|
||||||
|
//! let msg = vec![0,1,2,3,4];
|
||||||
|
//! let sig = kp.private.sign::<SHA224>(&msg);
|
||||||
|
//! assert!( kp.public.verify::<SHA224>(&msg, &sig) );
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
|
||||||
|
mod errors;
|
||||||
|
mod params;
|
||||||
|
mod private;
|
||||||
|
mod public;
|
||||||
|
/// Support for RFC6979 signing, which provides a secure way to generate
|
||||||
|
/// signatures without the use of a random number generator. This is used
|
||||||
|
/// in DSA signing as well as in ECDSA signing, but appears here because
|
||||||
|
/// ... well, because it was written for DSA first, both historically
|
||||||
|
/// (I think) and by me.
|
||||||
|
pub 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;
|
||||||
|
use super::KeyPair;
|
||||||
|
|
||||||
|
/// A DSA key pair, for use in signing and signature verification. Note
|
||||||
|
/// that you probably shouldn't be using DSA any more; ECDSA or ED25519
|
||||||
|
/// are probably better options.
|
||||||
|
///
|
||||||
|
/// DSA key pairs are parameterized by their DSA parameters, so that
|
||||||
|
/// you can't accidentally use them in the wrong place.
|
||||||
|
pub struct DSAKeyPair<P: DSAParameters>
|
||||||
|
{
|
||||||
|
pub private: DSAPrivateKey<P>,
|
||||||
|
pub public: DSAPublicKey<P>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: DSAParameters> KeyPair for DSAKeyPair<P>
|
||||||
|
{
|
||||||
|
type Private = DSAPrivateKey<P>;
|
||||||
|
type Public = DSAPublicKey<P>;
|
||||||
|
|
||||||
|
fn new(public: DSAPublicKey<P>, private: DSAPrivateKey<P>) -> DSAKeyPair<P>
|
||||||
|
{
|
||||||
|
DSAKeyPair{ private, public }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_dsa_pair {
|
||||||
|
($ptype: ident, $ltype: ident, $ntype: ident, $nbig: ident) => {
|
||||||
|
impl DSAKeyPair<$ptype>
|
||||||
|
{
|
||||||
|
/// Generate a DSA key pair using the given parameters and random
|
||||||
|
/// number generator. Please make sure that the RNG you're using
|
||||||
|
/// is suitable for key generators (look for the term "cryptographic"
|
||||||
|
/// or "crypto strong" in its documentation, or see if it matches
|
||||||
|
/// any of the NIST-suggested RNG algorithms).
|
||||||
|
pub 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 + 64) / 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 = DSAPrivateKey::<$ptype>::new(params.clone(), x);
|
||||||
|
let public = DSAPublicKey::<$ptype>::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);
|
||||||
225
src/dsa/params.rs
Normal file
225
src/dsa/params.rs
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
use cryptonum::unsigned::{CryptoNum,Decoder,Encoder,ModExp,PrimeGen};
|
||||||
|
use cryptonum::unsigned::{U192,U256,U1024,U2048,U3072};
|
||||||
|
use sha::{Hash,SHA256};
|
||||||
|
use simple_asn1::{ToASN1,ASN1Block,ASN1Class,ASN1EncodeErr};
|
||||||
|
use rand::Rng;
|
||||||
|
use utils::TranslateNums;
|
||||||
|
|
||||||
|
/// A trait that describes what a set of DSA parameters must support in
|
||||||
|
/// order to be used by the rest of the system.
|
||||||
|
pub trait DSAParameters : ToASN1
|
||||||
|
{
|
||||||
|
/// The fixed-width, unsigned type of values in L.
|
||||||
|
type L;
|
||||||
|
/// The fixed-width, unsigned type of values in N.
|
||||||
|
type N;
|
||||||
|
|
||||||
|
/// Given a `p`, `g`, and `q`, generate a new structure that includes
|
||||||
|
/// this information. Optionally, do any cross-checks needed.
|
||||||
|
fn new(p: Self::L, g: Self::L, q: Self::N) -> Self;
|
||||||
|
/// Generate a new set of DSA parameters given the provided random
|
||||||
|
/// number generator. Just as with key generation, this should be a
|
||||||
|
/// cryptographically-strong random number generator. If it's not,
|
||||||
|
/// you may be writing compromisable code.
|
||||||
|
fn generate<G: Rng>(rng: &mut G) -> Self;
|
||||||
|
/// Return the size of values of N in bits.
|
||||||
|
fn n_size() -> usize;
|
||||||
|
/// Return the size of values of L in bits.
|
||||||
|
fn l_size() -> usize;
|
||||||
|
/// Return the size of `q` in this particular instance of the parameters.
|
||||||
|
/// (Should be the same as `n_size()`, and the default implementation
|
||||||
|
/// simply uses `n_size(), but included for convenience)
|
||||||
|
fn n_bits(&self) -> usize {
|
||||||
|
Self::n_size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_parameters {
|
||||||
|
($name: ident, $ltype: ident, $ntype: ident, $l: expr, $n: expr) => {
|
||||||
|
/// DSA parameters to the given L and N, with the values given in bits.
|
||||||
|
#[derive(Clone,PartialEq)]
|
||||||
|
pub struct $name {
|
||||||
|
pub p: $ltype,
|
||||||
|
pub g: $ltype,
|
||||||
|
pub q: $ntype
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for $name {
|
||||||
|
type Error = ASN1EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let p = ASN1Block::Integer(c, 0, self.p.to_num());
|
||||||
|
let q = ASN1Block::Integer(c, 0, self.q.to_num());
|
||||||
|
let g = ASN1Block::Integer(c, 0, self.g.to_num());
|
||||||
|
Ok(vec![ASN1Block::Sequence(c, 0, vec![p, q, g])])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DSAParameters for $name
|
||||||
|
{
|
||||||
|
type L = $ltype;
|
||||||
|
type N = $ntype;
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
pub 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 highbit = $ntype::from(1u64) << (N - 1);
|
||||||
|
let lowbit = $ntype::from(1u64);
|
||||||
|
let q = U | highbit | lowbit;
|
||||||
|
// 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() * 8);
|
||||||
|
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::hash(&base)
|
||||||
|
}
|
||||||
159
src/dsa/private.rs
Normal file
159
src/dsa/private.rs
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use cryptonum::signed::ModInv;
|
||||||
|
use dsa::params::*;
|
||||||
|
use dsa::rfc6979::*;
|
||||||
|
use sha::Hash;
|
||||||
|
|
||||||
|
/// A DSA private key, parameterized by its DSA parameters (so that you don't
|
||||||
|
/// accidentally pass the wrong key to the wrong routine).
|
||||||
|
pub struct DSAPrivateKey<Params: DSAParameters>
|
||||||
|
{
|
||||||
|
pub(crate) params: Params,
|
||||||
|
pub(crate) x: Params::N
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generic DSA private key enum, which masks which kind of DSA key (1024,
|
||||||
|
/// 2048 with the small `n`, 2048 with the normal `n`, or 3072) you're using.
|
||||||
|
pub enum DSAPrivate {
|
||||||
|
DSA1024Private(DSAPrivateKey<L1024N160>),
|
||||||
|
DSA2048SmallPrivate(DSAPrivateKey<L2048N224>),
|
||||||
|
DSA2048Private(DSAPrivateKey<L2048N256>),
|
||||||
|
DSA3072Private(DSAPrivateKey<L3072N256>)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! privkey_impls {
|
||||||
|
($ptype: ident, $ltype: ident, $ntype: ident, $big: ident, $bigger: ident, $biggest: ident) => {
|
||||||
|
impl DSAPrivateKey<$ptype>
|
||||||
|
{
|
||||||
|
pub fn new(params: $ptype, x: $ntype) -> DSAPrivateKey<$ptype>
|
||||||
|
{
|
||||||
|
DSAPrivateKey{ params, x }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sign<H: Hash + Clone>(&self, m: &[u8]) -> DSASignature<$ntype>
|
||||||
|
{
|
||||||
|
// 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 = <H>::hash(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::<H,$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);
|
||||||
|
|
||||||
|
macro_rules! generate_tests {
|
||||||
|
( $( ($mod: ident, $params: ident, $lt: ident, $nt: ident) ),* ) => {
|
||||||
|
$(
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
mod $mod {
|
||||||
|
use cryptonum::unsigned::Decoder;
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn verify() {
|
||||||
|
let fname = format!("testdata/dsa/sign{}.test", stringify!($params));
|
||||||
|
run_test(fname.to_string(), 9, |case| {
|
||||||
|
let (neg0, pbytes) = case.get("p").unwrap();
|
||||||
|
let (neg1, qbytes) = case.get("q").unwrap();
|
||||||
|
let (neg2, gbytes) = case.get("g").unwrap();
|
||||||
|
let (neg3, _bytes) = case.get("y").unwrap();
|
||||||
|
let (neg4, xbytes) = case.get("x").unwrap();
|
||||||
|
let (neg5, mbytes) = case.get("m").unwrap();
|
||||||
|
let (neg6, hbytes) = case.get("h").unwrap();
|
||||||
|
let (neg7, rbytes) = case.get("r").unwrap();
|
||||||
|
let (neg8, sbytes) = case.get("s").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 &&
|
||||||
|
!neg5 && !neg6 && !neg7 && !neg8);
|
||||||
|
let p = $lt::from_bytes(pbytes);
|
||||||
|
let q = $nt::from_bytes(qbytes);
|
||||||
|
let g = $lt::from_bytes(gbytes);
|
||||||
|
let x = $nt::from_bytes(xbytes);
|
||||||
|
//let y = $lt::from_bytes(ybytes);
|
||||||
|
let h = usize::from($nt::from_bytes(hbytes));
|
||||||
|
let r = $nt::from_bytes(rbytes);
|
||||||
|
let s = $nt::from_bytes(sbytes);
|
||||||
|
|
||||||
|
let params = $params::new(p,g,q);
|
||||||
|
let private = DSAPrivateKey::<$params>::new(params, x);
|
||||||
|
let sig = match h {
|
||||||
|
224 => private.sign::<SHA224>(mbytes),
|
||||||
|
256 => private.sign::<SHA256>(mbytes),
|
||||||
|
384 => private.sign::<SHA384>(mbytes),
|
||||||
|
512 => private.sign::<SHA512>(mbytes),
|
||||||
|
_ => panic!("Unexpected hash {}", h)
|
||||||
|
};
|
||||||
|
assert_eq!(r, sig.r);
|
||||||
|
assert_eq!(s, sig.s);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_tests!( (DSA1024N160, L1024N160, U1024, U192),
|
||||||
|
(DSA2048N224, L2048N224, U2048, U256),
|
||||||
|
(DSA2048N256, L2048N256, U2048, U256),
|
||||||
|
(DSA3072N256, L3072N256, U3072, U256)
|
||||||
|
);
|
||||||
145
src/dsa/public.rs
Normal file
145
src/dsa/public.rs
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use cryptonum::signed::ModInv;
|
||||||
|
use dsa::params::*;
|
||||||
|
use dsa::rfc6979::DSASignature;
|
||||||
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,ToASN1};
|
||||||
|
use sha::Hash;
|
||||||
|
use std::cmp::min;
|
||||||
|
use utils::TranslateNums;
|
||||||
|
|
||||||
|
/// A DSA public key, parameterized by its DSA parameters (so that you don't
|
||||||
|
/// accidentally pass the wrong thing to the wrong function).
|
||||||
|
pub struct DSAPublicKey<Params: DSAParameters> {
|
||||||
|
pub(crate) params: Params,
|
||||||
|
pub(crate) y: Params::L
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An enumeration that hides exactly which parameters you're using. Use at
|
||||||
|
/// your own risk, as the types won't save you.
|
||||||
|
pub enum DSAPublic {
|
||||||
|
DSAPublicL1024N160(DSAPublicKey<L1024N160>),
|
||||||
|
DSAPublicL2048N224(DSAPublicKey<L2048N224>),
|
||||||
|
DSAPublicL2048N256(DSAPublicKey<L2048N256>),
|
||||||
|
DSAPublicL3072N256(DSAPublicKey<L3072N256>)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! pubkey_impls {
|
||||||
|
($ptype: ident, $ltype: ident, $ntype: ident, $dbl: ident, $bdbl: ident) => {
|
||||||
|
impl DSAPublicKey<$ptype>
|
||||||
|
{
|
||||||
|
pub fn new(params: $ptype, y: $ltype) -> DSAPublicKey<$ptype>
|
||||||
|
{
|
||||||
|
DSAPublicKey{ params, y }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify<H: Hash>(&self, m: &[u8], sig: &DSASignature<$ntype>) -> bool
|
||||||
|
{
|
||||||
|
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 = <H>::hash(m);
|
||||||
|
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 DSAPublicKey<$ptype> {
|
||||||
|
type Error = ASN1EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let inty = self.y.to_num();
|
||||||
|
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);
|
||||||
|
|
||||||
|
macro_rules! generate_tests {
|
||||||
|
( $( ($mod: ident, $params: ident, $lt: ident, $nt: ident) ),* ) => {
|
||||||
|
$(
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
mod $mod {
|
||||||
|
use cryptonum::unsigned::Decoder;
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn verify() {
|
||||||
|
let fname = format!("testdata/dsa/sign{}.test", stringify!($params));
|
||||||
|
run_test(fname.to_string(), 9, |case| {
|
||||||
|
let (neg0, pbytes) = case.get("p").unwrap();
|
||||||
|
let (neg1, qbytes) = case.get("q").unwrap();
|
||||||
|
let (neg2, gbytes) = case.get("g").unwrap();
|
||||||
|
let (neg3, ybytes) = case.get("y").unwrap();
|
||||||
|
let (neg4, _bytes) = case.get("x").unwrap();
|
||||||
|
let (neg5, mbytes) = case.get("m").unwrap();
|
||||||
|
let (neg6, hbytes) = case.get("h").unwrap();
|
||||||
|
let (neg7, rbytes) = case.get("r").unwrap();
|
||||||
|
let (neg8, sbytes) = case.get("s").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 &&
|
||||||
|
!neg5 && !neg6 && !neg7 && !neg8);
|
||||||
|
let p = $lt::from_bytes(pbytes);
|
||||||
|
let q = $nt::from_bytes(qbytes);
|
||||||
|
let g = $lt::from_bytes(gbytes);
|
||||||
|
//let x = $lt::from_bytes(xbytes);
|
||||||
|
let y = $lt::from_bytes(ybytes);
|
||||||
|
let h = usize::from($nt::from_bytes(hbytes));
|
||||||
|
let r = $nt::from_bytes(rbytes);
|
||||||
|
let s = $nt::from_bytes(sbytes);
|
||||||
|
|
||||||
|
let params = $params::new(p,g,q);
|
||||||
|
let public = DSAPublicKey::<$params>::new(params, y);
|
||||||
|
let sig = DSASignature::<$nt>::new(r, s);
|
||||||
|
match h {
|
||||||
|
224 => assert!(public.verify::<SHA224>(mbytes, &sig)),
|
||||||
|
256 => assert!(public.verify::<SHA256>(mbytes, &sig)),
|
||||||
|
384 => assert!(public.verify::<SHA384>(mbytes, &sig)),
|
||||||
|
512 => assert!(public.verify::<SHA512>(mbytes, &sig)),
|
||||||
|
_ => panic!("Unexpected hash {}", h)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_tests!( (DSA1024N160, L1024N160, U1024, U192),
|
||||||
|
(DSA2048N224, L2048N224, U2048, U256),
|
||||||
|
(DSA2048N256, L2048N256, U2048, U256),
|
||||||
|
(DSA3072N256, L3072N256, U3072, U256)
|
||||||
|
);
|
||||||
417
src/dsa/rfc6979.rs
Normal file
417
src/dsa/rfc6979.rs
Normal file
@@ -0,0 +1,417 @@
|
|||||||
|
use cryptonum::unsigned::{CryptoNum,Decoder,Encoder};
|
||||||
|
use hmac::HMAC;
|
||||||
|
use sha::Hash;
|
||||||
|
use num::BigInt;
|
||||||
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1DecodeErr,ASN1EncodeErr};
|
||||||
|
use simple_asn1::{FromASN1,ToASN1};
|
||||||
|
use utils::TranslateNums;
|
||||||
|
use std::ops::{Shr,Sub};
|
||||||
|
|
||||||
|
#[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: Hash + Clone,
|
||||||
|
N: Clone + Decoder + Encoder + PartialOrd + Shr<usize,Output=N>,
|
||||||
|
{
|
||||||
|
hmac_k: HMAC<H>,
|
||||||
|
V: Vec<u8>,
|
||||||
|
q: N,
|
||||||
|
qlen: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H,N> KIterator<H,N>
|
||||||
|
where
|
||||||
|
H: Hash + Clone,
|
||||||
|
N: Clone + Decoder + Encoder + PartialOrd + Shr<usize,Output=N> + Sub<Output=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::<H>::hmac(&K, &input);
|
||||||
|
// e. Set:
|
||||||
|
//
|
||||||
|
// V = HMAC_K(V)
|
||||||
|
V = HMAC::<H>::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::<H>::hmac(&K, &input);
|
||||||
|
// g. Set:
|
||||||
|
//
|
||||||
|
// V = HMAC_K(V)
|
||||||
|
V = HMAC::<H>::hmac(&K, &V);
|
||||||
|
// h is for later ...
|
||||||
|
KIterator {
|
||||||
|
hmac_k: HMAC::<H>::new(&K),
|
||||||
|
V: V,
|
||||||
|
q: q.clone(),
|
||||||
|
qlen: qlen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H,N> Iterator for KIterator<H,N>
|
||||||
|
where
|
||||||
|
H: Hash + Clone,
|
||||||
|
N: Clone + CryptoNum + Decoder + Encoder + PartialOrd + Shr<usize,Output=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(&K);
|
||||||
|
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>(x: &[u8], qlen: usize) -> X
|
||||||
|
where
|
||||||
|
X: Decoder + Shr<usize,Output=X>
|
||||||
|
{
|
||||||
|
|
||||||
|
if qlen < (x.len() * 8) {
|
||||||
|
let mut fixed_x = Vec::from(x);
|
||||||
|
let qlen_bytes = (qlen + 7) / 8;
|
||||||
|
let rounded_qlen = qlen_bytes * 8;
|
||||||
|
fixed_x.resize(qlen_bytes, 0);
|
||||||
|
X::from_bytes(&fixed_x) >> (rounded_qlen - qlen)
|
||||||
|
} else {
|
||||||
|
X::from_bytes(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bits2octets<X>(x: &[u8], q: &X, qlen: usize) -> Vec<u8>
|
||||||
|
where
|
||||||
|
X: Clone + Decoder + Encoder + PartialOrd + Sub<Output=X> + Shr<usize,Output=X>
|
||||||
|
{
|
||||||
|
let z1: X = bits2int(x, qlen);
|
||||||
|
let res = if &z1 > q { z1 - q.clone() } 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: Hash + Clone>(base: &HMAC<H>, m: &[u8]) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut runner = base.clone();
|
||||||
|
runner.update(&m);
|
||||||
|
runner.finalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone,Debug,PartialEq)]
|
||||||
|
pub enum DSADecodeError {
|
||||||
|
ASN1Error(ASN1DecodeErr),
|
||||||
|
NoSignatureFound,
|
||||||
|
InvalidRValue,
|
||||||
|
InvalidSValue
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ASN1DecodeErr> for DSADecodeError {
|
||||||
|
fn from(a: ASN1DecodeErr) -> DSADecodeError {
|
||||||
|
DSADecodeError::ASN1Error(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N> FromASN1 for DSASignature<N>
|
||||||
|
where N: TranslateNums<BigInt>
|
||||||
|
{
|
||||||
|
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)) => {
|
||||||
|
let r = N::from_num(rint).ok_or(DSADecodeError::InvalidRValue)?;
|
||||||
|
let s = N::from_num(sint).ok_or(DSADecodeError::InvalidSValue)?;
|
||||||
|
Ok((DSASignature{ r, s }, rest))
|
||||||
|
}
|
||||||
|
_ => Err(DSADecodeError::NoSignatureFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(DSADecodeError::NoSignatureFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N> ToASN1 for DSASignature<N>
|
||||||
|
where N: TranslateNums<BigInt>
|
||||||
|
{
|
||||||
|
type Error = ASN1EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let rb = ASN1Block::Integer(c, 0, self.r.to_num());
|
||||||
|
let sb = ASN1Block::Integer(c, 0, self.s.to_num());
|
||||||
|
Ok(vec![ASN1Block::Sequence(c, 0, vec![rb,sb])])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use cryptonum::unsigned::U192;
|
||||||
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
use super::*;
|
||||||
|
use testing::*;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use cryptonum::unsigned::*;
|
||||||
|
|
||||||
|
macro_rules! k_generator_tests {
|
||||||
|
($testname: ident, $hash: ident, $fname: expr) => {
|
||||||
|
#[test]
|
||||||
|
fn $testname() {
|
||||||
|
let fname = build_test_path("rfc6979", $fname);
|
||||||
|
run_test(fname.to_string(), 7, |case| {
|
||||||
|
let (negq, qbytes) = case.get("q").unwrap();
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negx, xbytes) = case.get("x").unwrap();
|
||||||
|
let (negh, h1) = case.get("h").unwrap();
|
||||||
|
let (negk, kbytes) = case.get("k").unwrap();
|
||||||
|
let (negy, ybytes) = case.get("y").unwrap();
|
||||||
|
let (negz, zbytes) = case.get("z").unwrap();
|
||||||
|
|
||||||
|
assert!(!negq && !negl && !negx && !negh &&
|
||||||
|
!negk && !negy && !negz);
|
||||||
|
let qlen = usize::from(U192::from_bytes(lbytes));
|
||||||
|
assert!(qlen >= 160); assert!(qlen <= 521);
|
||||||
|
|
||||||
|
if qlen < 192 {
|
||||||
|
let q = U192::from_bytes(qbytes);
|
||||||
|
let x = U192::from_bytes(xbytes);
|
||||||
|
let k = U192::from_bytes(kbytes);
|
||||||
|
let y = U192::from_bytes(ybytes);
|
||||||
|
let z = U192::from_bytes(zbytes);
|
||||||
|
|
||||||
|
let mut kiter = KIterator::<$hash,U192>::new(h1,qlen,&q,&x);
|
||||||
|
assert_eq!(Some(k), kiter.next(), "first value test");
|
||||||
|
assert_eq!(Some(y), kiter.next(), "second value test");
|
||||||
|
assert_eq!(Some(z), kiter.next(), "third value test");
|
||||||
|
} else if qlen < 256 {
|
||||||
|
let q = U256::from_bytes(qbytes);
|
||||||
|
let x = U256::from_bytes(xbytes);
|
||||||
|
let k = U256::from_bytes(kbytes);
|
||||||
|
let y = U256::from_bytes(ybytes);
|
||||||
|
let z = U256::from_bytes(zbytes);
|
||||||
|
|
||||||
|
let mut kiter = KIterator::<$hash,U256>::new(h1,qlen,&q,&x);
|
||||||
|
assert_eq!(Some(k), kiter.next(), "first value test");
|
||||||
|
assert_eq!(Some(y), kiter.next(), "second value test");
|
||||||
|
assert_eq!(Some(z), kiter.next(), "third value test");
|
||||||
|
} else if qlen < 512 {
|
||||||
|
let q = U512::from_bytes(qbytes);
|
||||||
|
let x = U512::from_bytes(xbytes);
|
||||||
|
let k = U512::from_bytes(kbytes);
|
||||||
|
let y = U512::from_bytes(ybytes);
|
||||||
|
let z = U512::from_bytes(zbytes);
|
||||||
|
|
||||||
|
let mut kiter = KIterator::<$hash,U512>::new(h1,qlen,&q,&x);
|
||||||
|
assert_eq!(Some(k), kiter.next(), "first value test");
|
||||||
|
assert_eq!(Some(y), kiter.next(), "second value test");
|
||||||
|
assert_eq!(Some(z), kiter.next(), "third value test");
|
||||||
|
} else {
|
||||||
|
let q = U576::from_bytes(qbytes);
|
||||||
|
let x = U576::from_bytes(xbytes);
|
||||||
|
let k = U576::from_bytes(kbytes);
|
||||||
|
let y = U576::from_bytes(ybytes);
|
||||||
|
let z = U576::from_bytes(zbytes);
|
||||||
|
|
||||||
|
let mut kiter = KIterator::<$hash,U576>::new(h1,qlen,&q,&x);
|
||||||
|
assert_eq!(Some(k), kiter.next(), "first value test");
|
||||||
|
assert_eq!(Some(y), kiter.next(), "second value test");
|
||||||
|
assert_eq!(Some(z), kiter.next(), "third value test");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
k_generator_tests!(kgen_sha224, SHA224, "SHA224");
|
||||||
|
k_generator_tests!(kgen_sha256, SHA256, "SHA256");
|
||||||
|
k_generator_tests!(kgen_sha384, SHA384, "SHA384");
|
||||||
|
k_generator_tests!(kgen_sha512, SHA512, "SHA512");
|
||||||
|
|
||||||
|
}
|
||||||
535
src/dsa/tests.rs
Normal file
535
src/dsa/tests.rs
Normal file
@@ -0,0 +1,535 @@
|
|||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use sha::{Hash,SHA1,SHA224,SHA256,SHA384,SHA512};
|
||||||
|
use simple_asn1::{der_decode,der_encode};
|
||||||
|
use dsa::params::{DSAParameters,L1024N160,L2048N256};
|
||||||
|
use dsa::private::DSAPrivateKey;
|
||||||
|
use dsa::public::DSAPublicKey;
|
||||||
|
use dsa::rfc6979::KIterator;
|
||||||
|
|
||||||
|
macro_rules! run_rfc6979_test {
|
||||||
|
($hash: ty, $ntype: ident, $val: ident, $params: ident, $public: ident, $private: ident,
|
||||||
|
k $k: expr,
|
||||||
|
r $r: expr,
|
||||||
|
s $s: expr) => ({
|
||||||
|
let h1 = <$hash>::hash(&$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, $params.n_bits(), &$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 = DSAPrivateKey::<L1024N160>::new(params.clone(), x);
|
||||||
|
let public = DSAPublicKey::<L1024N160>::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, params, 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, params, 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, params, 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, params, 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, params, 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, params, 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, params, 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, params, 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, params, 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, params, 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 = DSAPrivateKey::<L2048N256>::new(params.clone(), x);
|
||||||
|
let public = DSAPublicKey::<L2048N256>::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, params, 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, params, 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, params, 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, params, 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, params, 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, params, 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, params, 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, params, 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, params, 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, params, 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]);
|
||||||
|
}
|
||||||
498
src/ecdsa/curve.rs
Normal file
498
src/ecdsa/curve.rs
Normal file
@@ -0,0 +1,498 @@
|
|||||||
|
use cryptonum::signed::{I192,I256,I384,I576};
|
||||||
|
use cryptonum::unsigned::{Decoder};
|
||||||
|
use cryptonum::unsigned::{U192,U256,U384,U576};
|
||||||
|
use ecdsa::point::Point;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
/// Elliptic curves must implement this trait in order to work with the rest
|
||||||
|
/// of the ECDSA system. I've included instances for the core NIST curves
|
||||||
|
/// used in most systems, but this could be extended without issues.
|
||||||
|
/// (Eventually the curves defined here should actually be extended in
|
||||||
|
/// interesting ways to make the math faster, but we haven't gotten there
|
||||||
|
/// yet.)
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub trait EllipticCurve {
|
||||||
|
/// The unsigned numeric type that fits constants for this curve.
|
||||||
|
type Unsigned : Clone;
|
||||||
|
/// The signed numeric type that fits constants for this curve.
|
||||||
|
type Signed : Clone + Debug + PartialEq;
|
||||||
|
/// The type of a point on the curve
|
||||||
|
type Point;
|
||||||
|
|
||||||
|
/// The size of the curve in bits.
|
||||||
|
fn size() -> usize;
|
||||||
|
/// The `p` value for the curve.
|
||||||
|
fn p() -> Self::Unsigned;
|
||||||
|
/// The `p` value for the curve.
|
||||||
|
fn n() -> Self::Unsigned;
|
||||||
|
/// The seed value for the curve.
|
||||||
|
fn SEED() -> Self::Unsigned;
|
||||||
|
/// The `c` value for the curve.
|
||||||
|
fn c() -> Self::Unsigned;
|
||||||
|
/// The `a` value for the curve.
|
||||||
|
fn a() -> Self::Unsigned;
|
||||||
|
/// The `b` value for the curve.
|
||||||
|
fn b() -> Self::Unsigned;
|
||||||
|
/// The `x` coordinate of the base point for the curve.
|
||||||
|
fn Gx() -> Self::Signed;
|
||||||
|
/// The `y` coordinate of the base point for the curve.
|
||||||
|
fn Gy() -> Self::Signed;
|
||||||
|
/// Generate a point for the curve given the provided values.
|
||||||
|
fn new_point(x: Self::Unsigned, y: Self::Unsigned) -> Self::Point;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NIST curve P-192 (FIPS 186-4, page 101-102), a.k.a. secp192r1 from RFC5480
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct P192 {}
|
||||||
|
|
||||||
|
impl EllipticCurve for P192 {
|
||||||
|
type Unsigned = U192;
|
||||||
|
type Signed = I192;
|
||||||
|
type Point = Point<P192>;
|
||||||
|
|
||||||
|
fn size() -> usize {
|
||||||
|
192
|
||||||
|
}
|
||||||
|
|
||||||
|
fn p() -> U192 {
|
||||||
|
U192::from([0xffffffffffffffff, 0xfffffffffffffffe, 0xffffffffffffffff])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn n() -> U192 {
|
||||||
|
U192::from([0x146bc9b1b4d22831, 0xffffffff99def836, 0xffffffffffffffff])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn SEED() -> U192 {
|
||||||
|
U192::from([0xd38020eae12196d5, 0xc8422f64ed579528, 0x3045ae6f])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c() -> U192 {
|
||||||
|
U192::from([0x5f3d6fe2c745de65, 0x542dcd5fb078b6ef, 0x3099d2bbbfcb2538])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn a() -> U192 {
|
||||||
|
U192::from([0xfffffffffffffffc, 0xfffffffffffffffe, 0xffffffffffffffff])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() -> U192 {
|
||||||
|
U192::from([0xfeb8deecc146b9b1, 0x0fa7e9ab72243049, 0x64210519e59c80e7])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gx() -> I192 {
|
||||||
|
I192::from(U192::from([0xf4ff0afd82ff1012, 0x7cbf20eb43a18800, 0x188da80eb03090f6]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gy() -> I192 {
|
||||||
|
I192::from(U192::from([0x73f977a11e794811, 0x631011ed6b24cdd5, 0x07192b95ffc8da78]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_point(x: Self::Unsigned, y: Self::Unsigned) -> Self::Point {
|
||||||
|
Point::<P192>{ x: I192::from(x), y: I192::from(y) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NIST curve P-224 (FIPS 186-4, page 102), a.k.a. secp224r1 from RFC5480
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct P224 {}
|
||||||
|
|
||||||
|
impl EllipticCurve for P224 {
|
||||||
|
type Unsigned = U256;
|
||||||
|
type Signed = I256;
|
||||||
|
type Point = Point<P224>;
|
||||||
|
|
||||||
|
fn size() -> usize {
|
||||||
|
224
|
||||||
|
}
|
||||||
|
|
||||||
|
fn p() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x01
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn n() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
|
||||||
|
0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
|
||||||
|
0x5c, 0x5c, 0x2a, 0x3d
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn SEED() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0xbd, 0x71, 0x34, 0x47, 0x99, 0xd5, 0xc7, 0xfc,
|
||||||
|
0xdc, 0x45, 0xb5, 0x9f, 0xa3, 0xb9, 0xab, 0x8f,
|
||||||
|
0x6a, 0x94, 0x8b, 0xc5
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0x5b, 0x05, 0x6c, 0x7e, 0x11, 0xdd, 0x68, 0xf4,
|
||||||
|
0x04, 0x69, 0xee, 0x7f, 0x3c, 0x7a, 0x7d, 0x74,
|
||||||
|
0xf7, 0xd1, 0x21, 0x11, 0x65, 0x06, 0xd0, 0x31,
|
||||||
|
0x21, 0x82, 0x91, 0xfb
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn a() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xfe
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0xb4, 0x05, 0x0a, 0x85, 0x0c, 0x04, 0xb3, 0xab,
|
||||||
|
0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7,
|
||||||
|
0xd7, 0xbf, 0xd8, 0xba, 0x27, 0x0b, 0x39, 0x43,
|
||||||
|
0x23, 0x55, 0xff, 0xb4
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gx() -> I256 {
|
||||||
|
I256::from(U256::from_bytes(&[
|
||||||
|
0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f,
|
||||||
|
0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3,
|
||||||
|
0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6,
|
||||||
|
0x11, 0x5c, 0x1d, 0x21
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gy() -> I256 {
|
||||||
|
I256::from(U256::from_bytes(&[
|
||||||
|
0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb,
|
||||||
|
0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0,
|
||||||
|
0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
|
||||||
|
0x85, 0x00, 0x7e, 0x34
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_point(x: Self::Unsigned, y: Self::Unsigned) -> Self::Point {
|
||||||
|
Point::<P224>{ x: I256::from(x), y: I256::from(y) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NIST curve P-256 (FIPS 186-4, page 102-103), a.k.a. secp256r1 from RFC5480
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct P256 {}
|
||||||
|
|
||||||
|
impl EllipticCurve for P256 {
|
||||||
|
type Signed = I256;
|
||||||
|
type Unsigned = U256;
|
||||||
|
type Point = Point<P256>;
|
||||||
|
|
||||||
|
fn size() -> usize {
|
||||||
|
256
|
||||||
|
}
|
||||||
|
|
||||||
|
fn p() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn n() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84,
|
||||||
|
0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn SEED() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93,
|
||||||
|
0x6a, 0x66, 0x78, 0xe1, 0x13, 0x9d, 0x26, 0xb7,
|
||||||
|
0x81, 0x9f, 0x7e, 0x90
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn c() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0x7e, 0xfb, 0xa1, 0x66, 0x29, 0x85, 0xbe, 0x94,
|
||||||
|
0x03, 0xcb, 0x05, 0x5c, 0x75, 0xd4, 0xf7, 0xe0,
|
||||||
|
0xce, 0x8d, 0x84, 0xa9, 0xc5, 0x11, 0x4a, 0xbc,
|
||||||
|
0xaf, 0x31, 0x77, 0x68, 0x01, 0x04, 0xfa, 0x0d
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn a() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() -> U256 {
|
||||||
|
U256::from_bytes(&[
|
||||||
|
0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7,
|
||||||
|
0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc,
|
||||||
|
0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6,
|
||||||
|
0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gx() -> I256 {
|
||||||
|
I256::from(U256::from_bytes(&[
|
||||||
|
0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
|
||||||
|
0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2,
|
||||||
|
0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
|
||||||
|
0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gy() -> I256 {
|
||||||
|
I256::from(U256::from_bytes(&[
|
||||||
|
0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b,
|
||||||
|
0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
|
||||||
|
0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
|
||||||
|
0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_point(x: Self::Unsigned, y: Self::Unsigned) -> Self::Point {
|
||||||
|
Point::<P256>{ x: I256::from(x), y: I256::from(y) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NIST curve P-384 (FIPS 186-4, page 103-104), a.k.a. secp384r1 from RFC5480
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct P384 {}
|
||||||
|
|
||||||
|
impl EllipticCurve for P384 {
|
||||||
|
type Signed = I384;
|
||||||
|
type Unsigned = U384;
|
||||||
|
type Point = Point<P384>;
|
||||||
|
|
||||||
|
fn size() -> usize {
|
||||||
|
384
|
||||||
|
}
|
||||||
|
|
||||||
|
fn p() -> U384 {
|
||||||
|
U384::from_bytes(&[
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn n() -> U384 {
|
||||||
|
U384::from_bytes(&[
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf,
|
||||||
|
0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a,
|
||||||
|
0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn SEED() -> U384 {
|
||||||
|
U384::from_bytes(&[
|
||||||
|
0xa3, 0x35, 0x92, 0x6a, 0xa3, 0x19, 0xa2, 0x7a,
|
||||||
|
0x1d, 0x00, 0x89, 0x6a, 0x67, 0x73, 0xa4, 0x82,
|
||||||
|
0x7a, 0xcd, 0xac, 0x73
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c() -> U384 {
|
||||||
|
U384::from_bytes(&[
|
||||||
|
0x79, 0xd1, 0xe6, 0x55, 0xf8, 0x68, 0xf0, 0x2f,
|
||||||
|
0xff, 0x48, 0xdc, 0xde, 0xe1, 0x41, 0x51, 0xdd,
|
||||||
|
0xb8, 0x06, 0x43, 0xc1, 0x40, 0x6d, 0x0c, 0xa1,
|
||||||
|
0x0d, 0xfe, 0x6f, 0xc5, 0x20, 0x09, 0x54, 0x0a,
|
||||||
|
0x49, 0x5e, 0x80, 0x42, 0xea, 0x5f, 0x74, 0x4f,
|
||||||
|
0x6e, 0x18, 0x46, 0x67, 0xcc, 0x72, 0x24, 0x83
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn a() -> U384 {
|
||||||
|
U384::from_bytes(&[
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() -> U384 {
|
||||||
|
U384::from_bytes(&[
|
||||||
|
0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4,
|
||||||
|
0x98, 0x8e, 0x05, 0x6b, 0xe3, 0xf8, 0x2d, 0x19,
|
||||||
|
0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12,
|
||||||
|
0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a,
|
||||||
|
0xc6, 0x56, 0x39, 0x8d, 0x8a, 0x2e, 0xd1, 0x9d,
|
||||||
|
0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gx() -> I384 {
|
||||||
|
I384::from(U384::from_bytes(&[
|
||||||
|
0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37,
|
||||||
|
0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74,
|
||||||
|
0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98,
|
||||||
|
0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38,
|
||||||
|
0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c,
|
||||||
|
0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gy() -> I384 {
|
||||||
|
I384::from(U384::from_bytes(&[
|
||||||
|
0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f,
|
||||||
|
0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29,
|
||||||
|
0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
|
||||||
|
0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0,
|
||||||
|
0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d,
|
||||||
|
0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_point(x: Self::Unsigned, y: Self::Unsigned) -> Self::Point {
|
||||||
|
Point::<P384>{ x: I384::from(x), y: I384::from(y) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NIST curve P-521 (FIPS 186-4, page 104), a.k.a. secp521r1 from RFC5480
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct P521 {}
|
||||||
|
|
||||||
|
impl EllipticCurve for P521 {
|
||||||
|
type Signed = I576;
|
||||||
|
type Unsigned = U576;
|
||||||
|
type Point = Point<P521>;
|
||||||
|
|
||||||
|
fn size() -> usize {
|
||||||
|
521
|
||||||
|
}
|
||||||
|
|
||||||
|
fn p() -> U576 {
|
||||||
|
U576::from_bytes(&[
|
||||||
|
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn n() -> U576 {
|
||||||
|
U576::from_bytes(&[
|
||||||
|
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xfa, 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f,
|
||||||
|
0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09,
|
||||||
|
0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c,
|
||||||
|
0x47, 0xae, 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38,
|
||||||
|
0x64, 0x09
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn SEED() -> U576 {
|
||||||
|
U576::from_bytes(&[
|
||||||
|
0xd0, 0x9e, 0x88, 0x00, 0x29, 0x1c, 0xb8, 0x53,
|
||||||
|
0x96, 0xcc, 0x67, 0x17, 0x39, 0x32, 0x84, 0xaa,
|
||||||
|
0xa0, 0xda, 0x64, 0xba
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c() -> U576 {
|
||||||
|
U576::from_bytes(&[
|
||||||
|
0xb4, 0x8b, 0xfa, 0x5f, 0x42, 0x0a, 0x34, 0x94,
|
||||||
|
0x95, 0x39, 0xd2, 0xbd, 0xfc, 0x26, 0x4e, 0xee,
|
||||||
|
0xeb, 0x07, 0x76, 0x88, 0xe4, 0x4f, 0xbf, 0x0a,
|
||||||
|
0xd8, 0xf6, 0xd0, 0xed, 0xb3, 0x7b, 0xd6, 0xb5,
|
||||||
|
0x33, 0x28, 0x10, 0x00, 0x51, 0x8e, 0x19, 0xf1,
|
||||||
|
0xb9, 0xff, 0xbe, 0x0f, 0xe9, 0xed, 0x8a, 0x3c,
|
||||||
|
0x22, 0x00, 0xb8, 0xf8, 0x75, 0xe5, 0x23, 0x86,
|
||||||
|
0x8c, 0x70, 0xc1, 0xe5, 0xbf, 0x55, 0xba, 0xd6,
|
||||||
|
0x37
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn a() -> U576 {
|
||||||
|
U576::from_bytes(&[
|
||||||
|
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xfc
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() -> U576 {
|
||||||
|
U576::from_bytes(&[
|
||||||
|
0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a,
|
||||||
|
0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40,
|
||||||
|
0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, 0x15,
|
||||||
|
0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09,
|
||||||
|
0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93,
|
||||||
|
0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, 0xbf,
|
||||||
|
0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34,
|
||||||
|
0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, 0x3f,
|
||||||
|
0x00
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gx() -> I576 {
|
||||||
|
I576::from(U576::from_bytes(&[
|
||||||
|
0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04,
|
||||||
|
0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95,
|
||||||
|
0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
|
||||||
|
0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d,
|
||||||
|
0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7,
|
||||||
|
0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
|
||||||
|
0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a,
|
||||||
|
0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5,
|
||||||
|
0xbd, 0x66
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gy() -> I576 {
|
||||||
|
I576::from(U576::from_bytes(&[
|
||||||
|
0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b,
|
||||||
|
0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d,
|
||||||
|
0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
|
||||||
|
0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e,
|
||||||
|
0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4,
|
||||||
|
0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
|
||||||
|
0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72,
|
||||||
|
0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1,
|
||||||
|
0x66, 0x50
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_point(x: Self::Unsigned, y: Self::Unsigned) -> Self::Point {
|
||||||
|
Point::<P521>{ x: I576::from(x), y: I576::from(y) }
|
||||||
|
}
|
||||||
|
}
|
||||||
121
src/ecdsa/mod.rs
Normal file
121
src/ecdsa/mod.rs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
//! The generation and use of ECDSA keys is pretty straightforward, compared
|
||||||
|
//! to DSA and RSA. You should be able to find what you want to do in the
|
||||||
|
//! following code snippet, as an example:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::ecdsa::{ECDSAKeyPair,P384};
|
||||||
|
//! use simple_crypto::sha::SHA256;
|
||||||
|
//!
|
||||||
|
//! // Generate a new ECDSA key for curve P384 (this is a good choice, by
|
||||||
|
//! // the way, if you're wondering which curve to use).
|
||||||
|
//! let mut rng = rand::rngs::OsRng::new().unwrap();
|
||||||
|
//! let kp = ECDSAKeyPair::<P384>::generate(&mut rng);
|
||||||
|
//!
|
||||||
|
//! // Now that you have this key pair, you can sign and verify messages
|
||||||
|
//! // using it. For example, to sign the vector [0,1,2,3,4] with SHA256
|
||||||
|
//! // and then verify that signature, we would write:
|
||||||
|
//! let msg = vec![0,1,2,3,4];
|
||||||
|
//! let sig = kp.private.sign::<SHA256>(&msg);
|
||||||
|
//! assert!( kp.public.verify::<SHA256>(&msg, &sig) );
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
mod curve;
|
||||||
|
pub(crate) mod point;
|
||||||
|
mod private;
|
||||||
|
mod public;
|
||||||
|
|
||||||
|
use cryptonum::signed::{I192,I256,I384,I576};
|
||||||
|
use cryptonum::unsigned::{CryptoNum,Decoder};
|
||||||
|
use cryptonum::unsigned::{U192,U256,U384,U576};
|
||||||
|
use rand::Rng;
|
||||||
|
use rand::distributions::Standard;
|
||||||
|
pub use self::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
||||||
|
use self::point::{ECCPoint,Point};
|
||||||
|
pub use self::private::{ECDSAPrivate,ECCPrivateKey};
|
||||||
|
pub use self::public::{ECDSAPublic,ECCPublicKey};
|
||||||
|
pub use self::public::{ECDSADecodeErr,ECDSAEncodeErr};
|
||||||
|
use super::KeyPair;
|
||||||
|
|
||||||
|
/// An ECDSA key pair for the given curve.
|
||||||
|
pub struct ECDSAKeyPair<Curve: EllipticCurve> {
|
||||||
|
pub public: ECCPublicKey<Curve>,
|
||||||
|
pub private: ECCPrivateKey<Curve>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generic ECDSA key pair that implements one of our known curves, for cases
|
||||||
|
/// when you're not sure which one you're going to have.
|
||||||
|
pub enum ECDSAPair {
|
||||||
|
P192(ECCPublicKey<P192>,ECCPrivateKey<P192>),
|
||||||
|
P224(ECCPublicKey<P224>,ECCPrivateKey<P224>),
|
||||||
|
P256(ECCPublicKey<P256>,ECCPrivateKey<P256>),
|
||||||
|
P384(ECCPublicKey<P384>,ECCPrivateKey<P384>),
|
||||||
|
P521(ECCPublicKey<P521>,ECCPrivateKey<P521>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyPair for ECDSAPair {
|
||||||
|
type Public = ECDSAPublic;
|
||||||
|
type Private = ECDSAPrivate;
|
||||||
|
|
||||||
|
fn new(pu: ECDSAPublic, pr: ECDSAPrivate) -> ECDSAPair
|
||||||
|
{
|
||||||
|
match (pu, pr) {
|
||||||
|
(ECDSAPublic::P192(pbl),ECDSAPrivate::P192(prv)) => ECDSAPair::P192(pbl,prv),
|
||||||
|
(ECDSAPublic::P224(pbl),ECDSAPrivate::P224(prv)) => ECDSAPair::P224(pbl,prv),
|
||||||
|
(ECDSAPublic::P256(pbl),ECDSAPrivate::P256(prv)) => ECDSAPair::P256(pbl,prv),
|
||||||
|
(ECDSAPublic::P384(pbl),ECDSAPrivate::P384(prv)) => ECDSAPair::P384(pbl,prv),
|
||||||
|
(ECDSAPublic::P521(pbl),ECDSAPrivate::P521(prv)) => ECDSAPair::P521(pbl,prv),
|
||||||
|
_ =>
|
||||||
|
panic!("Non-matching public/private pairs in ECDSAPair::new()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_impl {
|
||||||
|
($curve: ident, $un: ident, $si: ident) => {
|
||||||
|
impl KeyPair for ECDSAKeyPair<$curve> {
|
||||||
|
type Public = ECCPublicKey<$curve>;
|
||||||
|
type Private = ECCPrivateKey<$curve>;
|
||||||
|
|
||||||
|
fn new(public: ECCPublicKey<$curve>, private: ECCPrivateKey<$curve>) -> ECDSAKeyPair<$curve>
|
||||||
|
{
|
||||||
|
ECDSAKeyPair{ public, private }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ECDSAKeyPair<$curve> {
|
||||||
|
/// Generate a fresh ECDSA key pair for this curve, given the
|
||||||
|
/// provided random number generator. THIS MUST BE A CRYPTO
|
||||||
|
/// STRONG RNG. If it's not, then you're going to generate weak
|
||||||
|
/// keys and the crypto gremlins will get you.
|
||||||
|
pub fn generate<G: Rng>(rng: &mut G) -> ECDSAKeyPair<$curve>
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
let size = ($curve::size() + 7) / 8;
|
||||||
|
let random_bytes: Vec<u8> = rng.sample_iter(&Standard).take(size).collect();
|
||||||
|
let proposed_d = $un::from_bytes(&random_bytes);
|
||||||
|
|
||||||
|
if proposed_d.is_zero() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if proposed_d >= $curve::n() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let d = $si::from(&proposed_d);
|
||||||
|
let public_point = Point::<$curve>::default().scale(&d);
|
||||||
|
let public = ECCPublicKey::<$curve>::new(public_point);
|
||||||
|
let private = ECCPrivateKey::<$curve>::new(proposed_d);
|
||||||
|
|
||||||
|
return ECDSAKeyPair{ public, private };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_impl!(P192, U192, I192);
|
||||||
|
generate_impl!(P224, U256, I256);
|
||||||
|
generate_impl!(P256, U256, I256);
|
||||||
|
generate_impl!(P384, U384, I384);
|
||||||
|
generate_impl!(P521, U576, I576);
|
||||||
329
src/ecdsa/point.rs
Normal file
329
src/ecdsa/point.rs
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
use cryptonum::signed::*;
|
||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use ecdsa::curve::*;
|
||||||
|
|
||||||
|
pub trait ECCPoint : Sized {
|
||||||
|
type Curve: EllipticCurve;
|
||||||
|
type Scale;
|
||||||
|
|
||||||
|
fn default() -> Self;
|
||||||
|
fn negate(&self) -> Self;
|
||||||
|
fn double(&self) -> Self;
|
||||||
|
fn add(&self, other: &Self) -> Self;
|
||||||
|
fn scale(&self, amt: &Self::Scale) -> Self;
|
||||||
|
fn double_scalar_mult(x1: &Self::Scale, p1: &Self, x2: &Self::Scale, p2: &Self) -> Self
|
||||||
|
{
|
||||||
|
// FIXME: Replace this with something not stupid.
|
||||||
|
let big1 = p1.scale(x1);
|
||||||
|
let big2 = p2.scale(x2);
|
||||||
|
big1.add(&big2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct Point<T: EllipticCurve>
|
||||||
|
{
|
||||||
|
pub x: T::Signed,
|
||||||
|
pub y: T::Signed
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! point_impl
|
||||||
|
{
|
||||||
|
($curve: ident, $base: ident,
|
||||||
|
$s2: ident, $u2: ident,
|
||||||
|
$s2p1: ident, $u2p1: ident) =>
|
||||||
|
{
|
||||||
|
impl Clone for Point<$curve> {
|
||||||
|
fn clone(&self) -> Point<$curve> {
|
||||||
|
Point {
|
||||||
|
x: self.x.clone(),
|
||||||
|
y: self.y.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ECCPoint for Point<$curve> {
|
||||||
|
type Curve = $curve;
|
||||||
|
type Scale = $base;
|
||||||
|
|
||||||
|
fn default() -> Point<$curve>
|
||||||
|
{
|
||||||
|
Point {
|
||||||
|
x: $curve::Gx(),
|
||||||
|
y: $curve::Gy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn negate(&self) -> Point<$curve>
|
||||||
|
{
|
||||||
|
let mut newy = $base::new(false, $curve::p());
|
||||||
|
newy -= &self.y;
|
||||||
|
Point{ x: self.x.clone(), y: newy }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn double(&self) -> Point<$curve>
|
||||||
|
{
|
||||||
|
let up = $curve::p();
|
||||||
|
let bigp = $s2::new(false, $u2::from(&up));
|
||||||
|
// lambda = (3 * xp ^ 2 + a) / 2 yp
|
||||||
|
let xsquared = self.x.square();
|
||||||
|
let mut lambda_top = &xsquared * 3u64;
|
||||||
|
lambda_top += $s2p1::new(false, $u2p1::from($curve::a()));
|
||||||
|
let mut lambda_bot = $s2p1::from(&self.y);
|
||||||
|
lambda_bot <<= 1;
|
||||||
|
let lambda = $base::from(lambda_top.moddiv(&lambda_bot, &$s2p1::from(&bigp)));
|
||||||
|
// xr = lambda^2 - 2 xp
|
||||||
|
let mut xr = lambda.square();
|
||||||
|
let mut xr_right = $s2::from(&self.x);
|
||||||
|
xr_right <<= 1;
|
||||||
|
xr -= xr_right;
|
||||||
|
xr %= &bigp;
|
||||||
|
let x = $base::from(xr);
|
||||||
|
// yr = lambda (xp - xr) - yp
|
||||||
|
let xdiff = $base::from(&self.x - &x);
|
||||||
|
let mut yr = &lambda * &xdiff;
|
||||||
|
yr -= $s2::from(&self.y);
|
||||||
|
let y = $base::from(&yr % &bigp);
|
||||||
|
//
|
||||||
|
Point{ x, y }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&self, other: &Point<$curve>) -> Point<$curve>
|
||||||
|
{
|
||||||
|
let mut xdiff = self.x.clone(); xdiff -= &other.x;
|
||||||
|
let mut ydiff = self.y.clone(); ydiff -= &other.y;
|
||||||
|
let signedp = $base::new(false, $curve::p());
|
||||||
|
let s = ydiff.moddiv(&xdiff, &signedp);
|
||||||
|
let mut xr = &s * &s;
|
||||||
|
xr -= $s2::from(&self.x);
|
||||||
|
xr -= $s2::from(&other.x);
|
||||||
|
let bigsignedp = $s2::from(&signedp);
|
||||||
|
xr %= &bigsignedp;
|
||||||
|
let mut yr = $s2::from(&self.x);
|
||||||
|
yr -= &xr;
|
||||||
|
yr *= $s2::from(&s);
|
||||||
|
yr -= $s2::from(&self.y);
|
||||||
|
yr %= &bigsignedp;
|
||||||
|
Point{ x: $base::from(xr), y: $base::from(yr) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scale(&self, d: &$base) -> Point<$curve>
|
||||||
|
{
|
||||||
|
assert!(!d.is_zero());
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let mut Q: Point<$curve> = self.clone();
|
||||||
|
let mut bit = ($base::bit_length() - 1) as isize;
|
||||||
|
|
||||||
|
// Skip down until we hit a set bit
|
||||||
|
while !d.testbit(bit as usize) {
|
||||||
|
bit -= 1;
|
||||||
|
}
|
||||||
|
// drop one
|
||||||
|
bit -= 1;
|
||||||
|
// do the double and add algorithm
|
||||||
|
while bit >= 0 {
|
||||||
|
Q = Q.double();
|
||||||
|
|
||||||
|
let test = d.testbit(bit as usize);
|
||||||
|
if test {
|
||||||
|
Q = Q.add(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
bit -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.is_negative() {
|
||||||
|
Q.negate()
|
||||||
|
} else {
|
||||||
|
Q
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
point_impl!(P192, I192, I384, U384, I448, U448);
|
||||||
|
point_impl!(P224, I256, I512, U512, I576, U576);
|
||||||
|
point_impl!(P256, I256, I512, U512, I576, U576);
|
||||||
|
point_impl!(P384, I384, I768, U768, I832, U832);
|
||||||
|
point_impl!(P521, I576, I1152, U1152, I1216, U1216);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! negate_test_body
|
||||||
|
{
|
||||||
|
($curve: ident, $lcurve: ident, $stype: ident, $utype: ident) => {
|
||||||
|
let fname = build_test_path("ecc/negate",stringify!($curve));
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (negx, xbytes) = case.get("x").unwrap();
|
||||||
|
let (negy, ybytes) = case.get("y").unwrap();
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
|
||||||
|
let x = $stype::new(*negx, $utype::from_bytes(xbytes));
|
||||||
|
let y = $stype::new(*negy, $utype::from_bytes(ybytes));
|
||||||
|
let a = $stype::new(*nega, $utype::from_bytes(abytes));
|
||||||
|
let b = $stype::new(*negb, $utype::from_bytes(bbytes));
|
||||||
|
let point = Point::<$curve>{ x, y };
|
||||||
|
let dbl = point.negate();
|
||||||
|
assert_eq!(a, dbl.x, "x equivalence");
|
||||||
|
assert_eq!(b, dbl.y, "y equivalence");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! double_test_body
|
||||||
|
{
|
||||||
|
($curve: ident, $lcurve: ident, $stype: ident, $utype: ident) => {
|
||||||
|
let fname = build_test_path("ecc/double",stringify!($curve));
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (negx, xbytes) = case.get("x").unwrap();
|
||||||
|
let (negy, ybytes) = case.get("y").unwrap();
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
|
||||||
|
let x = $stype::new(*negx, $utype::from_bytes(xbytes));
|
||||||
|
let y = $stype::new(*negy, $utype::from_bytes(ybytes));
|
||||||
|
let a = $stype::new(*nega, $utype::from_bytes(abytes));
|
||||||
|
let b = $stype::new(*negb, $utype::from_bytes(bbytes));
|
||||||
|
let point = Point::<$curve>{ x, y };
|
||||||
|
let dbl = point.double();
|
||||||
|
assert_eq!(a, dbl.x, "x equivalence");
|
||||||
|
assert_eq!(b, dbl.y, "y equivalence");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! add_test_body
|
||||||
|
{
|
||||||
|
($curve: ident, $lcurve: ident, $stype: ident, $utype: ident) => {
|
||||||
|
let fname = build_test_path("ecc/add",stringify!($curve));
|
||||||
|
run_test(fname.to_string(), 6, move |case| {
|
||||||
|
let (negx, xbytes) = case.get("x").unwrap();
|
||||||
|
let (negy, ybytes) = case.get("y").unwrap();
|
||||||
|
let (negu, ubytes) = case.get("u").unwrap();
|
||||||
|
let (negv, vbytes) = case.get("v").unwrap();
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
|
||||||
|
let x = $stype::new(*negx, $utype::from_bytes(xbytes));
|
||||||
|
let y = $stype::new(*negy, $utype::from_bytes(ybytes));
|
||||||
|
let u = $stype::new(*negu, $utype::from_bytes(ubytes));
|
||||||
|
let v = $stype::new(*negv, $utype::from_bytes(vbytes));
|
||||||
|
let a = $stype::new(*nega, $utype::from_bytes(abytes));
|
||||||
|
let b = $stype::new(*negb, $utype::from_bytes(bbytes));
|
||||||
|
let point1 = Point::<$curve>{ x: x, y: y };
|
||||||
|
let point2 = Point::<$curve>{ x: u, y: v };
|
||||||
|
let res = point1.add(&point2);
|
||||||
|
assert_eq!(a, res.x, "x equivalence");
|
||||||
|
assert_eq!(b, res.y, "y equivalence");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! scale_test_body
|
||||||
|
{
|
||||||
|
($curve: ident, $lcurve: ident, $stype: ident, $utype: ident) => {
|
||||||
|
let fname = build_test_path("ecc/scale",stringify!($curve));
|
||||||
|
run_test(fname.to_string(), 5, |case| {
|
||||||
|
let (negx, xbytes) = case.get("x").unwrap();
|
||||||
|
let (negy, ybytes) = case.get("y").unwrap();
|
||||||
|
let (negk, kbytes) = case.get("k").unwrap();
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
|
||||||
|
let x = $stype::new(*negx, $utype::from_bytes(xbytes));
|
||||||
|
let y = $stype::new(*negy, $utype::from_bytes(ybytes));
|
||||||
|
let k = $stype::new(*negk, $utype::from_bytes(kbytes));
|
||||||
|
let a = $stype::new(*nega, $utype::from_bytes(abytes));
|
||||||
|
let b = $stype::new(*negb, $utype::from_bytes(bbytes));
|
||||||
|
let point = Point::<$curve>{ x: x, y: y };
|
||||||
|
let res = point.scale(&k);
|
||||||
|
assert_eq!(a, res.x, "x equivalence");
|
||||||
|
assert_eq!(b, res.y, "y equivalence");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! add_scale2_test_body
|
||||||
|
{
|
||||||
|
($curve: ident, $lcurve: ident, $stype: ident, $utype: ident) => {
|
||||||
|
let fname = build_test_path("ecc/add_scale2",stringify!($curve));
|
||||||
|
run_test(fname.to_string(), 8, |case| {
|
||||||
|
let (negx, xbytes) = case.get("x").unwrap();
|
||||||
|
let (negy, ybytes) = case.get("y").unwrap();
|
||||||
|
let (negp, pbytes) = case.get("p").unwrap();
|
||||||
|
let (negq, qbytes) = case.get("q").unwrap();
|
||||||
|
let (negn, nbytes) = case.get("n").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negr, rbytes) = case.get("r").unwrap();
|
||||||
|
let (negs, sbytes) = case.get("s").unwrap();
|
||||||
|
|
||||||
|
let x = $stype::new(*negx, $utype::from_bytes(xbytes));
|
||||||
|
let y = $stype::new(*negy, $utype::from_bytes(ybytes));
|
||||||
|
let p = $stype::new(*negp, $utype::from_bytes(pbytes));
|
||||||
|
let q = $stype::new(*negq, $utype::from_bytes(qbytes));
|
||||||
|
let n = $stype::new(*negn, $utype::from_bytes(nbytes));
|
||||||
|
let m = $stype::new(*negm, $utype::from_bytes(mbytes));
|
||||||
|
let r = $stype::new(*negr, $utype::from_bytes(rbytes));
|
||||||
|
let s = $stype::new(*negs, $utype::from_bytes(sbytes));
|
||||||
|
let p1 = Point::<$curve>{ x: x, y: y };
|
||||||
|
let p2 = Point::<$curve>{ x: p, y: q };
|
||||||
|
let res = Point::<$curve>::double_scalar_mult(&n, &p1, &m, &p2);
|
||||||
|
assert_eq!(r, res.x, "x equivalence");
|
||||||
|
assert_eq!(s, res.y, "y equivalence");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! point_tests
|
||||||
|
{
|
||||||
|
($curve: ident, $lcurve: ident, $stype: ident, $utype: ident) => {
|
||||||
|
#[cfg(test)]
|
||||||
|
mod $lcurve {
|
||||||
|
use super::*;
|
||||||
|
use testing::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn negate() { negate_test_body!($curve, $lcurve, $stype, $utype); }
|
||||||
|
#[test]
|
||||||
|
fn double() { double_test_body!($curve, $lcurve, $stype, $utype); }
|
||||||
|
#[test]
|
||||||
|
fn add() { add_test_body!($curve, $lcurve, $stype, $utype); }
|
||||||
|
#[test]
|
||||||
|
fn scale() { scale_test_body!($curve, $lcurve, $stype, $utype); }
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn add_scale2() { add_scale2_test_body!($curve, $lcurve, $stype, $utype); }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(ignore_expensive $curve: ident, $lcurve: ident, $stype: ident, $utype: ident) => {
|
||||||
|
#[cfg(test)]
|
||||||
|
mod $lcurve {
|
||||||
|
use super::*;
|
||||||
|
use testing::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn negate() { negate_test_body!($curve, $lcurve, $stype, $utype); }
|
||||||
|
#[test]
|
||||||
|
fn double() { double_test_body!($curve, $lcurve, $stype, $utype); }
|
||||||
|
#[test]
|
||||||
|
fn add() { add_test_body!($curve, $lcurve, $stype, $utype); }
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn scale() { scale_test_body!($curve, $lcurve, $stype, $utype); }
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn add_scale2() { add_scale2_test_body!($curve, $lcurve, $stype, $utype); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
point_tests!(P192, p192, I192, U192);
|
||||||
|
point_tests!(ignore_expensive P224, p224, I256, U256);
|
||||||
|
point_tests!(ignore_expensive P256, p256, I256, U256);
|
||||||
|
point_tests!(ignore_expensive P384, p384, I384, U384);
|
||||||
|
point_tests!(ignore_expensive P521, p521, I576, U576);
|
||||||
179
src/ecdsa/private.rs
Normal file
179
src/ecdsa/private.rs
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
use cryptonum::signed::*;
|
||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use dsa::rfc6979::{DSASignature,KIterator,bits2int};
|
||||||
|
use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
||||||
|
use ecdsa::point::{ECCPoint,Point};
|
||||||
|
use sha::Hash;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// A private key for the given curve.
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub struct ECCPrivateKey<Curve: EllipticCurve> {
|
||||||
|
pub(crate) d: Curve::Unsigned
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Curve: EllipticCurve> fmt::Debug for ECCPrivateKey<Curve> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error>
|
||||||
|
{
|
||||||
|
f.write_str("<ECCPrivateKey>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generic private key.
|
||||||
|
pub enum ECDSAPrivate {
|
||||||
|
P192(ECCPrivateKey<P192>),
|
||||||
|
P224(ECCPrivateKey<P224>),
|
||||||
|
P256(ECCPrivateKey<P256>),
|
||||||
|
P384(ECCPrivateKey<P384>),
|
||||||
|
P521(ECCPrivateKey<P521>),
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_privates
|
||||||
|
{
|
||||||
|
($curve: ident, $base: ident, $sig: ident, $dbl: ident, $quad: ident) => {
|
||||||
|
impl ECCPrivateKey<$curve>
|
||||||
|
{
|
||||||
|
/// Generate a new private key using the given private scalar.
|
||||||
|
pub fn new(d: $base) -> ECCPrivateKey<$curve>
|
||||||
|
{
|
||||||
|
ECCPrivateKey{ d }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sign the given message with the current key, using the hash provided
|
||||||
|
/// in the type.
|
||||||
|
pub fn sign<H: Hash + Clone>(&self, m: &[u8]) -> DSASignature<$base>
|
||||||
|
{
|
||||||
|
// 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 = <H>::hash(m);
|
||||||
|
let size = <$curve>::size();
|
||||||
|
let h0: $base = bits2int(&h1, size);
|
||||||
|
let n = <$curve>::n();
|
||||||
|
let h = h0 % &n;
|
||||||
|
|
||||||
|
// 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::<H,$base>::new(&h1, size, &n, &self.d) {
|
||||||
|
// 3. A value r (modulo q) is computed from k and the key
|
||||||
|
// parameters:
|
||||||
|
// * For DSA ...
|
||||||
|
// * 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 g = Point::<$curve>::default();
|
||||||
|
let ki = $sig::new(false, k.clone());
|
||||||
|
let kg = g.scale(&ki);
|
||||||
|
let ni = $sig::from(&n);
|
||||||
|
let ri = &kg.x % ∋
|
||||||
|
if ri.is_zero() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ri.is_negative() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let r = $base::from(ri);
|
||||||
|
// 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(&n) {
|
||||||
|
let mut hxr = &self.d * &r;
|
||||||
|
hxr += $dbl::from(&h);
|
||||||
|
let base = hxr * $dbl::from(kinv);
|
||||||
|
let s = $base::from(base % $quad::from(n));
|
||||||
|
return DSASignature{ r, s };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic!("The world is broken; couldn't find a k in sign().");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_privates!(P192, U192, I192, U384, U768);
|
||||||
|
generate_privates!(P224, U256, I256, U512, U1024);
|
||||||
|
generate_privates!(P256, U256, I256, U512, U1024);
|
||||||
|
generate_privates!(P384, U384, I384, U768, U1536);
|
||||||
|
generate_privates!(P521, U576, I576, U1152, U2304);
|
||||||
|
|
||||||
|
/************* TESTING ********************************************************/
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::*;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! sign_test_body
|
||||||
|
{
|
||||||
|
($name: ident, $curve: ident, $base: ident) => {
|
||||||
|
let fname = build_test_path("ecc/sign",stringify!($curve));
|
||||||
|
run_test(fname.to_string(), 9, |case| {
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
let (negk, _bytes) = case.get("k").unwrap();
|
||||||
|
let (negx, xbytes) = case.get("x").unwrap();
|
||||||
|
let (negy, ybytes) = case.get("y").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negh, hbytes) = case.get("h").unwrap();
|
||||||
|
let (negr, rbytes) = case.get("r").unwrap();
|
||||||
|
let (negs, sbytes) = case.get("s").unwrap();
|
||||||
|
|
||||||
|
assert!(!negd && !negk && !negx && !negy &&
|
||||||
|
!negm && !negh && !negr && !negs);
|
||||||
|
let d = $base::from_bytes(dbytes);
|
||||||
|
let _ = $base::from_bytes(xbytes);
|
||||||
|
let _ = $base::from_bytes(ybytes);
|
||||||
|
let h = $base::from_bytes(hbytes);
|
||||||
|
let r = $base::from_bytes(rbytes);
|
||||||
|
let s = $base::from_bytes(sbytes);
|
||||||
|
|
||||||
|
let private = ECCPrivateKey::<$curve>::new(d);
|
||||||
|
let sig = match usize::from(h) {
|
||||||
|
224 => private.sign::<SHA224>(mbytes),
|
||||||
|
256 => private.sign::<SHA256>(mbytes),
|
||||||
|
384 => private.sign::<SHA384>(mbytes),
|
||||||
|
512 => private.sign::<SHA512>(mbytes),
|
||||||
|
x => panic!("Unknown hash algorithm {}", x)
|
||||||
|
};
|
||||||
|
assert_eq!(r, sig.r, "r signature check");
|
||||||
|
assert_eq!(s, sig.s, "s signature check");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_tests {
|
||||||
|
($name: ident, $curve: ident, $base: ident) => {
|
||||||
|
#[test]
|
||||||
|
fn $name() {
|
||||||
|
sign_test_body!($name, $curve, $base);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(ignore $name: ident, $curve: ident, $base: ident) => {
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn $name() {
|
||||||
|
sign_test_body!($name, $curve, $base);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_tests!(p192_sign, P192, U192);
|
||||||
|
generate_tests!(ignore p224_sign, P224, U256);
|
||||||
|
generate_tests!(ignore p256_sign, P256, U256);
|
||||||
|
generate_tests!(ignore p384_sign, P384, U384);
|
||||||
|
generate_tests!(ignore p521_sign, P521, U576);
|
||||||
230
src/ecdsa/public.rs
Normal file
230
src/ecdsa/public.rs
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
use cryptonum::signed::*;
|
||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use dsa::rfc6979::DSASignature;
|
||||||
|
use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
||||||
|
use ecdsa::point::{ECCPoint,Point};
|
||||||
|
use sha::Hash;
|
||||||
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1DecodeErr,ASN1EncodeErr,FromASN1,ToASN1};
|
||||||
|
use std::cmp::min;
|
||||||
|
|
||||||
|
/// An ECDSA public key for the given curve.
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct ECCPublicKey<Curve: EllipticCurve> {
|
||||||
|
pub(crate) q: Point<Curve>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generic ECDSA public key, when you're not sure which curve you're
|
||||||
|
/// going to get.
|
||||||
|
pub enum ECDSAPublic {
|
||||||
|
P192(ECCPublicKey<P192>),
|
||||||
|
P224(ECCPublicKey<P224>),
|
||||||
|
P256(ECCPublicKey<P256>),
|
||||||
|
P384(ECCPublicKey<P384>),
|
||||||
|
P521(ECCPublicKey<P521>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An error that can occur when encoding an ECDSA public key as an ASN.1
|
||||||
|
/// object.
|
||||||
|
pub enum ECDSAEncodeErr {
|
||||||
|
ASN1EncodeErr(ASN1EncodeErr),
|
||||||
|
XValueNegative, YValueNegative
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ASN1EncodeErr> for ECDSAEncodeErr {
|
||||||
|
fn from(x: ASN1EncodeErr) -> ECDSAEncodeErr {
|
||||||
|
ECDSAEncodeErr::ASN1EncodeErr(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An error that can occur when decoding an ECDSA public key from an
|
||||||
|
/// ASN.1 blob.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ECDSADecodeErr {
|
||||||
|
ASN1DecodeErr(ASN1DecodeErr),
|
||||||
|
NoKeyFound,
|
||||||
|
InvalidKeyFormat,
|
||||||
|
InvalidKeyBlockSize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ASN1DecodeErr> for ECDSADecodeErr {
|
||||||
|
fn from(x: ASN1DecodeErr) -> ECDSADecodeErr {
|
||||||
|
ECDSADecodeErr::ASN1DecodeErr(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! public_impl {
|
||||||
|
($curve: ident, $un: ident, $si: ident) => {
|
||||||
|
impl ECCPublicKey<$curve>
|
||||||
|
{
|
||||||
|
/// Generate a new public key object from the given public point.
|
||||||
|
pub fn new(q: Point<$curve>) -> ECCPublicKey<$curve>
|
||||||
|
{
|
||||||
|
ECCPublicKey{ q }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the given message matches the given signature,
|
||||||
|
/// assuming the provided hash function.
|
||||||
|
pub fn verify<H: Hash>(&self, m: &[u8], sig: &DSASignature<$un>) -> bool
|
||||||
|
{
|
||||||
|
let n = <$curve>::n();
|
||||||
|
|
||||||
|
if sig.r.is_zero() || (sig.r >= n) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if sig.s.is_zero() || (sig.s >= n) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// e = the leftmost min(N, outlen) bits of Hash(M').
|
||||||
|
let mut digest_bytes = <H>::hash(m);
|
||||||
|
let len = min(digest_bytes.len(), $curve::size() / 8);
|
||||||
|
digest_bytes.truncate(len);
|
||||||
|
|
||||||
|
if let Some(c) = sig.s.modinv(&n) {
|
||||||
|
let e = $un::from_bytes(&digest_bytes);
|
||||||
|
let u1 = e.modmul(&c, &n);
|
||||||
|
let u2 = sig.r.modmul(&c, &n);
|
||||||
|
let g = Point::<$curve>::default();
|
||||||
|
let u1i = $si::from(u1);
|
||||||
|
let u2i = $si::from(u2);
|
||||||
|
let point = Point::<$curve>::double_scalar_mult(&u1i, &g, &u2i, &self.q);
|
||||||
|
!point.x.is_negative() && (sig.r == $un::from(point.x))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for ECCPublicKey<$curve> {
|
||||||
|
type Error = ECDSAEncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class) -> Result<Vec<ASN1Block>,ECDSAEncodeErr>
|
||||||
|
{
|
||||||
|
if self.q.x.is_negative() {
|
||||||
|
return Err(ECDSAEncodeErr::XValueNegative);
|
||||||
|
}
|
||||||
|
if self.q.y.is_negative() {
|
||||||
|
return Err(ECDSAEncodeErr::YValueNegative);
|
||||||
|
}
|
||||||
|
|
||||||
|
let xval = $un::from(&self.q.x);
|
||||||
|
let yval = $un::from(&self.q.y);
|
||||||
|
let mut xbytes = xval.to_bytes();
|
||||||
|
let mut ybytes = yval.to_bytes();
|
||||||
|
let goalsize = ($curve::size() + 7) / 8;
|
||||||
|
let mut target = Vec::with_capacity(1 + (goalsize * 2));
|
||||||
|
|
||||||
|
while xbytes.len() > goalsize { xbytes.remove(0); };
|
||||||
|
while xbytes.len() < goalsize { xbytes.insert(0,0) };
|
||||||
|
while ybytes.len() > goalsize { ybytes.remove(0); };
|
||||||
|
while ybytes.len() < goalsize { ybytes.insert(0,0) };
|
||||||
|
|
||||||
|
target.push(4);
|
||||||
|
target.append(&mut xbytes);
|
||||||
|
target.append(&mut ybytes);
|
||||||
|
|
||||||
|
let result = ASN1Block::BitString(c, 0, target.len() * 8, target);
|
||||||
|
Ok(vec![result])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for ECCPublicKey<$curve> {
|
||||||
|
type Error = ECDSADecodeErr;
|
||||||
|
|
||||||
|
fn from_asn1(bs: &[ASN1Block]) -> Result<(ECCPublicKey<$curve>,&[ASN1Block]),ECDSADecodeErr>
|
||||||
|
{
|
||||||
|
let (x, rest) = bs.split_first().ok_or(ECDSADecodeErr::NoKeyFound)?;
|
||||||
|
if let ASN1Block::BitString(_, _, _, target) = x {
|
||||||
|
let (hdr, xy_bstr) = target.split_first().ok_or(ECDSADecodeErr::InvalidKeyFormat)?;
|
||||||
|
if *hdr != 4 {
|
||||||
|
return Err(ECDSADecodeErr::InvalidKeyFormat);
|
||||||
|
}
|
||||||
|
let goalsize = ($curve::size() + 7) / 8;
|
||||||
|
if xy_bstr.len() != (2 * goalsize) {
|
||||||
|
return Err(ECDSADecodeErr::InvalidKeyBlockSize);
|
||||||
|
}
|
||||||
|
let (xbstr, ybstr) = xy_bstr.split_at(goalsize);
|
||||||
|
let x = $un::from_bytes(xbstr);
|
||||||
|
let y = $un::from_bytes(ybstr);
|
||||||
|
let point = Point::<$curve>{ x: $si::from(x), y: $si::from(y) };
|
||||||
|
let res = ECCPublicKey::<$curve>::new(point);
|
||||||
|
Ok((res, rest))
|
||||||
|
} else {
|
||||||
|
Err(ECDSADecodeErr::InvalidKeyFormat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public_impl!(P192, U192, I192);
|
||||||
|
public_impl!(P224, U256, I256);
|
||||||
|
public_impl!(P256, U256, I256);
|
||||||
|
public_impl!(P384, U384, I384);
|
||||||
|
public_impl!(P521, U576, I576);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::*;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! verify_test_body
|
||||||
|
{
|
||||||
|
($name: ident, $curve: ident, $un: ident, $si: ident) => {
|
||||||
|
let fname = build_test_path("ecc/sign",stringify!($curve));
|
||||||
|
run_test(fname.to_string(), 9, |case| {
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
let (negk, _bytes) = case.get("k").unwrap();
|
||||||
|
let (negx, xbytes) = case.get("x").unwrap();
|
||||||
|
let (negy, ybytes) = case.get("y").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negh, hbytes) = case.get("h").unwrap();
|
||||||
|
let (negr, rbytes) = case.get("r").unwrap();
|
||||||
|
let (negs, sbytes) = case.get("s").unwrap();
|
||||||
|
|
||||||
|
assert!(!negd && !negk && !negx && !negy &&
|
||||||
|
!negm && !negh && !negr && !negs);
|
||||||
|
let _ = $un::from_bytes(dbytes);
|
||||||
|
let x = $un::from_bytes(xbytes);
|
||||||
|
let y = $un::from_bytes(ybytes);
|
||||||
|
let h = $un::from_bytes(hbytes);
|
||||||
|
let r = $un::from_bytes(rbytes);
|
||||||
|
let s = $un::from_bytes(sbytes);
|
||||||
|
|
||||||
|
let point = Point::<$curve>{ x: $si::from(x), y: $si::from(y) };
|
||||||
|
let public = ECCPublicKey::<$curve>::new(point);
|
||||||
|
let sig = DSASignature::new(r, s);
|
||||||
|
match usize::from(h) {
|
||||||
|
224 => assert!(public.verify::<SHA224>(mbytes, &sig)),
|
||||||
|
256 => assert!(public.verify::<SHA256>(mbytes, &sig)),
|
||||||
|
384 => assert!(public.verify::<SHA384>(mbytes, &sig)),
|
||||||
|
512 => assert!(public.verify::<SHA512>(mbytes, &sig)),
|
||||||
|
x => panic!("Unknown hash algorithm {}", x)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! test_impl {
|
||||||
|
($name: ident, $curve: ident, $un: ident, $si: ident) => {
|
||||||
|
#[test]
|
||||||
|
fn $name() {
|
||||||
|
verify_test_body!($name, $curve, $un, $si);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(ignore $name: ident, $curve: ident, $un: ident, $si: ident) => {
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn $name() {
|
||||||
|
verify_test_body!($name, $curve, $un, $si);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test_impl!(p192,P192,U192,I192);
|
||||||
|
test_impl!(p224,P224,U256,I256);
|
||||||
|
test_impl!(ignore p256,P256,U256,I256);
|
||||||
|
test_impl!(ignore p384,P384,U384,I384);
|
||||||
|
test_impl!(ignore p521,P521,U576,I576);
|
||||||
1500
src/ed25519/constants.rs
Normal file
1500
src/ed25519/constants.rs
Normal file
File diff suppressed because it is too large
Load Diff
1090
src/ed25519/fe.rs
Normal file
1090
src/ed25519/fe.rs
Normal file
File diff suppressed because it is too large
Load Diff
33
src/ed25519/loads.rs
Normal file
33
src/ed25519/loads.rs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
use cryptonum::unsigned::{Decoder,U192};
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
pub fn load3(x: &[u8]) -> u64
|
||||||
|
{
|
||||||
|
(x[0] as u64) | ((x[1] as u64) << 8) | ((x[2] as u64) << 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load4(x: &[u8]) -> u64
|
||||||
|
{
|
||||||
|
(x[0] as u64) | ((x[1] as u64) << 8) |
|
||||||
|
((x[2] as u64) << 16) | ((x[3] as u64) << 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn loads() {
|
||||||
|
let fname = "testdata/ed25519/load.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negx, xbytes) = case.get("x").unwrap();
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
|
||||||
|
assert!(!negx && !nega && !negb);
|
||||||
|
let res3 = u64::from(U192::from_bytes(abytes));
|
||||||
|
let res4 = u64::from(U192::from_bytes(bbytes));
|
||||||
|
assert_eq!(res3, load3(&xbytes), "load3");
|
||||||
|
assert_eq!(res4, load4(&xbytes), "load4");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
267
src/ed25519/mod.rs
Normal file
267
src/ed25519/mod.rs
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
//! The generation and use of ED25519 keys is the most straightforward
|
||||||
|
//! of all the asymmetric crypto schemes, because you basically get no
|
||||||
|
//! choices. There's just one key size, and you're going to use the
|
||||||
|
//! built-in hash (which is a good one, if you were worried). So if
|
||||||
|
//! you're not sure, this is a pretty good choice.
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::ed25519::ED25519KeyPair;
|
||||||
|
//!
|
||||||
|
//! // Generate a new ED25519 key
|
||||||
|
//! let mut rng = rand::rngs::OsRng::new().unwrap();
|
||||||
|
//! let kp = ED25519KeyPair::generate(&mut rng);
|
||||||
|
//!
|
||||||
|
//! // Now that you have this key pair, you can sign and verify messages
|
||||||
|
//! // using it. For example, to sign the vector [0,1,2,3,4] and then
|
||||||
|
//! // verify that signature, we would write:
|
||||||
|
//! let msg = vec![0,1,2,3,4];
|
||||||
|
//! let sig = kp.private.sign(&msg);
|
||||||
|
//! assert!( kp.public.verify(&msg, &sig) );
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
mod constants;
|
||||||
|
mod fe;
|
||||||
|
mod loads;
|
||||||
|
mod point;
|
||||||
|
mod scalars;
|
||||||
|
|
||||||
|
use rand::Rng;
|
||||||
|
use sha::{Hash,SHA512};
|
||||||
|
use self::scalars::{curve25519_scalar_mask,x25519_sc_muladd,x25519_sc_reduce};
|
||||||
|
use self::point::{Point,Point2};
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
#[cfg(test)]
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use super::KeyPair;
|
||||||
|
|
||||||
|
/// An ED25519 key pair
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct ED25519KeyPair
|
||||||
|
{
|
||||||
|
pub public: ED25519Public,
|
||||||
|
pub private: ED25519Private
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyPair for ED25519KeyPair
|
||||||
|
{
|
||||||
|
type Public = ED25519Public;
|
||||||
|
type Private = ED25519Private;
|
||||||
|
|
||||||
|
fn new(pbl: ED25519Public, prv: ED25519Private) -> ED25519KeyPair
|
||||||
|
{
|
||||||
|
ED25519KeyPair {
|
||||||
|
public: pbl,
|
||||||
|
private: prv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ED25519KeyPair
|
||||||
|
{
|
||||||
|
/// Generate a random ED25519 key pair, using the given random number
|
||||||
|
/// generator. You really need to use a good, cryptographically-strong
|
||||||
|
/// RNG if you want good keys.
|
||||||
|
pub fn generate<G: Rng>(rng: &mut G) -> ED25519KeyPair
|
||||||
|
{
|
||||||
|
let mut seed = [0; 32];
|
||||||
|
rng.fill_bytes(&mut seed);
|
||||||
|
let private = ED25519Private::from_seed(&seed);
|
||||||
|
let public = ED25519Public::from(&private);
|
||||||
|
ED25519KeyPair::new(public, private)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate the ED25519 key pair defined by the given seed value.
|
||||||
|
/// This should be a block of 32 bytes.
|
||||||
|
pub fn from_seed(seed: &[u8]) -> ED25519KeyPair
|
||||||
|
{
|
||||||
|
let private = ED25519Private::from_seed(seed);
|
||||||
|
let public = ED25519Public::from(&private);
|
||||||
|
ED25519KeyPair{ public, private }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An ED25519 private key.
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct ED25519Private
|
||||||
|
{
|
||||||
|
seed: [u8; 32],
|
||||||
|
private: [u8; 32],
|
||||||
|
prefix: [u8; 32],
|
||||||
|
public: [u8; 32]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ED25519Private {
|
||||||
|
/// Generate the ED25519 private key defined by the given 32 byte seed
|
||||||
|
/// value.
|
||||||
|
pub fn from_seed(seed: &[u8]) -> ED25519Private {
|
||||||
|
let mut result = ED25519Private {
|
||||||
|
seed: [0; 32],
|
||||||
|
private: [0; 32],
|
||||||
|
prefix: [0; 32],
|
||||||
|
public: [0; 32]
|
||||||
|
};
|
||||||
|
result.seed.copy_from_slice(seed);
|
||||||
|
let mut expanded = SHA512::hash(seed);
|
||||||
|
let (private, prefix) = expanded.split_at_mut(32);
|
||||||
|
result.private.copy_from_slice(private);
|
||||||
|
result.prefix.copy_from_slice(prefix);
|
||||||
|
curve25519_scalar_mask(&mut result.private);
|
||||||
|
let a = Point::scalarmult_base(&result.private);
|
||||||
|
result.public.copy_from_slice(&a.encode());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sign the given message, returning the signature. Unlike most other
|
||||||
|
/// public/private schemes, you don't get a choice on the hash used to
|
||||||
|
/// compute this signature. (On the bright side, it's SHA2-512.)
|
||||||
|
pub fn sign(&self, msg: &[u8]) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut signature_s = [0u8; 32];
|
||||||
|
|
||||||
|
let mut ctx = SHA512::new();
|
||||||
|
ctx.update(&self.prefix);
|
||||||
|
ctx.update(&msg);
|
||||||
|
let nonce = digest_scalar(&ctx.finalize());
|
||||||
|
let r = Point::scalarmult_base(&nonce);
|
||||||
|
let signature_r = r.encode();
|
||||||
|
let hram_digest = eddsa_digest(&signature_r, &self.public, &msg);
|
||||||
|
let hram = digest_scalar(&hram_digest);
|
||||||
|
x25519_sc_muladd(&mut signature_s, &hram, &self.private, &nonce);
|
||||||
|
let mut result = Vec::with_capacity(64);
|
||||||
|
result.extend_from_slice(&signature_r);
|
||||||
|
result.extend_from_slice(&signature_s);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Covert the given private key into its byte representation. This is
|
||||||
|
/// guaranteed to be exactly 32 bytes.
|
||||||
|
pub fn to_bytes(&self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
self.seed.to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An ED25519 Public key
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct ED25519Public
|
||||||
|
{
|
||||||
|
bytes: [u8; 32],
|
||||||
|
point: Point
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a ED25519Private> for ED25519Public
|
||||||
|
{
|
||||||
|
fn from(x: &ED25519Private) -> ED25519Public
|
||||||
|
{
|
||||||
|
ED25519Public::new(&x.public).expect("Broke converting private ED25519 to public. (?!)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The kinds of errors you can get when you try to generate a public key from,
|
||||||
|
/// for example, an unknown block of bytes.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ED25519PublicImportError
|
||||||
|
{
|
||||||
|
WrongNumberOfBytes(usize),
|
||||||
|
InvalidPublicPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ED25519Public {
|
||||||
|
/// Generate an ED25519 public key given the provided (32 byte) bytes. This
|
||||||
|
/// can return errors if the value isn't a reasonable representation of an
|
||||||
|
/// ED25519 point.
|
||||||
|
pub fn new(bytes: &[u8]) -> Result<ED25519Public,ED25519PublicImportError>
|
||||||
|
{
|
||||||
|
if bytes.len() != 32 {
|
||||||
|
return Err(ED25519PublicImportError::WrongNumberOfBytes(bytes.len()));
|
||||||
|
}
|
||||||
|
match Point::from_bytes(&bytes) {
|
||||||
|
None =>
|
||||||
|
Err(ED25519PublicImportError::InvalidPublicPoint),
|
||||||
|
Some(a) => {
|
||||||
|
let mut res = ED25519Public{ bytes: [0; 32], point: a };
|
||||||
|
res.bytes.copy_from_slice(&bytes);
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify that the given signature matches the given message.
|
||||||
|
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool
|
||||||
|
{
|
||||||
|
assert_eq!(sig.len(), 64);
|
||||||
|
|
||||||
|
let signature_r = &sig[..32];
|
||||||
|
let signature_s = &sig[32..];
|
||||||
|
|
||||||
|
if signature_s[31] & 0b11100000 != 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ainv = self.point.invert();
|
||||||
|
let h_digest = eddsa_digest(signature_r, &self.bytes, msg);
|
||||||
|
let h = digest_scalar(&h_digest);
|
||||||
|
let r = Point2::double_scalarmult_vartime(&h, &ainv, &signature_s);
|
||||||
|
let r_check = r.encode();
|
||||||
|
signature_r.to_vec() == r_check
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Turn the ED25519 into its byte representation. This will always be a
|
||||||
|
/// 32 byte block.
|
||||||
|
pub fn to_bytes(&self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
self.bytes.to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eddsa_digest(signature_r: &[u8], public_key: &[u8], msg: &[u8]) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut ctx = SHA512::new();
|
||||||
|
ctx.update(signature_r);
|
||||||
|
ctx.update(public_key);
|
||||||
|
ctx.update(msg);
|
||||||
|
ctx.finalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn digest_scalar(digest: &[u8]) -> Vec<u8> {
|
||||||
|
assert_eq!(digest.len(), 512/8);
|
||||||
|
let mut copy = [0; 512/8];
|
||||||
|
copy.copy_from_slice(digest);
|
||||||
|
x25519_sc_reduce(&mut copy);
|
||||||
|
copy[..32].to_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn run_signing_testcase(case: HashMap<String,(bool,Vec<u8>)>)
|
||||||
|
{
|
||||||
|
let (negr, rbytes) = case.get("r").unwrap();
|
||||||
|
let (negu, ubytes) = case.get("u").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negs, sbytes) = case.get("s").unwrap();
|
||||||
|
|
||||||
|
assert!(!negr && !negu && !negm && !negs);
|
||||||
|
let keypair = ED25519KeyPair::from_seed(rbytes);
|
||||||
|
assert_eq!(ubytes, &keypair.public.bytes.to_vec());
|
||||||
|
let mut privpub = Vec::new();
|
||||||
|
privpub.append(&mut rbytes.clone());
|
||||||
|
privpub.append(&mut ubytes.clone());
|
||||||
|
let sig = keypair.private.sign(&mbytes);
|
||||||
|
assert_eq!(sig.len(), sbytes.len());
|
||||||
|
assert!(sig.iter().eq(sbytes.iter()));
|
||||||
|
assert!(keypair.public.verify(&mbytes, &sig));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn rfc8072() {
|
||||||
|
let fname = "testdata/ed25519/rfc8032.test";
|
||||||
|
run_test(fname.to_string(), 4, run_signing_testcase);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn signing() {
|
||||||
|
let fname = "testdata/ed25519/sign.test";
|
||||||
|
run_test(fname.to_string(), 4, run_signing_testcase);
|
||||||
|
}
|
||||||
733
src/ed25519/point.rs
Normal file
733
src/ed25519/point.rs
Normal file
@@ -0,0 +1,733 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
use ed25519::fe::*;
|
||||||
|
use ed25519::constants::*;
|
||||||
|
use std::ops::*;
|
||||||
|
|
||||||
|
// This is ge_p3 in the original source code
|
||||||
|
#[derive(Clone,Debug,PartialEq)]
|
||||||
|
pub struct Point {
|
||||||
|
pub x: FieldElement,
|
||||||
|
pub y: FieldElement,
|
||||||
|
pub z: FieldElement,
|
||||||
|
pub t: FieldElement
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Point {
|
||||||
|
fn zero() -> Point
|
||||||
|
{
|
||||||
|
Point {
|
||||||
|
x: FieldElement::zero(),
|
||||||
|
y: FieldElement::one(),
|
||||||
|
z: FieldElement::one(),
|
||||||
|
t: FieldElement::zero(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn load_test_value(xs: &[u8]) -> Point {
|
||||||
|
assert!(xs.len() == 160);
|
||||||
|
Point {
|
||||||
|
x: test_from_bytes(&xs[0..40]),
|
||||||
|
y: test_from_bytes(&xs[40..80]),
|
||||||
|
z: test_from_bytes(&xs[80..120]),
|
||||||
|
t: test_from_bytes(&xs[120..])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert 32 bytes into an ED25519 point. This routine is not
|
||||||
|
/// statically timed, so don't use it if that's important to you.
|
||||||
|
pub fn from_bytes(s: &[u8]) -> Option<Point>
|
||||||
|
{
|
||||||
|
let hy = FieldElement::from_bytes(s);
|
||||||
|
let hz = FieldElement::one();
|
||||||
|
let mut u = hy.square();
|
||||||
|
let mut v = &u * &D;
|
||||||
|
u = &u - &hz; /* u = y^2-1 */
|
||||||
|
v += &hz;
|
||||||
|
|
||||||
|
let mut v3 = v.square();
|
||||||
|
v3 *= &v; /* v3 = v^3 */
|
||||||
|
let mut hx = v3.square();
|
||||||
|
hx *= &v;
|
||||||
|
hx *= &u; /* x = uv^7 */
|
||||||
|
hx = hx.pow22523(); /* x = (uv^7)^((q-5)/8) */
|
||||||
|
hx *= &v3;
|
||||||
|
hx *= &u; /* x = uv^3(uv^7)^((q-5)/8) */
|
||||||
|
|
||||||
|
let mut vxx = hx.square();
|
||||||
|
vxx *= &v;
|
||||||
|
let mut check = &vxx - &u; /* vx^2-u */
|
||||||
|
if check.isnonzero() {
|
||||||
|
check = &vxx + &u;
|
||||||
|
if check.isnonzero() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
hx *= &SQRTM1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if hx.isnegative() != ((s[31] >> 7) == 1) {
|
||||||
|
hx = -&hx;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ht = &hx * &hy;
|
||||||
|
return Some(Point{ x: hx, y: hy, z: hz, t: ht });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode(&self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
into_encoded_point(&self.x, &self.y, &self.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invert(&self) -> Point
|
||||||
|
{
|
||||||
|
Point {
|
||||||
|
x: -&self.x,
|
||||||
|
y: self.y.clone(),
|
||||||
|
z: self.z.clone(),
|
||||||
|
t: -&self.t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const D: FieldElement = FieldElement {
|
||||||
|
value: [-10913610, 13857413, -15372611, 6949391, 114729,
|
||||||
|
-8787816, -6275908, -3247719, -18696448, -12055116]
|
||||||
|
};
|
||||||
|
|
||||||
|
const SQRTM1: FieldElement = FieldElement {
|
||||||
|
value: [-32595792, -7943725, 9377950, 3500415, 12389472,
|
||||||
|
-272473, -25146209, -2005654, 326686, 11406482]
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn from_bytes_vartime() {
|
||||||
|
let fname = "testdata/ed25519/fbv.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
let (negc, cbytes) = case.get("c").unwrap();
|
||||||
|
|
||||||
|
assert!(!nega && !negb && !negc);
|
||||||
|
let target = Point::load_test_value(&cbytes);
|
||||||
|
let mine = Point::from_bytes(&abytes);
|
||||||
|
if bbytes.len() < cbytes.len() {
|
||||||
|
assert!(mine.is_none());
|
||||||
|
} else {
|
||||||
|
assert_eq!(target, mine.unwrap());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct Point2 {
|
||||||
|
pub x: FieldElement,
|
||||||
|
pub y: FieldElement,
|
||||||
|
pub z: FieldElement,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Point2 {
|
||||||
|
pub fn zero() -> Point2
|
||||||
|
{
|
||||||
|
Point2 {
|
||||||
|
x: FieldElement::zero(),
|
||||||
|
y: FieldElement::one(),
|
||||||
|
z: FieldElement::one()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn load_test_value(xs: &[u8]) -> Point2 {
|
||||||
|
assert!(xs.len() == 120);
|
||||||
|
Point2 {
|
||||||
|
x: test_from_bytes(&xs[0..40]),
|
||||||
|
y: test_from_bytes(&xs[40..80]),
|
||||||
|
z: test_from_bytes(&xs[80..120]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode(&self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
into_encoded_point(&self.x, &self.y, &self.z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Point> for Point2 {
|
||||||
|
fn from(p: &Point) -> Point2 {
|
||||||
|
Point2 {
|
||||||
|
x: p.x.clone(),
|
||||||
|
y: p.y.clone(),
|
||||||
|
z: p.z.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
pub struct PointP1P1 {
|
||||||
|
x: FieldElement,
|
||||||
|
y: FieldElement,
|
||||||
|
z: FieldElement,
|
||||||
|
t: FieldElement
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointP1P1 {
|
||||||
|
#[cfg(test)]
|
||||||
|
fn load_test_value(xs: &[u8]) -> PointP1P1 {
|
||||||
|
assert!(xs.len() == 160);
|
||||||
|
PointP1P1 {
|
||||||
|
x: test_from_bytes(&xs[0..40]),
|
||||||
|
y: test_from_bytes(&xs[40..80]),
|
||||||
|
z: test_from_bytes(&xs[80..120]),
|
||||||
|
t: test_from_bytes(&xs[120..])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,PartialEq)]
|
||||||
|
struct Cached {
|
||||||
|
yplusx: FieldElement,
|
||||||
|
yminusx: FieldElement,
|
||||||
|
z: FieldElement,
|
||||||
|
t2d: FieldElement
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cached
|
||||||
|
{
|
||||||
|
fn new() -> Cached
|
||||||
|
{
|
||||||
|
Cached {
|
||||||
|
yplusx: FieldElement::new(),
|
||||||
|
yminusx: FieldElement::new(),
|
||||||
|
z: FieldElement::new(),
|
||||||
|
t2d: FieldElement::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn load_test_value(xs: &[u8]) -> Cached {
|
||||||
|
assert!(xs.len() == 160);
|
||||||
|
Cached {
|
||||||
|
yplusx: test_from_bytes(&xs[0..40]),
|
||||||
|
yminusx: test_from_bytes(&xs[40..80]),
|
||||||
|
z: test_from_bytes(&xs[80..120]),
|
||||||
|
t2d: test_from_bytes(&xs[120..])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const D2: FieldElement = FieldElement {
|
||||||
|
value: [-21827239, -5839606, -30745221, 13898782, 229458,
|
||||||
|
15978800, -12551817, -6495438, 29715968, 9444199]
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'a> From<&'a Point> for Cached
|
||||||
|
{
|
||||||
|
fn from(p: &Point) -> Cached
|
||||||
|
{
|
||||||
|
Cached {
|
||||||
|
yplusx: &p.y + &p.x,
|
||||||
|
yminusx: &p.y - &p.x,
|
||||||
|
z: p.z.clone(),
|
||||||
|
t2d: &p.t * &D2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a PointP1P1> for Point2
|
||||||
|
{
|
||||||
|
fn from(p: &PointP1P1) -> Point2
|
||||||
|
{
|
||||||
|
Point2 {
|
||||||
|
x: &p.x * &p.t,
|
||||||
|
y: &p.y * &p.z,
|
||||||
|
z: &p.z * &p.t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a PointP1P1> for Point
|
||||||
|
{
|
||||||
|
fn from(p: &PointP1P1) -> Point
|
||||||
|
{
|
||||||
|
Point {
|
||||||
|
x: &p.x * &p.t,
|
||||||
|
y: &p.y * &p.z,
|
||||||
|
z: &p.z * &p.t,
|
||||||
|
t: &p.x * &p.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn conversion() {
|
||||||
|
let fname = "testdata/ed25519/conversion.test";
|
||||||
|
run_test(fname.to_string(), 6, |case| {
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negc, cbytes) = case.get("c").unwrap();
|
||||||
|
let (negt, tbytes) = case.get("t").unwrap();
|
||||||
|
let (nego, obytes) = case.get("o").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
|
||||||
|
let a = Point::load_test_value(&abytes);
|
||||||
|
let c = Cached::load_test_value(&cbytes);
|
||||||
|
let t = Point2::load_test_value(&tbytes);
|
||||||
|
let o = PointP1P1::load_test_value(&obytes);
|
||||||
|
let d = Point2::load_test_value(&dbytes);
|
||||||
|
let b = Point::load_test_value(&bbytes);
|
||||||
|
|
||||||
|
assert!(!nega && !negc && !negt && !nego && !negd && !negb);
|
||||||
|
|
||||||
|
let myc = Cached::from(&a);
|
||||||
|
assert_eq!(myc, c);
|
||||||
|
|
||||||
|
let myt = Point2::from(&a);
|
||||||
|
assert_eq!(myt, t);
|
||||||
|
|
||||||
|
let myo = a.double();
|
||||||
|
assert_eq!(myo, o);
|
||||||
|
|
||||||
|
let myd = Point2::from(&o);
|
||||||
|
assert_eq!(myd, d);
|
||||||
|
|
||||||
|
let myb = Point::from(&o);
|
||||||
|
assert_eq!(myb, b);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* r = 2 * p */
|
||||||
|
impl Point2 {
|
||||||
|
fn double(&self) -> PointP1P1
|
||||||
|
{
|
||||||
|
let x0 = self.x.square();
|
||||||
|
let z0 = self.y.square();
|
||||||
|
let t0 = self.z.sq2();
|
||||||
|
let y0 = &self.x + &self.y;
|
||||||
|
let ry = &z0 + &x0;
|
||||||
|
let rz = &z0 - &x0;
|
||||||
|
let rx = &y0.square() - &ry;
|
||||||
|
let rt = &t0 - &rz;
|
||||||
|
PointP1P1 { x: rx, y: ry, z: rz, t: rt }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* r = 2 * p */
|
||||||
|
impl Point {
|
||||||
|
fn double(&self) -> PointP1P1
|
||||||
|
{
|
||||||
|
Point2::from(self).double()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn double() {
|
||||||
|
let fname = "testdata/ed25519/pt_double.test";
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
let (negc, cbytes) = case.get("c").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!nega && !negb && !negc && !negd);
|
||||||
|
let a = Point::load_test_value(abytes);
|
||||||
|
let b = PointP1P1::load_test_value(bbytes);
|
||||||
|
let c = Point2::load_test_value(cbytes);
|
||||||
|
let d = PointP1P1::load_test_value(dbytes);
|
||||||
|
|
||||||
|
let myb = a.double();
|
||||||
|
assert_eq!(myb, b);
|
||||||
|
let myd = c.double();
|
||||||
|
assert_eq!(myd, d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a,'b> Add<&'a Precomp> for &'b Point
|
||||||
|
{
|
||||||
|
type Output = PointP1P1;
|
||||||
|
|
||||||
|
fn add(self, q: &Precomp) -> PointP1P1
|
||||||
|
{
|
||||||
|
let mut rx;
|
||||||
|
let mut ry;
|
||||||
|
let mut rz;
|
||||||
|
let mut rt;
|
||||||
|
|
||||||
|
rx = &self.y + &self.x;
|
||||||
|
ry = &self.y - &self.x;
|
||||||
|
rz = &rx * &q.yplusx;
|
||||||
|
ry *= &q.yminusx;
|
||||||
|
rt = &q.xy2d * &self.t;
|
||||||
|
let t0 = &self.z + &self.z;
|
||||||
|
rx = &rz - &ry;
|
||||||
|
ry += &rz;
|
||||||
|
rz = &t0 + &rt;
|
||||||
|
rt = &t0 - &rt;
|
||||||
|
|
||||||
|
PointP1P1 { x: rx, y: ry, z: rz, t: rt }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a,'b> Sub<&'a Precomp> for &'b Point
|
||||||
|
{
|
||||||
|
type Output = PointP1P1;
|
||||||
|
|
||||||
|
/* r = p - q */
|
||||||
|
fn sub(self, q: &Precomp) -> PointP1P1
|
||||||
|
{
|
||||||
|
let mut rx = &self.y + &self.x;
|
||||||
|
let mut ry = &self.y - &self.x;
|
||||||
|
let mut rz = &rx * &q.yminusx;
|
||||||
|
ry *= &q.yplusx;
|
||||||
|
let mut rt = &q.xy2d * &self.t;
|
||||||
|
let t0 = &self.z + &self.z;
|
||||||
|
rx = &rz - &ry;
|
||||||
|
ry += &rz;
|
||||||
|
rz = &t0 - &rt;
|
||||||
|
rt += &t0;
|
||||||
|
PointP1P1{ x: rx, y: ry, z: rz, t: rt }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn maddsub() {
|
||||||
|
let fname = "testdata/ed25519/maddsub.test";
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
let (negc, cbytes) = case.get("c").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!nega && !negb && !negc && !negd);
|
||||||
|
let a = Point::load_test_value(abytes);
|
||||||
|
let b = PointP1P1::load_test_value(bbytes);
|
||||||
|
let c = Precomp::load_test_value(cbytes);
|
||||||
|
let d = PointP1P1::load_test_value(dbytes);
|
||||||
|
|
||||||
|
let myb = &a + &c;
|
||||||
|
assert_eq!(myb, b);
|
||||||
|
let myd = &a - &c;
|
||||||
|
assert_eq!(myd, d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a,'b> Add<&'a Cached> for &'b Point
|
||||||
|
{
|
||||||
|
type Output = PointP1P1;
|
||||||
|
|
||||||
|
fn add(self, q: &Cached) -> PointP1P1
|
||||||
|
{
|
||||||
|
let mut rx;
|
||||||
|
let mut ry;
|
||||||
|
let mut rz;
|
||||||
|
let mut rt;
|
||||||
|
|
||||||
|
rx = &self.y + &self.x;
|
||||||
|
ry = &self.y - &self.x;
|
||||||
|
rz = &rx * &q.yplusx;
|
||||||
|
ry *= &q.yminusx;
|
||||||
|
rt = &q.t2d * &self.t;
|
||||||
|
rx = &self.z * &q.z;
|
||||||
|
let t0 = &rx + ℞
|
||||||
|
rx = &rz - &ry;
|
||||||
|
ry += &rz;
|
||||||
|
rz = &t0 + &rt;
|
||||||
|
rt = &t0 - &rt;
|
||||||
|
|
||||||
|
PointP1P1{ x: rx, y: ry, z: rz, t: rt }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a,'b> Sub<&'a Cached> for &'b Point
|
||||||
|
{
|
||||||
|
type Output = PointP1P1;
|
||||||
|
|
||||||
|
fn sub(self, q: &Cached) -> PointP1P1
|
||||||
|
{
|
||||||
|
let mut rx;
|
||||||
|
let mut ry;
|
||||||
|
let mut rz;
|
||||||
|
let mut rt;
|
||||||
|
|
||||||
|
rx = &self.y + &self.x;
|
||||||
|
ry = &self.y - &self.x;
|
||||||
|
rz = &rx * &q.yminusx;
|
||||||
|
ry *= &q.yplusx;
|
||||||
|
rt = &q.t2d * &self.t;
|
||||||
|
rx = &self.z * &q.z;
|
||||||
|
let t0 = &rx + ℞
|
||||||
|
rx = &rz - &ry;
|
||||||
|
ry += &rz;
|
||||||
|
rz = &t0 - &rt;
|
||||||
|
rt += &t0;
|
||||||
|
|
||||||
|
PointP1P1{ x: rx, y: ry, z: rz, t: rt }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn addsub() {
|
||||||
|
let fname = "testdata/ed25519/ptaddsub.test";
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
let (negc, cbytes) = case.get("c").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!nega && !negb && !negc && !negd);
|
||||||
|
let a = Point::load_test_value(abytes);
|
||||||
|
let b = PointP1P1::load_test_value(bbytes);
|
||||||
|
let c = Cached::load_test_value(cbytes);
|
||||||
|
let d = PointP1P1::load_test_value(dbytes);
|
||||||
|
|
||||||
|
let myb = &a + &c;
|
||||||
|
assert_eq!(myb, b);
|
||||||
|
let myd = &a - &c;
|
||||||
|
assert_eq!(myd, d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Point {
|
||||||
|
/* h = a * B
|
||||||
|
* where a = a[0]+256*a[1]+...+256^31 a[31]
|
||||||
|
* B is the Ed25519 base point (x,4/5) with x positive.
|
||||||
|
*
|
||||||
|
* Preconditions:
|
||||||
|
* a[31] <= 127 */
|
||||||
|
pub fn scalarmult_base(a: &[u8]) -> Point
|
||||||
|
{
|
||||||
|
let mut e: [i8; 64] = [0; 64];
|
||||||
|
for i in 0..32 {
|
||||||
|
e[2 * i + 0] = ((a[i] >> 0) & 15) as i8;
|
||||||
|
e[2 * i + 1] = ((a[i] >> 4) & 15) as i8;
|
||||||
|
}
|
||||||
|
/* each e[i] is between 0 and 15 */
|
||||||
|
/* e[63] is between 0 and 7 */
|
||||||
|
|
||||||
|
let mut carry = 0;
|
||||||
|
for i in 0..63 {
|
||||||
|
e[i] += carry;
|
||||||
|
carry = e[i] + 8;
|
||||||
|
carry >>= 4;
|
||||||
|
e[i] -= carry << 4;
|
||||||
|
}
|
||||||
|
e[63] += carry;
|
||||||
|
/* each e[i] is between -8 and 8 */
|
||||||
|
|
||||||
|
let mut r;
|
||||||
|
let mut t;
|
||||||
|
|
||||||
|
let mut h = Point::zero();
|
||||||
|
for i in &[1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63] {
|
||||||
|
t = Precomp::table_select(*i / 2, e[*i as usize]);
|
||||||
|
r = &h + &t;
|
||||||
|
h = Point::from(&r);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = h.double();
|
||||||
|
let mut s = Point2::from(&r);
|
||||||
|
r = s.double();
|
||||||
|
s = Point2::from(&r);
|
||||||
|
r = s.double();
|
||||||
|
s = Point2::from(&r);
|
||||||
|
r = s.double();
|
||||||
|
h = Point::from(&r);
|
||||||
|
|
||||||
|
for i in &[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62] {
|
||||||
|
t = Precomp::table_select(*i / 2, e[*i as usize]);
|
||||||
|
r = &h + &t;
|
||||||
|
h = Point::from(&r);
|
||||||
|
}
|
||||||
|
|
||||||
|
h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn scalarmult_base() {
|
||||||
|
let fname = "testdata/ed25519/scalar_mult.test";
|
||||||
|
run_test(fname.to_string(), 2, |case| {
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
|
||||||
|
assert!(!nega && !negb);
|
||||||
|
let b = Point::load_test_value(bbytes);
|
||||||
|
let mine = Point::scalarmult_base(&abytes);
|
||||||
|
assert_eq!(mine, b);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slide(r: &mut [i8], a: &[u8])
|
||||||
|
{
|
||||||
|
for i in 0..256 {
|
||||||
|
r[i] = (1 & (a[i >> 3] >> (i & 7))) as i8;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..256 {
|
||||||
|
if r[i] != 0 {
|
||||||
|
let mut b = 1;
|
||||||
|
while (b <= 6) && ((i + b) < 256) {
|
||||||
|
if r[i + b] != 0 {
|
||||||
|
if r[i] + (r[i + b] << b) <= 15 {
|
||||||
|
r[i] += r[i + b] << b;
|
||||||
|
r[i + b] = 0;
|
||||||
|
} else if r[i] - (r[i + b] << b) >= -15 {
|
||||||
|
r[i] -= r[i + b] << b;
|
||||||
|
for k in (i+b)..256 {
|
||||||
|
if r[k] == 0 {
|
||||||
|
r[k] = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
r[k] = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn helper_slide() {
|
||||||
|
let fname = "testdata/ed25519/slide.test";
|
||||||
|
run_test(fname.to_string(), 2, |case| {
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
|
||||||
|
assert!(!nega && !negb);
|
||||||
|
let mut mine = [0; 256];
|
||||||
|
slide(&mut mine, &abytes);
|
||||||
|
for i in 0..256 {
|
||||||
|
assert_eq!(mine[i], bbytes[i] as i8);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Point2
|
||||||
|
{
|
||||||
|
/* r = a * A + b * B
|
||||||
|
* where a = a[0]+256*a[1]+...+256^31 a[31].
|
||||||
|
* and b = b[0]+256*b[1]+...+256^31 b[31].
|
||||||
|
* B is the Ed25519 base point (x,4/5) with x positive. */
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn double_scalarmult_vartime(a: &[u8], A: &Point, b: &[u8]) -> Point2
|
||||||
|
{
|
||||||
|
let mut aslide: [i8; 256] = [0; 256];
|
||||||
|
let mut bslide: [i8; 256] = [0; 256];
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
let mut Ai: [Cached; 8] = [Cached::new(), Cached::new(), Cached::new(), Cached::new(),
|
||||||
|
Cached::new(), Cached::new(), Cached::new(), Cached::new()];
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
|
||||||
|
slide(&mut aslide, &a);
|
||||||
|
slide(&mut bslide, &b);
|
||||||
|
|
||||||
|
Ai[0] = Cached::from(A);
|
||||||
|
let mut t = A.double();
|
||||||
|
let A2 = Point::from(&t);
|
||||||
|
t = &A2 + &Ai[0];
|
||||||
|
let mut u = Point::from(&t);
|
||||||
|
Ai[1] = Cached::from(&u);
|
||||||
|
t = &A2 + &Ai[1];
|
||||||
|
u = Point::from(&t);
|
||||||
|
Ai[2] = Cached::from(&u);
|
||||||
|
t = &A2 + &Ai[2];
|
||||||
|
u = Point::from(&t);
|
||||||
|
Ai[3] = Cached::from(&u);
|
||||||
|
t = &A2 + &Ai[3];
|
||||||
|
u = Point::from(&t);
|
||||||
|
Ai[4] = Cached::from(&u);
|
||||||
|
t = &A2 + &Ai[4];
|
||||||
|
u = Point::from(&t);
|
||||||
|
Ai[5] = Cached::from(&u);
|
||||||
|
t = &A2 + &Ai[5];
|
||||||
|
u = Point::from(&t);
|
||||||
|
Ai[6] = Cached::from(&u);
|
||||||
|
t = &A2 + &Ai[6];
|
||||||
|
u = Point::from(&t);
|
||||||
|
Ai[7] = Cached::from(&u);
|
||||||
|
|
||||||
|
let mut r = Point2::zero();
|
||||||
|
|
||||||
|
let mut i: i32 = 255;
|
||||||
|
loop {
|
||||||
|
if (aslide[i as usize] != 0) || (bslide[i as usize] != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i -= 1;
|
||||||
|
if i < 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while i >= 0 {
|
||||||
|
t = r.double();
|
||||||
|
|
||||||
|
if aslide[i as usize] > 0 {
|
||||||
|
u = Point::from(&t);
|
||||||
|
let idx = (aslide[i as usize] / 2) as usize;
|
||||||
|
t = &u + &Ai[idx]
|
||||||
|
} else if aslide[i as usize] < 0 {
|
||||||
|
u = Point::from(&t);
|
||||||
|
let idx = ((-aslide[i as usize]) / 2) as usize;
|
||||||
|
t = &u - &Ai[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
if bslide[i as usize] > 0 {
|
||||||
|
u = Point::from(&t);
|
||||||
|
let idx = (bslide[i as usize] / 2) as usize;
|
||||||
|
t = &u + &BI[idx];
|
||||||
|
} else if bslide[i as usize] < 0 {
|
||||||
|
u = Point::from(&t);
|
||||||
|
let idx = ((-bslide[i as usize]) / 2) as usize;
|
||||||
|
t = &u - &BI[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
r = Point2::from(&t);
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn double_scalarmult() {
|
||||||
|
let fname = "testdata/ed25519/scalar_mult_gen.test";
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
let (negc, cbytes) = case.get("c").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!nega && !negb && !negc && !negd);
|
||||||
|
let b = Point::load_test_value(bbytes);
|
||||||
|
let d = Point2::load_test_value(dbytes);
|
||||||
|
let mine = Point2::double_scalarmult_vartime(&abytes, &b, &cbytes);
|
||||||
|
assert_eq!(mine, d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_encoded_point(x: &FieldElement, y: &FieldElement, z: &FieldElement) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let recip = z.invert();
|
||||||
|
let x_over_z = x * &recip;
|
||||||
|
let y_over_z = y * &recip;
|
||||||
|
let mut bytes = y_over_z.to_bytes();
|
||||||
|
let sign_bit = if x_over_z.isnegative() { 1 } else { 0 };
|
||||||
|
// The preceding computations must execute in constant time, but this
|
||||||
|
// doesn't need to.
|
||||||
|
bytes[31] ^= sign_bit << 7;
|
||||||
|
bytes
|
||||||
|
}
|
||||||
3363
src/ed25519/rfc8032.txt
Normal file
3363
src/ed25519/rfc8032.txt
Normal file
File diff suppressed because it is too large
Load Diff
881
src/ed25519/scalars.rs
Normal file
881
src/ed25519/scalars.rs
Normal file
@@ -0,0 +1,881 @@
|
|||||||
|
use ed25519::loads::{load3,load4};
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
/* The set of scalars is \Z/l
|
||||||
|
* where l = 2^252 + 27742317777372353535851937790883648493. */
|
||||||
|
|
||||||
|
/* Input:
|
||||||
|
* s[0]+256*s[1]+...+256^63*s[63] = s
|
||||||
|
*
|
||||||
|
* Output:
|
||||||
|
* s[0]+256*s[1]+...+256^31*s[31] = s mod l
|
||||||
|
* where l = 2^252 + 27742317777372353535851937790883648493.
|
||||||
|
* Overwrites s in place. */
|
||||||
|
pub fn x25519_sc_reduce(s: &mut [u8])
|
||||||
|
{
|
||||||
|
let mut s0 : i64 = 2097151 & load3(s) as i64;
|
||||||
|
let mut s1 : i64 = 2097151 & (load4(&s[2..]) >> 5) as i64;
|
||||||
|
let mut s2 : i64 = 2097151 & (load3(&s[5..]) >> 2) as i64;
|
||||||
|
let mut s3 : i64 = 2097151 & (load4(&s[7..]) >> 7) as i64;
|
||||||
|
let mut s4 : i64 = 2097151 & (load4(&s[10..]) >> 4) as i64;
|
||||||
|
let mut s5 : i64 = 2097151 & (load3(&s[13..]) >> 1) as i64;
|
||||||
|
let mut s6 : i64 = 2097151 & (load4(&s[15..]) >> 6) as i64;
|
||||||
|
let mut s7 : i64 = 2097151 & (load3(&s[18..]) >> 3) as i64;
|
||||||
|
let mut s8 : i64 = 2097151 & load3(&s[21..]) as i64;
|
||||||
|
let mut s9 : i64 = 2097151 & (load4(&s[23..]) >> 5) as i64;
|
||||||
|
let mut s10 : i64 = 2097151 & (load3(&s[26..]) >> 2) as i64;
|
||||||
|
let mut s11 : i64 = 2097151 & (load4(&s[28..]) >> 7) as i64;
|
||||||
|
let mut s12 : i64 = 2097151 & (load4(&s[31..]) >> 4) as i64;
|
||||||
|
let mut s13 : i64 = 2097151 & (load3(&s[34..]) >> 1) as i64;
|
||||||
|
let mut s14 : i64 = 2097151 & (load4(&s[36..]) >> 6) as i64;
|
||||||
|
let mut s15 : i64 = 2097151 & (load3(&s[39..]) >> 3) as i64;
|
||||||
|
let mut s16 : i64 = 2097151 & load3(&s[42..]) as i64;
|
||||||
|
let mut s17 : i64 = 2097151 & (load4(&s[44..]) >> 5) as i64;
|
||||||
|
let s18 : i64 = 2097151 & (load3(&s[47..]) >> 2) as i64;
|
||||||
|
let s19 : i64 = 2097151 & (load4(&s[49..]) >> 7) as i64;
|
||||||
|
let s20 : i64 = 2097151 & (load4(&s[52..]) >> 4) as i64;
|
||||||
|
let s21 : i64 = 2097151 & (load3(&s[55..]) >> 1) as i64;
|
||||||
|
let s22 : i64 = 2097151 & (load4(&s[57..]) >> 6) as i64;
|
||||||
|
let s23 : i64 = (load4(&s[60..]) >> 3) as i64 as i64;
|
||||||
|
let mut carry0 : i64;
|
||||||
|
let mut carry1 : i64;
|
||||||
|
let mut carry2 : i64;
|
||||||
|
let mut carry3 : i64;
|
||||||
|
let mut carry4 : i64;
|
||||||
|
let mut carry5 : i64;
|
||||||
|
let mut carry6 : i64;
|
||||||
|
let mut carry7 : i64;
|
||||||
|
let mut carry8 : i64;
|
||||||
|
let mut carry9 : i64;
|
||||||
|
let mut carry10 : i64;
|
||||||
|
let mut carry11 : i64;
|
||||||
|
let carry12 : i64;
|
||||||
|
let carry13 : i64;
|
||||||
|
let carry14 : i64;
|
||||||
|
let carry15 : i64;
|
||||||
|
let carry16 : i64;
|
||||||
|
|
||||||
|
s11 += s23 * 666643;
|
||||||
|
s12 += s23 * 470296;
|
||||||
|
s13 += s23 * 654183;
|
||||||
|
s14 -= s23 * 997805;
|
||||||
|
s15 += s23 * 136657;
|
||||||
|
s16 -= s23 * 683901;
|
||||||
|
//s23 = 0;
|
||||||
|
|
||||||
|
s10 += s22 * 666643;
|
||||||
|
s11 += s22 * 470296;
|
||||||
|
s12 += s22 * 654183;
|
||||||
|
s13 -= s22 * 997805;
|
||||||
|
s14 += s22 * 136657;
|
||||||
|
s15 -= s22 * 683901;
|
||||||
|
//s22 = 0;
|
||||||
|
|
||||||
|
s9 += s21 * 666643;
|
||||||
|
s10 += s21 * 470296;
|
||||||
|
s11 += s21 * 654183;
|
||||||
|
s12 -= s21 * 997805;
|
||||||
|
s13 += s21 * 136657;
|
||||||
|
s14 -= s21 * 683901;
|
||||||
|
//s21 = 0;
|
||||||
|
|
||||||
|
s8 += s20 * 666643;
|
||||||
|
s9 += s20 * 470296;
|
||||||
|
s10 += s20 * 654183;
|
||||||
|
s11 -= s20 * 997805;
|
||||||
|
s12 += s20 * 136657;
|
||||||
|
s13 -= s20 * 683901;
|
||||||
|
//s20 = 0;
|
||||||
|
|
||||||
|
s7 += s19 * 666643;
|
||||||
|
s8 += s19 * 470296;
|
||||||
|
s9 += s19 * 654183;
|
||||||
|
s10 -= s19 * 997805;
|
||||||
|
s11 += s19 * 136657;
|
||||||
|
s12 -= s19 * 683901;
|
||||||
|
//s19 = 0;
|
||||||
|
|
||||||
|
s6 += s18 * 666643;
|
||||||
|
s7 += s18 * 470296;
|
||||||
|
s8 += s18 * 654183;
|
||||||
|
s9 -= s18 * 997805;
|
||||||
|
s10 += s18 * 136657;
|
||||||
|
s11 -= s18 * 683901;
|
||||||
|
//s18 = 0;
|
||||||
|
|
||||||
|
carry6 = (s6 + (1 << 20)) >> 21;
|
||||||
|
s7 += carry6;
|
||||||
|
s6 -= carry6 << 21;
|
||||||
|
carry8 = (s8 + (1 << 20)) >> 21;
|
||||||
|
s9 += carry8;
|
||||||
|
s8 -= carry8 << 21;
|
||||||
|
carry10 = (s10 + (1 << 20)) >> 21;
|
||||||
|
s11 += carry10;
|
||||||
|
s10 -= carry10 << 21;
|
||||||
|
carry12 = (s12 + (1 << 20)) >> 21;
|
||||||
|
s13 += carry12;
|
||||||
|
s12 -= carry12 << 21;
|
||||||
|
carry14 = (s14 + (1 << 20)) >> 21;
|
||||||
|
s15 += carry14;
|
||||||
|
s14 -= carry14 << 21;
|
||||||
|
carry16 = (s16 + (1 << 20)) >> 21;
|
||||||
|
s17 += carry16;
|
||||||
|
s16 -= carry16 << 21;
|
||||||
|
|
||||||
|
carry7 = (s7 + (1 << 20)) >> 21;
|
||||||
|
s8 += carry7;
|
||||||
|
s7 -= carry7 << 21;
|
||||||
|
carry9 = (s9 + (1 << 20)) >> 21;
|
||||||
|
s10 += carry9;
|
||||||
|
s9 -= carry9 << 21;
|
||||||
|
carry11 = (s11 + (1 << 20)) >> 21;
|
||||||
|
s12 += carry11;
|
||||||
|
s11 -= carry11 << 21;
|
||||||
|
carry13 = (s13 + (1 << 20)) >> 21;
|
||||||
|
s14 += carry13;
|
||||||
|
s13 -= carry13 << 21;
|
||||||
|
carry15 = (s15 + (1 << 20)) >> 21;
|
||||||
|
s16 += carry15;
|
||||||
|
s15 -= carry15 << 21;
|
||||||
|
|
||||||
|
s5 += s17 * 666643;
|
||||||
|
s6 += s17 * 470296;
|
||||||
|
s7 += s17 * 654183;
|
||||||
|
s8 -= s17 * 997805;
|
||||||
|
s9 += s17 * 136657;
|
||||||
|
s10 -= s17 * 683901;
|
||||||
|
//s17 = 0;
|
||||||
|
|
||||||
|
s4 += s16 * 666643;
|
||||||
|
s5 += s16 * 470296;
|
||||||
|
s6 += s16 * 654183;
|
||||||
|
s7 -= s16 * 997805;
|
||||||
|
s8 += s16 * 136657;
|
||||||
|
s9 -= s16 * 683901;
|
||||||
|
//s16 = 0;
|
||||||
|
|
||||||
|
s3 += s15 * 666643;
|
||||||
|
s4 += s15 * 470296;
|
||||||
|
s5 += s15 * 654183;
|
||||||
|
s6 -= s15 * 997805;
|
||||||
|
s7 += s15 * 136657;
|
||||||
|
s8 -= s15 * 683901;
|
||||||
|
//s15 = 0;
|
||||||
|
|
||||||
|
s2 += s14 * 666643;
|
||||||
|
s3 += s14 * 470296;
|
||||||
|
s4 += s14 * 654183;
|
||||||
|
s5 -= s14 * 997805;
|
||||||
|
s6 += s14 * 136657;
|
||||||
|
s7 -= s14 * 683901;
|
||||||
|
//s14 = 0;
|
||||||
|
|
||||||
|
s1 += s13 * 666643;
|
||||||
|
s2 += s13 * 470296;
|
||||||
|
s3 += s13 * 654183;
|
||||||
|
s4 -= s13 * 997805;
|
||||||
|
s5 += s13 * 136657;
|
||||||
|
s6 -= s13 * 683901;
|
||||||
|
//s13 = 0;
|
||||||
|
|
||||||
|
s0 += s12 * 666643;
|
||||||
|
s1 += s12 * 470296;
|
||||||
|
s2 += s12 * 654183;
|
||||||
|
s3 -= s12 * 997805;
|
||||||
|
s4 += s12 * 136657;
|
||||||
|
s5 -= s12 * 683901;
|
||||||
|
s12 = 0;
|
||||||
|
|
||||||
|
carry0 = (s0 + (1 << 20)) >> 21;
|
||||||
|
s1 += carry0;
|
||||||
|
s0 -= carry0 << 21;
|
||||||
|
carry2 = (s2 + (1 << 20)) >> 21;
|
||||||
|
s3 += carry2;
|
||||||
|
s2 -= carry2 << 21;
|
||||||
|
carry4 = (s4 + (1 << 20)) >> 21;
|
||||||
|
s5 += carry4;
|
||||||
|
s4 -= carry4 << 21;
|
||||||
|
carry6 = (s6 + (1 << 20)) >> 21;
|
||||||
|
s7 += carry6;
|
||||||
|
s6 -= carry6 << 21;
|
||||||
|
carry8 = (s8 + (1 << 20)) >> 21;
|
||||||
|
s9 += carry8;
|
||||||
|
s8 -= carry8 << 21;
|
||||||
|
carry10 = (s10 + (1 << 20)) >> 21;
|
||||||
|
s11 += carry10;
|
||||||
|
s10 -= carry10 << 21;
|
||||||
|
|
||||||
|
carry1 = (s1 + (1 << 20)) >> 21;
|
||||||
|
s2 += carry1;
|
||||||
|
s1 -= carry1 << 21;
|
||||||
|
carry3 = (s3 + (1 << 20)) >> 21;
|
||||||
|
s4 += carry3;
|
||||||
|
s3 -= carry3 << 21;
|
||||||
|
carry5 = (s5 + (1 << 20)) >> 21;
|
||||||
|
s6 += carry5;
|
||||||
|
s5 -= carry5 << 21;
|
||||||
|
carry7 = (s7 + (1 << 20)) >> 21;
|
||||||
|
s8 += carry7;
|
||||||
|
s7 -= carry7 << 21;
|
||||||
|
carry9 = (s9 + (1 << 20)) >> 21;
|
||||||
|
s10 += carry9;
|
||||||
|
s9 -= carry9 << 21;
|
||||||
|
carry11 = (s11 + (1 << 20)) >> 21;
|
||||||
|
s12 += carry11;
|
||||||
|
s11 -= carry11 << 21;
|
||||||
|
|
||||||
|
s0 += s12 * 666643;
|
||||||
|
s1 += s12 * 470296;
|
||||||
|
s2 += s12 * 654183;
|
||||||
|
s3 -= s12 * 997805;
|
||||||
|
s4 += s12 * 136657;
|
||||||
|
s5 -= s12 * 683901;
|
||||||
|
s12 = 0;
|
||||||
|
|
||||||
|
carry0 = s0 >> 21;
|
||||||
|
s1 += carry0;
|
||||||
|
s0 -= carry0 << 21;
|
||||||
|
carry1 = s1 >> 21;
|
||||||
|
s2 += carry1;
|
||||||
|
s1 -= carry1 << 21;
|
||||||
|
carry2 = s2 >> 21;
|
||||||
|
s3 += carry2;
|
||||||
|
s2 -= carry2 << 21;
|
||||||
|
carry3 = s3 >> 21;
|
||||||
|
s4 += carry3;
|
||||||
|
s3 -= carry3 << 21;
|
||||||
|
carry4 = s4 >> 21;
|
||||||
|
s5 += carry4;
|
||||||
|
s4 -= carry4 << 21;
|
||||||
|
carry5 = s5 >> 21;
|
||||||
|
s6 += carry5;
|
||||||
|
s5 -= carry5 << 21;
|
||||||
|
carry6 = s6 >> 21;
|
||||||
|
s7 += carry6;
|
||||||
|
s6 -= carry6 << 21;
|
||||||
|
carry7 = s7 >> 21;
|
||||||
|
s8 += carry7;
|
||||||
|
s7 -= carry7 << 21;
|
||||||
|
carry8 = s8 >> 21;
|
||||||
|
s9 += carry8;
|
||||||
|
s8 -= carry8 << 21;
|
||||||
|
carry9 = s9 >> 21;
|
||||||
|
s10 += carry9;
|
||||||
|
s9 -= carry9 << 21;
|
||||||
|
carry10 = s10 >> 21;
|
||||||
|
s11 += carry10;
|
||||||
|
s10 -= carry10 << 21;
|
||||||
|
carry11 = s11 >> 21;
|
||||||
|
s12 += carry11;
|
||||||
|
s11 -= carry11 << 21;
|
||||||
|
|
||||||
|
s0 += s12 * 666643;
|
||||||
|
s1 += s12 * 470296;
|
||||||
|
s2 += s12 * 654183;
|
||||||
|
s3 -= s12 * 997805;
|
||||||
|
s4 += s12 * 136657;
|
||||||
|
s5 -= s12 * 683901;
|
||||||
|
//s12 = 0;
|
||||||
|
|
||||||
|
carry0 = s0 >> 21;
|
||||||
|
s1 += carry0;
|
||||||
|
s0 -= carry0 << 21;
|
||||||
|
carry1 = s1 >> 21;
|
||||||
|
s2 += carry1;
|
||||||
|
s1 -= carry1 << 21;
|
||||||
|
carry2 = s2 >> 21;
|
||||||
|
s3 += carry2;
|
||||||
|
s2 -= carry2 << 21;
|
||||||
|
carry3 = s3 >> 21;
|
||||||
|
s4 += carry3;
|
||||||
|
s3 -= carry3 << 21;
|
||||||
|
carry4 = s4 >> 21;
|
||||||
|
s5 += carry4;
|
||||||
|
s4 -= carry4 << 21;
|
||||||
|
carry5 = s5 >> 21;
|
||||||
|
s6 += carry5;
|
||||||
|
s5 -= carry5 << 21;
|
||||||
|
carry6 = s6 >> 21;
|
||||||
|
s7 += carry6;
|
||||||
|
s6 -= carry6 << 21;
|
||||||
|
carry7 = s7 >> 21;
|
||||||
|
s8 += carry7;
|
||||||
|
s7 -= carry7 << 21;
|
||||||
|
carry8 = s8 >> 21;
|
||||||
|
s9 += carry8;
|
||||||
|
s8 -= carry8 << 21;
|
||||||
|
carry9 = s9 >> 21;
|
||||||
|
s10 += carry9;
|
||||||
|
s9 -= carry9 << 21;
|
||||||
|
carry10 = s10 >> 21;
|
||||||
|
s11 += carry10;
|
||||||
|
s10 -= carry10 << 21;
|
||||||
|
|
||||||
|
s[0] = (s0 >> 0) as u8;
|
||||||
|
s[1] = (s0 >> 8) as u8;
|
||||||
|
s[2] = ((s0 >> 16) | (s1 << 5)) as u8;
|
||||||
|
s[3] = (s1 >> 3) as u8;
|
||||||
|
s[4] = (s1 >> 11) as u8;
|
||||||
|
s[5] = ((s1 >> 19) | (s2 << 2)) as u8;
|
||||||
|
s[6] = (s2 >> 6) as u8;
|
||||||
|
s[7] = ((s2 >> 14) | (s3 << 7)) as u8;
|
||||||
|
s[8] = (s3 >> 1) as u8;
|
||||||
|
s[9] = (s3 >> 9) as u8;
|
||||||
|
s[10] = ((s3 >> 17) | (s4 << 4)) as u8;
|
||||||
|
s[11] = (s4 >> 4) as u8;
|
||||||
|
s[12] = (s4 >> 12) as u8;
|
||||||
|
s[13] = ((s4 >> 20) | (s5 << 1)) as u8;
|
||||||
|
s[14] = (s5 >> 7) as u8;
|
||||||
|
s[15] = ((s5 >> 15) | (s6 << 6)) as u8;
|
||||||
|
s[16] = (s6 >> 2) as u8;
|
||||||
|
s[17] = (s6 >> 10) as u8;
|
||||||
|
s[18] = ((s6 >> 18) | (s7 << 3)) as u8;
|
||||||
|
s[19] = (s7 >> 5) as u8;
|
||||||
|
s[20] = (s7 >> 13) as u8;
|
||||||
|
s[21] = (s8 >> 0) as u8;
|
||||||
|
s[22] = (s8 >> 8) as u8;
|
||||||
|
s[23] = ((s8 >> 16) | (s9 << 5)) as u8;
|
||||||
|
s[24] = (s9 >> 3) as u8;
|
||||||
|
s[25] = (s9 >> 11) as u8;
|
||||||
|
s[26] = ((s9 >> 19) | (s10 << 2)) as u8;
|
||||||
|
s[27] = (s10 >> 6) as u8;
|
||||||
|
s[28] = ((s10 >> 14) | (s11 << 7)) as u8;
|
||||||
|
s[29] = (s11 >> 1) as u8;
|
||||||
|
s[30] = (s11 >> 9) as u8;
|
||||||
|
s[31] = (s11 >> 17) as u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn reduce() {
|
||||||
|
let fname = "testdata/ed25519/reduce.test";
|
||||||
|
run_test(fname.to_string(), 2, |case| {
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
|
||||||
|
assert!(!nega && !negb);
|
||||||
|
assert_eq!(abytes.len(), 64);
|
||||||
|
assert_eq!(bbytes.len(), 32);
|
||||||
|
let mut copy = abytes.clone();
|
||||||
|
x25519_sc_reduce(&mut copy);
|
||||||
|
assert_eq!(©[0..32], &bbytes[0..]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input:
|
||||||
|
* a[0]+256*a[1]+...+256^31*a[31] = a
|
||||||
|
* b[0]+256*b[1]+...+256^31*b[31] = b
|
||||||
|
* c[0]+256*c[1]+...+256^31*c[31] = c
|
||||||
|
*
|
||||||
|
* Output:
|
||||||
|
* s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
|
||||||
|
* where l = 2^252 + 27742317777372353535851937790883648493. */
|
||||||
|
pub fn x25519_sc_muladd(s: &mut [u8], a: &[u8], b: &[u8], c: &[u8])
|
||||||
|
{
|
||||||
|
let a0 : i64 = 2097151 & load3(a) as i64;
|
||||||
|
let a1 : i64 = 2097151 & (load4(&a[2..]) >> 5) as i64;
|
||||||
|
let a2 : i64 = 2097151 & (load3(&a[5..]) >> 2) as i64;
|
||||||
|
let a3 : i64 = 2097151 & (load4(&a[7..]) >> 7) as i64;
|
||||||
|
let a4 : i64 = 2097151 & (load4(&a[10..]) >> 4) as i64;
|
||||||
|
let a5 : i64 = 2097151 & (load3(&a[13..]) >> 1) as i64;
|
||||||
|
let a6 : i64 = 2097151 & (load4(&a[15..]) >> 6) as i64;
|
||||||
|
let a7 : i64 = 2097151 & (load3(&a[18..]) >> 3) as i64;
|
||||||
|
let a8 : i64 = 2097151 & load3(&a[21..]) as i64;
|
||||||
|
let a9 : i64 = 2097151 & (load4(&a[23..]) >> 5) as i64;
|
||||||
|
let a10 : i64 = 2097151 & (load3(&a[26..]) >> 2) as i64;
|
||||||
|
let a11 : i64 = (load4(&a[28..]) >> 7) as i64;
|
||||||
|
let b0 : i64 = 2097151 & load3(b) as i64;
|
||||||
|
let b1 : i64 = 2097151 & (load4(&b[2..]) >> 5) as i64;
|
||||||
|
let b2 : i64 = 2097151 & (load3(&b[5..]) >> 2) as i64;
|
||||||
|
let b3 : i64 = 2097151 & (load4(&b[7..]) >> 7) as i64;
|
||||||
|
let b4 : i64 = 2097151 & (load4(&b[10..]) >> 4) as i64;
|
||||||
|
let b5 : i64 = 2097151 & (load3(&b[13..]) >> 1) as i64;
|
||||||
|
let b6 : i64 = 2097151 & (load4(&b[15..]) >> 6) as i64;
|
||||||
|
let b7 : i64 = 2097151 & (load3(&b[18..]) >> 3) as i64;
|
||||||
|
let b8 : i64 = 2097151 & load3(&b[21..]) as i64;
|
||||||
|
let b9 : i64 = 2097151 & (load4(&b[23..]) >> 5) as i64;
|
||||||
|
let b10 : i64 = 2097151 & (load3(&b[26..]) >> 2) as i64;
|
||||||
|
let b11 : i64 = (load4(&b[28..]) >> 7) as i64;
|
||||||
|
let c0 : i64 = 2097151 & load3(c) as i64;
|
||||||
|
let c1 : i64 = 2097151 & (load4(&c[2..]) >> 5) as i64;
|
||||||
|
let c2 : i64 = 2097151 & (load3(&c[5..]) >> 2) as i64;
|
||||||
|
let c3 : i64 = 2097151 & (load4(&c[7..]) >> 7) as i64;
|
||||||
|
let c4 : i64 = 2097151 & (load4(&c[10..]) >> 4) as i64;
|
||||||
|
let c5 : i64 = 2097151 & (load3(&c[13..]) >> 1) as i64;
|
||||||
|
let c6 : i64 = 2097151 & (load4(&c[15..]) >> 6) as i64;
|
||||||
|
let c7 : i64 = 2097151 & (load3(&c[18..]) >> 3) as i64;
|
||||||
|
let c8 : i64 = 2097151 & load3(&c[21..]) as i64;
|
||||||
|
let c9 : i64 = 2097151 & (load4(&c[23..]) >> 5) as i64;
|
||||||
|
let c10 : i64 = 2097151 & (load3(&c[26..]) >> 2) as i64;
|
||||||
|
let c11 : i64 = (load4(&c[28..]) >> 7) as i64;
|
||||||
|
let mut s0 : i64;
|
||||||
|
let mut s1 : i64;
|
||||||
|
let mut s2 : i64;
|
||||||
|
let mut s3 : i64;
|
||||||
|
let mut s4 : i64;
|
||||||
|
let mut s5 : i64;
|
||||||
|
let mut s6 : i64;
|
||||||
|
let mut s7 : i64;
|
||||||
|
let mut s8 : i64;
|
||||||
|
let mut s9 : i64;
|
||||||
|
let mut s10 : i64;
|
||||||
|
let mut s11 : i64;
|
||||||
|
let mut s12 : i64;
|
||||||
|
let mut s13 : i64;
|
||||||
|
let mut s14 : i64;
|
||||||
|
let mut s15 : i64;
|
||||||
|
let mut s16 : i64;
|
||||||
|
let mut s17 : i64;
|
||||||
|
let mut s18 : i64;
|
||||||
|
let mut s19 : i64;
|
||||||
|
let mut s20 : i64;
|
||||||
|
let mut s21 : i64;
|
||||||
|
let mut s22 : i64;
|
||||||
|
let mut s23 : i64;
|
||||||
|
let mut carry0 : i64;
|
||||||
|
let mut carry1 : i64;
|
||||||
|
let mut carry2 : i64;
|
||||||
|
let mut carry3 : i64;
|
||||||
|
let mut carry4 : i64;
|
||||||
|
let mut carry5 : i64;
|
||||||
|
let mut carry6 : i64;
|
||||||
|
let mut carry7 : i64;
|
||||||
|
let mut carry8 : i64;
|
||||||
|
let mut carry9 : i64;
|
||||||
|
let mut carry10 : i64;
|
||||||
|
let mut carry11 : i64;
|
||||||
|
let mut carry12 : i64;
|
||||||
|
let mut carry13 : i64;
|
||||||
|
let mut carry14 : i64;
|
||||||
|
let mut carry15 : i64;
|
||||||
|
let mut carry16 : i64;
|
||||||
|
let carry17 : i64;
|
||||||
|
let carry18 : i64;
|
||||||
|
let carry19 : i64;
|
||||||
|
let carry20 : i64;
|
||||||
|
let carry21 : i64;
|
||||||
|
let carry22 : i64;
|
||||||
|
|
||||||
|
s0 = c0 + a0 * b0;
|
||||||
|
s1 = c1 + a0 * b1 + a1 * b0;
|
||||||
|
s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
|
||||||
|
s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
|
||||||
|
s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
|
||||||
|
s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
|
||||||
|
s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
|
||||||
|
s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
|
||||||
|
a6 * b1 + a7 * b0;
|
||||||
|
s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
|
||||||
|
a6 * b2 + a7 * b1 + a8 * b0;
|
||||||
|
s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
|
||||||
|
a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
|
||||||
|
s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
|
||||||
|
a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
|
||||||
|
s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
|
||||||
|
a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
|
||||||
|
s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 +
|
||||||
|
a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
|
||||||
|
s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 +
|
||||||
|
a9 * b4 + a10 * b3 + a11 * b2;
|
||||||
|
s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 +
|
||||||
|
a10 * b4 + a11 * b3;
|
||||||
|
s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 +
|
||||||
|
a11 * b4;
|
||||||
|
s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
|
||||||
|
s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
|
||||||
|
s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
|
||||||
|
s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
|
||||||
|
s20 = a9 * b11 + a10 * b10 + a11 * b9;
|
||||||
|
s21 = a10 * b11 + a11 * b10;
|
||||||
|
s22 = a11 * b11;
|
||||||
|
s23 = 0;
|
||||||
|
|
||||||
|
carry0 = (s0 + (1 << 20)) >> 21;
|
||||||
|
s1 += carry0;
|
||||||
|
s0 -= carry0 << 21;
|
||||||
|
carry2 = (s2 + (1 << 20)) >> 21;
|
||||||
|
s3 += carry2;
|
||||||
|
s2 -= carry2 << 21;
|
||||||
|
carry4 = (s4 + (1 << 20)) >> 21;
|
||||||
|
s5 += carry4;
|
||||||
|
s4 -= carry4 << 21;
|
||||||
|
carry6 = (s6 + (1 << 20)) >> 21;
|
||||||
|
s7 += carry6;
|
||||||
|
s6 -= carry6 << 21;
|
||||||
|
carry8 = (s8 + (1 << 20)) >> 21;
|
||||||
|
s9 += carry8;
|
||||||
|
s8 -= carry8 << 21;
|
||||||
|
carry10 = (s10 + (1 << 20)) >> 21;
|
||||||
|
s11 += carry10;
|
||||||
|
s10 -= carry10 << 21;
|
||||||
|
carry12 = (s12 + (1 << 20)) >> 21;
|
||||||
|
s13 += carry12;
|
||||||
|
s12 -= carry12 << 21;
|
||||||
|
carry14 = (s14 + (1 << 20)) >> 21;
|
||||||
|
s15 += carry14;
|
||||||
|
s14 -= carry14 << 21;
|
||||||
|
carry16 = (s16 + (1 << 20)) >> 21;
|
||||||
|
s17 += carry16;
|
||||||
|
s16 -= carry16 << 21;
|
||||||
|
carry18 = (s18 + (1 << 20)) >> 21;
|
||||||
|
s19 += carry18;
|
||||||
|
s18 -= carry18 << 21;
|
||||||
|
carry20 = (s20 + (1 << 20)) >> 21;
|
||||||
|
s21 += carry20;
|
||||||
|
s20 -= carry20 << 21;
|
||||||
|
carry22 = (s22 + (1 << 20)) >> 21;
|
||||||
|
s23 += carry22;
|
||||||
|
s22 -= carry22 << 21;
|
||||||
|
|
||||||
|
carry1 = (s1 + (1 << 20)) >> 21;
|
||||||
|
s2 += carry1;
|
||||||
|
s1 -= carry1 << 21;
|
||||||
|
carry3 = (s3 + (1 << 20)) >> 21;
|
||||||
|
s4 += carry3;
|
||||||
|
s3 -= carry3 << 21;
|
||||||
|
carry5 = (s5 + (1 << 20)) >> 21;
|
||||||
|
s6 += carry5;
|
||||||
|
s5 -= carry5 << 21;
|
||||||
|
carry7 = (s7 + (1 << 20)) >> 21;
|
||||||
|
s8 += carry7;
|
||||||
|
s7 -= carry7 << 21;
|
||||||
|
carry9 = (s9 + (1 << 20)) >> 21;
|
||||||
|
s10 += carry9;
|
||||||
|
s9 -= carry9 << 21;
|
||||||
|
carry11 = (s11 + (1 << 20)) >> 21;
|
||||||
|
s12 += carry11;
|
||||||
|
s11 -= carry11 << 21;
|
||||||
|
carry13 = (s13 + (1 << 20)) >> 21;
|
||||||
|
s14 += carry13;
|
||||||
|
s13 -= carry13 << 21;
|
||||||
|
carry15 = (s15 + (1 << 20)) >> 21;
|
||||||
|
s16 += carry15;
|
||||||
|
s15 -= carry15 << 21;
|
||||||
|
carry17 = (s17 + (1 << 20)) >> 21;
|
||||||
|
s18 += carry17;
|
||||||
|
s17 -= carry17 << 21;
|
||||||
|
carry19 = (s19 + (1 << 20)) >> 21;
|
||||||
|
s20 += carry19;
|
||||||
|
s19 -= carry19 << 21;
|
||||||
|
carry21 = (s21 + (1 << 20)) >> 21;
|
||||||
|
s22 += carry21;
|
||||||
|
s21 -= carry21 << 21;
|
||||||
|
|
||||||
|
s11 += s23 * 666643;
|
||||||
|
s12 += s23 * 470296;
|
||||||
|
s13 += s23 * 654183;
|
||||||
|
s14 -= s23 * 997805;
|
||||||
|
s15 += s23 * 136657;
|
||||||
|
s16 -= s23 * 683901;
|
||||||
|
//s23 = 0;
|
||||||
|
|
||||||
|
s10 += s22 * 666643;
|
||||||
|
s11 += s22 * 470296;
|
||||||
|
s12 += s22 * 654183;
|
||||||
|
s13 -= s22 * 997805;
|
||||||
|
s14 += s22 * 136657;
|
||||||
|
s15 -= s22 * 683901;
|
||||||
|
//s22 = 0;
|
||||||
|
|
||||||
|
s9 += s21 * 666643;
|
||||||
|
s10 += s21 * 470296;
|
||||||
|
s11 += s21 * 654183;
|
||||||
|
s12 -= s21 * 997805;
|
||||||
|
s13 += s21 * 136657;
|
||||||
|
s14 -= s21 * 683901;
|
||||||
|
//s21 = 0;
|
||||||
|
|
||||||
|
s8 += s20 * 666643;
|
||||||
|
s9 += s20 * 470296;
|
||||||
|
s10 += s20 * 654183;
|
||||||
|
s11 -= s20 * 997805;
|
||||||
|
s12 += s20 * 136657;
|
||||||
|
s13 -= s20 * 683901;
|
||||||
|
//s20 = 0;
|
||||||
|
|
||||||
|
s7 += s19 * 666643;
|
||||||
|
s8 += s19 * 470296;
|
||||||
|
s9 += s19 * 654183;
|
||||||
|
s10 -= s19 * 997805;
|
||||||
|
s11 += s19 * 136657;
|
||||||
|
s12 -= s19 * 683901;
|
||||||
|
//s19 = 0;
|
||||||
|
|
||||||
|
s6 += s18 * 666643;
|
||||||
|
s7 += s18 * 470296;
|
||||||
|
s8 += s18 * 654183;
|
||||||
|
s9 -= s18 * 997805;
|
||||||
|
s10 += s18 * 136657;
|
||||||
|
s11 -= s18 * 683901;
|
||||||
|
//s18 = 0;
|
||||||
|
|
||||||
|
carry6 = (s6 + (1 << 20)) >> 21;
|
||||||
|
s7 += carry6;
|
||||||
|
s6 -= carry6 << 21;
|
||||||
|
carry8 = (s8 + (1 << 20)) >> 21;
|
||||||
|
s9 += carry8;
|
||||||
|
s8 -= carry8 << 21;
|
||||||
|
carry10 = (s10 + (1 << 20)) >> 21;
|
||||||
|
s11 += carry10;
|
||||||
|
s10 -= carry10 << 21;
|
||||||
|
carry12 = (s12 + (1 << 20)) >> 21;
|
||||||
|
s13 += carry12;
|
||||||
|
s12 -= carry12 << 21;
|
||||||
|
carry14 = (s14 + (1 << 20)) >> 21;
|
||||||
|
s15 += carry14;
|
||||||
|
s14 -= carry14 << 21;
|
||||||
|
carry16 = (s16 + (1 << 20)) >> 21;
|
||||||
|
s17 += carry16;
|
||||||
|
s16 -= carry16 << 21;
|
||||||
|
|
||||||
|
carry7 = (s7 + (1 << 20)) >> 21;
|
||||||
|
s8 += carry7;
|
||||||
|
s7 -= carry7 << 21;
|
||||||
|
carry9 = (s9 + (1 << 20)) >> 21;
|
||||||
|
s10 += carry9;
|
||||||
|
s9 -= carry9 << 21;
|
||||||
|
carry11 = (s11 + (1 << 20)) >> 21;
|
||||||
|
s12 += carry11;
|
||||||
|
s11 -= carry11 << 21;
|
||||||
|
carry13 = (s13 + (1 << 20)) >> 21;
|
||||||
|
s14 += carry13;
|
||||||
|
s13 -= carry13 << 21;
|
||||||
|
carry15 = (s15 + (1 << 20)) >> 21;
|
||||||
|
s16 += carry15;
|
||||||
|
s15 -= carry15 << 21;
|
||||||
|
|
||||||
|
s5 += s17 * 666643;
|
||||||
|
s6 += s17 * 470296;
|
||||||
|
s7 += s17 * 654183;
|
||||||
|
s8 -= s17 * 997805;
|
||||||
|
s9 += s17 * 136657;
|
||||||
|
s10 -= s17 * 683901;
|
||||||
|
//s17 = 0;
|
||||||
|
|
||||||
|
s4 += s16 * 666643;
|
||||||
|
s5 += s16 * 470296;
|
||||||
|
s6 += s16 * 654183;
|
||||||
|
s7 -= s16 * 997805;
|
||||||
|
s8 += s16 * 136657;
|
||||||
|
s9 -= s16 * 683901;
|
||||||
|
//s16 = 0;
|
||||||
|
|
||||||
|
s3 += s15 * 666643;
|
||||||
|
s4 += s15 * 470296;
|
||||||
|
s5 += s15 * 654183;
|
||||||
|
s6 -= s15 * 997805;
|
||||||
|
s7 += s15 * 136657;
|
||||||
|
s8 -= s15 * 683901;
|
||||||
|
//s15 = 0;
|
||||||
|
|
||||||
|
s2 += s14 * 666643;
|
||||||
|
s3 += s14 * 470296;
|
||||||
|
s4 += s14 * 654183;
|
||||||
|
s5 -= s14 * 997805;
|
||||||
|
s6 += s14 * 136657;
|
||||||
|
s7 -= s14 * 683901;
|
||||||
|
//s14 = 0;
|
||||||
|
|
||||||
|
s1 += s13 * 666643;
|
||||||
|
s2 += s13 * 470296;
|
||||||
|
s3 += s13 * 654183;
|
||||||
|
s4 -= s13 * 997805;
|
||||||
|
s5 += s13 * 136657;
|
||||||
|
s6 -= s13 * 683901;
|
||||||
|
//s13 = 0;
|
||||||
|
|
||||||
|
s0 += s12 * 666643;
|
||||||
|
s1 += s12 * 470296;
|
||||||
|
s2 += s12 * 654183;
|
||||||
|
s3 -= s12 * 997805;
|
||||||
|
s4 += s12 * 136657;
|
||||||
|
s5 -= s12 * 683901;
|
||||||
|
s12 = 0;
|
||||||
|
|
||||||
|
carry0 = (s0 + (1 << 20)) >> 21;
|
||||||
|
s1 += carry0;
|
||||||
|
s0 -= carry0 << 21;
|
||||||
|
carry2 = (s2 + (1 << 20)) >> 21;
|
||||||
|
s3 += carry2;
|
||||||
|
s2 -= carry2 << 21;
|
||||||
|
carry4 = (s4 + (1 << 20)) >> 21;
|
||||||
|
s5 += carry4;
|
||||||
|
s4 -= carry4 << 21;
|
||||||
|
carry6 = (s6 + (1 << 20)) >> 21;
|
||||||
|
s7 += carry6;
|
||||||
|
s6 -= carry6 << 21;
|
||||||
|
carry8 = (s8 + (1 << 20)) >> 21;
|
||||||
|
s9 += carry8;
|
||||||
|
s8 -= carry8 << 21;
|
||||||
|
carry10 = (s10 + (1 << 20)) >> 21;
|
||||||
|
s11 += carry10;
|
||||||
|
s10 -= carry10 << 21;
|
||||||
|
|
||||||
|
carry1 = (s1 + (1 << 20)) >> 21;
|
||||||
|
s2 += carry1;
|
||||||
|
s1 -= carry1 << 21;
|
||||||
|
carry3 = (s3 + (1 << 20)) >> 21;
|
||||||
|
s4 += carry3;
|
||||||
|
s3 -= carry3 << 21;
|
||||||
|
carry5 = (s5 + (1 << 20)) >> 21;
|
||||||
|
s6 += carry5;
|
||||||
|
s5 -= carry5 << 21;
|
||||||
|
carry7 = (s7 + (1 << 20)) >> 21;
|
||||||
|
s8 += carry7;
|
||||||
|
s7 -= carry7 << 21;
|
||||||
|
carry9 = (s9 + (1 << 20)) >> 21;
|
||||||
|
s10 += carry9;
|
||||||
|
s9 -= carry9 << 21;
|
||||||
|
carry11 = (s11 + (1 << 20)) >> 21;
|
||||||
|
s12 += carry11;
|
||||||
|
s11 -= carry11 << 21;
|
||||||
|
|
||||||
|
s0 += s12 * 666643;
|
||||||
|
s1 += s12 * 470296;
|
||||||
|
s2 += s12 * 654183;
|
||||||
|
s3 -= s12 * 997805;
|
||||||
|
s4 += s12 * 136657;
|
||||||
|
s5 -= s12 * 683901;
|
||||||
|
s12 = 0;
|
||||||
|
|
||||||
|
carry0 = s0 >> 21;
|
||||||
|
s1 += carry0;
|
||||||
|
s0 -= carry0 << 21;
|
||||||
|
carry1 = s1 >> 21;
|
||||||
|
s2 += carry1;
|
||||||
|
s1 -= carry1 << 21;
|
||||||
|
carry2 = s2 >> 21;
|
||||||
|
s3 += carry2;
|
||||||
|
s2 -= carry2 << 21;
|
||||||
|
carry3 = s3 >> 21;
|
||||||
|
s4 += carry3;
|
||||||
|
s3 -= carry3 << 21;
|
||||||
|
carry4 = s4 >> 21;
|
||||||
|
s5 += carry4;
|
||||||
|
s4 -= carry4 << 21;
|
||||||
|
carry5 = s5 >> 21;
|
||||||
|
s6 += carry5;
|
||||||
|
s5 -= carry5 << 21;
|
||||||
|
carry6 = s6 >> 21;
|
||||||
|
s7 += carry6;
|
||||||
|
s6 -= carry6 << 21;
|
||||||
|
carry7 = s7 >> 21;
|
||||||
|
s8 += carry7;
|
||||||
|
s7 -= carry7 << 21;
|
||||||
|
carry8 = s8 >> 21;
|
||||||
|
s9 += carry8;
|
||||||
|
s8 -= carry8 << 21;
|
||||||
|
carry9 = s9 >> 21;
|
||||||
|
s10 += carry9;
|
||||||
|
s9 -= carry9 << 21;
|
||||||
|
carry10 = s10 >> 21;
|
||||||
|
s11 += carry10;
|
||||||
|
s10 -= carry10 << 21;
|
||||||
|
carry11 = s11 >> 21;
|
||||||
|
s12 += carry11;
|
||||||
|
s11 -= carry11 << 21;
|
||||||
|
|
||||||
|
s0 += s12 * 666643;
|
||||||
|
s1 += s12 * 470296;
|
||||||
|
s2 += s12 * 654183;
|
||||||
|
s3 -= s12 * 997805;
|
||||||
|
s4 += s12 * 136657;
|
||||||
|
s5 -= s12 * 683901;
|
||||||
|
//s12 = 0;
|
||||||
|
|
||||||
|
carry0 = s0 >> 21;
|
||||||
|
s1 += carry0;
|
||||||
|
s0 -= carry0 << 21;
|
||||||
|
carry1 = s1 >> 21;
|
||||||
|
s2 += carry1;
|
||||||
|
s1 -= carry1 << 21;
|
||||||
|
carry2 = s2 >> 21;
|
||||||
|
s3 += carry2;
|
||||||
|
s2 -= carry2 << 21;
|
||||||
|
carry3 = s3 >> 21;
|
||||||
|
s4 += carry3;
|
||||||
|
s3 -= carry3 << 21;
|
||||||
|
carry4 = s4 >> 21;
|
||||||
|
s5 += carry4;
|
||||||
|
s4 -= carry4 << 21;
|
||||||
|
carry5 = s5 >> 21;
|
||||||
|
s6 += carry5;
|
||||||
|
s5 -= carry5 << 21;
|
||||||
|
carry6 = s6 >> 21;
|
||||||
|
s7 += carry6;
|
||||||
|
s6 -= carry6 << 21;
|
||||||
|
carry7 = s7 >> 21;
|
||||||
|
s8 += carry7;
|
||||||
|
s7 -= carry7 << 21;
|
||||||
|
carry8 = s8 >> 21;
|
||||||
|
s9 += carry8;
|
||||||
|
s8 -= carry8 << 21;
|
||||||
|
carry9 = s9 >> 21;
|
||||||
|
s10 += carry9;
|
||||||
|
s9 -= carry9 << 21;
|
||||||
|
carry10 = s10 >> 21;
|
||||||
|
s11 += carry10;
|
||||||
|
s10 -= carry10 << 21;
|
||||||
|
|
||||||
|
s[0] = (s0 >> 0) as u8;
|
||||||
|
s[1] = (s0 >> 8) as u8;
|
||||||
|
s[2] = ((s0 >> 16) | (s1 << 5)) as u8;
|
||||||
|
s[3] = (s1 >> 3) as u8;
|
||||||
|
s[4] = (s1 >> 11) as u8;
|
||||||
|
s[5] = ((s1 >> 19) | (s2 << 2)) as u8;
|
||||||
|
s[6] = (s2 >> 6) as u8;
|
||||||
|
s[7] = ((s2 >> 14) | (s3 << 7)) as u8;
|
||||||
|
s[8] = (s3 >> 1) as u8;
|
||||||
|
s[9] = (s3 >> 9) as u8;
|
||||||
|
s[10] = ((s3 >> 17) | (s4 << 4)) as u8;
|
||||||
|
s[11] = (s4 >> 4) as u8;
|
||||||
|
s[12] = (s4 >> 12) as u8;
|
||||||
|
s[13] = ((s4 >> 20) | (s5 << 1)) as u8;
|
||||||
|
s[14] = (s5 >> 7) as u8;
|
||||||
|
s[15] = ((s5 >> 15) | (s6 << 6)) as u8;
|
||||||
|
s[16] = (s6 >> 2) as u8;
|
||||||
|
s[17] = (s6 >> 10) as u8;
|
||||||
|
s[18] = ((s6 >> 18) | (s7 << 3)) as u8;
|
||||||
|
s[19] = (s7 >> 5) as u8;
|
||||||
|
s[20] = (s7 >> 13) as u8;
|
||||||
|
s[21] = (s8 >> 0) as u8;
|
||||||
|
s[22] = (s8 >> 8) as u8;
|
||||||
|
s[23] = ((s8 >> 16) | (s9 << 5)) as u8;
|
||||||
|
s[24] = (s9 >> 3) as u8;
|
||||||
|
s[25] = (s9 >> 11) as u8;
|
||||||
|
s[26] = ((s9 >> 19) | (s10 << 2)) as u8;
|
||||||
|
s[27] = (s10 >> 6) as u8;
|
||||||
|
s[28] = ((s10 >> 14) | (s11 << 7)) as u8;
|
||||||
|
s[29] = (s11 >> 1) as u8;
|
||||||
|
s[30] = (s11 >> 9) as u8;
|
||||||
|
s[31] = (s11 >> 17) as u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn muladd() {
|
||||||
|
let fname = "testdata/ed25519/muladd.test";
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (nega, abytes) = case.get("a").unwrap();
|
||||||
|
let (negb, bbytes) = case.get("b").unwrap();
|
||||||
|
let (negc, cbytes) = case.get("c").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!nega && !negb && !negc && !negd);
|
||||||
|
let mut mine = [0; 32];
|
||||||
|
x25519_sc_muladd(&mut mine, abytes, bbytes, cbytes);
|
||||||
|
for i in 0..32 {
|
||||||
|
assert_eq!(&mine[i], &dbytes[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn curve25519_scalar_mask(a: &mut [u8])
|
||||||
|
{
|
||||||
|
assert_eq!(a.len(), 32);
|
||||||
|
a[0] &= 248;
|
||||||
|
a[31] &= 127;
|
||||||
|
a[31] |= 64;
|
||||||
|
}
|
||||||
|
|
||||||
196
src/hmac.rs
Normal file
196
src/hmac.rs
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
//! This module implements the Keyed-Hash Message Authentication Code, or HMAC,
|
||||||
|
//! as defined by NIST 198-1. Now, you might have questions, like:
|
||||||
|
//! * *Where did the 'K' go in the acronym?* I don't know. Maybe we should
|
||||||
|
//! always be saying Keyed-HMAC? It's a mystery.
|
||||||
|
//! * *What is this good for?* I do know the answer to that! HMACs are
|
||||||
|
//! useful when you want to extend the ability of a hash to tell you if
|
||||||
|
//! a message has been modified with the ability to determine if the
|
||||||
|
//! person that sent it had hold of a key. It's thus a version of the
|
||||||
|
//! message signing capability used in asymmetric crypto (`DSA`, `RSA`,
|
||||||
|
//! `ECDSA`, and `ED25519`, as implemented in this crate), but with a
|
||||||
|
//! symmetric key, instead.
|
||||||
|
//!
|
||||||
|
//! Because HMAC can be used with a variety of hash functions, this module
|
||||||
|
//! implements it as a generic structure that takes the associated hash as
|
||||||
|
//! a type argument. This should provide a reasonable level of flexibility,
|
||||||
|
//! while allowing the type system from preventing us from making any number
|
||||||
|
//! of really annoying mistakes. You can specify which of the hash functions
|
||||||
|
//! you want to use by using your standard turbofish:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::hmac::HMAC;
|
||||||
|
//! use simple_crypto::sha::SHA256;
|
||||||
|
//!
|
||||||
|
//! let key = [0,1,2,3,4]; // very secure
|
||||||
|
//! let msg = [5,6,7,8];
|
||||||
|
//! let hmac = HMAC::<SHA256>::hmac(&key, &msg);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Much like with `SHAKE128` and `SHAKE256` the interface for HMAC is
|
||||||
|
//! similar to, but not quite, the interface for `Hash`. We thus try to
|
||||||
|
//! copy as much of the standard `Hash` interface as we can, but extend
|
||||||
|
//! `new` with a key, rename `hash` to `hmac`, and extend `hmac` with a
|
||||||
|
//! key as well. This provides a similar ability to use HMACs both in an
|
||||||
|
//! incremental mode as well as just do it all at once, as follows:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::hmac::HMAC;
|
||||||
|
//! use simple_crypto::sha::SHA256;
|
||||||
|
//!
|
||||||
|
//! let key = [0,1,2,3,4]; // like my suitcase
|
||||||
|
//! let msg = [5,6,7,8];
|
||||||
|
//!
|
||||||
|
//! // Compute the HMAC incrementally
|
||||||
|
//! let mut hmacinc = HMAC::<SHA256>::new(&key);
|
||||||
|
//! hmacinc.update(&[5,6]);
|
||||||
|
//! hmacinc.update(&[7,8]);
|
||||||
|
//! let hmac_incremental = hmacinc.finalize();
|
||||||
|
//!
|
||||||
|
//! // Compute the HMAC all at once
|
||||||
|
//! let hmac_once = HMAC::<SHA256>::hmac(&key, &msg);
|
||||||
|
//!
|
||||||
|
//! // ... which should be the same thing
|
||||||
|
//! assert_eq!(hmac_incremental, hmac_once);
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
/// The HMAC structure, parameterized by its hash function.
|
||||||
|
///
|
||||||
|
/// Much like with `SHAKE128` and `SHAKE256` the interface for HMAC is
|
||||||
|
/// similar to, but not quite, the interface for `Hash`. We thus try to
|
||||||
|
/// copy as much of the standard `Hash` interface as we can, but extend
|
||||||
|
/// `new` with a key, rename `hash` to `hmac`, and extend `hmac` with a
|
||||||
|
/// key as well. This provides a similar ability to use HMACs both in an
|
||||||
|
/// incremental mode as well as just do it all at once, as follows:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::hmac::HMAC;
|
||||||
|
/// use simple_crypto::sha::SHA256;
|
||||||
|
///
|
||||||
|
/// let key = [0,1,2,3,4]; // like my suitcase
|
||||||
|
/// let msg = [5,6,7,8];
|
||||||
|
///
|
||||||
|
/// // Compute the HMAC incrementally
|
||||||
|
/// let mut hmacinc = HMAC::<SHA256>::new(&key);
|
||||||
|
/// hmacinc.update(&[5,6]);
|
||||||
|
/// hmacinc.update(&[7,8]);
|
||||||
|
/// let hmac_incremental = hmacinc.finalize();
|
||||||
|
///
|
||||||
|
/// // Compute the HMAC all at once
|
||||||
|
/// let hmac_once = HMAC::<SHA256>::hmac(&key, &msg);
|
||||||
|
///
|
||||||
|
/// // ... which should be the same thing
|
||||||
|
/// assert_eq!(hmac_incremental, hmac_once);
|
||||||
|
/// ```
|
||||||
|
use super::Hash;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct HMAC<H: Hash + Clone> {
|
||||||
|
ipad_hash: H,
|
||||||
|
opad_hash: H,
|
||||||
|
result: Option<Vec<u8>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: Hash + Clone> HMAC<H> {
|
||||||
|
/// Generate a new HMAC construction for the provide underlying hash
|
||||||
|
/// function, and prep it to start taking input via the `update`
|
||||||
|
/// method.
|
||||||
|
pub fn new(inkey: &[u8]) -> Self {
|
||||||
|
let hash_blocklen_bytes = H::block_size() / 8;
|
||||||
|
|
||||||
|
// If the input key is longer than the hash block length, then we
|
||||||
|
// immediately hash it down to be the block length. Otherwise, we
|
||||||
|
// leave it be.
|
||||||
|
let mut key = if inkey.len() > hash_blocklen_bytes { H::hash(inkey) }
|
||||||
|
else { inkey.to_vec() };
|
||||||
|
// It may now be too small, or have started too small, in which case
|
||||||
|
// we pad it out with zeros.
|
||||||
|
key.resize(hash_blocklen_bytes, 0);
|
||||||
|
// Generate the inner and outer key pad from this key.
|
||||||
|
let o_key_pad: Vec<u8> = key.iter().map(|x| *x ^ 0x5c).collect();
|
||||||
|
let i_key_pad: Vec<u8> = key.iter().map(|x| *x ^ 0x36).collect();
|
||||||
|
// Now we can start the hashes; obviously we'll have to wait
|
||||||
|
// until we get the rest of the message to complete them.
|
||||||
|
let mut ipad_hash = H::new();
|
||||||
|
ipad_hash.update(&i_key_pad);
|
||||||
|
let mut opad_hash = H::new();
|
||||||
|
opad_hash.update(&o_key_pad);
|
||||||
|
let result = None;
|
||||||
|
HMAC { ipad_hash, opad_hash, result }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add more data as part of the HMAC computation. This can be called
|
||||||
|
/// zero or more times over the lifetime of the HMAC structure. That
|
||||||
|
/// being said, once you call `finalize`, this structure is done, and
|
||||||
|
/// it will ignore further calls to `update`.
|
||||||
|
pub fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
if self.result.is_none() {
|
||||||
|
self.ipad_hash.update(&buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provide the final HMAC value for the bitrstream as read. This shifts
|
||||||
|
/// this structure into a final mode, in which it will ignore any more
|
||||||
|
/// data provided to it from `update`. You can, however, call `finalize`
|
||||||
|
/// more than once; the HMAC structure caches the return value and will
|
||||||
|
/// return it as many times as you like.
|
||||||
|
pub fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if let Some(ref res) = self.result {
|
||||||
|
res.clone()
|
||||||
|
} else {
|
||||||
|
self.opad_hash.update(&self.ipad_hash.finalize());
|
||||||
|
let res = self.opad_hash.finalize();
|
||||||
|
self.result = Some(res.clone());
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A useful method for those situations in which you have only one block
|
||||||
|
/// of data to generate an HMAC for. Runs `new`, `update`, and `finalize`
|
||||||
|
/// for you, in order.
|
||||||
|
pub fn hmac(key: &[u8], val: &[u8]) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut h = Self::new(key);
|
||||||
|
h.update(val);
|
||||||
|
h.finalize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use sha::{SHA1,SHA224,SHA256,SHA384,SHA512};
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
#[cfg(test)]
|
||||||
|
use cryptonum::unsigned::{Decoder,U192};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_vectors() {
|
||||||
|
let fname = "testdata/sha/hmac.test";
|
||||||
|
run_test(fname.to_string(), 6, |case| {
|
||||||
|
let (negh, hbytes) = case.get("h").unwrap();
|
||||||
|
let (negr, rbytes) = case.get("r").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negk, kbytes) = case.get("k").unwrap();
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negt, tbytes) = case.get("t").unwrap();
|
||||||
|
|
||||||
|
assert!(!negh && !negr && !negm && !negk && !negl && !negt);
|
||||||
|
let l = usize::from(U192::from_bytes(lbytes));
|
||||||
|
let h = usize::from(U192::from_bytes(hbytes));
|
||||||
|
assert_eq!(l, kbytes.len());
|
||||||
|
let mut res = match h {
|
||||||
|
160 => HMAC::<SHA1>::hmac(&kbytes, &mbytes),
|
||||||
|
224 => HMAC::<SHA224>::hmac(&kbytes, &mbytes),
|
||||||
|
256 => HMAC::<SHA256>::hmac(&kbytes, &mbytes),
|
||||||
|
384 => HMAC::<SHA384>::hmac(&kbytes, &mbytes),
|
||||||
|
512 => HMAC::<SHA512>::hmac(&kbytes, &mbytes),
|
||||||
|
_ => panic!("Weird hash size in HMAC test file")
|
||||||
|
};
|
||||||
|
let t = usize::from(U192::from_bytes(tbytes));
|
||||||
|
res.resize(t, 0);
|
||||||
|
assert_eq!(rbytes, &res);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
90
src/lib.rs
90
src/lib.rs
@@ -1,4 +1,3 @@
|
|||||||
#![feature(i128_type)]
|
|
||||||
//! # Simple Crypto: A quaint little crypto library for rust.
|
//! # Simple Crypto: A quaint little crypto library for rust.
|
||||||
//!
|
//!
|
||||||
//! This is the simple_crypto library. Its goal is to provide straightforward
|
//! This is the simple_crypto library. Its goal is to provide straightforward
|
||||||
@@ -10,21 +9,92 @@
|
|||||||
//! that a new user should use, along with documentation regarding how and
|
//! that a new user should use, along with documentation regarding how and
|
||||||
//! when they should use it, and examples. For now, it mostly just fowards
|
//! when they should use it, and examples. For now, it mostly just fowards
|
||||||
//! off to more detailed modules. Help requested!
|
//! off to more detailed modules. Help requested!
|
||||||
|
extern crate base64;
|
||||||
|
extern crate byteorder;
|
||||||
|
extern crate chrono;
|
||||||
|
extern crate cryptonum;
|
||||||
|
extern crate num;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate quickcheck;
|
extern crate quickcheck;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate simple_asn1;
|
||||||
|
|
||||||
/// The cryptonum module provides support for large numbers at fixed,
|
/// The `rsa` module provides bare-bones support for RSA signing, verification,
|
||||||
/// cryptographically-relevant sizes.
|
/// encryption, decryption, and key generation.
|
||||||
pub mod cryptonum;
|
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;
|
||||||
|
/// The `ecdsa` module provides bare-bones support for ECDSA signing,
|
||||||
|
/// verification, and key generation.
|
||||||
|
pub mod ecdsa;
|
||||||
|
/// The `ed25519` provides signing and verification using ED25519.
|
||||||
|
pub mod ed25519;
|
||||||
|
/// The `ssh` module provides support for parsing OpenSSH-formatted SSH keys,
|
||||||
|
/// both public and private.
|
||||||
|
pub mod ssh;
|
||||||
|
/// The `shake` module provides support for SHAKE128 and SHAKE256, two
|
||||||
|
/// variable-length hash functions that derive from the same core hash
|
||||||
|
/// as SHA3.
|
||||||
|
pub mod shake;
|
||||||
|
/// The `hmac` module provides support for keyed-hash message authentication,
|
||||||
|
/// or HMAC, based on any of the hash functions defined in this module.
|
||||||
|
pub mod hmac;
|
||||||
|
/// The `x509` module supports parsing and generating x.509 certificates, as
|
||||||
|
/// used by TLS and others.
|
||||||
|
pub mod x509;
|
||||||
|
/// An implementation of the SHA family of hashes, including the relatively
|
||||||
|
/// weak SHA1 and a bunch of hashes you should use, like the SHA2 and SHA3
|
||||||
|
/// hashes.
|
||||||
|
pub mod sha;
|
||||||
|
|
||||||
#[cfg(test)]
|
/// A generic trait for defining what a key pair looks like. This is useful
|
||||||
mod test {
|
/// in a couple places in which we want to define code regardless of the
|
||||||
|
/// kind of key it is, but is unlikely to be hugely useful to users of the
|
||||||
|
/// library.
|
||||||
|
pub trait KeyPair {
|
||||||
|
/// The type of the public key of this pair.
|
||||||
|
type Public;
|
||||||
|
/// The type of the private key of this pair.
|
||||||
|
type Private;
|
||||||
|
|
||||||
#[test]
|
/// Generate a key pair given the provided public and private keys.
|
||||||
fn testing_works() {
|
fn new(pbl: Self::Public, prv: Self::Private) -> Self;
|
||||||
assert!(true);
|
}
|
||||||
|
|
||||||
|
/// A generic trait for defining a hash function.
|
||||||
|
pub trait Hash: Sized
|
||||||
|
{
|
||||||
|
/// Generate a fresh instance of this hash function, set to the
|
||||||
|
/// appropriate initial state.
|
||||||
|
fn new() -> Self;
|
||||||
|
/// Update the hash function with some more data for it to chew on.
|
||||||
|
/// Nom nom nom. If you give it more information after calling
|
||||||
|
/// `finalize`, the implementation is welcome to do anything it
|
||||||
|
/// wants; mostly they will just ignore additional data, but
|
||||||
|
/// maybe just don't do that.
|
||||||
|
fn update(&mut self, data: &[u8]);
|
||||||
|
/// Finalize the hash function, returning the hash value.
|
||||||
|
fn finalize(&mut self) -> Vec<u8>;
|
||||||
|
/// Return the block size of the underlying hash function, in
|
||||||
|
/// bits. This is mostly useful internally to this crate.
|
||||||
|
fn block_size() -> usize;
|
||||||
|
|
||||||
|
/// This is a convenience routine that runs new(), update(), and
|
||||||
|
/// finalize() on a piece of data all at once. Because that's
|
||||||
|
/// mostly what people want to do.
|
||||||
|
fn hash(data: &[u8]) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut x = Self::new();
|
||||||
|
x.update(&data);
|
||||||
|
x.finalize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod testing;
|
||||||
|
mod utils;
|
||||||
|
|||||||
64
src/rsa/core.rs
Normal file
64
src/rsa/core.rs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use num::bigint::BigUint;
|
||||||
|
use rsa::errors::RSAError;
|
||||||
|
use simple_asn1::{ASN1Block,ASN1DecodeErr};
|
||||||
|
|
||||||
|
/// A valid key size for RSA keys, basically, and a (slightly annoying)
|
||||||
|
/// trait that is used to tie these types to their Barrett value types.
|
||||||
|
pub trait RSAMode {
|
||||||
|
type Barrett;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RSAMode for U512 { type Barrett = BarrettU512; }
|
||||||
|
impl RSAMode for U1024 { type Barrett = BarrettU1024; }
|
||||||
|
impl RSAMode for U2048 { type Barrett = BarrettU2048; }
|
||||||
|
impl RSAMode for U3072 { type Barrett = BarrettU3072; }
|
||||||
|
impl RSAMode for U4096 { type Barrett = BarrettU4096; }
|
||||||
|
impl RSAMode for U8192 { type Barrett = BarrettU8192; }
|
||||||
|
impl RSAMode for U15360 { type Barrett = BarrettU15360; }
|
||||||
|
|
||||||
|
|
||||||
|
pub fn pkcs1_pad(ident: &[u8], hash: &[u8], keylen: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut idhash = Vec::new();
|
||||||
|
idhash.extend_from_slice(ident);
|
||||||
|
idhash.extend_from_slice(hash);
|
||||||
|
let tlen = idhash.len();
|
||||||
|
assert!(keylen > (tlen + 3));
|
||||||
|
let mut padding = Vec::new();
|
||||||
|
padding.resize(keylen - tlen - 3, 0xFF);
|
||||||
|
let mut result = vec![0x00,0x01];
|
||||||
|
result.append(&mut padding);
|
||||||
|
result.push(0x00);
|
||||||
|
result.append(&mut idhash);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drop0s(a: &[u8]) -> &[u8] {
|
||||||
|
let mut idx = 0;
|
||||||
|
|
||||||
|
while (idx < a.len()) && (a[idx] == 0) {
|
||||||
|
idx = idx + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&a[idx..]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xor_vecs(a: &Vec<u8>, b: &Vec<u8>) -> Vec<u8> {
|
||||||
|
a.iter().zip(b.iter()).map(|(a,b)| a^b).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_biguint(b: &ASN1Block) -> Result<BigUint,RSAError> {
|
||||||
|
match b {
|
||||||
|
&ASN1Block::Integer(_, _, ref v) => {
|
||||||
|
match v.to_biguint() {
|
||||||
|
Some(sn) => Ok(sn),
|
||||||
|
_ => Err(RSAError::InvalidKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(RSAError::ASN1DecodeErr(ASN1DecodeErr::EmptyBuffer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
29
src/rsa/errors.rs
Normal file
29
src/rsa/errors.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
use simple_asn1::ASN1DecodeErr;
|
||||||
|
use rand;
|
||||||
|
|
||||||
|
/// A bunch of errors that you can get generating, reading, or
|
||||||
|
/// writing RSA keys.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum RSAError {
|
||||||
|
BadMessageSize,
|
||||||
|
KeyTooSmallForHash,
|
||||||
|
DecryptionError,
|
||||||
|
DecryptHashMismatch,
|
||||||
|
InvalidKey,
|
||||||
|
RandomGenError(rand::Error),
|
||||||
|
ASN1DecodeErr(ASN1DecodeErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<rand::Error> for RSAError {
|
||||||
|
fn from(e: rand::Error) -> RSAError {
|
||||||
|
RSAError::RandomGenError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ASN1DecodeErr> for RSAError {
|
||||||
|
fn from(e: ASN1DecodeErr) -> RSAError {
|
||||||
|
RSAError::ASN1DecodeErr(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
339
src/rsa/mod.rs
Normal file
339
src/rsa/mod.rs
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
//! A simple RSA library.
|
||||||
|
//!
|
||||||
|
//! This library performs all the standard bits and pieces that you'd expect
|
||||||
|
//! from an RSA library, and does so using only Rust. It's a bit slow at the
|
||||||
|
//! moment, but it gets the job done.
|
||||||
|
//!
|
||||||
|
//! Key generation is supported, using either the native `OsRng` or a random
|
||||||
|
//! number generator of your choice. Obviously, you should be careful to use
|
||||||
|
//! a cryptographically-sound random number generator sufficient for the
|
||||||
|
//! security level you're going for.
|
||||||
|
//!
|
||||||
|
//! Signing and verification are via standard PKCS1 padding, but can be
|
||||||
|
//! adjusted based on the exact hash you want. This library also supports
|
||||||
|
//! somewhat arbitrary signing mechanisms used by your weirder network
|
||||||
|
//! protocols. (I'm looking at you, Tor.)
|
||||||
|
//!
|
||||||
|
//! Encryption and decryption are via the OAEP mechanism, as described in
|
||||||
|
//! NIST documents.
|
||||||
|
//!
|
||||||
|
//! The following is an example of generating an RSA2048 key pair, then using
|
||||||
|
//! it to sign, verify, encrypt, and decrypt some data.
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! extern crate cryptonum;
|
||||||
|
//!
|
||||||
|
//! use simple_crypto::rsa::RSAKeyPair;
|
||||||
|
//! use simple_crypto::rsa::SIGNING_HASH_SHA256;
|
||||||
|
//! use simple_crypto::rsa::OAEPParams;
|
||||||
|
//! use simple_crypto::sha::SHA256;
|
||||||
|
//! use cryptonum::unsigned::U2048;
|
||||||
|
//!
|
||||||
|
//! // Generate a new RSA with key size 2048. (This is an acceptable but
|
||||||
|
//! // not great key size, but is a nice compromise given that this little
|
||||||
|
//! // example runs as part of the test suite.)
|
||||||
|
//! let mut rng = rand::rngs::OsRng::new().unwrap();
|
||||||
|
//! let kp = RSAKeyPair::<U2048>::generate(&mut rng);
|
||||||
|
//!
|
||||||
|
//! // Now that you have this key pair, you can sign and verify messages
|
||||||
|
//! // using it. For example, to sign the vector [0,1,2,3,4] with SHA256
|
||||||
|
//! // and then verify that signature, we would write:
|
||||||
|
//! let msg = vec![0,1,2,3,4];
|
||||||
|
//! let sig = kp.private.sign(&SIGNING_HASH_SHA256, &msg);
|
||||||
|
//! assert!( kp.public.verify(&SIGNING_HASH_SHA256, &msg, &sig) );
|
||||||
|
//!
|
||||||
|
//! // We can also use RSA public keys to encrypt data, which can then be
|
||||||
|
//! // decrypted by the private key.
|
||||||
|
//! let params = OAEPParams::<SHA256>::new(String::from("example!"));
|
||||||
|
//! let cipher = kp.public.encrypt(¶ms, &msg).expect("Encryption error");
|
||||||
|
//! let msg2 = kp.private.decrypt(¶ms, &cipher).expect("Decryption error");
|
||||||
|
//! assert_eq!(msg, msg2);
|
||||||
|
//! ```
|
||||||
|
mod core;
|
||||||
|
mod errors;
|
||||||
|
mod oaep;
|
||||||
|
mod private;
|
||||||
|
mod public;
|
||||||
|
mod signing_hashes;
|
||||||
|
|
||||||
|
pub use self::core::RSAMode;
|
||||||
|
pub use self::errors::RSAError;
|
||||||
|
pub use self::signing_hashes::{SigningHash,
|
||||||
|
SIGNING_HASH_NULL,
|
||||||
|
SIGNING_HASH_SHA1,
|
||||||
|
SIGNING_HASH_SHA224,
|
||||||
|
SIGNING_HASH_SHA256,
|
||||||
|
SIGNING_HASH_SHA384,
|
||||||
|
SIGNING_HASH_SHA512};
|
||||||
|
pub use self::oaep::OAEPParams;
|
||||||
|
pub use self::private::{RSAPrivate, RSAPrivateKey};
|
||||||
|
pub use self::public::{RSAPublic, RSAPublicKey};
|
||||||
|
use cryptonum::signed::{EGCD,ModInv};
|
||||||
|
use cryptonum::unsigned::{CryptoNum,PrimeGen};
|
||||||
|
use cryptonum::unsigned::{U256,U512,U1024,U1536,U2048,U3072,U4096,U7680,U8192,U15360};
|
||||||
|
use rand::RngCore;
|
||||||
|
#[cfg(test)]
|
||||||
|
use std::fmt;
|
||||||
|
use std::ops::Sub;
|
||||||
|
use super::KeyPair;
|
||||||
|
|
||||||
|
fn diff<T>(a: &T, b: &T) -> T
|
||||||
|
where
|
||||||
|
T: Clone + PartialOrd,
|
||||||
|
T: Sub<T,Output=T>
|
||||||
|
{
|
||||||
|
if a > b {
|
||||||
|
a.clone() - b.clone()
|
||||||
|
} else {
|
||||||
|
b.clone() - a.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An RSA key pair containing keys of the given size; keeping them in the
|
||||||
|
/// type means you'll never forget which one you have.
|
||||||
|
///
|
||||||
|
/// As an aside:
|
||||||
|
/// * `U512` should only be used for testing
|
||||||
|
/// * `U1024` should only be used to support old protocols or devices
|
||||||
|
/// * `U2048` is probably your bare minimum
|
||||||
|
/// * `U3072` is a very reasonable choice
|
||||||
|
/// * **`U4096` is what you should use**
|
||||||
|
/// * `U8192` is starting to get a bit silly (and slow)
|
||||||
|
/// * `U15360` is for when you're using encryption to heat your house or server room
|
||||||
|
pub struct RSAKeyPair<R: RSAMode> {
|
||||||
|
pub public: RSAPublicKey<R>,
|
||||||
|
pub private: RSAPrivateKey<R>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generic RSA key pair that is agnostic about its key size. It's not
|
||||||
|
/// totally clear why this is useful, at this point.
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum RSAPair {
|
||||||
|
R512(RSAPublicKey<U512>, RSAPrivateKey<U512>),
|
||||||
|
R1024(RSAPublicKey<U1024>, RSAPrivateKey<U1024>),
|
||||||
|
R2048(RSAPublicKey<U2048>, RSAPrivateKey<U2048>),
|
||||||
|
R3072(RSAPublicKey<U3072>, RSAPrivateKey<U3072>),
|
||||||
|
R4096(RSAPublicKey<U4096>, RSAPrivateKey<U4096>),
|
||||||
|
R8192(RSAPublicKey<U8192>, RSAPrivateKey<U8192>),
|
||||||
|
R15360(RSAPublicKey<U15360>, RSAPrivateKey<U15360>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl fmt::Debug for RSAPair {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
RSAPair::R512(_,_) => f.write_str("512-bit RSA key pair"),
|
||||||
|
RSAPair::R1024(_,_) => f.write_str("1024-bit RSA key pair"),
|
||||||
|
RSAPair::R2048(_,_) => f.write_str("2048-bit RSA key pair"),
|
||||||
|
RSAPair::R3072(_,_) => f.write_str("3072-bit RSA key pair"),
|
||||||
|
RSAPair::R4096(_,_) => f.write_str("4096-bit RSA key pair"),
|
||||||
|
RSAPair::R8192(_,_) => f.write_str("8192-bit RSA key pair"),
|
||||||
|
RSAPair::R15360(_,_) => f.write_str("15360-bit RSA key pair"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyPair for RSAPair {
|
||||||
|
type Public = RSAPublic;
|
||||||
|
type Private = RSAPrivate;
|
||||||
|
|
||||||
|
fn new(pu: RSAPublic, pr: RSAPrivate) -> RSAPair
|
||||||
|
{
|
||||||
|
match (pu, pr) {
|
||||||
|
(RSAPublic::Key512(pbl), RSAPrivate::Key512(prv)) =>
|
||||||
|
RSAPair::R512(pbl, prv),
|
||||||
|
(RSAPublic::Key1024(pbl), RSAPrivate::Key1024(prv)) =>
|
||||||
|
RSAPair::R1024(pbl, prv),
|
||||||
|
(RSAPublic::Key2048(pbl), RSAPrivate::Key2048(prv)) =>
|
||||||
|
RSAPair::R2048(pbl, prv),
|
||||||
|
(RSAPublic::Key3072(pbl), RSAPrivate::Key3072(prv)) =>
|
||||||
|
RSAPair::R3072(pbl, prv),
|
||||||
|
(RSAPublic::Key4096(pbl), RSAPrivate::Key4096(prv)) =>
|
||||||
|
RSAPair::R4096(pbl, prv),
|
||||||
|
(RSAPublic::Key8192(pbl), RSAPrivate::Key8192(prv)) =>
|
||||||
|
RSAPair::R8192(pbl, prv),
|
||||||
|
(RSAPublic::Key15360(pbl), RSAPrivate::Key15360(prv)) =>
|
||||||
|
RSAPair::R15360(pbl, prv),
|
||||||
|
_ =>
|
||||||
|
panic!("Unmatched public/private arguments to RSAPair::new()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RSAPair {
|
||||||
|
pub fn sign(&self, signhash: &SigningHash, msg: &[u8]) -> Vec<u8>
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
RSAPair::R512(_,prv) => prv.sign(signhash, msg),
|
||||||
|
RSAPair::R1024(_,prv) => prv.sign(signhash, msg),
|
||||||
|
RSAPair::R2048(_,prv) => prv.sign(signhash, msg),
|
||||||
|
RSAPair::R3072(_,prv) => prv.sign(signhash, msg),
|
||||||
|
RSAPair::R4096(_,prv) => prv.sign(signhash, msg),
|
||||||
|
RSAPair::R8192(_,prv) => prv.sign(signhash, msg),
|
||||||
|
RSAPair::R15360(_,prv) => prv.sign(signhash, msg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify(&self, signhash: &SigningHash, msg: &[u8], sig: &[u8]) -> bool
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
RSAPair::R512(pbl,_) => pbl.verify(signhash, msg, sig),
|
||||||
|
RSAPair::R1024(pbl,_) => pbl.verify(signhash, msg, sig),
|
||||||
|
RSAPair::R2048(pbl,_) => pbl.verify(signhash, msg, sig),
|
||||||
|
RSAPair::R3072(pbl,_) => pbl.verify(signhash, msg, sig),
|
||||||
|
RSAPair::R4096(pbl,_) => pbl.verify(signhash, msg, sig),
|
||||||
|
RSAPair::R8192(pbl,_) => pbl.verify(signhash, msg, sig),
|
||||||
|
RSAPair::R15360(pbl,_) => pbl.verify(signhash, msg, sig),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn public(&self) -> RSAPublic
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
&RSAPair::R512(ref pbl,_) => RSAPublic::Key512(pbl.clone()),
|
||||||
|
&RSAPair::R1024(ref pbl,_) => RSAPublic::Key1024(pbl.clone()),
|
||||||
|
&RSAPair::R2048(ref pbl,_) => RSAPublic::Key2048(pbl.clone()),
|
||||||
|
&RSAPair::R3072(ref pbl,_) => RSAPublic::Key3072(pbl.clone()),
|
||||||
|
&RSAPair::R4096(ref pbl,_) => RSAPublic::Key4096(pbl.clone()),
|
||||||
|
&RSAPair::R8192(ref pbl,_) => RSAPublic::Key8192(pbl.clone()),
|
||||||
|
&RSAPair::R15360(ref pbl,_) => RSAPublic::Key15360(pbl.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn private(&self) -> RSAPrivate
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
&RSAPair::R512(_,ref prv) => RSAPrivate::Key512(prv.clone()),
|
||||||
|
&RSAPair::R1024(_,ref prv) => RSAPrivate::Key1024(prv.clone()),
|
||||||
|
&RSAPair::R2048(_,ref prv) => RSAPrivate::Key2048(prv.clone()),
|
||||||
|
&RSAPair::R3072(_,ref prv) => RSAPrivate::Key3072(prv.clone()),
|
||||||
|
&RSAPair::R4096(_,ref prv) => RSAPrivate::Key4096(prv.clone()),
|
||||||
|
&RSAPair::R8192(_,ref prv) => RSAPrivate::Key8192(prv.clone()),
|
||||||
|
&RSAPair::R15360(_,ref prv) => RSAPrivate::Key15360(prv.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_rsa_pair
|
||||||
|
{
|
||||||
|
($uint: ident, $half: ident, $iterations: expr) => {
|
||||||
|
impl KeyPair for RSAKeyPair<$uint> {
|
||||||
|
type Public = RSAPublicKey<$uint>;
|
||||||
|
type Private = RSAPrivateKey<$uint>;
|
||||||
|
|
||||||
|
fn new(pu: RSAPublicKey<$uint>, pr: RSAPrivateKey<$uint>) -> RSAKeyPair<$uint> {
|
||||||
|
RSAKeyPair {
|
||||||
|
public: pu,
|
||||||
|
private: pr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RSAKeyPair<$uint> {
|
||||||
|
pub fn generate<G>(rng: &mut G) -> RSAKeyPair<$uint>
|
||||||
|
where G: RngCore
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
let ebase = 65537u32;
|
||||||
|
let e = $uint::from(ebase);
|
||||||
|
let (p, q) = RSAKeyPair::<$uint>::generate_pq(rng, &$half::from(ebase));
|
||||||
|
let one = $half::from(1u32);
|
||||||
|
let pminus1 = &p - &one;
|
||||||
|
let qminus1 = &q - &one;
|
||||||
|
let phi = pminus1 * qminus1;
|
||||||
|
let n = &p * &q;
|
||||||
|
if let Some(d) = e.modinv(&phi) {
|
||||||
|
let public = RSAPublicKey::<$uint>::new(n.clone(), e);
|
||||||
|
let private = RSAPrivateKey::<$uint>::new(n, d);
|
||||||
|
return RSAKeyPair::<$uint>::new(public, private);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_pq<G>(rng: &mut G, e: &$half) -> ($half, $half)
|
||||||
|
where G: RngCore
|
||||||
|
{
|
||||||
|
let sqrt2_32 = 6074001000u64;
|
||||||
|
let half_bitlen = $half::bit_length();
|
||||||
|
let minval = $half::from(sqrt2_32) << (half_bitlen - 33);
|
||||||
|
let mindiff = $half::from(1u64) << (half_bitlen - 101);
|
||||||
|
let p = $half::random_primef(rng, $iterations, |x| {
|
||||||
|
if (x >= minval) && x.gcd_is_one(e) {
|
||||||
|
Some(x)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let q = $half::random_primef(rng, $iterations, |x| {
|
||||||
|
if (x >= minval) && x.gcd_is_one(e) {
|
||||||
|
Some(x)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if diff(&p, &q) >= mindiff {
|
||||||
|
return (p, q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_rsa_pair!(U512, U256, 7);
|
||||||
|
generate_rsa_pair!(U1024, U512, 7);
|
||||||
|
generate_rsa_pair!(U2048, U1024, 4);
|
||||||
|
generate_rsa_pair!(U3072, U1536, 3);
|
||||||
|
generate_rsa_pair!(U4096, U2048, 3);
|
||||||
|
generate_rsa_pair!(U8192, U4096, 3);
|
||||||
|
generate_rsa_pair!(U15360, U7680, 3);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod generation {
|
||||||
|
use quickcheck::{Arbitrary,Gen};
|
||||||
|
use std::fmt;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
impl Clone for RSAKeyPair<U512> {
|
||||||
|
fn clone(&self) -> RSAKeyPair<U512> {
|
||||||
|
RSAKeyPair {
|
||||||
|
public: RSAPublicKey {
|
||||||
|
n: self.public.n.clone(),
|
||||||
|
nu: self.public.nu.clone(),
|
||||||
|
e: self.public.e.clone(),
|
||||||
|
},
|
||||||
|
private: RSAPrivateKey {
|
||||||
|
nu: self.private.nu.clone(),
|
||||||
|
d: self.private.d.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for RSAKeyPair<U512> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("RSA512KeyPair")
|
||||||
|
.field("n", &self.public.n)
|
||||||
|
.field("e", &self.public.e)
|
||||||
|
.field("d", &self.private.d)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Arbitrary for RSAKeyPair<U512> {
|
||||||
|
fn arbitrary<G: Gen>(g: &mut G) -> RSAKeyPair<U512> {
|
||||||
|
RSAKeyPair::<U512>::generate(g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quickcheck! {
|
||||||
|
fn generate_and_sign(keypair: RSAKeyPair<U512>, msg: Vec<u8>) -> bool {
|
||||||
|
let sig = keypair.private.sign(&SIGNING_HASH_SHA256, &msg);
|
||||||
|
keypair.public.verify(&SIGNING_HASH_SHA256, &msg, &sig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/rsa/oaep.rs
Normal file
46
src/rsa/oaep.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
use byteorder::{BigEndian,ByteOrder};
|
||||||
|
use sha::Hash;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
/// Parameters for OAEP encryption and decryption: a hash function to use as
|
||||||
|
/// part of the message generation function (MGF1, if you're curious),
|
||||||
|
/// and any labels you want to include as part of the encryption.
|
||||||
|
pub struct OAEPParams<H: Hash> {
|
||||||
|
pub label: String,
|
||||||
|
phantom: PhantomData<H>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: Hash> OAEPParams<H> {
|
||||||
|
pub fn new(label: String)
|
||||||
|
-> OAEPParams<H>
|
||||||
|
{
|
||||||
|
OAEPParams { label: label, phantom: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash_len(&self) -> usize {
|
||||||
|
H::hash(&[]).len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash(&self, input: &[u8]) -> Vec<u8> {
|
||||||
|
H::hash(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mgf1(&self, input: &[u8], len: usize) -> Vec<u8> {
|
||||||
|
let mut res = Vec::with_capacity(len);
|
||||||
|
let mut counter = 0u32;
|
||||||
|
|
||||||
|
while res.len() < len {
|
||||||
|
let mut buffer = [0; 4];
|
||||||
|
BigEndian::write_u32(&mut buffer, counter);
|
||||||
|
let mut digest = H::new();
|
||||||
|
digest.update(input);
|
||||||
|
digest.update(&buffer);
|
||||||
|
let chunk = digest.finalize();
|
||||||
|
res.extend_from_slice(chunk.as_slice());
|
||||||
|
counter = counter + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.truncate(len);
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
269
src/rsa/private.rs
Normal file
269
src/rsa/private.rs
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use rsa::core::{RSAMode,drop0s,pkcs1_pad,xor_vecs};
|
||||||
|
use rsa::errors::RSAError;
|
||||||
|
use rsa::oaep::OAEPParams;
|
||||||
|
use rsa::signing_hashes::SigningHash;
|
||||||
|
use sha::Hash;
|
||||||
|
|
||||||
|
/// An RSA private key. Useful for signing messages and decrypting encrypted
|
||||||
|
/// content.
|
||||||
|
#[derive(Clone,PartialEq)]
|
||||||
|
pub struct RSAPrivateKey<R: RSAMode>
|
||||||
|
{
|
||||||
|
pub(crate) nu: R::Barrett,
|
||||||
|
pub(crate) d: R
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generic RSA private key which is agnostic to its key size.
|
||||||
|
#[derive(Clone,PartialEq)]
|
||||||
|
pub enum RSAPrivate {
|
||||||
|
Key512(RSAPrivateKey<U512>),
|
||||||
|
Key1024(RSAPrivateKey<U1024>),
|
||||||
|
Key2048(RSAPrivateKey<U2048>),
|
||||||
|
Key3072(RSAPrivateKey<U3072>),
|
||||||
|
Key4096(RSAPrivateKey<U4096>),
|
||||||
|
Key8192(RSAPrivateKey<U8192>),
|
||||||
|
Key15360(RSAPrivateKey<U15360>)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_rsa_private
|
||||||
|
{
|
||||||
|
($num: ident, $bar: ident, $size: expr) => {
|
||||||
|
impl RSAPrivateKey<$num> {
|
||||||
|
/// Generate a new private key with the given modulus and private
|
||||||
|
/// number (`d`). This operation actually does a bit of computation
|
||||||
|
/// under the hood, in order to speed up future ones, so you might
|
||||||
|
/// want to strongly consider sharing rather than multiple
|
||||||
|
/// instantiation. But you do you.
|
||||||
|
pub fn new(n: $num, d: $num) -> RSAPrivateKey<$num> {
|
||||||
|
let nu = $bar::new(n.clone());
|
||||||
|
RSAPrivateKey{ nu: nu, d: d }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sign the given message with the given SigningHash, returning
|
||||||
|
/// the signature. This uses a deterministic PKCS1 method for
|
||||||
|
/// signing messages, so no RNG required.
|
||||||
|
pub fn sign(&self, signhash: &SigningHash, msg: &[u8])
|
||||||
|
-> Vec<u8>
|
||||||
|
{
|
||||||
|
let hash = (signhash.run)(msg);
|
||||||
|
let em = pkcs1_pad(&signhash.ident, &hash, $size/8);
|
||||||
|
let m = $num::from_bytes(&em);
|
||||||
|
let s = self.sp1(&m);
|
||||||
|
let sig = s.to_bytes();
|
||||||
|
sig
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decrypted the provided encrypted blob using the given
|
||||||
|
/// parameters. This does standard RSA OAEP decryption, which is
|
||||||
|
/// rather slow. If you have a choice, you should probably do
|
||||||
|
/// something clever, like only use this encryption/decryption
|
||||||
|
/// method to encrypt/decrypt a shared symmetric key, like an
|
||||||
|
/// AES key. That way, you only do this operation (which is
|
||||||
|
/// SO SLOW) for a relatively small amount of data.
|
||||||
|
pub fn decrypt<H: Hash>(&self, oaep: &OAEPParams<H>, msg: &[u8])
|
||||||
|
-> Result<Vec<u8>,RSAError>
|
||||||
|
{
|
||||||
|
let mut res = Vec::new();
|
||||||
|
|
||||||
|
for chunk in msg.chunks($size/8) {
|
||||||
|
let mut dchunk = self.oaep_decrypt(oaep, chunk)?;
|
||||||
|
res.append(&mut dchunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sp1(&self, m: &$num) -> $num {
|
||||||
|
m.modexp(&self.d, &self.nu)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dp(&self, c: &$num) -> $num {
|
||||||
|
c.modexp(&self.d, &self.nu)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn oaep_decrypt<H: Hash>(&self, oaep: &OAEPParams<H>, c: &[u8])
|
||||||
|
-> Result<Vec<u8>,RSAError>
|
||||||
|
{
|
||||||
|
let byte_len = $size / 8;
|
||||||
|
// Step 1b
|
||||||
|
if c.len() != byte_len {
|
||||||
|
return Err(RSAError::DecryptionError);
|
||||||
|
}
|
||||||
|
// Step 1c
|
||||||
|
if byte_len < ((2 * oaep.hash_len()) + 2) {
|
||||||
|
return Err(RSAError::DecryptHashMismatch);
|
||||||
|
}
|
||||||
|
// Step 2a
|
||||||
|
let c_ip = $num::from_bytes(&c);
|
||||||
|
// Step 2b
|
||||||
|
let m_ip = self.dp(&c_ip);
|
||||||
|
// Step 2c
|
||||||
|
let em = m_ip.to_bytes();
|
||||||
|
// Step 3a
|
||||||
|
let l_hash = oaep.hash(oaep.label.as_bytes());
|
||||||
|
// Step 3b
|
||||||
|
let (y, rest) = em.split_at(1);
|
||||||
|
let (masked_seed, masked_db) = rest.split_at(oaep.hash_len());
|
||||||
|
// Step 3c
|
||||||
|
let seed_mask = oaep.mgf1(masked_db, oaep.hash_len());
|
||||||
|
// Step 3d
|
||||||
|
let seed = xor_vecs(&masked_seed.to_vec(), &seed_mask);
|
||||||
|
// Step 3e
|
||||||
|
let db_mask = oaep.mgf1(&seed, byte_len - oaep.hash_len() - 1);
|
||||||
|
// Step 3f
|
||||||
|
let db = xor_vecs(&masked_db.to_vec(), &db_mask);
|
||||||
|
// Step 3g
|
||||||
|
let (l_hash2, ps_o_m) = db.split_at(oaep.hash_len());
|
||||||
|
let o_m = drop0s(ps_o_m);
|
||||||
|
let (o, m) = o_m.split_at(1);
|
||||||
|
// Checks!
|
||||||
|
if o != [1] {
|
||||||
|
return Err(RSAError::DecryptionError);
|
||||||
|
}
|
||||||
|
if l_hash != l_hash2 {
|
||||||
|
return Err(RSAError::DecryptionError);
|
||||||
|
}
|
||||||
|
if y != [0] {
|
||||||
|
return Err(RSAError::DecryptionError);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(m.to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_rsa_private!(U512, BarrettU512, 512);
|
||||||
|
generate_rsa_private!(U1024, BarrettU1024, 1024);
|
||||||
|
generate_rsa_private!(U2048, BarrettU2048, 2048);
|
||||||
|
generate_rsa_private!(U3072, BarrettU3072, 3072);
|
||||||
|
generate_rsa_private!(U4096, BarrettU4096, 4096);
|
||||||
|
generate_rsa_private!(U8192, BarrettU8192, 8192);
|
||||||
|
generate_rsa_private!(U15360, BarrettU15360, 15360);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! sign_test_body {
|
||||||
|
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||||
|
let fname = format!("testdata/rsa/sign{}.test", $size);
|
||||||
|
run_test(fname.to_string(), 7, |case| {
|
||||||
|
let (neg0, dbytes) = case.get("d").unwrap();
|
||||||
|
let (neg1, nbytes) = case.get("n").unwrap();
|
||||||
|
let (neg2, hbytes) = case.get("h").unwrap();
|
||||||
|
let (neg3, mbytes) = case.get("m").unwrap();
|
||||||
|
let (neg4, sbytes) = case.get("s").unwrap();
|
||||||
|
let (neg5, ubytes) = case.get("u").unwrap();
|
||||||
|
let (neg6, kbytes) = case.get("k").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0&&!neg1&&!neg2&&!neg3&&!neg4&&!neg5&&!neg6);
|
||||||
|
let n = $num64::from_bytes(nbytes);
|
||||||
|
let nu = $num64::from_bytes(ubytes);
|
||||||
|
let bigk = $num::from_bytes(kbytes);
|
||||||
|
let k = usize::from(bigk);
|
||||||
|
let d = $num::from_bytes(dbytes);
|
||||||
|
let sighash = match usize::from($num::from_bytes(hbytes)) {
|
||||||
|
224 => &SIGNING_HASH_SHA224,
|
||||||
|
256 => &SIGNING_HASH_SHA256,
|
||||||
|
384 => &SIGNING_HASH_SHA384,
|
||||||
|
512 => &SIGNING_HASH_SHA512,
|
||||||
|
x => panic!("Bad signing hash: {}", x)
|
||||||
|
};
|
||||||
|
let privkey = RSAPrivateKey{ nu: $bar::from_components(k, n.clone(), nu), d: d };
|
||||||
|
let sig = privkey.sign(sighash, &mbytes);
|
||||||
|
assert_eq!(*sbytes, sig);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! decrypt_test_body {
|
||||||
|
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||||
|
let fname = format!("testdata/rsa/encrypt{}.test", $size);
|
||||||
|
run_test(fname.to_string(), 9, |case| {
|
||||||
|
let (neg0, nbytes) = case.get("n").unwrap();
|
||||||
|
let (neg1, hbytes) = case.get("h").unwrap();
|
||||||
|
let (neg2, mbytes) = case.get("m").unwrap();
|
||||||
|
let (neg3, _bytes) = case.get("e").unwrap();
|
||||||
|
let (neg4, ubytes) = case.get("u").unwrap();
|
||||||
|
let (neg5, kbytes) = case.get("k").unwrap();
|
||||||
|
let (neg6, dbytes) = case.get("d").unwrap();
|
||||||
|
let (neg7, lbytes) = case.get("l").unwrap();
|
||||||
|
let (neg8, cbytes) = case.get("c").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 && !neg5 && !neg6 && !neg7 && !neg8);
|
||||||
|
let n = $num::from_bytes(nbytes);
|
||||||
|
let n64 = $num64::from(&n);
|
||||||
|
let nu = $num64::from_bytes(ubytes);
|
||||||
|
let bigk = $num::from_bytes(kbytes);
|
||||||
|
let k = usize::from(bigk);
|
||||||
|
let d = $num::from_bytes(dbytes);
|
||||||
|
let nu = $bar::from_components(k, n64, nu);
|
||||||
|
let privkey = RSAPrivateKey{ nu: nu, d: d };
|
||||||
|
let lstr = String::from_utf8(lbytes.clone()).unwrap();
|
||||||
|
let message = match usize::from($num::from_bytes(hbytes)) {
|
||||||
|
224 => privkey.decrypt(&OAEPParams::<SHA224>::new(lstr), &cbytes),
|
||||||
|
256 => privkey.decrypt(&OAEPParams::<SHA256>::new(lstr), &cbytes),
|
||||||
|
384 => privkey.decrypt(&OAEPParams::<SHA384>::new(lstr), &cbytes),
|
||||||
|
512 => privkey.decrypt(&OAEPParams::<SHA512>::new(lstr), &cbytes),
|
||||||
|
x => panic!("Unknown hash number: {}", x)
|
||||||
|
};
|
||||||
|
assert!(message.is_ok());
|
||||||
|
assert_eq!(mbytes, &message.unwrap());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_tests {
|
||||||
|
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
mod $mod {
|
||||||
|
use cryptonum::unsigned::Decoder;
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
use rsa::signing_hashes::*;
|
||||||
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sign() {
|
||||||
|
sign_test_body!($mod, $num, $bar, $num64, $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decrypt() {
|
||||||
|
decrypt_test_body!($mod, $num, $bar, $num64, $size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(ignore $mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
mod $mod {
|
||||||
|
use cryptonum::unsigned::Decoder;
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
use rsa::signing_hashes::*;
|
||||||
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn sign() {
|
||||||
|
sign_test_body!($mod, $num, $bar, $num64, $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn decrypt() {
|
||||||
|
decrypt_test_body!($mod, $num, $bar, $num64, $size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_tests!( RSA512, U512, BarrettU512, U576, 512);
|
||||||
|
generate_tests!( RSA1024, U1024, BarrettU1024, U1088, 1024);
|
||||||
|
generate_tests!( RSA2048, U2048, BarrettU2048, U2112, 2048);
|
||||||
|
generate_tests!( RSA3072, U3072, BarrettU3072, U3136, 3072);
|
||||||
|
generate_tests!( RSA4096, U4096, BarrettU4096, U4160, 4096);
|
||||||
|
generate_tests!(ignore RSA8192, U8192, BarrettU8192, U8256, 8192);
|
||||||
|
generate_tests!(ignore RSA15360, U15360, BarrettU15360, U15424, 15360);
|
||||||
526
src/rsa/public.rs
Normal file
526
src/rsa/public.rs
Normal file
@@ -0,0 +1,526 @@
|
|||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use rand::Rng;
|
||||||
|
use rand::rngs::OsRng;
|
||||||
|
use rsa::core::{RSAMode,decode_biguint,pkcs1_pad,xor_vecs};
|
||||||
|
use rsa::errors::RSAError;
|
||||||
|
use rsa::oaep::OAEPParams;
|
||||||
|
use rsa::signing_hashes::SigningHash;
|
||||||
|
use sha::Hash;
|
||||||
|
use simple_asn1::{ASN1Block,ASN1DecodeErr,ASN1EncodeErr,
|
||||||
|
ASN1Class,FromASN1,ToASN1};
|
||||||
|
#[cfg(test)]
|
||||||
|
use std::fmt;
|
||||||
|
use utils::TranslateNums;
|
||||||
|
|
||||||
|
/// An RSA public key. Useful for verifying signatures or encrypting data to
|
||||||
|
/// send to the private key holder.
|
||||||
|
#[derive(Clone,PartialEq)]
|
||||||
|
pub struct RSAPublicKey<R: RSAMode> {
|
||||||
|
pub(crate) n: R,
|
||||||
|
pub(crate) nu: R::Barrett,
|
||||||
|
pub(crate) e: R
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generic private key that is agnostic to the key size.
|
||||||
|
#[derive(Clone,PartialEq)]
|
||||||
|
pub enum RSAPublic {
|
||||||
|
Key512( RSAPublicKey<U512>),
|
||||||
|
Key1024( RSAPublicKey<U1024>),
|
||||||
|
Key2048( RSAPublicKey<U2048>),
|
||||||
|
Key3072( RSAPublicKey<U3072>),
|
||||||
|
Key4096( RSAPublicKey<U4096>),
|
||||||
|
Key8192( RSAPublicKey<U8192>),
|
||||||
|
Key15360(RSAPublicKey<U15360>)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RSAPublic {
|
||||||
|
/// Verify that the given signature is for the given message, passing
|
||||||
|
/// in the same signing arguments used to sign the message in the
|
||||||
|
/// first place.
|
||||||
|
pub fn verify(&self, signhash: &SigningHash, msg: &[u8], sig: &[u8]) -> bool
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
RSAPublic::Key512(x) => x.verify(signhash, msg, sig),
|
||||||
|
RSAPublic::Key1024(x) => x.verify(signhash, msg, sig),
|
||||||
|
RSAPublic::Key2048(x) => x.verify(signhash, msg, sig),
|
||||||
|
RSAPublic::Key3072(x) => x.verify(signhash, msg, sig),
|
||||||
|
RSAPublic::Key4096(x) => x.verify(signhash, msg, sig),
|
||||||
|
RSAPublic::Key8192(x) => x.verify(signhash, msg, sig),
|
||||||
|
RSAPublic::Key15360(x) => x.verify(signhash, msg, sig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for RSAPublic {
|
||||||
|
type Error = RSAError;
|
||||||
|
|
||||||
|
fn from_asn1(bs: &[ASN1Block])
|
||||||
|
-> Result<(RSAPublic,&[ASN1Block]),RSAError>
|
||||||
|
{
|
||||||
|
match bs.split_first() {
|
||||||
|
None =>
|
||||||
|
Err(RSAError::ASN1DecodeErr(ASN1DecodeErr::EmptyBuffer)),
|
||||||
|
Some((&ASN1Block::Sequence(_, _, ref items), rest))
|
||||||
|
if items.len() == 2 =>
|
||||||
|
{
|
||||||
|
let n = decode_biguint(&items[0])?;
|
||||||
|
let e = decode_biguint(&items[1])?;
|
||||||
|
let nsize = n.bits();
|
||||||
|
let mut rsa_size = 512;
|
||||||
|
|
||||||
|
while rsa_size < nsize {
|
||||||
|
rsa_size = rsa_size + 256;
|
||||||
|
}
|
||||||
|
match rsa_size {
|
||||||
|
512 => {
|
||||||
|
let n2 = U512::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let e2 = U512::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let res = RSAPublicKey::<U512>::new(n2, e2);
|
||||||
|
Ok((RSAPublic::Key512(res), rest))
|
||||||
|
}
|
||||||
|
1024 => {
|
||||||
|
let n2 = U1024::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let e2 = U1024::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let res = RSAPublicKey::<U1024>::new(n2, e2);
|
||||||
|
Ok((RSAPublic::Key1024(res), rest))
|
||||||
|
}
|
||||||
|
2048 => {
|
||||||
|
let n2 = U2048::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let e2 = U2048::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let res = RSAPublicKey::<U2048>::new(n2, e2);
|
||||||
|
Ok((RSAPublic::Key2048(res), rest))
|
||||||
|
}
|
||||||
|
3072 => {
|
||||||
|
let n2 = U3072::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let e2 = U3072::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let res = RSAPublicKey::<U3072>::new(n2, e2);
|
||||||
|
Ok((RSAPublic::Key3072(res), rest))
|
||||||
|
}
|
||||||
|
4096 => {
|
||||||
|
let n2 = U4096::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let e2 = U4096::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let res = RSAPublicKey::<U4096>::new(n2, e2);
|
||||||
|
Ok((RSAPublic::Key4096(res), rest))
|
||||||
|
}
|
||||||
|
8192 => {
|
||||||
|
let n2 = U8192::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let e2 = U8192::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let res = RSAPublicKey::<U8192>::new(n2, e2);
|
||||||
|
Ok((RSAPublic::Key8192(res), rest))
|
||||||
|
}
|
||||||
|
15360 => {
|
||||||
|
let n2 = U15360::from_num(&n).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let e2 = U15360::from_num(&e).ok_or(RSAError::InvalidKey)?;
|
||||||
|
let res = RSAPublicKey::<U15360>::new(n2, e2);
|
||||||
|
Ok((RSAPublic::Key15360(res), rest))
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(RSAError::InvalidKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(_) =>
|
||||||
|
Err(RSAError::InvalidKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for RSAPublic {
|
||||||
|
type Error = ASN1EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,Self::Error>
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
RSAPublic::Key512(x) => x.to_asn1_class(c),
|
||||||
|
RSAPublic::Key1024(x) => x.to_asn1_class(c),
|
||||||
|
RSAPublic::Key2048(x) => x.to_asn1_class(c),
|
||||||
|
RSAPublic::Key3072(x) => x.to_asn1_class(c),
|
||||||
|
RSAPublic::Key4096(x) => x.to_asn1_class(c),
|
||||||
|
RSAPublic::Key8192(x) => x.to_asn1_class(c),
|
||||||
|
RSAPublic::Key15360(x) => x.to_asn1_class(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl fmt::Debug for RSAPublic {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
RSAPublic::Key512(x) => write!(fmt, "RSA:{:?}", x),
|
||||||
|
RSAPublic::Key1024(x) => write!(fmt, "RSA:{:?}", x),
|
||||||
|
RSAPublic::Key2048(x) => write!(fmt, "RSA:{:?}", x),
|
||||||
|
RSAPublic::Key3072(x) => write!(fmt, "RSA:{:?}", x),
|
||||||
|
RSAPublic::Key4096(x) => write!(fmt, "RSA:{:?}", x),
|
||||||
|
RSAPublic::Key8192(x) => write!(fmt, "RSA:{:?}", x),
|
||||||
|
RSAPublic::Key15360(x) => write!(fmt, "RSA:{:?}", x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_rsa_public
|
||||||
|
{
|
||||||
|
($num: ident, $bar: ident, $var: ident, $size: expr) => {
|
||||||
|
impl RSAPublicKey<$num> {
|
||||||
|
/// Generate a new public key pair for the given modulus and
|
||||||
|
/// exponent. You should probably not call this directly unless
|
||||||
|
/// you're writing a key generation function or writing your own
|
||||||
|
/// public key parser.
|
||||||
|
pub fn new(n: $num, e: $num) -> RSAPublicKey<$num> {
|
||||||
|
let nu = $bar::new(n.clone());
|
||||||
|
RSAPublicKey{ n: n, nu: nu, e: e }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify that the provided signature is valid; that the private
|
||||||
|
/// key associated with this public key sent exactly this message.
|
||||||
|
/// The hash used here must exactly match the hash used to sign
|
||||||
|
/// the message, including its ASN.1 metadata.
|
||||||
|
pub fn verify(&self, signhash: &SigningHash, msg: &[u8], sig: &[u8])
|
||||||
|
-> bool
|
||||||
|
{
|
||||||
|
let hash: Vec<u8> = (signhash.run)(msg);
|
||||||
|
let s = $num::from_bytes(&sig);
|
||||||
|
let m = self.vp1(&s);
|
||||||
|
let em = m.to_bytes();
|
||||||
|
let em_ = pkcs1_pad(signhash.ident, &hash, $size/8);
|
||||||
|
em == em_
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encrypt the message with a hash function, given the appropriate
|
||||||
|
/// label. Please note that RSA encryption is not particularly fast,
|
||||||
|
/// and decryption is very slow indeed. Thus, most crypto systems that
|
||||||
|
/// need asymmetric encryption should generate a symmetric key, encrypt
|
||||||
|
/// that key with RSA encryption, and then encrypt the actual message
|
||||||
|
/// with that symmetric key.
|
||||||
|
///
|
||||||
|
/// In this variant of the function, we use an explicit random number
|
||||||
|
/// generator, just in case you have one you really like. It better be
|
||||||
|
/// cryptographically strong, though, as some of the padding protections
|
||||||
|
/// are relying on it.
|
||||||
|
pub fn encrypt_rng<G,H>(&self,g: &mut G,oaep: &OAEPParams<H>,msg: &[u8])
|
||||||
|
-> Result<Vec<u8>,RSAError>
|
||||||
|
where
|
||||||
|
G: Rng,
|
||||||
|
H: Hash
|
||||||
|
{
|
||||||
|
let byte_len = $size / 8;
|
||||||
|
let mut res = Vec::new();
|
||||||
|
|
||||||
|
if byte_len <= ((2 * oaep.hash_len()) + 2) {
|
||||||
|
return Err(RSAError::KeyTooSmallForHash);
|
||||||
|
}
|
||||||
|
for chunk in msg.chunks(byte_len - (2 * oaep.hash_len()) - 2) {
|
||||||
|
let mut newchunk = self.oaep_encrypt(g, oaep, chunk)?;
|
||||||
|
res.append(&mut newchunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encrypt the message with a hash function, given the appropriate
|
||||||
|
/// label. Please note that RSA encryption is not particularly fast,
|
||||||
|
/// and decryption is very slow indeed. Thus, most crypto systems that
|
||||||
|
/// need asymmetric encryption should generate a symmetric key, encrypt
|
||||||
|
/// that key with RSA encryption, and then encrypt the actual message
|
||||||
|
/// with that symmetric key.
|
||||||
|
///
|
||||||
|
/// This variant will just use the system RNG for its randomness.
|
||||||
|
pub fn encrypt<H: Hash>(&self,oaep:&OAEPParams<H>,msg:&[u8])
|
||||||
|
-> Result<Vec<u8>,RSAError>
|
||||||
|
{
|
||||||
|
let mut g = OsRng::new()?;
|
||||||
|
self.encrypt_rng(&mut g, oaep, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vp1(&self, s: &$num) -> $num {
|
||||||
|
s.modexp(&self.e, &self.nu)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ep(&self, m: &$num) -> $num {
|
||||||
|
m.modexp(&self.e, &self.nu)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn oaep_encrypt<G,H>(&self,g: &mut G,oaep: &OAEPParams<H>,m: &[u8])
|
||||||
|
-> Result<Vec<u8>,RSAError>
|
||||||
|
where
|
||||||
|
G: Rng,
|
||||||
|
H: Hash
|
||||||
|
{
|
||||||
|
let byte_len = $size / 8;
|
||||||
|
// Step 1b
|
||||||
|
if m.len() > (byte_len - (2 * oaep.hash_len()) - 2) {
|
||||||
|
return Err(RSAError::BadMessageSize)
|
||||||
|
}
|
||||||
|
// Step 2a
|
||||||
|
let mut lhash = oaep.hash(oaep.label.as_bytes());
|
||||||
|
// Step 2b
|
||||||
|
let num0s = byte_len - m.len() - (2 * oaep.hash_len()) - 2;
|
||||||
|
let mut ps = Vec::new();
|
||||||
|
ps.resize(num0s, 0);
|
||||||
|
// Step 2c
|
||||||
|
let mut db = Vec::new();
|
||||||
|
db.append(&mut lhash);
|
||||||
|
db.append(&mut ps);
|
||||||
|
db.push(1);
|
||||||
|
db.extend_from_slice(m);
|
||||||
|
// Step 2d
|
||||||
|
let mut seed: Vec<u8> = Vec::with_capacity(oaep.hash_len());
|
||||||
|
seed.resize(oaep.hash_len(), 0);
|
||||||
|
g.fill(seed.as_mut_slice());
|
||||||
|
// Step 2e
|
||||||
|
let db_mask = oaep.mgf1(&seed, byte_len - oaep.hash_len() - 1);
|
||||||
|
// Step 2f
|
||||||
|
let mut masked_db = xor_vecs(&db, &db_mask);
|
||||||
|
// Step 2g
|
||||||
|
let seed_mask = oaep.mgf1(&masked_db, oaep.hash_len());
|
||||||
|
// Step 2h
|
||||||
|
let mut masked_seed = xor_vecs(&seed, &seed_mask);
|
||||||
|
// Step 2i
|
||||||
|
let mut em = Vec::new();
|
||||||
|
em.push(0);
|
||||||
|
em.append(&mut masked_seed);
|
||||||
|
em.append(&mut masked_db);
|
||||||
|
// Step 3a
|
||||||
|
let m_i = $num::from_bytes(&em);
|
||||||
|
// Step 3b
|
||||||
|
let c_i = self.ep(&m_i);
|
||||||
|
// Step 3c
|
||||||
|
let c = c_i.to_bytes();
|
||||||
|
Ok(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for RSAPublicKey<$num> {
|
||||||
|
type Error = RSAError;
|
||||||
|
|
||||||
|
fn from_asn1(bs: &[ASN1Block])
|
||||||
|
-> Result<(RSAPublicKey<$num>,&[ASN1Block]),RSAError>
|
||||||
|
{
|
||||||
|
let (core, rest) = RSAPublic::from_asn1(bs)?;
|
||||||
|
|
||||||
|
match core {
|
||||||
|
RSAPublic::$var(x) => Ok((x, rest)),
|
||||||
|
_ => Err(RSAError::InvalidKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for RSAPublicKey<$num> {
|
||||||
|
type Error = ASN1EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,Self::Error>
|
||||||
|
{
|
||||||
|
let n = self.n.to_num();
|
||||||
|
let e = self.e.to_num();
|
||||||
|
let enc_n = ASN1Block::Integer(c, 0, n);
|
||||||
|
let enc_e = ASN1Block::Integer(c, 0, e);
|
||||||
|
let seq = ASN1Block::Sequence(c, 0, vec![enc_n, enc_e]);
|
||||||
|
Ok(vec![seq])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl fmt::Debug for RSAPublicKey<$num> {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt.debug_struct(stringify!($rsa))
|
||||||
|
.field("n", &self.n)
|
||||||
|
.field("nu", &self.nu)
|
||||||
|
.field("e", &self.e)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_rsa_public!(U512, BarrettU512, Key512, 512);
|
||||||
|
generate_rsa_public!(U1024, BarrettU1024, Key1024, 1024);
|
||||||
|
generate_rsa_public!(U2048, BarrettU2048, Key2048, 2048);
|
||||||
|
generate_rsa_public!(U3072, BarrettU3072, Key3072, 3072);
|
||||||
|
generate_rsa_public!(U4096, BarrettU4096, Key4096, 4096);
|
||||||
|
generate_rsa_public!(U8192, BarrettU8192, Key8192, 8192);
|
||||||
|
generate_rsa_public!(U15360, BarrettU15360, Key15360, 15360);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! new_test_body {
|
||||||
|
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||||
|
let fname = format!("testdata/rsa/sign{}.test", $size);
|
||||||
|
run_test(fname.to_string(), 7, |case| {
|
||||||
|
let (neg0, nbytes) = case.get("n").unwrap();
|
||||||
|
let (neg1, ubytes) = case.get("u").unwrap();
|
||||||
|
let (neg2, kbytes) = case.get("k").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0&&!neg1&&!neg2);
|
||||||
|
let n = $num::from_bytes(nbytes);
|
||||||
|
let n64 = $num64::from(&n);
|
||||||
|
let nu = $num64::from_bytes(ubytes);
|
||||||
|
let bigk = $num::from_bytes(kbytes);
|
||||||
|
let k = usize::from(bigk);
|
||||||
|
let e = $num::from(65537u64);
|
||||||
|
let pubkey2 = RSAPublicKey::<$num>::new(n.clone(), e.clone());
|
||||||
|
let pubkey1 = RSAPublicKey{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
|
||||||
|
assert_eq!(pubkey1, pubkey2);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! encode_test_body {
|
||||||
|
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||||
|
let fname = format!("testdata/rsa/sign{}.test", $size);
|
||||||
|
run_test(fname.to_string(), 7, |case| {
|
||||||
|
let (neg0, nbytes) = case.get("n").unwrap();
|
||||||
|
let (neg1, ubytes) = case.get("u").unwrap();
|
||||||
|
let (neg2, kbytes) = case.get("k").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0&&!neg1&&!neg2);
|
||||||
|
let n = $num::from_bytes(nbytes);
|
||||||
|
let n64 = $num64::from(&n);
|
||||||
|
let nu = $num64::from_bytes(ubytes);
|
||||||
|
let bigk = $num::from_bytes(kbytes);
|
||||||
|
let k = usize::from(bigk);
|
||||||
|
let e = $num::from(65537u64);
|
||||||
|
let pubkey = RSAPublicKey{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
|
||||||
|
let asn1 = pubkey.to_asn1().unwrap();
|
||||||
|
let (pubkey2, _) = RSAPublicKey::from_asn1(&asn1).unwrap();
|
||||||
|
assert_eq!(pubkey, pubkey2);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! verify_test_body {
|
||||||
|
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||||
|
let fname = format!("testdata/rsa/sign{}.test", $size);
|
||||||
|
run_test(fname.to_string(), 7, |case| {
|
||||||
|
let (neg0, nbytes) = case.get("n").unwrap();
|
||||||
|
let (neg1, hbytes) = case.get("h").unwrap();
|
||||||
|
let (neg2, mbytes) = case.get("m").unwrap();
|
||||||
|
let (neg3, sbytes) = case.get("s").unwrap();
|
||||||
|
let (neg4, ubytes) = case.get("u").unwrap();
|
||||||
|
let (neg5, kbytes) = case.get("k").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 && !neg5);
|
||||||
|
let n = $num::from_bytes(nbytes);
|
||||||
|
let n64 = $num64::from(&n);
|
||||||
|
let nu = $num64::from_bytes(ubytes);
|
||||||
|
let bigk = $num::from_bytes(kbytes);
|
||||||
|
let k = usize::from(bigk);
|
||||||
|
let e = $num::from(65537u64);
|
||||||
|
let pubkey = RSAPublicKey{ n: n, nu: $bar::from_components(k, n64, nu), e: e };
|
||||||
|
let hashnum = u64::from($num::from_bytes(hbytes));
|
||||||
|
let sighash = match hashnum {
|
||||||
|
160 => &SIGNING_HASH_SHA1,
|
||||||
|
224 => &SIGNING_HASH_SHA224,
|
||||||
|
256 => &SIGNING_HASH_SHA256,
|
||||||
|
384 => &SIGNING_HASH_SHA384,
|
||||||
|
512 => &SIGNING_HASH_SHA512,
|
||||||
|
_ => panic!("Bad signing hash: {}", hashnum)
|
||||||
|
};
|
||||||
|
assert!(pubkey.verify(sighash, &mbytes, &sbytes));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
macro_rules! encrypt_test_body {
|
||||||
|
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||||
|
let fname = format!("testdata/rsa/encrypt{}.test", $size);
|
||||||
|
run_test(fname.to_string(), 9, |case| {
|
||||||
|
let (neg0, nbytes) = case.get("n").unwrap();
|
||||||
|
let (neg1, hbytes) = case.get("h").unwrap();
|
||||||
|
let (neg2, mbytes) = case.get("m").unwrap();
|
||||||
|
let (neg3, _bytes) = case.get("e").unwrap();
|
||||||
|
let (neg4, ubytes) = case.get("u").unwrap();
|
||||||
|
let (neg5, kbytes) = case.get("k").unwrap();
|
||||||
|
let (neg6, dbytes) = case.get("d").unwrap();
|
||||||
|
let (neg7, lbytes) = case.get("l").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 && !neg5 && !neg6 && !neg7);
|
||||||
|
let n = $num::from_bytes(nbytes);
|
||||||
|
let n64 = $num64::from(&n);
|
||||||
|
let nu = $num64::from_bytes(ubytes);
|
||||||
|
let bigk = $num::from_bytes(kbytes);
|
||||||
|
let k = usize::from(bigk);
|
||||||
|
let e = $num::from(65537u64);
|
||||||
|
let d = $num::from_bytes(dbytes);
|
||||||
|
let nu = $bar::from_components(k, n64, nu);
|
||||||
|
let pubkey = RSAPublicKey{ n: n.clone(), nu: nu.clone(), e: e };
|
||||||
|
let privkey = RSAPrivateKey{ nu: nu, d: d };
|
||||||
|
let lstr = String::from_utf8(lbytes.clone()).unwrap();
|
||||||
|
let cipher = match usize::from($num::from_bytes(hbytes)) {
|
||||||
|
224 => pubkey.encrypt(&OAEPParams::<SHA224>::new(lstr.clone()), mbytes),
|
||||||
|
256 => pubkey.encrypt(&OAEPParams::<SHA256>::new(lstr.clone()), mbytes),
|
||||||
|
384 => pubkey.encrypt(&OAEPParams::<SHA384>::new(lstr.clone()), mbytes),
|
||||||
|
512 => pubkey.encrypt(&OAEPParams::<SHA512>::new(lstr.clone()), mbytes),
|
||||||
|
x => panic!("Unknown hash number: {}", x)
|
||||||
|
};
|
||||||
|
assert!(cipher.is_ok());
|
||||||
|
let message = match usize::from($num::from_bytes(hbytes)) {
|
||||||
|
224 => privkey.decrypt(&OAEPParams::<SHA224>::new(lstr), &cipher.unwrap()),
|
||||||
|
256 => privkey.decrypt(&OAEPParams::<SHA256>::new(lstr), &cipher.unwrap()),
|
||||||
|
384 => privkey.decrypt(&OAEPParams::<SHA384>::new(lstr), &cipher.unwrap()),
|
||||||
|
512 => privkey.decrypt(&OAEPParams::<SHA512>::new(lstr), &cipher.unwrap()),
|
||||||
|
x => panic!("Unknown hash number: {}", x)
|
||||||
|
};
|
||||||
|
assert!(message.is_ok());
|
||||||
|
assert_eq!(mbytes, &message.unwrap());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_tests {
|
||||||
|
($mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
mod $mod {
|
||||||
|
use cryptonum::unsigned::Decoder;
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
use rsa::private::*;
|
||||||
|
use rsa::signing_hashes::*;
|
||||||
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new() { new_test_body!($mod, $num, $bar, $num64, $size); }
|
||||||
|
#[test]
|
||||||
|
fn encode() { encode_test_body!($mod, $num, $bar, $num64, $size); }
|
||||||
|
#[test]
|
||||||
|
fn verify() { verify_test_body!($mod, $num, $bar, $num64, $size); }
|
||||||
|
#[test]
|
||||||
|
fn encrypt() { encrypt_test_body!($mod, $num, $bar, $num64, $size); }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(ignore $mod: ident, $num: ident, $bar: ident, $num64: ident, $size: expr) => {
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
mod $mod {
|
||||||
|
use cryptonum::unsigned::Decoder;
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
use rsa::private::*;
|
||||||
|
use rsa::signing_hashes::*;
|
||||||
|
use sha::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn new() { new_test_body!($mod, $num, $bar, $num64, $size); }
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn encode() { encode_test_body!($mod, $num, $bar, $num64, $size); }
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn verify() { verify_test_body!($mod, $num, $bar, $num64, $size); }
|
||||||
|
#[ignore]
|
||||||
|
#[test]
|
||||||
|
fn encrypt() { encrypt_test_body!($mod, $num, $bar, $num64, $size); }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_tests!( RSA512, U512, BarrettU512, U576, 512);
|
||||||
|
generate_tests!( RSA1024, U1024, BarrettU1024, U1088, 1024);
|
||||||
|
generate_tests!( RSA2048, U2048, BarrettU2048, U2112, 2048);
|
||||||
|
generate_tests!( RSA3072, U3072, BarrettU3072, U3136, 3072);
|
||||||
|
generate_tests!( RSA4096, U4096, BarrettU4096, U4160, 4096);
|
||||||
|
generate_tests!(ignore RSA8192, U8192, BarrettU8192, U8256, 8192);
|
||||||
|
generate_tests!(ignore RSA15360, U15360, BarrettU15360, U15424, 15360);
|
||||||
81
src/rsa/signing_hashes.rs
Normal file
81
src/rsa/signing_hashes.rs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
use sha::{Hash,SHA1,SHA224,SHA256,SHA384,SHA512};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// A hash that can be used to sign a message.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SigningHash {
|
||||||
|
/// The name of this hash (only used for display purposes)
|
||||||
|
pub name: &'static str,
|
||||||
|
/// The approved identity string for the hash.
|
||||||
|
pub ident: &'static [u8],
|
||||||
|
/// The hash
|
||||||
|
pub run: fn(&[u8]) -> Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for SigningHash {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The "null" signing hash. This signing hash has no identity, and will
|
||||||
|
/// simply pass the data through unhashed. You really should know what
|
||||||
|
/// you're doing if you use this, and probably using a somewhat strange
|
||||||
|
/// signing protocol. There's no good reason to use this in new code
|
||||||
|
/// for a new protocol or system.
|
||||||
|
pub static SIGNING_HASH_NULL: SigningHash = SigningHash {
|
||||||
|
name: "NULL",
|
||||||
|
ident: &[],
|
||||||
|
run: |x| { x.to_vec() }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Sign a hash based on SHA1. You shouldn't use this unless you're using
|
||||||
|
/// very small keys, and this is the only one available to you. Even then,
|
||||||
|
/// why are you using such small keys?!
|
||||||
|
pub static SIGNING_HASH_SHA1: SigningHash = SigningHash {
|
||||||
|
name: "SHA1",
|
||||||
|
ident: &[0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,
|
||||||
|
0x02,0x1a,0x05,0x00,0x04,0x14],
|
||||||
|
run: |x| { SHA1::hash(x) }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Sign a hash based on SHA2-224. This is the first reasonable choice
|
||||||
|
/// we've come across, and is useful when you have smaller RSA key sizes.
|
||||||
|
/// I wouldn't recommend it, though.
|
||||||
|
pub static SIGNING_HASH_SHA224: SigningHash = SigningHash {
|
||||||
|
name: "SHA224",
|
||||||
|
ident: &[0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
||||||
|
0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,
|
||||||
|
0x1c],
|
||||||
|
run: |x| { SHA224::hash(x) }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Sign a hash based on SHA2-256. The first one I'd recommend!
|
||||||
|
pub static SIGNING_HASH_SHA256: SigningHash = SigningHash {
|
||||||
|
name: "SHA256",
|
||||||
|
ident: &[0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
||||||
|
0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,
|
||||||
|
0x20],
|
||||||
|
run: |x| { SHA256::hash(x) }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Sign a hash based on SHA2-384. Approximately 50% better than
|
||||||
|
/// SHA-256.
|
||||||
|
pub static SIGNING_HASH_SHA384: SigningHash = SigningHash {
|
||||||
|
name: "SHA384",
|
||||||
|
ident: &[0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
||||||
|
0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,
|
||||||
|
0x30],
|
||||||
|
run: |x| { SHA384::hash(x) }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Sign a hash based on SHA2-512. At this point, you're getting a bit
|
||||||
|
/// silly. But if you want to through 8kbit RSA keys with a 512 bit SHA2
|
||||||
|
/// signing hash, we're totally behind you.
|
||||||
|
pub static SIGNING_HASH_SHA512: SigningHash = SigningHash {
|
||||||
|
name: "SHA512",
|
||||||
|
ident: &[0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,
|
||||||
|
0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,
|
||||||
|
0x40],
|
||||||
|
run: |x| { SHA512::hash(x) }
|
||||||
|
};
|
||||||
64
src/sha/mod.rs
Normal file
64
src/sha/mod.rs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
//! The SHA family of hash functions, as defined by NIST; specifically, from
|
||||||
|
//! NIST 180-4 (for SHA1 and SHA2) and NIST 202 (for SHA3).
|
||||||
|
//!
|
||||||
|
//! These hash functions are used through their instantiation of the `Hash`
|
||||||
|
//! trait, located in the parent `simple_crypto` module and re-exported
|
||||||
|
//! here for convenience. Thus, you're not going to see a lot of functions
|
||||||
|
//! or macros, here, just the type declarations.
|
||||||
|
//!
|
||||||
|
//! To use SHA2-384, as an example, you could run the following code:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::sha::{Hash,SHA384};
|
||||||
|
//!
|
||||||
|
//! let empty: [u8; 0] = [0; 0];
|
||||||
|
//! let mut digest_incremental = SHA384::new();
|
||||||
|
//! digest_incremental.update(&empty);
|
||||||
|
//! digest_incremental.update(&empty);
|
||||||
|
//! digest_incremental.update(&empty);
|
||||||
|
//! let result = digest_incremental.finalize();
|
||||||
|
//!
|
||||||
|
//! assert_eq!(result, vec![0x38,0xb0,0x60,0xa7,0x51,0xac,0x96,0x38,
|
||||||
|
//! 0x4c,0xd9,0x32,0x7e,0xb1,0xb1,0xe3,0x6a,
|
||||||
|
//! 0x21,0xfd,0xb7,0x11,0x14,0xbe,0x07,0x43,
|
||||||
|
//! 0x4c,0x0c,0xc7,0xbf,0x63,0xf6,0xe1,0xda,
|
||||||
|
//! 0x27,0x4e,0xde,0xbf,0xe7,0x6f,0x65,0xfb,
|
||||||
|
//! 0xd5,0x1a,0xd2,0xf1,0x48,0x98,0xb9,0x5b]);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! For other hashes, just substitute the appropriate hash structure for
|
||||||
|
//! `SHA384`. The `Hash` trait also includes a do-it-all-at-once built-in
|
||||||
|
//! function for those cases when you just have a single blob of data
|
||||||
|
//! you want to hash, rather than an incremental set of data:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::sha::{Hash,SHA3_256};
|
||||||
|
//!
|
||||||
|
//! let empty: [u8; 0] = [0; 0];
|
||||||
|
//! let result = SHA3_256::hash(&empty);
|
||||||
|
//!
|
||||||
|
//! assert_eq!(result, vec![0xa7,0xff,0xc6,0xf8,0xbf,0x1e,0xd7,0x66,
|
||||||
|
//! 0x51,0xc1,0x47,0x56,0xa0,0x61,0xd6,0x62,
|
||||||
|
//! 0xf5,0x80,0xff,0x4d,0xe4,0x3b,0x49,0xfa,
|
||||||
|
//! 0x82,0xd8,0x0a,0x4b,0x80,0xf8,0x43,0x4a]);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! In general, you should not use SHA1 for anything but supporting legacy
|
||||||
|
//! systems. We recommend either SHA2 or SHA3 at their 256-, 384-, or 512-bit
|
||||||
|
//! sizes. NIST claims (in FIPS 202, page 23-24) that SHA2 and SHA3 are
|
||||||
|
//! approximately equivalent in terms of security for collision, preimate,
|
||||||
|
//! and second preimage attacks, but that SHA3 improves upon SHA2 against
|
||||||
|
//! length-extension and other attacks. On the other hand, SHA2 has been
|
||||||
|
//! banged on for a little longer, and there's some claims that it's more
|
||||||
|
//! resistant to quantum attacks. So ... make your own decisions.
|
||||||
|
#[macro_use]
|
||||||
|
mod shared;
|
||||||
|
mod sha1;
|
||||||
|
mod sha2;
|
||||||
|
mod sha3;
|
||||||
|
|
||||||
|
pub use super::Hash;
|
||||||
|
pub use self::sha1::SHA1;
|
||||||
|
pub use self::sha2::{SHA224,SHA256,SHA384,SHA512};
|
||||||
|
pub use self::sha3::{SHA3_224,SHA3_256,SHA3_384,SHA3_512};
|
||||||
|
pub(crate) use self::sha3::Keccak;
|
||||||
306
src/sha/sha1.rs
Normal file
306
src/sha/sha1.rs
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
use byteorder::{BigEndian,WriteBytesExt};
|
||||||
|
use super::super::Hash;
|
||||||
|
use sha::shared::calculate_k;
|
||||||
|
|
||||||
|
/// The SHA1 hash. Don't use this except to support legacy systems.
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA1};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA1::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA1::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA1 {
|
||||||
|
state: [u32; 5],
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
done: bool,
|
||||||
|
l: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! sha1_step {
|
||||||
|
($op: ident, $out: ident, $ins: expr, $k: expr, $w: ident) => {
|
||||||
|
let $out = {
|
||||||
|
let [a,b,c,d,e] = $ins;
|
||||||
|
let ap = a.rotate_left(5) + $op!(b,c,d) + e + $k + $w;
|
||||||
|
let bp = a;
|
||||||
|
let cp = b.rotate_left(30);
|
||||||
|
let dp = c;
|
||||||
|
let ep = d;
|
||||||
|
[ap, bp, cp, dp, ep]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SHA1 {
|
||||||
|
fn process(&mut self, w00: u32, w01: u32, w02: u32, w03: u32,
|
||||||
|
w04: u32, w05: u32, w06: u32, w07: u32,
|
||||||
|
w08: u32, w09: u32, w10: u32, w11: u32,
|
||||||
|
w12: u32, w13: u32, w14: u32, w15: u32)
|
||||||
|
{
|
||||||
|
let w16 = (w13 ^ w08 ^ w02 ^ w00).rotate_left(1);
|
||||||
|
let w17 = (w14 ^ w09 ^ w03 ^ w01).rotate_left(1);
|
||||||
|
let w18 = (w15 ^ w10 ^ w04 ^ w02).rotate_left(1);
|
||||||
|
let w19 = (w16 ^ w11 ^ w05 ^ w03).rotate_left(1);
|
||||||
|
let w20 = (w17 ^ w12 ^ w06 ^ w04).rotate_left(1);
|
||||||
|
let w21 = (w18 ^ w13 ^ w07 ^ w05).rotate_left(1);
|
||||||
|
let w22 = (w19 ^ w14 ^ w08 ^ w06).rotate_left(1);
|
||||||
|
let w23 = (w20 ^ w15 ^ w09 ^ w07).rotate_left(1);
|
||||||
|
let w24 = (w21 ^ w16 ^ w10 ^ w08).rotate_left(1);
|
||||||
|
let w25 = (w22 ^ w17 ^ w11 ^ w09).rotate_left(1);
|
||||||
|
let w26 = (w23 ^ w18 ^ w12 ^ w10).rotate_left(1);
|
||||||
|
let w27 = (w24 ^ w19 ^ w13 ^ w11).rotate_left(1);
|
||||||
|
let w28 = (w25 ^ w20 ^ w14 ^ w12).rotate_left(1);
|
||||||
|
let w29 = (w26 ^ w21 ^ w15 ^ w13).rotate_left(1);
|
||||||
|
let w30 = (w27 ^ w22 ^ w16 ^ w14).rotate_left(1);
|
||||||
|
let w31 = (w28 ^ w23 ^ w17 ^ w15).rotate_left(1);
|
||||||
|
let w32 = (w29 ^ w24 ^ w18 ^ w16).rotate_left(1);
|
||||||
|
let w33 = (w30 ^ w25 ^ w19 ^ w17).rotate_left(1);
|
||||||
|
let w34 = (w31 ^ w26 ^ w20 ^ w18).rotate_left(1);
|
||||||
|
let w35 = (w32 ^ w27 ^ w21 ^ w19).rotate_left(1);
|
||||||
|
let w36 = (w33 ^ w28 ^ w22 ^ w20).rotate_left(1);
|
||||||
|
let w37 = (w34 ^ w29 ^ w23 ^ w21).rotate_left(1);
|
||||||
|
let w38 = (w35 ^ w30 ^ w24 ^ w22).rotate_left(1);
|
||||||
|
let w39 = (w36 ^ w31 ^ w25 ^ w23).rotate_left(1);
|
||||||
|
let w40 = (w37 ^ w32 ^ w26 ^ w24).rotate_left(1);
|
||||||
|
let w41 = (w38 ^ w33 ^ w27 ^ w25).rotate_left(1);
|
||||||
|
let w42 = (w39 ^ w34 ^ w28 ^ w26).rotate_left(1);
|
||||||
|
let w43 = (w40 ^ w35 ^ w29 ^ w27).rotate_left(1);
|
||||||
|
let w44 = (w41 ^ w36 ^ w30 ^ w28).rotate_left(1);
|
||||||
|
let w45 = (w42 ^ w37 ^ w31 ^ w29).rotate_left(1);
|
||||||
|
let w46 = (w43 ^ w38 ^ w32 ^ w30).rotate_left(1);
|
||||||
|
let w47 = (w44 ^ w39 ^ w33 ^ w31).rotate_left(1);
|
||||||
|
let w48 = (w45 ^ w40 ^ w34 ^ w32).rotate_left(1);
|
||||||
|
let w49 = (w46 ^ w41 ^ w35 ^ w33).rotate_left(1);
|
||||||
|
let w50 = (w47 ^ w42 ^ w36 ^ w34).rotate_left(1);
|
||||||
|
let w51 = (w48 ^ w43 ^ w37 ^ w35).rotate_left(1);
|
||||||
|
let w52 = (w49 ^ w44 ^ w38 ^ w36).rotate_left(1);
|
||||||
|
let w53 = (w50 ^ w45 ^ w39 ^ w37).rotate_left(1);
|
||||||
|
let w54 = (w51 ^ w46 ^ w40 ^ w38).rotate_left(1);
|
||||||
|
let w55 = (w52 ^ w47 ^ w41 ^ w39).rotate_left(1);
|
||||||
|
let w56 = (w53 ^ w48 ^ w42 ^ w40).rotate_left(1);
|
||||||
|
let w57 = (w54 ^ w49 ^ w43 ^ w41).rotate_left(1);
|
||||||
|
let w58 = (w55 ^ w50 ^ w44 ^ w42).rotate_left(1);
|
||||||
|
let w59 = (w56 ^ w51 ^ w45 ^ w43).rotate_left(1);
|
||||||
|
let w60 = (w57 ^ w52 ^ w46 ^ w44).rotate_left(1);
|
||||||
|
let w61 = (w58 ^ w53 ^ w47 ^ w45).rotate_left(1);
|
||||||
|
let w62 = (w59 ^ w54 ^ w48 ^ w46).rotate_left(1);
|
||||||
|
let w63 = (w60 ^ w55 ^ w49 ^ w47).rotate_left(1);
|
||||||
|
let w64 = (w61 ^ w56 ^ w50 ^ w48).rotate_left(1);
|
||||||
|
let w65 = (w62 ^ w57 ^ w51 ^ w49).rotate_left(1);
|
||||||
|
let w66 = (w63 ^ w58 ^ w52 ^ w50).rotate_left(1);
|
||||||
|
let w67 = (w64 ^ w59 ^ w53 ^ w51).rotate_left(1);
|
||||||
|
let w68 = (w65 ^ w60 ^ w54 ^ w52).rotate_left(1);
|
||||||
|
let w69 = (w66 ^ w61 ^ w55 ^ w53).rotate_left(1);
|
||||||
|
let w70 = (w67 ^ w62 ^ w56 ^ w54).rotate_left(1);
|
||||||
|
let w71 = (w68 ^ w63 ^ w57 ^ w55).rotate_left(1);
|
||||||
|
let w72 = (w69 ^ w64 ^ w58 ^ w56).rotate_left(1);
|
||||||
|
let w73 = (w70 ^ w65 ^ w59 ^ w57).rotate_left(1);
|
||||||
|
let w74 = (w71 ^ w66 ^ w60 ^ w58).rotate_left(1);
|
||||||
|
let w75 = (w72 ^ w67 ^ w61 ^ w59).rotate_left(1);
|
||||||
|
let w76 = (w73 ^ w68 ^ w62 ^ w60).rotate_left(1);
|
||||||
|
let w77 = (w74 ^ w69 ^ w63 ^ w61).rotate_left(1);
|
||||||
|
let w78 = (w75 ^ w70 ^ w64 ^ w62).rotate_left(1);
|
||||||
|
let w79 = (w76 ^ w71 ^ w65 ^ w63).rotate_left(1);
|
||||||
|
sha1_step!(ch, s01, self.state, 0x5a827999, w00);
|
||||||
|
sha1_step!(ch, s02, s01, 0x5a827999, w01);
|
||||||
|
sha1_step!(ch, s03, s02, 0x5a827999, w02);
|
||||||
|
sha1_step!(ch, s04, s03, 0x5a827999, w03);
|
||||||
|
sha1_step!(ch, s05, s04, 0x5a827999, w04);
|
||||||
|
sha1_step!(ch, s06, s05, 0x5a827999, w05);
|
||||||
|
sha1_step!(ch, s07, s06, 0x5a827999, w06);
|
||||||
|
sha1_step!(ch, s08, s07, 0x5a827999, w07);
|
||||||
|
sha1_step!(ch, s09, s08, 0x5a827999, w08);
|
||||||
|
sha1_step!(ch, s10, s09, 0x5a827999, w09);
|
||||||
|
sha1_step!(ch, s11, s10, 0x5a827999, w10);
|
||||||
|
sha1_step!(ch, s12, s11, 0x5a827999, w11);
|
||||||
|
sha1_step!(ch, s13, s12, 0x5a827999, w12);
|
||||||
|
sha1_step!(ch, s14, s13, 0x5a827999, w13);
|
||||||
|
sha1_step!(ch, s15, s14, 0x5a827999, w14);
|
||||||
|
sha1_step!(ch, s16, s15, 0x5a827999, w15);
|
||||||
|
sha1_step!(ch, s17, s16, 0x5a827999, w16);
|
||||||
|
sha1_step!(ch, s18, s17, 0x5a827999, w17);
|
||||||
|
sha1_step!(ch, s19, s18, 0x5a827999, w18);
|
||||||
|
sha1_step!(ch, s20, s19, 0x5a827999, w19);
|
||||||
|
sha1_step!(parity, s21, s20, 0x6ed9eba1, w20);
|
||||||
|
sha1_step!(parity, s22, s21, 0x6ed9eba1, w21);
|
||||||
|
sha1_step!(parity, s23, s22, 0x6ed9eba1, w22);
|
||||||
|
sha1_step!(parity, s24, s23, 0x6ed9eba1, w23);
|
||||||
|
sha1_step!(parity, s25, s24, 0x6ed9eba1, w24);
|
||||||
|
sha1_step!(parity, s26, s25, 0x6ed9eba1, w25);
|
||||||
|
sha1_step!(parity, s27, s26, 0x6ed9eba1, w26);
|
||||||
|
sha1_step!(parity, s28, s27, 0x6ed9eba1, w27);
|
||||||
|
sha1_step!(parity, s29, s28, 0x6ed9eba1, w28);
|
||||||
|
sha1_step!(parity, s30, s29, 0x6ed9eba1, w29);
|
||||||
|
sha1_step!(parity, s31, s30, 0x6ed9eba1, w30);
|
||||||
|
sha1_step!(parity, s32, s31, 0x6ed9eba1, w31);
|
||||||
|
sha1_step!(parity, s33, s32, 0x6ed9eba1, w32);
|
||||||
|
sha1_step!(parity, s34, s33, 0x6ed9eba1, w33);
|
||||||
|
sha1_step!(parity, s35, s34, 0x6ed9eba1, w34);
|
||||||
|
sha1_step!(parity, s36, s35, 0x6ed9eba1, w35);
|
||||||
|
sha1_step!(parity, s37, s36, 0x6ed9eba1, w36);
|
||||||
|
sha1_step!(parity, s38, s37, 0x6ed9eba1, w37);
|
||||||
|
sha1_step!(parity, s39, s38, 0x6ed9eba1, w38);
|
||||||
|
sha1_step!(parity, s40, s39, 0x6ed9eba1, w39);
|
||||||
|
sha1_step!(maj, s41, s40, 0x8f1bbcdc, w40);
|
||||||
|
sha1_step!(maj, s42, s41, 0x8f1bbcdc, w41);
|
||||||
|
sha1_step!(maj, s43, s42, 0x8f1bbcdc, w42);
|
||||||
|
sha1_step!(maj, s44, s43, 0x8f1bbcdc, w43);
|
||||||
|
sha1_step!(maj, s45, s44, 0x8f1bbcdc, w44);
|
||||||
|
sha1_step!(maj, s46, s45, 0x8f1bbcdc, w45);
|
||||||
|
sha1_step!(maj, s47, s46, 0x8f1bbcdc, w46);
|
||||||
|
sha1_step!(maj, s48, s47, 0x8f1bbcdc, w47);
|
||||||
|
sha1_step!(maj, s49, s48, 0x8f1bbcdc, w48);
|
||||||
|
sha1_step!(maj, s50, s49, 0x8f1bbcdc, w49);
|
||||||
|
sha1_step!(maj, s51, s50, 0x8f1bbcdc, w50);
|
||||||
|
sha1_step!(maj, s52, s51, 0x8f1bbcdc, w51);
|
||||||
|
sha1_step!(maj, s53, s52, 0x8f1bbcdc, w52);
|
||||||
|
sha1_step!(maj, s54, s53, 0x8f1bbcdc, w53);
|
||||||
|
sha1_step!(maj, s55, s54, 0x8f1bbcdc, w54);
|
||||||
|
sha1_step!(maj, s56, s55, 0x8f1bbcdc, w55);
|
||||||
|
sha1_step!(maj, s57, s56, 0x8f1bbcdc, w56);
|
||||||
|
sha1_step!(maj, s58, s57, 0x8f1bbcdc, w57);
|
||||||
|
sha1_step!(maj, s59, s58, 0x8f1bbcdc, w58);
|
||||||
|
sha1_step!(maj, s60, s59, 0x8f1bbcdc, w59);
|
||||||
|
sha1_step!(parity, s61, s60, 0xca62c1d6, w60);
|
||||||
|
sha1_step!(parity, s62, s61, 0xca62c1d6, w61);
|
||||||
|
sha1_step!(parity, s63, s62, 0xca62c1d6, w62);
|
||||||
|
sha1_step!(parity, s64, s63, 0xca62c1d6, w63);
|
||||||
|
sha1_step!(parity, s65, s64, 0xca62c1d6, w64);
|
||||||
|
sha1_step!(parity, s66, s65, 0xca62c1d6, w65);
|
||||||
|
sha1_step!(parity, s67, s66, 0xca62c1d6, w66);
|
||||||
|
sha1_step!(parity, s68, s67, 0xca62c1d6, w67);
|
||||||
|
sha1_step!(parity, s69, s68, 0xca62c1d6, w68);
|
||||||
|
sha1_step!(parity, s70, s69, 0xca62c1d6, w69);
|
||||||
|
sha1_step!(parity, s71, s70, 0xca62c1d6, w70);
|
||||||
|
sha1_step!(parity, s72, s71, 0xca62c1d6, w71);
|
||||||
|
sha1_step!(parity, s73, s72, 0xca62c1d6, w72);
|
||||||
|
sha1_step!(parity, s74, s73, 0xca62c1d6, w73);
|
||||||
|
sha1_step!(parity, s75, s74, 0xca62c1d6, w74);
|
||||||
|
sha1_step!(parity, s76, s75, 0xca62c1d6, w75);
|
||||||
|
sha1_step!(parity, s77, s76, 0xca62c1d6, w76);
|
||||||
|
sha1_step!(parity, s78, s77, 0xca62c1d6, w77);
|
||||||
|
sha1_step!(parity, s79, s78, 0xca62c1d6, w78);
|
||||||
|
sha1_step!(parity, s80, s79, 0xca62c1d6, w79);
|
||||||
|
self.state[0] += s80[0];
|
||||||
|
self.state[1] += s80[1];
|
||||||
|
self.state[2] += s80[2];
|
||||||
|
self.state[3] += s80[3];
|
||||||
|
self.state[4] += s80[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(&mut self)
|
||||||
|
{
|
||||||
|
let bitlen = self.l * 8;
|
||||||
|
let k = calculate_k(448, 512, bitlen);
|
||||||
|
// INVARIANT: k is necessarily > 0, and (k + 1) is a multiple of 8
|
||||||
|
let bytes_to_add = (k + 1) / 8;
|
||||||
|
let mut padvec = Vec::with_capacity(bytes_to_add + 8);
|
||||||
|
padvec.push(0x80); // Set the high bit, since the first bit after the data
|
||||||
|
// should be set
|
||||||
|
padvec.resize(bytes_to_add, 0);
|
||||||
|
padvec.write_u64::<BigEndian>(bitlen as u64).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
self.update(&padvec);
|
||||||
|
self.done = true;
|
||||||
|
assert_eq!(self.buffer.len(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA1
|
||||||
|
{
|
||||||
|
fn new() -> SHA1
|
||||||
|
{
|
||||||
|
SHA1 {
|
||||||
|
state: [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ],
|
||||||
|
buffer: Vec::with_capacity(64),
|
||||||
|
done: false,
|
||||||
|
l: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, block: &[u8])
|
||||||
|
{
|
||||||
|
if !self.done {
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
self.l += block.len();
|
||||||
|
|
||||||
|
if self.buffer.len() + block.len() < 64 {
|
||||||
|
self.buffer.extend_from_slice(block);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.buffer.len() > 0 {
|
||||||
|
// We must be able to build up a 64 byte chunk, at this point, otherwise
|
||||||
|
// the math above would've been wrong.
|
||||||
|
while self.buffer.len() < 64 {
|
||||||
|
self.buffer.push(block[offset]);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
process_u32_block!(self.buffer, 0, self);
|
||||||
|
// Reset the buffer now, we're done with that nonsense for the moment
|
||||||
|
self.buffer.resize(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset + 64) <= block.len() {
|
||||||
|
process_u32_block!(block, offset, self);
|
||||||
|
offset += 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset < block.len() {
|
||||||
|
self.buffer.extend_from_slice(&block[offset..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if !self.done {
|
||||||
|
self.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(20);
|
||||||
|
output.write_u32::<BigEndian>(self.state[0]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state[1]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state[2]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state[3]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state[4]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist() {
|
||||||
|
let fname = "testdata/sha/nist_sha1.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA1::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
842
src/sha/sha2.rs
Normal file
842
src/sha/sha2.rs
Normal file
@@ -0,0 +1,842 @@
|
|||||||
|
use byteorder::{BigEndian,ByteOrder,WriteBytesExt};
|
||||||
|
use sha::shared::calculate_k;
|
||||||
|
use super::super::Hash;
|
||||||
|
|
||||||
|
/// The SHA2-224 hash.
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA224};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA224::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA224::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA224 {
|
||||||
|
state: SHA256State
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA224 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
let state = SHA256State::new([0xc1059ed8,0x367cd507,0x3070dd17,0xf70e5939,
|
||||||
|
0xffc00b31,0x68581511,0x64f98fa7,0xbefa4fa4]);
|
||||||
|
SHA224{ state }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, data: &[u8])
|
||||||
|
{
|
||||||
|
self.state.update(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if !self.state.done {
|
||||||
|
self.state.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(28);
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[0]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[1]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[2]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[3]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[4]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[5]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[6]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA2-256 hash. [GOOD]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA256};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA256::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA256::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA256 {
|
||||||
|
state: SHA256State
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA256 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
let state = SHA256State::new([0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,
|
||||||
|
0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19]);
|
||||||
|
SHA256{ state }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, data: &[u8])
|
||||||
|
{
|
||||||
|
self.state.update(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if !self.state.done {
|
||||||
|
self.state.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(28);
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[0]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[1]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[2]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[3]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[4]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[5]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[6]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u32::<BigEndian>(self.state.state[7]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA2-384 hash. [BETTER]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA384};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA384::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA384::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA384 {
|
||||||
|
state: SHA512State
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA384 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
let state = SHA512State::new([0xcbbb9d5dc1059ed8,0x629a292a367cd507,
|
||||||
|
0x9159015a3070dd17,0x152fecd8f70e5939,
|
||||||
|
0x67332667ffc00b31,0x8eb44a8768581511,
|
||||||
|
0xdb0c2e0d64f98fa7,0x47b5481dbefa4fa4]);
|
||||||
|
SHA384{ state }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, data: &[u8])
|
||||||
|
{
|
||||||
|
self.state.update(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if !self.state.done {
|
||||||
|
self.state.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(64);
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[0]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[1]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[2]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[3]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[4]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[5]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA2-512 hash. [BEST]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA512};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA512::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA512::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA512 {
|
||||||
|
state: SHA512State
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA512 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
let state = SHA512State::new([0x6a09e667f3bcc908,0xbb67ae8584caa73b,
|
||||||
|
0x3c6ef372fe94f82b,0xa54ff53a5f1d36f1,
|
||||||
|
0x510e527fade682d1,0x9b05688c2b3e6c1f,
|
||||||
|
0x1f83d9abfb41bd6b,0x5be0cd19137e2179]);
|
||||||
|
SHA512{ state }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, data: &[u8])
|
||||||
|
{
|
||||||
|
self.state.update(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if !self.state.done {
|
||||||
|
self.state.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = Vec::with_capacity(64);
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[0]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[1]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[2]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[3]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[4]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[5]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[6]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output.write_u64::<BigEndian>(self.state.state[7]).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! bsig256_0 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(2) ^ $x.rotate_right(13) ^ $x.rotate_right(22)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! bsig256_1 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(6) ^ $x.rotate_right(11) ^ $x.rotate_right(25)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! lsig256_0 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(7) ^ $x.rotate_right(18) ^ ($x >> 3)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! lsig256_1 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(17) ^ $x.rotate_right(19) ^ ($x >> 10)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct SHA256State {
|
||||||
|
state: [u32; 8],
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
done: bool,
|
||||||
|
l: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SHA256State {
|
||||||
|
fn new(values: [u32; 8]) -> Self {
|
||||||
|
SHA256State {
|
||||||
|
state: values,
|
||||||
|
buffer: Vec::with_capacity(64),
|
||||||
|
done: false,
|
||||||
|
l: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, w00: u32, w01: u32, w02: u32, w03: u32,
|
||||||
|
w04: u32, w05: u32, w06: u32, w07: u32,
|
||||||
|
w08: u32, w09: u32, w10: u32, w11: u32,
|
||||||
|
w12: u32, w13: u32, w14: u32, w15: u32)
|
||||||
|
{
|
||||||
|
let w16 = lsig256_1!(w14) + w09 + lsig256_0!(w01) + w00;
|
||||||
|
let w17 = lsig256_1!(w15) + w10 + lsig256_0!(w02) + w01;
|
||||||
|
let w18 = lsig256_1!(w16) + w11 + lsig256_0!(w03) + w02;
|
||||||
|
let w19 = lsig256_1!(w17) + w12 + lsig256_0!(w04) + w03;
|
||||||
|
let w20 = lsig256_1!(w18) + w13 + lsig256_0!(w05) + w04;
|
||||||
|
let w21 = lsig256_1!(w19) + w14 + lsig256_0!(w06) + w05;
|
||||||
|
let w22 = lsig256_1!(w20) + w15 + lsig256_0!(w07) + w06;
|
||||||
|
let w23 = lsig256_1!(w21) + w16 + lsig256_0!(w08) + w07;
|
||||||
|
let w24 = lsig256_1!(w22) + w17 + lsig256_0!(w09) + w08;
|
||||||
|
let w25 = lsig256_1!(w23) + w18 + lsig256_0!(w10) + w09;
|
||||||
|
let w26 = lsig256_1!(w24) + w19 + lsig256_0!(w11) + w10;
|
||||||
|
let w27 = lsig256_1!(w25) + w20 + lsig256_0!(w12) + w11;
|
||||||
|
let w28 = lsig256_1!(w26) + w21 + lsig256_0!(w13) + w12;
|
||||||
|
let w29 = lsig256_1!(w27) + w22 + lsig256_0!(w14) + w13;
|
||||||
|
let w30 = lsig256_1!(w28) + w23 + lsig256_0!(w15) + w14;
|
||||||
|
let w31 = lsig256_1!(w29) + w24 + lsig256_0!(w16) + w15;
|
||||||
|
let w32 = lsig256_1!(w30) + w25 + lsig256_0!(w17) + w16;
|
||||||
|
let w33 = lsig256_1!(w31) + w26 + lsig256_0!(w18) + w17;
|
||||||
|
let w34 = lsig256_1!(w32) + w27 + lsig256_0!(w19) + w18;
|
||||||
|
let w35 = lsig256_1!(w33) + w28 + lsig256_0!(w20) + w19;
|
||||||
|
let w36 = lsig256_1!(w34) + w29 + lsig256_0!(w21) + w20;
|
||||||
|
let w37 = lsig256_1!(w35) + w30 + lsig256_0!(w22) + w21;
|
||||||
|
let w38 = lsig256_1!(w36) + w31 + lsig256_0!(w23) + w22;
|
||||||
|
let w39 = lsig256_1!(w37) + w32 + lsig256_0!(w24) + w23;
|
||||||
|
let w40 = lsig256_1!(w38) + w33 + lsig256_0!(w25) + w24;
|
||||||
|
let w41 = lsig256_1!(w39) + w34 + lsig256_0!(w26) + w25;
|
||||||
|
let w42 = lsig256_1!(w40) + w35 + lsig256_0!(w27) + w26;
|
||||||
|
let w43 = lsig256_1!(w41) + w36 + lsig256_0!(w28) + w27;
|
||||||
|
let w44 = lsig256_1!(w42) + w37 + lsig256_0!(w29) + w28;
|
||||||
|
let w45 = lsig256_1!(w43) + w38 + lsig256_0!(w30) + w29;
|
||||||
|
let w46 = lsig256_1!(w44) + w39 + lsig256_0!(w31) + w30;
|
||||||
|
let w47 = lsig256_1!(w45) + w40 + lsig256_0!(w32) + w31;
|
||||||
|
let w48 = lsig256_1!(w46) + w41 + lsig256_0!(w33) + w32;
|
||||||
|
let w49 = lsig256_1!(w47) + w42 + lsig256_0!(w34) + w33;
|
||||||
|
let w50 = lsig256_1!(w48) + w43 + lsig256_0!(w35) + w34;
|
||||||
|
let w51 = lsig256_1!(w49) + w44 + lsig256_0!(w36) + w35;
|
||||||
|
let w52 = lsig256_1!(w50) + w45 + lsig256_0!(w37) + w36;
|
||||||
|
let w53 = lsig256_1!(w51) + w46 + lsig256_0!(w38) + w37;
|
||||||
|
let w54 = lsig256_1!(w52) + w47 + lsig256_0!(w39) + w38;
|
||||||
|
let w55 = lsig256_1!(w53) + w48 + lsig256_0!(w40) + w39;
|
||||||
|
let w56 = lsig256_1!(w54) + w49 + lsig256_0!(w41) + w40;
|
||||||
|
let w57 = lsig256_1!(w55) + w50 + lsig256_0!(w42) + w41;
|
||||||
|
let w58 = lsig256_1!(w56) + w51 + lsig256_0!(w43) + w42;
|
||||||
|
let w59 = lsig256_1!(w57) + w52 + lsig256_0!(w44) + w43;
|
||||||
|
let w60 = lsig256_1!(w58) + w53 + lsig256_0!(w45) + w44;
|
||||||
|
let w61 = lsig256_1!(w59) + w54 + lsig256_0!(w46) + w45;
|
||||||
|
let w62 = lsig256_1!(w60) + w55 + lsig256_0!(w47) + w46;
|
||||||
|
let w63 = lsig256_1!(w61) + w56 + lsig256_0!(w48) + w47;
|
||||||
|
let s01 = step256(self.state,0x428a2f98,w00);
|
||||||
|
let s02 = step256(s01,0x71374491,w01);
|
||||||
|
let s03 = step256(s02,0xb5c0fbcf,w02);
|
||||||
|
let s04 = step256(s03,0xe9b5dba5,w03);
|
||||||
|
let s05 = step256(s04,0x3956c25b,w04);
|
||||||
|
let s06 = step256(s05,0x59f111f1,w05);
|
||||||
|
let s07 = step256(s06,0x923f82a4,w06);
|
||||||
|
let s08 = step256(s07,0xab1c5ed5,w07);
|
||||||
|
let s09 = step256(s08,0xd807aa98,w08);
|
||||||
|
let s10 = step256(s09,0x12835b01,w09);
|
||||||
|
let s11 = step256(s10,0x243185be,w10);
|
||||||
|
let s12 = step256(s11,0x550c7dc3,w11);
|
||||||
|
let s13 = step256(s12,0x72be5d74,w12);
|
||||||
|
let s14 = step256(s13,0x80deb1fe,w13);
|
||||||
|
let s15 = step256(s14,0x9bdc06a7,w14);
|
||||||
|
let s16 = step256(s15,0xc19bf174,w15);
|
||||||
|
let s17 = step256(s16,0xe49b69c1,w16);
|
||||||
|
let s18 = step256(s17,0xefbe4786,w17);
|
||||||
|
let s19 = step256(s18,0x0fc19dc6,w18);
|
||||||
|
let s20 = step256(s19,0x240ca1cc,w19);
|
||||||
|
let s21 = step256(s20,0x2de92c6f,w20);
|
||||||
|
let s22 = step256(s21,0x4a7484aa,w21);
|
||||||
|
let s23 = step256(s22,0x5cb0a9dc,w22);
|
||||||
|
let s24 = step256(s23,0x76f988da,w23);
|
||||||
|
let s25 = step256(s24,0x983e5152,w24);
|
||||||
|
let s26 = step256(s25,0xa831c66d,w25);
|
||||||
|
let s27 = step256(s26,0xb00327c8,w26);
|
||||||
|
let s28 = step256(s27,0xbf597fc7,w27);
|
||||||
|
let s29 = step256(s28,0xc6e00bf3,w28);
|
||||||
|
let s30 = step256(s29,0xd5a79147,w29);
|
||||||
|
let s31 = step256(s30,0x06ca6351,w30);
|
||||||
|
let s32 = step256(s31,0x14292967,w31);
|
||||||
|
let s33 = step256(s32,0x27b70a85,w32);
|
||||||
|
let s34 = step256(s33,0x2e1b2138,w33);
|
||||||
|
let s35 = step256(s34,0x4d2c6dfc,w34);
|
||||||
|
let s36 = step256(s35,0x53380d13,w35);
|
||||||
|
let s37 = step256(s36,0x650a7354,w36);
|
||||||
|
let s38 = step256(s37,0x766a0abb,w37);
|
||||||
|
let s39 = step256(s38,0x81c2c92e,w38);
|
||||||
|
let s40 = step256(s39,0x92722c85,w39);
|
||||||
|
let s41 = step256(s40,0xa2bfe8a1,w40);
|
||||||
|
let s42 = step256(s41,0xa81a664b,w41);
|
||||||
|
let s43 = step256(s42,0xc24b8b70,w42);
|
||||||
|
let s44 = step256(s43,0xc76c51a3,w43);
|
||||||
|
let s45 = step256(s44,0xd192e819,w44);
|
||||||
|
let s46 = step256(s45,0xd6990624,w45);
|
||||||
|
let s47 = step256(s46,0xf40e3585,w46);
|
||||||
|
let s48 = step256(s47,0x106aa070,w47);
|
||||||
|
let s49 = step256(s48,0x19a4c116,w48);
|
||||||
|
let s50 = step256(s49,0x1e376c08,w49);
|
||||||
|
let s51 = step256(s50,0x2748774c,w50);
|
||||||
|
let s52 = step256(s51,0x34b0bcb5,w51);
|
||||||
|
let s53 = step256(s52,0x391c0cb3,w52);
|
||||||
|
let s54 = step256(s53,0x4ed8aa4a,w53);
|
||||||
|
let s55 = step256(s54,0x5b9cca4f,w54);
|
||||||
|
let s56 = step256(s55,0x682e6ff3,w55);
|
||||||
|
let s57 = step256(s56,0x748f82ee,w56);
|
||||||
|
let s58 = step256(s57,0x78a5636f,w57);
|
||||||
|
let s59 = step256(s58,0x84c87814,w58);
|
||||||
|
let s60 = step256(s59,0x8cc70208,w59);
|
||||||
|
let s61 = step256(s60,0x90befffa,w60);
|
||||||
|
let s62 = step256(s61,0xa4506ceb,w61);
|
||||||
|
let s63 = step256(s62,0xbef9a3f7,w62);
|
||||||
|
let s64 = step256(s63,0xc67178f2,w63);
|
||||||
|
self.state[0] += s64[0];
|
||||||
|
self.state[1] += s64[1];
|
||||||
|
self.state[2] += s64[2];
|
||||||
|
self.state[3] += s64[3];
|
||||||
|
self.state[4] += s64[4];
|
||||||
|
self.state[5] += s64[5];
|
||||||
|
self.state[6] += s64[6];
|
||||||
|
self.state[7] += s64[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, block: &[u8]) {
|
||||||
|
if !self.done {
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
self.l += block.len();
|
||||||
|
|
||||||
|
if self.buffer.len() + block.len() < 64 {
|
||||||
|
self.buffer.extend_from_slice(block);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.buffer.len() > 0 {
|
||||||
|
// We must be able to build up a 64 byte chunk, at this point, otherwise
|
||||||
|
// the math above would've been wrong.
|
||||||
|
while self.buffer.len() < 64 {
|
||||||
|
self.buffer.push(block[offset]);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
process_u32_block!(self.buffer, 0, self);
|
||||||
|
// Reset the buffer now, we're done with that nonsense for the moment
|
||||||
|
self.buffer.resize(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset + 64) <= block.len() {
|
||||||
|
process_u32_block!(block, offset, self);
|
||||||
|
offset += 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset < block.len() {
|
||||||
|
self.buffer.extend_from_slice(&block[offset..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(&mut self) {
|
||||||
|
let bitlen = self.l * 8;
|
||||||
|
let k = calculate_k(448, 512, bitlen);
|
||||||
|
// INVARIANT: k is necessarily > 0, and (k + 1) is a multiple of 8
|
||||||
|
let bytes_to_add = (k + 1) / 8;
|
||||||
|
let mut padvec = Vec::with_capacity(bytes_to_add + 8);
|
||||||
|
padvec.push(0x80); // Set the high bit, since the first bit after the data
|
||||||
|
// should be set
|
||||||
|
padvec.resize(bytes_to_add, 0);
|
||||||
|
padvec.write_u64::<BigEndian>(bitlen as u64).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
self.update(&padvec);
|
||||||
|
self.done = true;
|
||||||
|
assert_eq!(self.buffer.len(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn step256(state0: [u32; 8], k: u32, w: u32) -> [u32; 8]
|
||||||
|
{
|
||||||
|
let [a,b,c,d,e,f,g,h] = state0;
|
||||||
|
let t1 = h + bsig256_1!(e) + ch!(e,f,g) + k + w;
|
||||||
|
let t2 = bsig256_0!(a) + maj!(a,b,c);
|
||||||
|
let hp = g;
|
||||||
|
let gp = f;
|
||||||
|
let fp = e;
|
||||||
|
let ep = d + t1;
|
||||||
|
let dp = c;
|
||||||
|
let cp = b;
|
||||||
|
let bp = a;
|
||||||
|
let ap = t1 + t2;
|
||||||
|
[ap,bp,cp,dp,ep,fp,gp,hp]
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! bsig512_0 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(28) ^ $x.rotate_right(34) ^ $x.rotate_right(39)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! bsig512_1 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(14) ^ $x.rotate_right(18) ^ $x.rotate_right(41)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! lsig512_0 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(1) ^ $x.rotate_right(8) ^ ($x >> 7)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! lsig512_1 {
|
||||||
|
($x: ident) => {
|
||||||
|
$x.rotate_right(19) ^ $x.rotate_right(61) ^ ($x >> 6)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! process_u64_block {
|
||||||
|
($buf: expr, $off: expr, $self: ident) => {{
|
||||||
|
let w00 = BigEndian::read_u64(&$buf[$off+0..]);
|
||||||
|
let w01 = BigEndian::read_u64(&$buf[$off+8..]);
|
||||||
|
let w02 = BigEndian::read_u64(&$buf[$off+16..]);
|
||||||
|
let w03 = BigEndian::read_u64(&$buf[$off+24..]);
|
||||||
|
let w04 = BigEndian::read_u64(&$buf[$off+32..]);
|
||||||
|
let w05 = BigEndian::read_u64(&$buf[$off+40..]);
|
||||||
|
let w06 = BigEndian::read_u64(&$buf[$off+48..]);
|
||||||
|
let w07 = BigEndian::read_u64(&$buf[$off+56..]);
|
||||||
|
let w08 = BigEndian::read_u64(&$buf[$off+64..]);
|
||||||
|
let w09 = BigEndian::read_u64(&$buf[$off+72..]);
|
||||||
|
let w10 = BigEndian::read_u64(&$buf[$off+80..]);
|
||||||
|
let w11 = BigEndian::read_u64(&$buf[$off+88..]);
|
||||||
|
let w12 = BigEndian::read_u64(&$buf[$off+96..]);
|
||||||
|
let w13 = BigEndian::read_u64(&$buf[$off+104..]);
|
||||||
|
let w14 = BigEndian::read_u64(&$buf[$off+112..]);
|
||||||
|
let w15 = BigEndian::read_u64(&$buf[$off+120..]);
|
||||||
|
$self.process(w00, w01, w02, w03, w04, w05, w06, w07,
|
||||||
|
w08, w09, w10, w11, w12, w13, w14, w15);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct SHA512State {
|
||||||
|
state: [u64; 8],
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
done: bool,
|
||||||
|
l: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SHA512State {
|
||||||
|
fn new(values: [u64; 8]) -> Self {
|
||||||
|
SHA512State {
|
||||||
|
state: values,
|
||||||
|
buffer: Vec::with_capacity(128),
|
||||||
|
done: false,
|
||||||
|
l: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, w00: u64, w01: u64, w02: u64, w03: u64,
|
||||||
|
w04: u64, w05: u64, w06: u64, w07: u64,
|
||||||
|
w08: u64, w09: u64, w10: u64, w11: u64,
|
||||||
|
w12: u64, w13: u64, w14: u64, w15: u64)
|
||||||
|
{
|
||||||
|
let w16 = lsig512_1!(w14) + w09 + lsig512_0!(w01) + w00;
|
||||||
|
let w17 = lsig512_1!(w15) + w10 + lsig512_0!(w02) + w01;
|
||||||
|
let w18 = lsig512_1!(w16) + w11 + lsig512_0!(w03) + w02;
|
||||||
|
let w19 = lsig512_1!(w17) + w12 + lsig512_0!(w04) + w03;
|
||||||
|
let w20 = lsig512_1!(w18) + w13 + lsig512_0!(w05) + w04;
|
||||||
|
let w21 = lsig512_1!(w19) + w14 + lsig512_0!(w06) + w05;
|
||||||
|
let w22 = lsig512_1!(w20) + w15 + lsig512_0!(w07) + w06;
|
||||||
|
let w23 = lsig512_1!(w21) + w16 + lsig512_0!(w08) + w07;
|
||||||
|
let w24 = lsig512_1!(w22) + w17 + lsig512_0!(w09) + w08;
|
||||||
|
let w25 = lsig512_1!(w23) + w18 + lsig512_0!(w10) + w09;
|
||||||
|
let w26 = lsig512_1!(w24) + w19 + lsig512_0!(w11) + w10;
|
||||||
|
let w27 = lsig512_1!(w25) + w20 + lsig512_0!(w12) + w11;
|
||||||
|
let w28 = lsig512_1!(w26) + w21 + lsig512_0!(w13) + w12;
|
||||||
|
let w29 = lsig512_1!(w27) + w22 + lsig512_0!(w14) + w13;
|
||||||
|
let w30 = lsig512_1!(w28) + w23 + lsig512_0!(w15) + w14;
|
||||||
|
let w31 = lsig512_1!(w29) + w24 + lsig512_0!(w16) + w15;
|
||||||
|
let w32 = lsig512_1!(w30) + w25 + lsig512_0!(w17) + w16;
|
||||||
|
let w33 = lsig512_1!(w31) + w26 + lsig512_0!(w18) + w17;
|
||||||
|
let w34 = lsig512_1!(w32) + w27 + lsig512_0!(w19) + w18;
|
||||||
|
let w35 = lsig512_1!(w33) + w28 + lsig512_0!(w20) + w19;
|
||||||
|
let w36 = lsig512_1!(w34) + w29 + lsig512_0!(w21) + w20;
|
||||||
|
let w37 = lsig512_1!(w35) + w30 + lsig512_0!(w22) + w21;
|
||||||
|
let w38 = lsig512_1!(w36) + w31 + lsig512_0!(w23) + w22;
|
||||||
|
let w39 = lsig512_1!(w37) + w32 + lsig512_0!(w24) + w23;
|
||||||
|
let w40 = lsig512_1!(w38) + w33 + lsig512_0!(w25) + w24;
|
||||||
|
let w41 = lsig512_1!(w39) + w34 + lsig512_0!(w26) + w25;
|
||||||
|
let w42 = lsig512_1!(w40) + w35 + lsig512_0!(w27) + w26;
|
||||||
|
let w43 = lsig512_1!(w41) + w36 + lsig512_0!(w28) + w27;
|
||||||
|
let w44 = lsig512_1!(w42) + w37 + lsig512_0!(w29) + w28;
|
||||||
|
let w45 = lsig512_1!(w43) + w38 + lsig512_0!(w30) + w29;
|
||||||
|
let w46 = lsig512_1!(w44) + w39 + lsig512_0!(w31) + w30;
|
||||||
|
let w47 = lsig512_1!(w45) + w40 + lsig512_0!(w32) + w31;
|
||||||
|
let w48 = lsig512_1!(w46) + w41 + lsig512_0!(w33) + w32;
|
||||||
|
let w49 = lsig512_1!(w47) + w42 + lsig512_0!(w34) + w33;
|
||||||
|
let w50 = lsig512_1!(w48) + w43 + lsig512_0!(w35) + w34;
|
||||||
|
let w51 = lsig512_1!(w49) + w44 + lsig512_0!(w36) + w35;
|
||||||
|
let w52 = lsig512_1!(w50) + w45 + lsig512_0!(w37) + w36;
|
||||||
|
let w53 = lsig512_1!(w51) + w46 + lsig512_0!(w38) + w37;
|
||||||
|
let w54 = lsig512_1!(w52) + w47 + lsig512_0!(w39) + w38;
|
||||||
|
let w55 = lsig512_1!(w53) + w48 + lsig512_0!(w40) + w39;
|
||||||
|
let w56 = lsig512_1!(w54) + w49 + lsig512_0!(w41) + w40;
|
||||||
|
let w57 = lsig512_1!(w55) + w50 + lsig512_0!(w42) + w41;
|
||||||
|
let w58 = lsig512_1!(w56) + w51 + lsig512_0!(w43) + w42;
|
||||||
|
let w59 = lsig512_1!(w57) + w52 + lsig512_0!(w44) + w43;
|
||||||
|
let w60 = lsig512_1!(w58) + w53 + lsig512_0!(w45) + w44;
|
||||||
|
let w61 = lsig512_1!(w59) + w54 + lsig512_0!(w46) + w45;
|
||||||
|
let w62 = lsig512_1!(w60) + w55 + lsig512_0!(w47) + w46;
|
||||||
|
let w63 = lsig512_1!(w61) + w56 + lsig512_0!(w48) + w47;
|
||||||
|
let w64 = lsig512_1!(w62) + w57 + lsig512_0!(w49) + w48;
|
||||||
|
let w65 = lsig512_1!(w63) + w58 + lsig512_0!(w50) + w49;
|
||||||
|
let w66 = lsig512_1!(w64) + w59 + lsig512_0!(w51) + w50;
|
||||||
|
let w67 = lsig512_1!(w65) + w60 + lsig512_0!(w52) + w51;
|
||||||
|
let w68 = lsig512_1!(w66) + w61 + lsig512_0!(w53) + w52;
|
||||||
|
let w69 = lsig512_1!(w67) + w62 + lsig512_0!(w54) + w53;
|
||||||
|
let w70 = lsig512_1!(w68) + w63 + lsig512_0!(w55) + w54;
|
||||||
|
let w71 = lsig512_1!(w69) + w64 + lsig512_0!(w56) + w55;
|
||||||
|
let w72 = lsig512_1!(w70) + w65 + lsig512_0!(w57) + w56;
|
||||||
|
let w73 = lsig512_1!(w71) + w66 + lsig512_0!(w58) + w57;
|
||||||
|
let w74 = lsig512_1!(w72) + w67 + lsig512_0!(w59) + w58;
|
||||||
|
let w75 = lsig512_1!(w73) + w68 + lsig512_0!(w60) + w59;
|
||||||
|
let w76 = lsig512_1!(w74) + w69 + lsig512_0!(w61) + w60;
|
||||||
|
let w77 = lsig512_1!(w75) + w70 + lsig512_0!(w62) + w61;
|
||||||
|
let w78 = lsig512_1!(w76) + w71 + lsig512_0!(w63) + w62;
|
||||||
|
let w79 = lsig512_1!(w77) + w72 + lsig512_0!(w64) + w63;
|
||||||
|
let s01 = step512(self.state,0x428a2f98d728ae22,w00);
|
||||||
|
let s02 = step512(s01,0x7137449123ef65cd,w01);
|
||||||
|
let s03 = step512(s02,0xb5c0fbcfec4d3b2f,w02);
|
||||||
|
let s04 = step512(s03,0xe9b5dba58189dbbc,w03);
|
||||||
|
let s05 = step512(s04,0x3956c25bf348b538,w04);
|
||||||
|
let s06 = step512(s05,0x59f111f1b605d019,w05);
|
||||||
|
let s07 = step512(s06,0x923f82a4af194f9b,w06);
|
||||||
|
let s08 = step512(s07,0xab1c5ed5da6d8118,w07);
|
||||||
|
let s09 = step512(s08,0xd807aa98a3030242,w08);
|
||||||
|
let s10 = step512(s09,0x12835b0145706fbe,w09);
|
||||||
|
let s11 = step512(s10,0x243185be4ee4b28c,w10);
|
||||||
|
let s12 = step512(s11,0x550c7dc3d5ffb4e2,w11);
|
||||||
|
let s13 = step512(s12,0x72be5d74f27b896f,w12);
|
||||||
|
let s14 = step512(s13,0x80deb1fe3b1696b1,w13);
|
||||||
|
let s15 = step512(s14,0x9bdc06a725c71235,w14);
|
||||||
|
let s16 = step512(s15,0xc19bf174cf692694,w15);
|
||||||
|
let s17 = step512(s16,0xe49b69c19ef14ad2,w16);
|
||||||
|
let s18 = step512(s17,0xefbe4786384f25e3,w17);
|
||||||
|
let s19 = step512(s18,0x0fc19dc68b8cd5b5,w18);
|
||||||
|
let s20 = step512(s19,0x240ca1cc77ac9c65,w19);
|
||||||
|
let s21 = step512(s20,0x2de92c6f592b0275,w20);
|
||||||
|
let s22 = step512(s21,0x4a7484aa6ea6e483,w21);
|
||||||
|
let s23 = step512(s22,0x5cb0a9dcbd41fbd4,w22);
|
||||||
|
let s24 = step512(s23,0x76f988da831153b5,w23);
|
||||||
|
let s25 = step512(s24,0x983e5152ee66dfab,w24);
|
||||||
|
let s26 = step512(s25,0xa831c66d2db43210,w25);
|
||||||
|
let s27 = step512(s26,0xb00327c898fb213f,w26);
|
||||||
|
let s28 = step512(s27,0xbf597fc7beef0ee4,w27);
|
||||||
|
let s29 = step512(s28,0xc6e00bf33da88fc2,w28);
|
||||||
|
let s30 = step512(s29,0xd5a79147930aa725,w29);
|
||||||
|
let s31 = step512(s30,0x06ca6351e003826f,w30);
|
||||||
|
let s32 = step512(s31,0x142929670a0e6e70,w31);
|
||||||
|
let s33 = step512(s32,0x27b70a8546d22ffc,w32);
|
||||||
|
let s34 = step512(s33,0x2e1b21385c26c926,w33);
|
||||||
|
let s35 = step512(s34,0x4d2c6dfc5ac42aed,w34);
|
||||||
|
let s36 = step512(s35,0x53380d139d95b3df,w35);
|
||||||
|
let s37 = step512(s36,0x650a73548baf63de,w36);
|
||||||
|
let s38 = step512(s37,0x766a0abb3c77b2a8,w37);
|
||||||
|
let s39 = step512(s38,0x81c2c92e47edaee6,w38);
|
||||||
|
let s40 = step512(s39,0x92722c851482353b,w39);
|
||||||
|
let s41 = step512(s40,0xa2bfe8a14cf10364,w40);
|
||||||
|
let s42 = step512(s41,0xa81a664bbc423001,w41);
|
||||||
|
let s43 = step512(s42,0xc24b8b70d0f89791,w42);
|
||||||
|
let s44 = step512(s43,0xc76c51a30654be30,w43);
|
||||||
|
let s45 = step512(s44,0xd192e819d6ef5218,w44);
|
||||||
|
let s46 = step512(s45,0xd69906245565a910,w45);
|
||||||
|
let s47 = step512(s46,0xf40e35855771202a,w46);
|
||||||
|
let s48 = step512(s47,0x106aa07032bbd1b8,w47);
|
||||||
|
let s49 = step512(s48,0x19a4c116b8d2d0c8,w48);
|
||||||
|
let s50 = step512(s49,0x1e376c085141ab53,w49);
|
||||||
|
let s51 = step512(s50,0x2748774cdf8eeb99,w50);
|
||||||
|
let s52 = step512(s51,0x34b0bcb5e19b48a8,w51);
|
||||||
|
let s53 = step512(s52,0x391c0cb3c5c95a63,w52);
|
||||||
|
let s54 = step512(s53,0x4ed8aa4ae3418acb,w53);
|
||||||
|
let s55 = step512(s54,0x5b9cca4f7763e373,w54);
|
||||||
|
let s56 = step512(s55,0x682e6ff3d6b2b8a3,w55);
|
||||||
|
let s57 = step512(s56,0x748f82ee5defb2fc,w56);
|
||||||
|
let s58 = step512(s57,0x78a5636f43172f60,w57);
|
||||||
|
let s59 = step512(s58,0x84c87814a1f0ab72,w58);
|
||||||
|
let s60 = step512(s59,0x8cc702081a6439ec,w59);
|
||||||
|
let s61 = step512(s60,0x90befffa23631e28,w60);
|
||||||
|
let s62 = step512(s61,0xa4506cebde82bde9,w61);
|
||||||
|
let s63 = step512(s62,0xbef9a3f7b2c67915,w62);
|
||||||
|
let s64 = step512(s63,0xc67178f2e372532b,w63);
|
||||||
|
let s65 = step512(s64,0xca273eceea26619c,w64);
|
||||||
|
let s66 = step512(s65,0xd186b8c721c0c207,w65);
|
||||||
|
let s67 = step512(s66,0xeada7dd6cde0eb1e,w66);
|
||||||
|
let s68 = step512(s67,0xf57d4f7fee6ed178,w67);
|
||||||
|
let s69 = step512(s68,0x06f067aa72176fba,w68);
|
||||||
|
let s70 = step512(s69,0x0a637dc5a2c898a6,w69);
|
||||||
|
let s71 = step512(s70,0x113f9804bef90dae,w70);
|
||||||
|
let s72 = step512(s71,0x1b710b35131c471b,w71);
|
||||||
|
let s73 = step512(s72,0x28db77f523047d84,w72);
|
||||||
|
let s74 = step512(s73,0x32caab7b40c72493,w73);
|
||||||
|
let s75 = step512(s74,0x3c9ebe0a15c9bebc,w74);
|
||||||
|
let s76 = step512(s75,0x431d67c49c100d4c,w75);
|
||||||
|
let s77 = step512(s76,0x4cc5d4becb3e42b6,w76);
|
||||||
|
let s78 = step512(s77,0x597f299cfc657e2a,w77);
|
||||||
|
let s79 = step512(s78,0x5fcb6fab3ad6faec,w78);
|
||||||
|
let s80 = step512(s79,0x6c44198c4a475817,w79);
|
||||||
|
self.state[0] += s80[0];
|
||||||
|
self.state[1] += s80[1];
|
||||||
|
self.state[2] += s80[2];
|
||||||
|
self.state[3] += s80[3];
|
||||||
|
self.state[4] += s80[4];
|
||||||
|
self.state[5] += s80[5];
|
||||||
|
self.state[6] += s80[6];
|
||||||
|
self.state[7] += s80[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, block: &[u8]) {
|
||||||
|
if !self.done {
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
self.l += block.len();
|
||||||
|
|
||||||
|
if self.buffer.len() + block.len() < 128 {
|
||||||
|
self.buffer.extend_from_slice(block);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.buffer.len() > 0 {
|
||||||
|
// We must be able to build up a 128 byte chunk, at this point, otherwise
|
||||||
|
// the math above would've been wrong.
|
||||||
|
while self.buffer.len() < 128 {
|
||||||
|
self.buffer.push(block[offset]);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
process_u64_block!(self.buffer, 0, self);
|
||||||
|
// Reset the buffer now, we're done with that nonsense for the moment
|
||||||
|
self.buffer.resize(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset + 128) <= block.len() {
|
||||||
|
process_u64_block!(block, offset, self);
|
||||||
|
offset += 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset < block.len() {
|
||||||
|
self.buffer.extend_from_slice(&block[offset..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(&mut self) {
|
||||||
|
let bitlen = self.l * 8;
|
||||||
|
let k = calculate_k(896, 1024, bitlen);
|
||||||
|
// INVARIANT: k is necessarily > 0, and (k + 1) is a multiple of 8
|
||||||
|
let bytes_to_add = (k + 1) / 8;
|
||||||
|
let mut padvec = Vec::with_capacity(bytes_to_add + 16);
|
||||||
|
padvec.push(0x80); // Set the high bit, since the first bit after the data
|
||||||
|
// should be set
|
||||||
|
padvec.resize(bytes_to_add, 0);
|
||||||
|
padvec.write_u128::<BigEndian>(bitlen as u128).expect("Broken writing value to pre-allocated Vec?");
|
||||||
|
self.update(&padvec);
|
||||||
|
self.done = true;
|
||||||
|
assert_eq!(self.buffer.len(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn step512(state0: [u64; 8], k: u64, w: u64) -> [u64; 8]
|
||||||
|
{
|
||||||
|
let [a,b,c,d,e,f,g,h] = state0;
|
||||||
|
let t1 = h + bsig512_1!(e) + ch!(e,f,g) + k + w;
|
||||||
|
let t2 = bsig512_0!(a) + maj!(a,b,c);
|
||||||
|
let hp = g;
|
||||||
|
let gp = f;
|
||||||
|
let fp = e;
|
||||||
|
let ep = d + t1;
|
||||||
|
let dp = c;
|
||||||
|
let cp = b;
|
||||||
|
let bp = a;
|
||||||
|
let ap = t1 + t2;
|
||||||
|
[ap,bp,cp,dp,ep,fp,gp,hp]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_sha224() {
|
||||||
|
let fname = "testdata/sha/nist_sha224.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA224::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_sha256() {
|
||||||
|
let fname = "testdata/sha/nist_sha256.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA256::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_sha384() {
|
||||||
|
let fname = "testdata/sha/nist_sha384.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA384::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_sha512() {
|
||||||
|
let fname = "testdata/sha/nist_sha512.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA512::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
610
src/sha/sha3.rs
Normal file
610
src/sha/sha3.rs
Normal file
@@ -0,0 +1,610 @@
|
|||||||
|
use super::super::Hash;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) struct Keccak {
|
||||||
|
rate_in_bytes: usize,
|
||||||
|
rate_in_longs: usize,
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
state: [u64; 25], // This is Keccak-f[1600]
|
||||||
|
output: Option<Vec<u8>>
|
||||||
|
}
|
||||||
|
|
||||||
|
const KECCAK_ROUND_CONSTANTS: [u64; 24] =
|
||||||
|
[ 0x0000000000000001u64, 0x0000000000008082u64,
|
||||||
|
0x800000000000808au64, 0x8000000080008000u64,
|
||||||
|
0x000000000000808bu64, 0x0000000080000001u64,
|
||||||
|
0x8000000080008081u64, 0x8000000000008009u64,
|
||||||
|
0x000000000000008au64, 0x0000000000000088u64,
|
||||||
|
0x0000000080008009u64, 0x000000008000000au64,
|
||||||
|
0x000000008000808bu64, 0x800000000000008bu64,
|
||||||
|
0x8000000000008089u64, 0x8000000000008003u64,
|
||||||
|
0x8000000000008002u64, 0x8000000000000080u64,
|
||||||
|
0x000000000000800au64, 0x800000008000000au64,
|
||||||
|
0x8000000080008081u64, 0x8000000000008080u64,
|
||||||
|
0x0000000080000001u64, 0x8000000080008008u64,
|
||||||
|
];
|
||||||
|
|
||||||
|
macro_rules! absorb {
|
||||||
|
($self: ident, $block: expr, $sidx: expr) => {{
|
||||||
|
let mut i = 0;
|
||||||
|
let mut off = 0;
|
||||||
|
|
||||||
|
while i < $self.rate_in_longs {
|
||||||
|
let word = ($block[$sidx+off+0] as u64) << 00 |
|
||||||
|
($block[$sidx+off+1] as u64) << 08 |
|
||||||
|
($block[$sidx+off+2] as u64) << 16 |
|
||||||
|
($block[$sidx+off+3] as u64) << 24 |
|
||||||
|
($block[$sidx+off+4] as u64) << 32 |
|
||||||
|
($block[$sidx+off+5] as u64) << 40 |
|
||||||
|
($block[$sidx+off+6] as u64) << 48 |
|
||||||
|
($block[$sidx+off+7] as u64) << 56;
|
||||||
|
$self.state[i] ^= word;
|
||||||
|
off += 8;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self.permute();
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Keccak {
|
||||||
|
pub fn new(rate: usize) -> Self
|
||||||
|
{
|
||||||
|
assert_eq!(rate % 64, 0);
|
||||||
|
Keccak {
|
||||||
|
rate_in_bytes: rate / 8,
|
||||||
|
rate_in_longs: rate / 64,
|
||||||
|
buffer: Vec::with_capacity(rate),
|
||||||
|
state: [0; 25],
|
||||||
|
output: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn permute(&mut self)
|
||||||
|
{
|
||||||
|
// This is a translation of the very easy-to-read implementation in BouncyCastle
|
||||||
|
for i in 0..24 {
|
||||||
|
// Theta!
|
||||||
|
let c0 = self.state[0] ^ self.state[5] ^ self.state[10] ^ self.state[15] ^ self.state[20];
|
||||||
|
let c1 = self.state[1] ^ self.state[6] ^ self.state[11] ^ self.state[16] ^ self.state[21];
|
||||||
|
let c2 = self.state[2] ^ self.state[7] ^ self.state[12] ^ self.state[17] ^ self.state[22];
|
||||||
|
let c3 = self.state[3] ^ self.state[8] ^ self.state[13] ^ self.state[18] ^ self.state[23];
|
||||||
|
let c4 = self.state[4] ^ self.state[9] ^ self.state[14] ^ self.state[19] ^ self.state[24];
|
||||||
|
let d0 = c0.rotate_left(1) ^ c3;
|
||||||
|
let d1 = c1.rotate_left(1) ^ c4;
|
||||||
|
let d2 = c2.rotate_left(1) ^ c0;
|
||||||
|
let d3 = c3.rotate_left(1) ^ c1;
|
||||||
|
let d4 = c4.rotate_left(1) ^ c2;
|
||||||
|
self.state[0] ^= d1; self.state[5] ^= d1; self.state[10] ^= d1; self.state[15] ^= d1; self.state[20] ^= d1;
|
||||||
|
self.state[1] ^= d2; self.state[6] ^= d2; self.state[11] ^= d2; self.state[16] ^= d2; self.state[21] ^= d2;
|
||||||
|
self.state[2] ^= d3; self.state[7] ^= d3; self.state[12] ^= d3; self.state[17] ^= d3; self.state[22] ^= d3;
|
||||||
|
self.state[3] ^= d4; self.state[8] ^= d4; self.state[13] ^= d4; self.state[18] ^= d4; self.state[23] ^= d4;
|
||||||
|
self.state[4] ^= d0; self.state[9] ^= d0; self.state[14] ^= d0; self.state[19] ^= d0; self.state[24] ^= d0;
|
||||||
|
// Rho & Pi!
|
||||||
|
let t1 = self.state[01].rotate_left(1);
|
||||||
|
self.state[01] = self.state[06].rotate_left(44);
|
||||||
|
self.state[06] = self.state[09].rotate_left(20);
|
||||||
|
self.state[09] = self.state[22].rotate_left(61);
|
||||||
|
self.state[22] = self.state[14].rotate_left(39);
|
||||||
|
self.state[14] = self.state[20].rotate_left(18);
|
||||||
|
self.state[20] = self.state[02].rotate_left(62);
|
||||||
|
self.state[02] = self.state[12].rotate_left(43);
|
||||||
|
self.state[12] = self.state[13].rotate_left(25);
|
||||||
|
self.state[13] = self.state[19].rotate_left(8);
|
||||||
|
self.state[19] = self.state[23].rotate_left(56);
|
||||||
|
self.state[23] = self.state[15].rotate_left(41);
|
||||||
|
self.state[15] = self.state[04].rotate_left(27);
|
||||||
|
self.state[04] = self.state[24].rotate_left(14);
|
||||||
|
self.state[24] = self.state[21].rotate_left(2);
|
||||||
|
self.state[21] = self.state[08].rotate_left(55);
|
||||||
|
self.state[08] = self.state[16].rotate_left(45);
|
||||||
|
self.state[16] = self.state[05].rotate_left(36);
|
||||||
|
self.state[05] = self.state[03].rotate_left(28);
|
||||||
|
self.state[03] = self.state[18].rotate_left(21);
|
||||||
|
self.state[18] = self.state[17].rotate_left(15);
|
||||||
|
self.state[17] = self.state[11].rotate_left(10);
|
||||||
|
self.state[11] = self.state[07].rotate_left(6);
|
||||||
|
self.state[07] = self.state[10].rotate_left(3);
|
||||||
|
self.state[10] = t1;
|
||||||
|
// Chi!
|
||||||
|
let t2 = self.state[00] ^ (!self.state[01] & self.state[02]);
|
||||||
|
let t3 = self.state[01] ^ (!self.state[02] & self.state[03]);
|
||||||
|
self.state[02] ^= !self.state[03] & self.state[04];
|
||||||
|
self.state[03] ^= !self.state[04] & self.state[00];
|
||||||
|
self.state[04] ^= !self.state[00] & self.state[01];
|
||||||
|
self.state[00] = t2;
|
||||||
|
self.state[01] = t3;
|
||||||
|
|
||||||
|
let t4 = self.state[05] ^ (!self.state[06] & self.state[07]);
|
||||||
|
let t5 = self.state[06] ^ (!self.state[07] & self.state[08]);
|
||||||
|
self.state[07] ^= !self.state[08] & self.state[09];
|
||||||
|
self.state[08] ^= !self.state[09] & self.state[05];
|
||||||
|
self.state[09] ^= !self.state[05] & self.state[06];
|
||||||
|
self.state[05] = t4;
|
||||||
|
self.state[06] = t5;
|
||||||
|
|
||||||
|
let t6 = self.state[10] ^ (!self.state[11] & self.state[12]);
|
||||||
|
let t7 = self.state[11] ^ (!self.state[12] & self.state[13]);
|
||||||
|
self.state[12] ^= !self.state[13] & self.state[14];
|
||||||
|
self.state[13] ^= !self.state[14] & self.state[10];
|
||||||
|
self.state[14] ^= !self.state[10] & self.state[11];
|
||||||
|
self.state[10] = t6;
|
||||||
|
self.state[11] = t7;
|
||||||
|
|
||||||
|
let t8 = self.state[15] ^ (!self.state[16] & self.state[17]);
|
||||||
|
let t9 = self.state[16] ^ (!self.state[17] & self.state[18]);
|
||||||
|
self.state[17] ^= !self.state[18] & self.state[19];
|
||||||
|
self.state[18] ^= !self.state[19] & self.state[15];
|
||||||
|
self.state[19] ^= !self.state[15] & self.state[16];
|
||||||
|
self.state[15] = t8;
|
||||||
|
self.state[16] = t9;
|
||||||
|
|
||||||
|
let ta = self.state[20] ^ (!self.state[21] & self.state[22]);
|
||||||
|
let tb = self.state[21] ^ (!self.state[22] & self.state[23]);
|
||||||
|
self.state[22] ^= !self.state[23] & self.state[24];
|
||||||
|
self.state[23] ^= !self.state[24] & self.state[20];
|
||||||
|
self.state[24] ^= !self.state[20] & self.state[21];
|
||||||
|
self.state[20] = ta;
|
||||||
|
self.state[21] = tb;
|
||||||
|
|
||||||
|
// iota
|
||||||
|
self.state[00] ^= KECCAK_ROUND_CONSTANTS[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process(&mut self, bytes: &[u8])
|
||||||
|
{
|
||||||
|
if self.output.is_none() {
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
if self.buffer.len() + bytes.len() < self.rate_in_bytes {
|
||||||
|
self.buffer.extend_from_slice(bytes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.buffer.len() > 0 {
|
||||||
|
// We must be able to build up a chunk at our absorbtion rate, at this
|
||||||
|
// point, otherwise the math above would've been wrong.
|
||||||
|
while self.buffer.len() < self.rate_in_bytes {
|
||||||
|
self.buffer.push(bytes[offset]);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
absorb!(self, self.buffer, 0);
|
||||||
|
// Reset the buffer now, we're done with that nonsense for the moment
|
||||||
|
self.buffer.resize(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (offset + self.rate_in_bytes) <= bytes.len() {
|
||||||
|
absorb!(self, bytes, offset);
|
||||||
|
offset += self.rate_in_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset < bytes.len() {
|
||||||
|
self.buffer.extend_from_slice(&bytes[offset..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tag_and_pad(&mut self, tag_byte: u8)
|
||||||
|
{
|
||||||
|
if self.output.is_none() {
|
||||||
|
assert!(self.buffer.len() < self.rate_in_bytes);
|
||||||
|
// what we need to do here is tag on a final 01, to tag that as SHA3,
|
||||||
|
// and then pad it out, with an 0x80 at the end.
|
||||||
|
self.buffer.push(tag_byte);
|
||||||
|
self.buffer.resize(self.rate_in_bytes, 0);
|
||||||
|
self.buffer[self.rate_in_bytes-1] |= 0x80;
|
||||||
|
absorb!(self, self.buffer, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn squeeze(&mut self, output_len: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
if let Some(ref result) = self.output {
|
||||||
|
result.clone()
|
||||||
|
} else {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
|
||||||
|
while res.len() < output_len {
|
||||||
|
for i in 0..self.rate_in_longs {
|
||||||
|
res.push( (self.state[i] >> 00) as u8 );
|
||||||
|
res.push( (self.state[i] >> 08) as u8 );
|
||||||
|
res.push( (self.state[i] >> 16) as u8 );
|
||||||
|
res.push( (self.state[i] >> 24) as u8 );
|
||||||
|
res.push( (self.state[i] >> 32) as u8 );
|
||||||
|
res.push( (self.state[i] >> 40) as u8 );
|
||||||
|
res.push( (self.state[i] >> 48) as u8 );
|
||||||
|
res.push( (self.state[i] >> 56) as u8 );
|
||||||
|
}
|
||||||
|
self.permute();
|
||||||
|
}
|
||||||
|
|
||||||
|
res.resize(output_len, 0);
|
||||||
|
self.output = Some(res.clone());
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA3-224 hash.
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA3_224};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA3_224::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA3_224::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA3_224 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA3_224 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
SHA3_224{ state: Keccak::new(1600 - 448) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
self.state.tag_and_pad(0x06);
|
||||||
|
self.state.squeeze(224 / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
1152
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod sha224 {
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-224_Msg0.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_empty_example() {
|
||||||
|
let empty = [0; 0];
|
||||||
|
let hashres = [0x6B,0x4E,0x03,0x42,0x36,0x67,0xDB,0xB7,0x3B,0x6E,0x15,
|
||||||
|
0x45,0x4F,0x0E,0xB1,0xAB,0xD4,0x59,0x7F,0x9A,0x1B,0x07,
|
||||||
|
0x8E,0x3F,0x5B,0x5A,0x6B,0xC7];
|
||||||
|
let mine = SHA3_224::hash(&empty);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-224_1600.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_1600_example() {
|
||||||
|
let example = [0xA3; 200];
|
||||||
|
let hashres = [0x93,0x76,0x81,0x6A,0xBA,0x50,0x3F,0x72,
|
||||||
|
0xF9,0x6C,0xE7,0xEB,0x65,0xAC,0x09,0x5D,
|
||||||
|
0xEE,0xE3,0xBE,0x4B,0xF9,0xBB,0xC2,0xA1,
|
||||||
|
0xCB,0x7E,0x11,0xE0];
|
||||||
|
let mine = SHA3_224::hash(&example);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_test_vectors() {
|
||||||
|
let fname = "testdata/sha/nist_sha3_224.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA3_224::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA3-256 hash. [GOOD]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA3_256};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA3_256::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA3_256::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA3_256 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA3_256 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
SHA3_256{ state: Keccak::new(1600 - 512) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
self.state.tag_and_pad(0x06);
|
||||||
|
self.state.squeeze(256 / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
1088
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod sha256 {
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-256.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_empty_example() {
|
||||||
|
let empty = [0; 0];
|
||||||
|
let hashres = [0xA7,0xFF,0xC6,0xF8,0xBF,0x1E,0xD7,0x66,
|
||||||
|
0x51,0xC1,0x47,0x56,0xA0,0x61,0xD6,0x62,
|
||||||
|
0xF5,0x80,0xFF,0x4D,0xE4,0x3B,0x49,0xFA,
|
||||||
|
0x82,0xD8,0x0A,0x4B,0x80,0xF8,0x43,0x4A];
|
||||||
|
let mine = SHA3_256::hash(&empty);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-256_1600.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_1600_example() {
|
||||||
|
let example = [0xA3; 200];
|
||||||
|
let hashres = [0x79,0xF3,0x8A,0xDE,0xC5,0xC2,0x03,0x07,
|
||||||
|
0xA9,0x8E,0xF7,0x6E,0x83,0x24,0xAF,0xBF,
|
||||||
|
0xD4,0x6C,0xFD,0x81,0xB2,0x2E,0x39,0x73,
|
||||||
|
0xC6,0x5F,0xA1,0xBD,0x9D,0xE3,0x17,0x87];
|
||||||
|
let mine = SHA3_256::hash(&example);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_test_vectors() {
|
||||||
|
let fname = "testdata/sha/nist_sha3_256.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA3_256::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA3-384 hash. [BETTER]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA3_384};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA3_384::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA3_384::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA3_384 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA3_384 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
SHA3_384{ state: Keccak::new(1600 - 768) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
self.state.tag_and_pad(0x06);
|
||||||
|
self.state.squeeze(384 / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
832
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod sha384 {
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-384_Msg0.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_empty_example() {
|
||||||
|
let empty = [0; 0];
|
||||||
|
let hashres = [0x0C,0x63,0xA7,0x5B,0x84,0x5E,0x4F,0x7D,
|
||||||
|
0x01,0x10,0x7D,0x85,0x2E,0x4C,0x24,0x85,
|
||||||
|
0xC5,0x1A,0x50,0xAA,0xAA,0x94,0xFC,0x61,
|
||||||
|
0x99,0x5E,0x71,0xBB,0xEE,0x98,0x3A,0x2A,
|
||||||
|
0xC3,0x71,0x38,0x31,0x26,0x4A,0xDB,0x47,
|
||||||
|
0xFB,0x6B,0xD1,0xE0,0x58,0xD5,0xF0,0x04];
|
||||||
|
let mine = SHA3_384::hash(&empty);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-384_1600.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_1600_example() {
|
||||||
|
let example = [0xA3; 200];
|
||||||
|
let hashres = [0x18,0x81,0xDE,0x2C,0xA7,0xE4,0x1E,0xF9,
|
||||||
|
0x5D,0xC4,0x73,0x2B,0x8F,0x5F,0x00,0x2B,
|
||||||
|
0x18,0x9C,0xC1,0xE4,0x2B,0x74,0x16,0x8E,
|
||||||
|
0xD1,0x73,0x26,0x49,0xCE,0x1D,0xBC,0xDD,
|
||||||
|
0x76,0x19,0x7A,0x31,0xFD,0x55,0xEE,0x98,
|
||||||
|
0x9F,0x2D,0x70,0x50,0xDD,0x47,0x3E,0x8F];
|
||||||
|
let mine = SHA3_384::hash(&example);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_test_vectors() {
|
||||||
|
let fname = "testdata/sha/nist_sha3_384.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA3_384::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHA3-512 hash. [BEST]
|
||||||
|
///
|
||||||
|
/// To use, you can run it in incremental mode -- by calling new(),
|
||||||
|
/// update() zero or more times, and then finalize() -- or you can
|
||||||
|
/// just invoke the hash directly. For example:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::sha::{Hash,SHA3_512};
|
||||||
|
///
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// // Do the hash using the incremental API
|
||||||
|
/// let mut hashf = SHA3_512::new();
|
||||||
|
/// hashf.update(&empty);
|
||||||
|
/// let result_incremental = hashf.finalize();
|
||||||
|
/// // Do the hash using the direct API
|
||||||
|
/// let result_direct = SHA3_512::hash(&empty);
|
||||||
|
/// // ... and they should be the same
|
||||||
|
/// assert_eq!(result_incremental,result_direct);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SHA3_512 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for SHA3_512 {
|
||||||
|
fn new() -> Self
|
||||||
|
{
|
||||||
|
SHA3_512{ state: Keccak::new(1600 - 1024) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(&mut self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
self.state.tag_and_pad(0x06);
|
||||||
|
self.state.squeeze(512 / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_size() -> usize
|
||||||
|
{
|
||||||
|
576
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod sha512 {
|
||||||
|
use super::*;
|
||||||
|
use testing::run_test;
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-512_Msg0.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_empty_example() {
|
||||||
|
let empty = [0; 0];
|
||||||
|
let hashres = [0xA6,0x9F,0x73,0xCC,0xA2,0x3A,0x9A,0xC5,
|
||||||
|
0xC8,0xB5,0x67,0xDC,0x18,0x5A,0x75,0x6E,
|
||||||
|
0x97,0xC9,0x82,0x16,0x4F,0xE2,0x58,0x59,
|
||||||
|
0xE0,0xD1,0xDC,0xC1,0x47,0x5C,0x80,0xA6,
|
||||||
|
0x15,0xB2,0x12,0x3A,0xF1,0xF5,0xF9,0x4C,
|
||||||
|
0x11,0xE3,0xE9,0x40,0x2C,0x3A,0xC5,0x58,
|
||||||
|
0xF5,0x00,0x19,0x9D,0x95,0xB6,0xD3,0xE3,
|
||||||
|
0x01,0x75,0x85,0x86,0x28,0x1D,0xCD,0x26];
|
||||||
|
let mine = SHA3_512::hash(&empty);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-512_1600.pdf
|
||||||
|
#[test]
|
||||||
|
fn nist_1600_example() {
|
||||||
|
let example = [0xA3; 200];
|
||||||
|
let hashres = [0xE7,0x6D,0xFA,0xD2,0x20,0x84,0xA8,0xB1,
|
||||||
|
0x46,0x7F,0xCF,0x2F,0xFA,0x58,0x36,0x1B,
|
||||||
|
0xEC,0x76,0x28,0xED,0xF5,0xF3,0xFD,0xC0,
|
||||||
|
0xE4,0x80,0x5D,0xC4,0x8C,0xAE,0xEC,0xA8,
|
||||||
|
0x1B,0x7C,0x13,0xC3,0x0A,0xDF,0x52,0xA3,
|
||||||
|
0x65,0x95,0x84,0x73,0x9A,0x2D,0xF4,0x6B,
|
||||||
|
0xE5,0x89,0xC5,0x1C,0xA1,0xA4,0xA8,0x41,
|
||||||
|
0x6D,0xF6,0x54,0x5A,0x1C,0xE8,0xBA,0x00];
|
||||||
|
let mine = SHA3_512::hash(&example);
|
||||||
|
assert_eq!(hashres.to_vec(), mine);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn nist_test_vectors() {
|
||||||
|
let fname = "testdata/sha/nist_sha3_512.test";
|
||||||
|
run_test(fname.to_string(), 3, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let digest = SHA3_512::hash(&msg);
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
101
src/sha/shared.rs
Normal file
101
src/sha/shared.rs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
macro_rules! ch {
|
||||||
|
($x: expr, $y: expr, $z: expr) => {{
|
||||||
|
let xval = $x;
|
||||||
|
(xval & $y) ^ (!xval & $z)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! parity {
|
||||||
|
($x: expr, $y: expr, $z: expr) => {
|
||||||
|
$x ^ $y ^ $z
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! maj {
|
||||||
|
($x: expr, $y: expr, $z: expr) => {{
|
||||||
|
/* the original function is (x & y) ^ (x & z) ^ (y & z).
|
||||||
|
if you fire off truth tables, this is equivalent to
|
||||||
|
(x & y) | (x & z) | (y & z)
|
||||||
|
which you can then use distribution on:
|
||||||
|
(x & (y | z)) | (y & z)
|
||||||
|
which saves one operation */
|
||||||
|
let yval = $y;
|
||||||
|
let zval = $z;
|
||||||
|
($x & (yval | zval)) | (yval & zval)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! process_u32_block {
|
||||||
|
($buf: expr, $off: expr, $self: ident) => {{
|
||||||
|
let w00 = ($buf[$off+0] as u32) << 24 | ($buf[$off+1] as u32) << 16 |
|
||||||
|
($buf[$off+2] as u32) << 8 | ($buf[$off+3] as u32);
|
||||||
|
let w01 = ($buf[$off+4] as u32) << 24 | ($buf[$off+5] as u32) << 16 |
|
||||||
|
($buf[$off+6] as u32) << 8 | ($buf[$off+7] as u32);
|
||||||
|
let w02 = ($buf[$off+8] as u32) << 24 | ($buf[$off+9] as u32) << 16 |
|
||||||
|
($buf[$off+10] as u32) << 8 | ($buf[$off+11] as u32);
|
||||||
|
let w03 = ($buf[$off+12] as u32) << 24 | ($buf[$off+13] as u32) << 16 |
|
||||||
|
($buf[$off+14] as u32) << 8 | ($buf[$off+15] as u32);
|
||||||
|
let w04 = ($buf[$off+16] as u32) << 24 | ($buf[$off+17] as u32) << 16 |
|
||||||
|
($buf[$off+18] as u32) << 8 | ($buf[$off+19] as u32);
|
||||||
|
let w05 = ($buf[$off+20] as u32) << 24 | ($buf[$off+21] as u32) << 16 |
|
||||||
|
($buf[$off+22] as u32) << 8 | ($buf[$off+23] as u32);
|
||||||
|
let w06 = ($buf[$off+24] as u32) << 24 | ($buf[$off+25] as u32) << 16 |
|
||||||
|
($buf[$off+26] as u32) << 8 | ($buf[$off+27] as u32);
|
||||||
|
let w07 = ($buf[$off+28] as u32) << 24 | ($buf[$off+29] as u32) << 16 |
|
||||||
|
($buf[$off+30] as u32) << 8 | ($buf[$off+31] as u32);
|
||||||
|
let w08 = ($buf[$off+32] as u32) << 24 | ($buf[$off+33] as u32) << 16 |
|
||||||
|
($buf[$off+34] as u32) << 8 | ($buf[$off+35] as u32);
|
||||||
|
let w09 = ($buf[$off+36] as u32) << 24 | ($buf[$off+37] as u32) << 16 |
|
||||||
|
($buf[$off+38] as u32) << 8 | ($buf[$off+39] as u32);
|
||||||
|
let w10 = ($buf[$off+40] as u32) << 24 | ($buf[$off+41] as u32) << 16 |
|
||||||
|
($buf[$off+42] as u32) << 8 | ($buf[$off+43] as u32);
|
||||||
|
let w11 = ($buf[$off+44] as u32) << 24 | ($buf[$off+45] as u32) << 16 |
|
||||||
|
($buf[$off+46] as u32) << 8 | ($buf[$off+47] as u32);
|
||||||
|
let w12 = ($buf[$off+48] as u32) << 24 | ($buf[$off+49] as u32) << 16 |
|
||||||
|
($buf[$off+50] as u32) << 8 | ($buf[$off+51] as u32);
|
||||||
|
let w13 = ($buf[$off+52] as u32) << 24 | ($buf[$off+53] as u32) << 16 |
|
||||||
|
($buf[$off+54] as u32) << 8 | ($buf[$off+55] as u32);
|
||||||
|
let w14 = ($buf[$off+56] as u32) << 24 | ($buf[$off+57] as u32) << 16 |
|
||||||
|
($buf[$off+58] as u32) << 8 | ($buf[$off+59] as u32);
|
||||||
|
let w15 = ($buf[$off+60] as u32) << 24 | ($buf[$off+61] as u32) << 16 |
|
||||||
|
($buf[$off+62] as u32) << 8 | ($buf[$off+63] as u32);
|
||||||
|
$self.process(w00, w01, w02, w03, w04, w05, w06, w07,
|
||||||
|
w08, w09, w10, w11, w12, w13, w14, w15);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate the value `k` used in the padding for all the hashes, solving the
|
||||||
|
// equation (l + 1 + k) mod b = a.
|
||||||
|
pub fn calculate_k(a: usize, b: usize, l: usize) -> usize
|
||||||
|
{
|
||||||
|
(a - (l + 1)) % b
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
quickcheck!
|
||||||
|
{
|
||||||
|
fn maj_rewrite_ok(x: u64, y: u64, z: u64) -> bool
|
||||||
|
{
|
||||||
|
let orig = (x & y) ^ (x & z) ^ (y & z);
|
||||||
|
maj!(x, y, z) == orig
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, these two laws hold because we hash with bytes as the atomic size,
|
||||||
|
// not bits. If we hashed true bit streams, we'd be in trouble.
|
||||||
|
fn sha1_k_plus_1_multiple_of_8(lbytes: usize) -> bool
|
||||||
|
{
|
||||||
|
let l = lbytes * 8;
|
||||||
|
(calculate_k(448,512,l) + 1) % 8 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, these two laws hold because we hash with bytes as the atomic size,
|
||||||
|
// not bits. If we hashed true bit streams, we'd be in trouble.
|
||||||
|
fn sha2_k_plus_1_multiple_of_8(lbytes: usize) -> bool
|
||||||
|
{
|
||||||
|
let l = lbytes * 8;
|
||||||
|
(calculate_k(896,1024,l) + 1) % 8 == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
215
src/shake.rs
Normal file
215
src/shake.rs
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
//! This module implements the SHAKE family of variable-length hash functions,
|
||||||
|
//! which NIST also referes to as Extendable-Output Functions (XOFs). They are
|
||||||
|
//! based on the same underlying hashing mechanism used in SHA3, but can be
|
||||||
|
//! tuned to output a variety of different hash lengths. One trick is that the
|
||||||
|
//! security of the hash is the minimum of the defined bit size (128 for
|
||||||
|
//! SHAKE128, or 256 for SHAKE256) and the output hash length, so if you use
|
||||||
|
//! shorter hashes you lose some amount of collision protection.
|
||||||
|
//!
|
||||||
|
//! Because the output is variable length, these don't quite fit into the
|
||||||
|
//! normal `Hash` trait. Instead, they implement the same basic functions,
|
||||||
|
//! but with `hash` and `finalize` functions extended with an additional
|
||||||
|
//! output length function. Usage is thus in the analagous way to normal
|
||||||
|
//! hashing:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::shake::SHAKE128;
|
||||||
|
//!
|
||||||
|
//! // Use SHAKE incrementally
|
||||||
|
//! let empty = [0; 0];
|
||||||
|
//! let mut shakef = SHAKE128::new();
|
||||||
|
//! shakef.update(&empty);
|
||||||
|
//! let result_inc = shakef.finalize(384);
|
||||||
|
//! // Use SHAKE directly
|
||||||
|
//! let result_dir = SHAKE128::hash(&empty, 384);
|
||||||
|
//! // ... and the answers should be the same.
|
||||||
|
//! assert_eq!(result_inc, result_dir);
|
||||||
|
//! ```
|
||||||
|
use sha::Keccak;
|
||||||
|
|
||||||
|
/// The SHAKE128 variable-length hash.
|
||||||
|
///
|
||||||
|
/// This generates a variable-length hash value, although it's not necessarily as
|
||||||
|
/// strong as a hash of the same value. My understanding (which is admittedly
|
||||||
|
/// limited; I've never seen these used) is that this is more for convenience
|
||||||
|
/// when you want to fit into particularly-sized regions. The 128 is the
|
||||||
|
/// approximate maximum bit strength of the hash in bits; the true strength is
|
||||||
|
/// the minimum of the length of the output hash and 128.
|
||||||
|
///
|
||||||
|
/// `SHAKE128` does not implement `Hash`, because it is finalized differently,
|
||||||
|
/// but we've kept something of the flavor of the `Hash` interface for
|
||||||
|
/// familiarity.
|
||||||
|
///
|
||||||
|
/// Like the SHA3 variants, this can be used incrementally or directly, as per
|
||||||
|
/// usual:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::shake::SHAKE128;
|
||||||
|
///
|
||||||
|
/// // Use SHAKE incrementally
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// let mut shakef = SHAKE128::new();
|
||||||
|
/// shakef.update(&empty);
|
||||||
|
/// let result_inc = shakef.finalize(384);
|
||||||
|
/// // Use SHAKE directly
|
||||||
|
/// let result_dir = SHAKE128::hash(&empty, 384);
|
||||||
|
/// // ... and the answers should be the same.
|
||||||
|
/// assert_eq!(result_inc, result_dir);
|
||||||
|
/// ```
|
||||||
|
pub struct SHAKE128 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SHAKE128 {
|
||||||
|
/// Create a fresh, new SHAKE128 instance for incremental use.
|
||||||
|
pub fn new() -> Self
|
||||||
|
{
|
||||||
|
SHAKE128{
|
||||||
|
state: Keccak::new(1600 - 256)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add more data into the hash function for processing.
|
||||||
|
pub fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate the final hash. Because this is a variable-length hash,
|
||||||
|
/// you will need to provide the output size in bits. Note that this
|
||||||
|
/// output size *must* be a multiple of 8, and that the security
|
||||||
|
/// strength of the whole hash is approximately the minimum of this
|
||||||
|
/// length and 128 bits.
|
||||||
|
pub fn finalize(&mut self, outsize: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
assert_eq!(outsize % 8, 0);
|
||||||
|
self.state.tag_and_pad(0x1F);
|
||||||
|
self.state.squeeze(outsize / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Directly generate the SHAKE128 hash of the given buffer, returning
|
||||||
|
/// a hash value of the given size (in bits). Presently, the output
|
||||||
|
/// size *must* be a multiple of 8, although this may change in the
|
||||||
|
/// future.
|
||||||
|
pub fn hash(buffer: &[u8], outsize: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut x = Self::new();
|
||||||
|
x.update(&buffer);
|
||||||
|
x.finalize(outsize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use testing::run_test;
|
||||||
|
#[cfg(test)]
|
||||||
|
use cryptonum::unsigned::{Decoder,U192};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn shake128() {
|
||||||
|
let fname = "testdata/sha/shake128.test";
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
let (nego, obytes) = case.get("o").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd && !nego);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let osize = usize::from(U192::from_bytes(obytes));
|
||||||
|
let digest = SHAKE128::hash(&msg, osize);;
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The SHAKE256 variable-length hash.
|
||||||
|
///
|
||||||
|
/// This generates a variable-length hash value, although it's not necessarily as
|
||||||
|
/// strong as a hash of the same value. My understanding (which is admittedly
|
||||||
|
/// limited; I've never seen these used) is that this is more for convenience
|
||||||
|
/// when you want to fit into particularly-sized regions. The 256 is the
|
||||||
|
/// approximate maximum bit strength of the hash in bits; the true strength is
|
||||||
|
/// the minimum of the length of the output hash and 256.
|
||||||
|
///
|
||||||
|
/// `SHAKE256` does not implement `Hash`, because it is finalized differently,
|
||||||
|
/// but we've kept something of the flavor of the `Hash` interface for
|
||||||
|
/// familiarity.
|
||||||
|
///
|
||||||
|
/// Like the SHA3 variants, this can be used incrementally or directly, as per
|
||||||
|
/// usual:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use simple_crypto::shake::SHAKE256;
|
||||||
|
///
|
||||||
|
/// // Use SHAKE incrementally
|
||||||
|
/// let empty = [0; 0];
|
||||||
|
/// let mut shakef = SHAKE256::new();
|
||||||
|
/// shakef.update(&empty);
|
||||||
|
/// let result_inc = shakef.finalize(384);
|
||||||
|
/// // Use SHAKE directly
|
||||||
|
/// let result_dir = SHAKE256::hash(&empty, 384);
|
||||||
|
/// // ... and the answers should be the same.
|
||||||
|
/// assert_eq!(result_inc, result_dir);
|
||||||
|
/// ```
|
||||||
|
pub struct SHAKE256 {
|
||||||
|
state: Keccak
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SHAKE256 {
|
||||||
|
/// Create a fresh, new SHAKE256 instance for incremental use.
|
||||||
|
pub fn new() -> Self
|
||||||
|
{
|
||||||
|
SHAKE256{
|
||||||
|
state: Keccak::new(1600 - 512)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add more data into the hash function for processing.
|
||||||
|
pub fn update(&mut self, buffer: &[u8])
|
||||||
|
{
|
||||||
|
self.state.process(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate the final hash. Because this is a variable-length hash,
|
||||||
|
/// you will need to provide the output size in bits. Note that this
|
||||||
|
/// output size *must* be a multiple of 8, and that the security
|
||||||
|
/// strength of the whole hash is approximately the minimum of this
|
||||||
|
/// length and 256 bits.
|
||||||
|
pub fn finalize(&mut self, outsize: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
assert_eq!(outsize % 8, 0);
|
||||||
|
self.state.tag_and_pad(0x1F);
|
||||||
|
self.state.squeeze(outsize / 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Directly generate the SHAKE256 hash of the given buffer, returning
|
||||||
|
/// a hash value of the given size (in bits). Presently, the output
|
||||||
|
/// size *must* be a multiple of 8, although this may change in the
|
||||||
|
/// future.
|
||||||
|
pub fn hash(buffer: &[u8], outsize: usize) -> Vec<u8>
|
||||||
|
{
|
||||||
|
let mut x = Self::new();
|
||||||
|
x.update(&buffer);
|
||||||
|
x.finalize(outsize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn shake256() {
|
||||||
|
let fname = "testdata/sha/shake256.test";
|
||||||
|
run_test(fname.to_string(), 4, |case| {
|
||||||
|
let (negl, lbytes) = case.get("l").unwrap();
|
||||||
|
let (negm, mbytes) = case.get("m").unwrap();
|
||||||
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
|
let (nego, obytes) = case.get("o").unwrap();
|
||||||
|
|
||||||
|
assert!(!negl && !negm && !negd && !nego);
|
||||||
|
let msg = if lbytes[0] == 0 { Vec::new() } else { mbytes.clone() };
|
||||||
|
let osize = usize::from(U192::from_bytes(obytes));
|
||||||
|
let digest = SHAKE256::hash(&msg, osize);;
|
||||||
|
assert_eq!(dbytes, &digest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
75
src/ssh/dsa.rs
Normal file
75
src/ssh/dsa.rs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use dsa::{DSAKeyPair,DSAParameters,DSAPublicKey,DSAPrivateKey,L1024N160};
|
||||||
|
use std::io::{Read,Write};
|
||||||
|
use ssh::errors::{SSHKeyParseError,SSHKeyRenderError};
|
||||||
|
use ssh::frame::*;
|
||||||
|
use ssh::SSHKey;
|
||||||
|
|
||||||
|
impl SSHKey for DSAKeyPair<L1024N160> {
|
||||||
|
fn valid_keytype(s: &str) -> bool {
|
||||||
|
(s == "ssh-dss") || (s == "dss")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ssh_public_info<I: Read>(inp: &mut I) -> Result<Self::Public,SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let pubkey_type = parse_openssh_string(inp)?;
|
||||||
|
if !Self::valid_keytype(&pubkey_type) {
|
||||||
|
return Err(SSHKeyParseError::UnknownKeyType(pubkey_type));
|
||||||
|
}
|
||||||
|
let pubp = parse_openssh_number(inp)?;
|
||||||
|
let pubq = parse_openssh_number(inp)?;
|
||||||
|
let pubg = parse_openssh_number(inp)?;
|
||||||
|
let pubparams = L1024N160::new(pubp, pubg, pubq);
|
||||||
|
let puby: U1024 = parse_openssh_number(inp)?;
|
||||||
|
for _ in inp.bytes() { return Err(SSHKeyParseError::UnknownTrailingData); }
|
||||||
|
Ok(DSAPublicKey::<L1024N160>::new(pubparams.clone(), puby.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ssh_private_info<I: Read>(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let check1 = parse_openssh_u32(inp)?;
|
||||||
|
let check2 = parse_openssh_u32(inp)?;
|
||||||
|
if check1 != check2 {
|
||||||
|
return Err(SSHKeyParseError::PrivateKeyCorruption);
|
||||||
|
}
|
||||||
|
let privkey_type = parse_openssh_string(inp)?;
|
||||||
|
if !Self::valid_keytype(&privkey_type) {
|
||||||
|
return Err(SSHKeyParseError::InconsistentKeyTypes("ssh-dss".to_string(), privkey_type));
|
||||||
|
}
|
||||||
|
let privp = parse_openssh_number(inp)?;
|
||||||
|
let privq = parse_openssh_number(inp)?;
|
||||||
|
let privg = parse_openssh_number(inp)?;
|
||||||
|
let privparams = L1024N160::new(privp, privg, privq);
|
||||||
|
let _ = parse_openssh_buffer(inp)?; // a copy of y we don't need
|
||||||
|
let privx = parse_openssh_number(inp)?;
|
||||||
|
|
||||||
|
let privkey = DSAPrivateKey::<L1024N160>::new(privparams, privx);
|
||||||
|
let comment = parse_openssh_string(inp)?;
|
||||||
|
for (idx,byte) in inp.bytes().enumerate() {
|
||||||
|
if ((idx+1) as u8) != byte? {
|
||||||
|
return Err(SSHKeyParseError::InvalidPadding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((privkey,comment))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ssh_public_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
render_openssh_string(out, "ssh-dss")?;
|
||||||
|
render_openssh_number(out, &self.public.params.p)?;
|
||||||
|
render_openssh_number(out, &self.public.params.q)?;
|
||||||
|
render_openssh_number(out, &self.public.params.g)?;
|
||||||
|
render_openssh_number(out, &self.public.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ssh_private_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
render_openssh_string(out, "ssh-dss")?;
|
||||||
|
render_openssh_number(out, &self.private.params.p)?;
|
||||||
|
render_openssh_number(out, &self.private.params.q)?;
|
||||||
|
render_openssh_number(out, &self.private.params.g)?;
|
||||||
|
render_openssh_number(out, &self.public.y)?;
|
||||||
|
render_openssh_number(out, &self.private.x)
|
||||||
|
}
|
||||||
|
}
|
||||||
171
src/ssh/ecdsa.rs
Normal file
171
src/ssh/ecdsa.rs
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use ecdsa::{ECDSAPair,ECDSAPublic,ECCPublicKey,ECDSAPrivate,ECCPrivateKey};
|
||||||
|
use ecdsa::{EllipticCurve,P256,P384,P521};
|
||||||
|
use std::io::{Read,Write};
|
||||||
|
use ssh::errors::{SSHKeyParseError,SSHKeyRenderError};
|
||||||
|
use ssh::frame::*;
|
||||||
|
use ssh::SSHKey;
|
||||||
|
|
||||||
|
impl SSHKey for ECDSAPair {
|
||||||
|
fn valid_keytype(s: &str) -> bool {
|
||||||
|
(s == "ssh-ecdsa") || (s == "ecdsa") || (s == "ecdsa-sha2-nistp256") ||
|
||||||
|
(s == "ecdsa-sha2-nistp384") || (s == "ecdsa-sha2-nistp521")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ssh_public_info<I: Read>(inp: &mut I) -> Result<Self::Public,SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let pubkey_type = parse_openssh_string(inp)?;
|
||||||
|
if !Self::valid_keytype(&pubkey_type) {
|
||||||
|
return Err(SSHKeyParseError::UnknownKeyType(pubkey_type));
|
||||||
|
}
|
||||||
|
// this peaks a little under the cover a bit (it'd be nice to pretend
|
||||||
|
// that we didn't know the number format was the same as the buffer
|
||||||
|
// one), but we need to infer what kind of key this is, and this appears
|
||||||
|
// to be the easiest / fastest way.
|
||||||
|
let curve = parse_openssh_string(inp)?;
|
||||||
|
match curve.as_ref() {
|
||||||
|
"nistp256" => {
|
||||||
|
let val = parse_openssh_buffer(inp)?;
|
||||||
|
if val[0] != 4 || val.len() != 65 {
|
||||||
|
return Err(SSHKeyParseError::InvalidECPointCompression);
|
||||||
|
}
|
||||||
|
let x = U256::from_bytes(&val[1..33]);
|
||||||
|
let y = U256::from_bytes(&val[33..]);
|
||||||
|
let p = P256::new_point(x, y);
|
||||||
|
let pbl = ECCPublicKey::<P256>::new(p);
|
||||||
|
Ok(ECDSAPublic::P256(pbl))
|
||||||
|
}
|
||||||
|
"nistp384" => {
|
||||||
|
let val = parse_openssh_buffer(inp)?;
|
||||||
|
if val[0] != 4 || val.len() != 97 {
|
||||||
|
return Err(SSHKeyParseError::InvalidECPointCompression);
|
||||||
|
}
|
||||||
|
let x = U384::from_bytes(&val[1..49]);
|
||||||
|
let y = U384::from_bytes(&val[49..]);
|
||||||
|
let p = P384::new_point(x, y);
|
||||||
|
let pbl = ECCPublicKey::<P384>::new(p);
|
||||||
|
Ok(ECDSAPublic::P384(pbl))
|
||||||
|
}
|
||||||
|
"nistp521" => {
|
||||||
|
let val = parse_openssh_buffer(inp)?;
|
||||||
|
if val[0] != 4 || val.len() != 133 {
|
||||||
|
return Err(SSHKeyParseError::InvalidECPointCompression);
|
||||||
|
}
|
||||||
|
let x = U576::from_bytes(&val[1..67]);
|
||||||
|
let y = U576::from_bytes(&val[67..]);
|
||||||
|
let p = P521::new_point(x, y);
|
||||||
|
let pbl = ECCPublicKey::<P521>::new(p);
|
||||||
|
Ok(ECDSAPublic::P521(pbl))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(SSHKeyParseError::UnknownECDSACurve(curve))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ssh_private_info<I: Read>(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let check1 = parse_openssh_u32(inp)?;
|
||||||
|
let check2 = parse_openssh_u32(inp)?;
|
||||||
|
if check1 != check2 {
|
||||||
|
return Err(SSHKeyParseError::PrivateKeyCorruption);
|
||||||
|
}
|
||||||
|
let res = match ECDSAPair::parse_ssh_public_info(inp)? {
|
||||||
|
ECDSAPublic::P192(_) => return Err(SSHKeyParseError::PrivateKeyCorruption),
|
||||||
|
ECDSAPublic::P224(_) => return Err(SSHKeyParseError::PrivateKeyCorruption),
|
||||||
|
ECDSAPublic::P256(_) => {
|
||||||
|
let mut dbytes = parse_openssh_buffer(inp)?;
|
||||||
|
while dbytes[0] == 0 { dbytes.remove(0); }
|
||||||
|
assert!(dbytes.len() <= 32);
|
||||||
|
let d = U256::from_bytes(&dbytes);
|
||||||
|
ECDSAPrivate::P256(ECCPrivateKey::<P256>::new(d))
|
||||||
|
}
|
||||||
|
ECDSAPublic::P384(_) => {
|
||||||
|
let mut dbytes = parse_openssh_buffer(inp)?;
|
||||||
|
while dbytes[0] == 0 { dbytes.remove(0); }
|
||||||
|
assert!(dbytes.len() <= 48);
|
||||||
|
let d = U384::from_bytes(&dbytes);
|
||||||
|
ECDSAPrivate::P384(ECCPrivateKey::<P384>::new(d))
|
||||||
|
}
|
||||||
|
ECDSAPublic::P521(_) => {
|
||||||
|
let mut dbytes = parse_openssh_buffer(inp)?;
|
||||||
|
while dbytes[0] == 0 { dbytes.remove(0); }
|
||||||
|
assert!(dbytes.len() <= 66);
|
||||||
|
let d = U576::from_bytes(&dbytes);
|
||||||
|
ECDSAPrivate::P521(ECCPrivateKey::<P521>::new(d))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let comment = parse_openssh_string(inp)?;
|
||||||
|
for (idx,byte) in inp.bytes().enumerate() {
|
||||||
|
if ((idx+1) as u8) != byte? {
|
||||||
|
return Err(SSHKeyParseError::InvalidPadding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((res, comment))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ssh_public_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
render_openssh_string(out, "ssh-ecdsa")?;
|
||||||
|
match self {
|
||||||
|
ECDSAPair::P192(_,_) =>
|
||||||
|
return Err(SSHKeyRenderError::IllegalECDSAKeyType("P192".to_string())),
|
||||||
|
ECDSAPair::P224(_,_) =>
|
||||||
|
return Err(SSHKeyRenderError::IllegalECDSAKeyType("P224".to_string())),
|
||||||
|
ECDSAPair::P256(pu,_) => {
|
||||||
|
render_openssh_string(out, "nistp256")?;
|
||||||
|
let mut vec = Vec::with_capacity(66);
|
||||||
|
vec.write(&[4u8])?;
|
||||||
|
render_number(256, &mut vec, &U256::from(pu.q.x.clone()))?;
|
||||||
|
render_number(256, &mut vec, &U256::from(pu.q.y.clone()))?;
|
||||||
|
render_openssh_buffer(out, &vec)?;
|
||||||
|
}
|
||||||
|
ECDSAPair::P384(pu,_) => {
|
||||||
|
render_openssh_string(out, "nistp384")?;
|
||||||
|
let mut vec = Vec::with_capacity(66);
|
||||||
|
vec.write(&[4u8])?;
|
||||||
|
render_number(384, &mut vec, &U384::from(pu.q.x.clone()))?;
|
||||||
|
render_number(384, &mut vec, &U384::from(pu.q.y.clone()))?;
|
||||||
|
render_openssh_buffer(out, &vec)?;
|
||||||
|
}
|
||||||
|
ECDSAPair::P521(pu,_) => {
|
||||||
|
render_openssh_string(out, "nistp521")?;
|
||||||
|
let mut vec = Vec::with_capacity(66);
|
||||||
|
vec.write(&[4u8])?;
|
||||||
|
render_number(521, &mut vec, &U576::from(pu.q.x.clone()))?;
|
||||||
|
render_number(521, &mut vec, &U576::from(pu.q.y.clone()))?;
|
||||||
|
render_openssh_buffer(out, &vec)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ssh_private_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
self.render_ssh_public_info(out)?;
|
||||||
|
match self {
|
||||||
|
ECDSAPair::P192(_,_) =>
|
||||||
|
return Err(SSHKeyRenderError::IllegalECDSAKeyType("P192".to_string())),
|
||||||
|
ECDSAPair::P224(_,_) =>
|
||||||
|
return Err(SSHKeyRenderError::IllegalECDSAKeyType("P224".to_string())),
|
||||||
|
ECDSAPair::P256(_,pr) => { render_openssh_u32(out, 256/8)?; render_number(256, out, &pr.d)?; }
|
||||||
|
ECDSAPair::P384(_,pr) => { render_openssh_u32(out, 384/8)?; render_number(384, out, &pr.d)?; }
|
||||||
|
ECDSAPair::P521(_,pr) => { render_openssh_u32(out, 528/8)?; render_number(521, out, &pr.d)?; }
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_number<O,N>(bitlen: usize, out: &mut O, val: &N) -> Result<(),SSHKeyRenderError>
|
||||||
|
where
|
||||||
|
O: Write,
|
||||||
|
N: Encoder
|
||||||
|
{
|
||||||
|
let mut outvec = Vec::new();
|
||||||
|
outvec.write(&val.to_bytes())?;
|
||||||
|
while outvec.len() < ((bitlen + 7) / 8) { outvec.insert(0,0); }
|
||||||
|
while outvec.len() > ((bitlen + 7) / 8) { outvec.remove(0); }
|
||||||
|
out.write(&outvec)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
58
src/ssh/ed25519.rs
Normal file
58
src/ssh/ed25519.rs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
use ed25519::{ED25519KeyPair,ED25519Private,ED25519Public};
|
||||||
|
use std::io::{Read,Write};
|
||||||
|
use ssh::errors::{SSHKeyParseError,SSHKeyRenderError};
|
||||||
|
use ssh::frame::*;
|
||||||
|
use ssh::SSHKey;
|
||||||
|
|
||||||
|
impl SSHKey for ED25519KeyPair {
|
||||||
|
fn valid_keytype(s: &str) -> bool {
|
||||||
|
(s == "ssh-ed25519")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ssh_public_info<I: Read>(inp: &mut I) -> Result<Self::Public,SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let pubkey_type = parse_openssh_string(inp)?;
|
||||||
|
if !Self::valid_keytype(&pubkey_type) {
|
||||||
|
return Err(SSHKeyParseError::UnknownKeyType(pubkey_type));
|
||||||
|
}
|
||||||
|
let pubkey_bytes = parse_openssh_buffer(inp)?;
|
||||||
|
Ok(ED25519Public::new(&pubkey_bytes)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ssh_private_info<I: Read>(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let check1 = parse_openssh_u32(inp)?;
|
||||||
|
let check2 = parse_openssh_u32(inp)?;
|
||||||
|
if check1 != check2 {
|
||||||
|
return Err(SSHKeyParseError::PrivateKeyCorruption);
|
||||||
|
}
|
||||||
|
let public = ED25519KeyPair::parse_ssh_public_info(inp)?;
|
||||||
|
let private_bytes = parse_openssh_buffer(inp)?;
|
||||||
|
let private = ED25519Private::from_seed(&private_bytes[0..32]);
|
||||||
|
let comment = parse_openssh_string(inp)?;
|
||||||
|
for (idx,byte) in inp.bytes().enumerate() {
|
||||||
|
if ((idx+1) as u8) != byte? {
|
||||||
|
return Err(SSHKeyParseError::InvalidPadding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(public, ED25519Public::from(&private));
|
||||||
|
|
||||||
|
Ok((private, comment))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ssh_public_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
render_openssh_string(out, "ssh-ed25519")?;
|
||||||
|
render_openssh_buffer(out, &self.public.to_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ssh_private_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
self.render_ssh_public_info(out)?;
|
||||||
|
let mut private_bytes = self.private.to_bytes();
|
||||||
|
private_bytes.append(&mut self.public.to_bytes());
|
||||||
|
render_openssh_buffer(out, &private_bytes)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
68
src/ssh/errors.rs
Normal file
68
src/ssh/errors.rs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
use base64::DecodeError;
|
||||||
|
use ed25519::ED25519PublicImportError;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
/// A whole pile of errors that you can get when parsing an SSH key from
|
||||||
|
/// disk or memory.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SSHKeyParseError
|
||||||
|
{
|
||||||
|
DecodeError(DecodeError),
|
||||||
|
IOError(io::Error),
|
||||||
|
NoBeginBannerFound, NoEndBannerFound,
|
||||||
|
NoOpenSSHMagicHeader,
|
||||||
|
UnknownKeyCipher(String),
|
||||||
|
UnknownKDF(String), UnexpectedKDFOptions,
|
||||||
|
InvalidNumberOfKeys(u32),
|
||||||
|
UnknownTrailingData,
|
||||||
|
UnknownKeyType(String),
|
||||||
|
InvalidPublicKeyMaterial,
|
||||||
|
PrivateKeyCorruption,
|
||||||
|
InconsistentKeyTypes(String,String),
|
||||||
|
InconsistentPublicKeyValue,
|
||||||
|
InvalidPrivateKeyValue,
|
||||||
|
InvalidPadding,
|
||||||
|
InvalidPublicKeyType,
|
||||||
|
BrokenPublicKeyLine,
|
||||||
|
UnknownECDSACurve(String),
|
||||||
|
InvalidECPointCompression
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DecodeError> for SSHKeyParseError {
|
||||||
|
fn from(e: DecodeError) -> SSHKeyParseError {
|
||||||
|
SSHKeyParseError::DecodeError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for SSHKeyParseError {
|
||||||
|
fn from(e: io::Error) -> SSHKeyParseError {
|
||||||
|
SSHKeyParseError::IOError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ED25519PublicImportError> for SSHKeyParseError {
|
||||||
|
fn from(e: ED25519PublicImportError) -> SSHKeyParseError {
|
||||||
|
match e {
|
||||||
|
ED25519PublicImportError::WrongNumberOfBytes(_) =>
|
||||||
|
SSHKeyParseError::InvalidPublicKeyMaterial,
|
||||||
|
ED25519PublicImportError::InvalidPublicPoint =>
|
||||||
|
SSHKeyParseError::InvalidPublicKeyMaterial,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A much smaller set of errors you can get when rendering an SSH key into
|
||||||
|
/// a file or memory block.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SSHKeyRenderError {
|
||||||
|
IOError(io::Error),
|
||||||
|
StringTooLong,
|
||||||
|
BufferTooLarge,
|
||||||
|
IllegalECDSAKeyType(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for SSHKeyRenderError {
|
||||||
|
fn from(e: io::Error) -> SSHKeyRenderError {
|
||||||
|
SSHKeyRenderError::IOError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
320
src/ssh/frame.rs
Normal file
320
src/ssh/frame.rs
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
use base64::{decode,encode};
|
||||||
|
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};
|
||||||
|
use cryptonum::unsigned::{Decoder,Encoder};
|
||||||
|
use ssh::errors::{SSHKeyParseError,SSHKeyRenderError};
|
||||||
|
#[cfg(test)]
|
||||||
|
use std::io::Cursor;
|
||||||
|
#[cfg(test)]
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::iter::Iterator;
|
||||||
|
|
||||||
|
const OPENER: &'static str = "-----BEGIN OPENSSH PRIVATE KEY-----";
|
||||||
|
const CLOSER: &'static str = "-----END OPENSSH PRIVATE KEY-----";
|
||||||
|
|
||||||
|
/// Given a string defining an ASCII SSH key blob (one that starts with
|
||||||
|
/// "--BEGIN..."), decode the body of the blob and return it as binary
|
||||||
|
/// data.
|
||||||
|
pub fn parse_ssh_private_key_data(s: &str) -> Result<Vec<u8>,SSHKeyParseError>
|
||||||
|
{
|
||||||
|
if s.starts_with(OPENER) {
|
||||||
|
if let Some(endidx) = s.find(CLOSER) {
|
||||||
|
let b64str: String = s[OPENER.len()..endidx].chars().filter(|x| !x.is_whitespace()).collect();
|
||||||
|
let bytes = decode(&b64str)?;
|
||||||
|
Ok(bytes)
|
||||||
|
} else {
|
||||||
|
Err(SSHKeyParseError::NoEndBannerFound)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(SSHKeyParseError::NoBeginBannerFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Once you've figured out the binary data you want to produce for an SSH key
|
||||||
|
/// blob, use this routine to render it into its ASCII encoding.
|
||||||
|
pub fn render_ssh_private_key_data(bytes: &[u8]) -> String
|
||||||
|
{
|
||||||
|
let mut bytestr = encode(bytes);
|
||||||
|
let mut output = String::new();
|
||||||
|
|
||||||
|
output.push_str(OPENER);
|
||||||
|
#[cfg(target_os="windows")]
|
||||||
|
output.push_str("\r");
|
||||||
|
output.push_str("\n");
|
||||||
|
while bytestr.len() > 70 {
|
||||||
|
let rest = bytestr.split_off(70);
|
||||||
|
output.push_str(&bytestr);
|
||||||
|
#[cfg(target_os="windows")]
|
||||||
|
output.push_str("\r");
|
||||||
|
output.push_str("\n");
|
||||||
|
bytestr = rest;
|
||||||
|
}
|
||||||
|
output.push_str(&bytestr);
|
||||||
|
#[cfg(target_os="windows")]
|
||||||
|
output.push_str("\r");
|
||||||
|
output.push_str("\n");
|
||||||
|
output.push_str(CLOSER);
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const OPENSSH_MAGIC_HEADER: &'static str = "openssh-key-v1\0";
|
||||||
|
const OPENSSH_MAGIC_HEADER_LEN: usize = 15;
|
||||||
|
|
||||||
|
/// Parse the magic header in an SSH key file.
|
||||||
|
pub fn parse_openssh_header<R: Read>(input: &mut R) -> Result<(),SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let mut limited_input_header = input.take(OPENSSH_MAGIC_HEADER_LEN as u64);
|
||||||
|
let mut header: [u8; OPENSSH_MAGIC_HEADER_LEN] = [0; OPENSSH_MAGIC_HEADER_LEN];
|
||||||
|
|
||||||
|
assert_eq!(OPENSSH_MAGIC_HEADER.len(), OPENSSH_MAGIC_HEADER_LEN);
|
||||||
|
limited_input_header.read_exact(&mut header)?;
|
||||||
|
|
||||||
|
for (left, right) in OPENSSH_MAGIC_HEADER.bytes().zip(header.iter()) {
|
||||||
|
if left != *right {
|
||||||
|
return Err(SSHKeyParseError::NoOpenSSHMagicHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the magic header in an SSH key file.
|
||||||
|
pub fn render_openssh_header<O: Write>(output: &mut O) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
Ok(output.write_all(OPENSSH_MAGIC_HEADER.as_bytes())?)
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Parse an unsigned u32 from the SSH key stream. (This does the appropriate
|
||||||
|
/// conversion from network order to native order.)
|
||||||
|
pub fn parse_openssh_u32<I: Read>(input: &mut I) -> Result<u32,SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let mut limited_input_header = input.take(4);
|
||||||
|
let res = limited_input_header.read_u32::<BigEndian>()?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render an unsigned u32 from the SSH key stream. (This does the appropriate
|
||||||
|
/// conversion from network order to native order.)
|
||||||
|
pub fn render_openssh_u32<O: Write>(output: &mut O, val: u32) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
Ok(output.write_u32::<BigEndian>(val)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Parse a string from the SSH key stream. This does some validation to ensure
|
||||||
|
/// that the data being read is actually in a form that Rust will recognize as
|
||||||
|
/// being a valid string.
|
||||||
|
pub fn parse_openssh_string<I: Read>(input: &mut I) -> Result<String,SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let length = parse_openssh_u32(input)?;
|
||||||
|
let mut limited_input = input.take(length as u64);
|
||||||
|
let mut result = String::new();
|
||||||
|
limited_input.read_to_string(&mut result)?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render a string into the SSH key stream.
|
||||||
|
pub fn render_openssh_string<O: Write>(output: &mut O, v: &str) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
let vbytes: Vec<u8> = v.bytes().collect();
|
||||||
|
let len = vbytes.len();
|
||||||
|
|
||||||
|
if len > 0xFFFFFFFF {
|
||||||
|
return Err(SSHKeyRenderError::StringTooLong);
|
||||||
|
}
|
||||||
|
|
||||||
|
render_openssh_u32(output, vbytes.len() as u32)?;
|
||||||
|
output.write_all(&vbytes)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Read a buffer from the SSH key stream.
|
||||||
|
pub fn parse_openssh_buffer<I: Read>(input: &mut I) -> Result<Vec<u8>,SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let length = parse_openssh_u32(input)?;
|
||||||
|
let mut limited_input = input.take(length as u64);
|
||||||
|
let mut res = Vec::with_capacity(length as usize);
|
||||||
|
limited_input.read_to_end(&mut res)?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render a buffer into the SSH key stream.
|
||||||
|
pub fn render_openssh_buffer<O: Write>(output: &mut O, b: &[u8]) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
if b.len() > 0xFFFFFFFF {
|
||||||
|
return Err(SSHKeyRenderError::BufferTooLarge);
|
||||||
|
}
|
||||||
|
|
||||||
|
render_openssh_u32(output, b.len() as u32)?;
|
||||||
|
if b.len() > 0 {
|
||||||
|
output.write_all(b)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Parse a fixed-width number from the SSH key stream and return it.
|
||||||
|
pub fn parse_openssh_number<I,D>(input: &mut I) -> Result<D,SSHKeyParseError>
|
||||||
|
where
|
||||||
|
I: Read,
|
||||||
|
D: Decoder
|
||||||
|
{
|
||||||
|
let mut buffer = parse_openssh_buffer(input)?;
|
||||||
|
while buffer[0] == 0 { buffer.remove(0); }
|
||||||
|
Ok(D::from_bytes(&buffer))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render a fixed-width number into the SSH key stream.
|
||||||
|
pub fn render_openssh_number<O,D>(output: &mut O, n: &D) -> Result<(),SSHKeyRenderError>
|
||||||
|
where
|
||||||
|
O: Write,
|
||||||
|
D: Encoder
|
||||||
|
{
|
||||||
|
let bytes = n.to_bytes();
|
||||||
|
render_openssh_buffer(output, &bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use cryptonum::unsigned::{U192,U1024,U2048,U4096};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
quickcheck! {
|
||||||
|
fn bytes_roundtrip(x: Vec<u8>) -> bool {
|
||||||
|
let rendered = render_ssh_private_key_data(&x);
|
||||||
|
let returned = parse_ssh_private_key_data(&rendered).unwrap();
|
||||||
|
returned == x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blocks_formatted(x: Vec<u8>) -> bool {
|
||||||
|
let rendered = render_ssh_private_key_data(&x);
|
||||||
|
let mut is_ok = true;
|
||||||
|
|
||||||
|
for line in rendered.lines() {
|
||||||
|
let clean_line: String = line.chars().filter(|x| *x != '\r').collect();
|
||||||
|
is_ok &= clean_line.len() <= 70;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_ok
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u32s_roundtrip_rp(x: u32) -> bool {
|
||||||
|
let mut buffer = vec![];
|
||||||
|
render_openssh_u32(&mut buffer, x).unwrap();
|
||||||
|
let mut cursor = Cursor::new(buffer);
|
||||||
|
let check = parse_openssh_u32(&mut cursor).unwrap();
|
||||||
|
x == check
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u32s_roundtrip_pr(a: u8, b: u8, c: u8, d: u8) -> bool {
|
||||||
|
let block = [a,b,c,d];
|
||||||
|
let mut cursor = Cursor::new(block);
|
||||||
|
let base = parse_openssh_u32(&mut cursor).unwrap();
|
||||||
|
let mut rendered = vec![];
|
||||||
|
render_openssh_u32(&mut rendered, base).unwrap();
|
||||||
|
(block[0] == rendered[0]) &&
|
||||||
|
(block[1] == rendered[1]) &&
|
||||||
|
(block[2] == rendered[2]) &&
|
||||||
|
(block[3] == rendered[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_roundtrip(s: String) -> bool {
|
||||||
|
let mut buffer = vec![];
|
||||||
|
render_openssh_string(&mut buffer, &s).unwrap();
|
||||||
|
let mut cursor = Cursor::new(buffer);
|
||||||
|
let check = parse_openssh_string(&mut cursor).unwrap();
|
||||||
|
s == check
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buffer(os: Vec<u8>) -> bool {
|
||||||
|
let mut buffer = vec![];
|
||||||
|
render_openssh_buffer(&mut buffer, &os).unwrap();
|
||||||
|
let mut cursor = Cursor::new(buffer);
|
||||||
|
let check = parse_openssh_buffer(&mut cursor).unwrap();
|
||||||
|
os == check
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u192(x: U192) -> bool {
|
||||||
|
let mut buffer = vec![];
|
||||||
|
render_openssh_number(&mut buffer, &x).unwrap();
|
||||||
|
let mut cursor = Cursor::new(buffer);
|
||||||
|
let check: U192 = parse_openssh_number(&mut cursor).unwrap();
|
||||||
|
check == x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u1024(x: U1024) -> bool {
|
||||||
|
let mut buffer = vec![];
|
||||||
|
render_openssh_number(&mut buffer, &x).unwrap();
|
||||||
|
let mut cursor = Cursor::new(buffer);
|
||||||
|
let check: U1024 = parse_openssh_number(&mut cursor).unwrap();
|
||||||
|
check == x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u2048(x: U2048) -> bool {
|
||||||
|
let mut buffer = vec![];
|
||||||
|
render_openssh_number(&mut buffer, &x).unwrap();
|
||||||
|
let mut cursor = Cursor::new(buffer);
|
||||||
|
let check: U2048 = parse_openssh_number(&mut cursor).unwrap();
|
||||||
|
check == x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u4096(x: U4096) -> bool {
|
||||||
|
let mut buffer = vec![];
|
||||||
|
render_openssh_number(&mut buffer, &x).unwrap();
|
||||||
|
let mut cursor = Cursor::new(buffer);
|
||||||
|
let check: U4096 = parse_openssh_number(&mut cursor).unwrap();
|
||||||
|
check == x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn pregenerated_reencode() {
|
||||||
|
let test_files = ["dsa1024-1", "dsa1024-2", "dsa1024-3",
|
||||||
|
"ecdsa256-1", "ecdsa256-2", "ecdsa256-3",
|
||||||
|
"ecdsa384-1", "ecdsa384-2", "ecdsa384-3",
|
||||||
|
"ecdsa521-1", "ecdsa521-2", "ecdsa521-3",
|
||||||
|
"ed25519-1", "ed25519-2", "ed25519-3",
|
||||||
|
"rsa1024-1", "rsa1024-2", "rsa1024-3",
|
||||||
|
"rsa2048-1", "rsa2048-2", "rsa2048-3",
|
||||||
|
"rsa3072-1", "rsa3072-2", "rsa3072-3",
|
||||||
|
"rsa4096-1", "rsa4096-2", "rsa4096-3",
|
||||||
|
"rsa8192-1", "rsa8192-2", "rsa8192-3" ];
|
||||||
|
|
||||||
|
for file in test_files.iter() {
|
||||||
|
let path = format!("testdata/ssh/{}",file);
|
||||||
|
let mut fd = File::open(path).unwrap();
|
||||||
|
let mut contents = String::new();
|
||||||
|
fd.read_to_string(&mut contents).unwrap();
|
||||||
|
let parsed = parse_ssh_private_key_data(&contents).unwrap();
|
||||||
|
let rendered = render_ssh_private_key_data(&parsed);
|
||||||
|
// we remove white space in this to avoid a couple issues with files
|
||||||
|
// generated in Windows or not, as well as trailing white space that
|
||||||
|
// doesn't really matter.
|
||||||
|
let cleaned_orig: String = contents.chars().filter(|x| !x.is_whitespace()).collect();
|
||||||
|
let cleaned_rend: String = rendered.chars().filter(|x| !x.is_whitespace()).collect();
|
||||||
|
assert_eq!(cleaned_orig, cleaned_rend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn header_roundtrips() {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
assert!(render_openssh_header(&mut vec).is_ok());
|
||||||
|
let mut cursor = Cursor::new(vec);
|
||||||
|
assert!(parse_openssh_header(&mut cursor).is_ok());
|
||||||
|
}
|
||||||
428
src/ssh/mod.rs
Normal file
428
src/ssh/mod.rs
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
//! Most of the routines you want are exported from this module as functions,
|
||||||
|
//! not as structs, macros, enums, or what have you. In particular, you
|
||||||
|
//! probably want the `decode` or `encode` functions, or one of the functions
|
||||||
|
//! that `load`s data from disk or `write`s it. Here's some example code
|
||||||
|
//! to get you started, using a generated ED25519 key for fun:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use simple_crypto::ed25519::ED25519KeyPair;
|
||||||
|
//! use simple_crypto::ssh::*;
|
||||||
|
//!
|
||||||
|
//! // Generate a new ED25519 key
|
||||||
|
//! let mut rng = rand::rngs::OsRng::new().unwrap();
|
||||||
|
//! let kp = ED25519KeyPair::generate(&mut rng);
|
||||||
|
//!
|
||||||
|
//! // Now that we have it, we can encode it as a handy ASCII string in memory,
|
||||||
|
//! // using a totally fake email address for fun:
|
||||||
|
//! let ascii_rep = encode_ssh(&kp, "fake@email.addr").expect("Encode failure!");
|
||||||
|
//!
|
||||||
|
//! // As usual, we should be able to decode anything we encode, and the
|
||||||
|
//! // keys should match:
|
||||||
|
//! let (kp2, addr2) = decode_ssh(&ascii_rep).expect("Decode failure!");
|
||||||
|
//! assert_eq!(kp, kp2);
|
||||||
|
//! assert_eq!(&addr2, "fake@email.addr");
|
||||||
|
//!
|
||||||
|
//! // If you want to write this to a file, you can just do so directly:
|
||||||
|
//! write_ssh_keyfile("test.ed25519", &kp, "fake@email.addr").expect("write error");
|
||||||
|
//! // And then load it back:
|
||||||
|
//! let (kp3, addr3) = load_ssh_keyfile("test.ed25519").expect("load error");
|
||||||
|
//! // And, of course, it should be the same.
|
||||||
|
//! assert_eq!(kp, kp3);
|
||||||
|
//! assert_eq!(addr2, addr3);
|
||||||
|
//! ```
|
||||||
|
mod dsa;
|
||||||
|
mod ecdsa;
|
||||||
|
mod ed25519;
|
||||||
|
mod errors;
|
||||||
|
pub mod frame;
|
||||||
|
mod rsa;
|
||||||
|
|
||||||
|
pub use self::errors::{SSHKeyParseError,SSHKeyRenderError};
|
||||||
|
|
||||||
|
use base64::decode;
|
||||||
|
use self::frame::*;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{Cursor,Read,Write};
|
||||||
|
use std::path::Path;
|
||||||
|
use super::KeyPair;
|
||||||
|
|
||||||
|
/// A trait defining keys that can be parsed / rendered by this library. Note
|
||||||
|
/// that you probably don't want to use these routines directly; they're mostly
|
||||||
|
/// used by the internal functions. Perhaps the only reason to use them is to
|
||||||
|
/// implement them, because you've got another kind of key you want to parse that
|
||||||
|
/// isn't already part of the library. (In that case, though ... maybe send a
|
||||||
|
/// patch?)
|
||||||
|
pub trait SSHKey: Sized + KeyPair {
|
||||||
|
/// Return true if the given string is a valid key type identifier for this
|
||||||
|
/// key type. (i.e., "ssh-ed25519" is the identifier for ED25519, and "dss"
|
||||||
|
/// and "ssh-dss" are both valid identifiers for DSA keys.)
|
||||||
|
fn valid_keytype(s: &str) -> bool;
|
||||||
|
|
||||||
|
/// Parse the public blob info within an SSH blob. I strongly recommend
|
||||||
|
/// using the functions in `ssh::frame` for this.
|
||||||
|
fn parse_ssh_public_info<I: Read>(inp: &mut I) -> Result<Self::Public,SSHKeyParseError>;
|
||||||
|
/// Parse the private blob info within an SSH blob. I strongly recommend
|
||||||
|
/// using the functions in `ssh::frame` for this.
|
||||||
|
fn parse_ssh_private_info<I: Read>(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError>;
|
||||||
|
|
||||||
|
/// Render the public blob info within an SSH blob. I strongly recommend
|
||||||
|
/// using the functions in `ssh::frame` for this.
|
||||||
|
fn render_ssh_public_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>;
|
||||||
|
/// Render the private blob info within an SSH blob. I strongly recommend
|
||||||
|
/// using the functions in `ssh::frame` for this.
|
||||||
|
fn render_ssh_private_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decode a string containing a private key into the appropriate key type and
|
||||||
|
/// the comment associated with it, usually an email address or similar.
|
||||||
|
pub fn decode_ssh<KP: SSHKey>(x: &str) -> Result<(KP, String),SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let bytes = parse_ssh_private_key_data(x)?;
|
||||||
|
let data_size = bytes.len() as u64;
|
||||||
|
let mut byte_cursor = Cursor::new(bytes);
|
||||||
|
|
||||||
|
parse_openssh_header(&mut byte_cursor)?;
|
||||||
|
let ciphername = parse_openssh_string(&mut byte_cursor)?;
|
||||||
|
if ciphername != "none" {
|
||||||
|
return Err(SSHKeyParseError::UnknownKeyCipher(ciphername));
|
||||||
|
}
|
||||||
|
let kdfname = parse_openssh_string(&mut byte_cursor)?;
|
||||||
|
if kdfname != "none" {
|
||||||
|
return Err(SSHKeyParseError::UnknownKeyCipher(kdfname));
|
||||||
|
}
|
||||||
|
let kdfoptions = parse_openssh_buffer(&mut byte_cursor)?;
|
||||||
|
if kdfoptions.len() > 0 {
|
||||||
|
return Err(SSHKeyParseError::UnexpectedKDFOptions);
|
||||||
|
}
|
||||||
|
let numkeys = parse_openssh_u32(&mut byte_cursor)?;
|
||||||
|
if numkeys != 1 {
|
||||||
|
return Err(SSHKeyParseError::InvalidNumberOfKeys(numkeys));
|
||||||
|
}
|
||||||
|
let pubkey0 = parse_openssh_buffer(&mut byte_cursor)?;
|
||||||
|
let privkeys = parse_openssh_buffer(&mut byte_cursor)?;
|
||||||
|
if byte_cursor.position() < data_size {
|
||||||
|
return Err(SSHKeyParseError::UnknownTrailingData);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut pubcursor = Cursor::new(pubkey0);
|
||||||
|
let public = KP::parse_ssh_public_info(&mut pubcursor)?;
|
||||||
|
let mut privcursor = Cursor::new(privkeys);
|
||||||
|
let (private, comment) = KP::parse_ssh_private_info(&mut privcursor)?;
|
||||||
|
|
||||||
|
Ok((KP::new(public, private), comment))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decode a string containing a public key into an appropriate key type and
|
||||||
|
/// the comment associated with it, usually an email address or similar.
|
||||||
|
pub fn decode_ssh_pubkey<KP: SSHKey>(s: &str) -> Result<(KP::Public, String),SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let mut splitter = s.split_whitespace();
|
||||||
|
|
||||||
|
match (splitter.next(), splitter.next(), splitter.next(), splitter.next()) {
|
||||||
|
(Some(keytype), Some(keymaterial), Some(comment), None) => {
|
||||||
|
if !KP::valid_keytype(keytype) {
|
||||||
|
return Err(SSHKeyParseError::InvalidPublicKeyType);
|
||||||
|
}
|
||||||
|
|
||||||
|
let bytes = decode(keymaterial)?;
|
||||||
|
let mut byte_cursor = Cursor::new(bytes);
|
||||||
|
let key = KP::parse_ssh_public_info(&mut byte_cursor)?;
|
||||||
|
|
||||||
|
Ok((key, comment.to_string()))
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(SSHKeyParseError::BrokenPublicKeyLine)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load an SSH private key file, returning the appropriate key type and the
|
||||||
|
/// comment associated with it.
|
||||||
|
pub fn load_ssh_keyfile<KP,P>(path: P) -> Result<(KP, String),SSHKeyParseError>
|
||||||
|
where
|
||||||
|
KP: SSHKey,
|
||||||
|
P: AsRef<Path>
|
||||||
|
{
|
||||||
|
let mut file = File::open(path)?;
|
||||||
|
let mut contents = String::new();
|
||||||
|
file.read_to_string(&mut contents)?;
|
||||||
|
decode_ssh(&contents)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load all the public keys from a file into memory.
|
||||||
|
pub fn load_ssh_pubkeys<KP,P>(path: P) -> Result<Vec<(KP::Public, String)>,SSHKeyParseError>
|
||||||
|
where
|
||||||
|
KP: SSHKey,
|
||||||
|
P: AsRef<Path>
|
||||||
|
{
|
||||||
|
let mut file = File::open(path)?;
|
||||||
|
let mut contents = String::new();
|
||||||
|
file.read_to_string(&mut contents)?;
|
||||||
|
let mut result = Vec::new();
|
||||||
|
|
||||||
|
for line in contents.lines() {
|
||||||
|
result.push( decode_ssh_pubkey::<KP>(line)? );
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encode a supported key into its ASCII SSH format, with the given comment.
|
||||||
|
pub fn encode_ssh<KP: SSHKey>(x: &KP, comment: &str) -> Result<String,SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
let mut pubkeybin = Vec::with_capacity(8192);
|
||||||
|
let mut privkeybin = Vec::with_capacity(8192);
|
||||||
|
let mut binary = Vec::with_capacity(16384);
|
||||||
|
|
||||||
|
// create the public key bits
|
||||||
|
x.render_ssh_public_info(&mut pubkeybin)?;
|
||||||
|
// create the private key bits
|
||||||
|
render_openssh_u32(&mut privkeybin, 0xDEADBEEF)?; // FIXME: Any reason for this to be random?
|
||||||
|
render_openssh_u32(&mut privkeybin, 0xDEADBEEF)?; // ditto
|
||||||
|
x.render_ssh_private_info(&mut privkeybin)?;
|
||||||
|
render_openssh_string(&mut privkeybin, comment)?;
|
||||||
|
// add some padding (not quite sure why)
|
||||||
|
let mut i = comment.len();
|
||||||
|
while (i % 16) != 0 {
|
||||||
|
privkeybin.write(&[(i - comment.len() + 1) as u8])?;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
// render a bunch of the framing stuff
|
||||||
|
render_openssh_header(&mut binary)?;
|
||||||
|
render_openssh_string(&mut binary, "none")?; // ciphername
|
||||||
|
render_openssh_string(&mut binary, "none")?; // kdfname
|
||||||
|
render_openssh_buffer(&mut binary, &[])?; // kdfoptions
|
||||||
|
render_openssh_u32(&mut binary, 1)?; // numkeys
|
||||||
|
render_openssh_buffer(&mut binary, &pubkeybin)?;
|
||||||
|
render_openssh_buffer(&mut binary, &privkeybin)?;
|
||||||
|
Ok(render_ssh_private_key_data(&binary))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encode a supported key into the given file, with the given comment.
|
||||||
|
pub fn write_ssh_keyfile<KP,P>(path: P, x: &KP, comment: &str) -> Result<(),SSHKeyRenderError>
|
||||||
|
where
|
||||||
|
KP: SSHKey,
|
||||||
|
P: AsRef<Path>
|
||||||
|
{
|
||||||
|
let mut file = File::create(path)?;
|
||||||
|
let contents = encode_ssh(x, comment)?;
|
||||||
|
let bytes = contents.into_bytes();
|
||||||
|
file.write_all(&bytes)?;
|
||||||
|
file.sync_all()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use dsa::{DSAKeyPair,DSAPublicKey,L1024N160};
|
||||||
|
#[cfg(test)]
|
||||||
|
use ecdsa::ECDSAPair;
|
||||||
|
#[cfg(test)]
|
||||||
|
use ed25519::ED25519KeyPair;
|
||||||
|
#[cfg(test)]
|
||||||
|
use rsa::{RSAPair,RSAPublic,SIGNING_HASH_SHA256};
|
||||||
|
#[cfg(test)]
|
||||||
|
use sha::SHA256;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn dsa_examples() {
|
||||||
|
let test_files = ["dsa1024-1", "dsa1024-2", "dsa1024-3"];
|
||||||
|
|
||||||
|
for file in test_files.iter() {
|
||||||
|
let path = format!("testdata/ssh/{}",file);
|
||||||
|
let mkeypair = load_ssh_keyfile(path);
|
||||||
|
match mkeypair {
|
||||||
|
Err(e) => assert!(false, format!("reading error: {:?}", e)),
|
||||||
|
Ok((keypair, comment)) => {
|
||||||
|
let buffer = [0,1,2,3,4,6,2];
|
||||||
|
let _ : DSAKeyPair<L1024N160> = keypair;
|
||||||
|
let sig = keypair.private.sign::<SHA256>(&buffer);
|
||||||
|
assert!(keypair.public.verify::<SHA256>(&buffer, &sig));
|
||||||
|
let buffer2 = [0,1,2,3,4,6,5];
|
||||||
|
assert!(!keypair.public.verify::<SHA256>(&buffer2, &sig));
|
||||||
|
match encode_ssh(&keypair, &comment) {
|
||||||
|
Err(e2) => assert!(false, format!("render error: {:?}", e2)),
|
||||||
|
Ok(encodedstr) => {
|
||||||
|
match decode_ssh(&encodedstr) {
|
||||||
|
Err(e3) => assert!(false, format!("reparse error: {:?}", e3)),
|
||||||
|
Ok((keypair2,comment2)) => {
|
||||||
|
let _ : DSAKeyPair<L1024N160> = keypair2;
|
||||||
|
assert_eq!(keypair.public.params.p,keypair2.public.params.p,"failed to reparse key pair (p)");
|
||||||
|
assert_eq!(keypair.public.params.q,keypair2.public.params.q,"failed to reparse key pair (q)");
|
||||||
|
assert_eq!(keypair.public.params.g,keypair2.public.params.g,"failed to reparse key pair (g)");
|
||||||
|
assert_eq!(keypair.private.params.p,keypair2.private.params.p,"failed to reparse key pair (p)");
|
||||||
|
assert_eq!(keypair.private.params.q,keypair2.private.params.q,"failed to reparse key pair (q)");
|
||||||
|
assert_eq!(keypair.private.params.g,keypair2.private.params.g,"failed to reparse key pair (g)");
|
||||||
|
assert_eq!(keypair.public.y,keypair2.public.y,"failed to reparse key pair (y)");
|
||||||
|
assert_eq!(keypair.private.x,keypair2.private.x,"failed to reparse key pair (x)");
|
||||||
|
assert_eq!(comment,comment2,"failed to reparse comment");
|
||||||
|
let ppath = format!("testdata/ssh/{}.pub",file);
|
||||||
|
match load_ssh_pubkeys::<DSAKeyPair<L1024N160>,String>(ppath) {
|
||||||
|
Err(e4) => assert!(false, format!("pubkey error: {:?}", e4)),
|
||||||
|
Ok(pubkeys) => {
|
||||||
|
let _ : Vec<(DSAPublicKey<L1024N160>,String)> = pubkeys;
|
||||||
|
for (pubkey, comment3) in pubkeys {
|
||||||
|
assert_eq!(pubkey.params.p, keypair.public.params.p, "public key check (p)");
|
||||||
|
assert_eq!(pubkey.params.q, keypair.public.params.q, "public key check (q)");
|
||||||
|
assert_eq!(pubkey.params.g, keypair.public.params.g, "public key check (g)");
|
||||||
|
assert_eq!(pubkey.y, keypair.public.y, "public key check (y)");
|
||||||
|
assert_eq!(comment, comment3, "public key check comment")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn rsa_examples() {
|
||||||
|
let test_files = ["rsa1024-1", "rsa1024-2", "rsa1024-3",
|
||||||
|
"rsa2048-1", "rsa2048-2", "rsa2048-3",
|
||||||
|
"rsa3072-1", "rsa3072-2", "rsa3072-3",
|
||||||
|
"rsa4096-1", "rsa4096-2", "rsa4096-3",
|
||||||
|
"rsa8192-1", "rsa8192-2", "rsa8192-3"];
|
||||||
|
|
||||||
|
for file in test_files.iter() {
|
||||||
|
let path = format!("testdata/ssh/{}",file);
|
||||||
|
let mkeypair = load_ssh_keyfile::<RSAPair,String>(path);
|
||||||
|
match mkeypair {
|
||||||
|
Err(e) => assert!(false, format!("reading error: {:?}", e)),
|
||||||
|
Ok((keypair, comment)) => {
|
||||||
|
let buffer = [0,1,2,3,4,6,2];
|
||||||
|
let sig = keypair.sign(&SIGNING_HASH_SHA256, &buffer);
|
||||||
|
assert!(keypair.verify(&SIGNING_HASH_SHA256, &buffer, &sig));
|
||||||
|
match encode_ssh(&keypair, &comment) {
|
||||||
|
Err(e2) => assert!(false, format!("render error: {:?}", e2)),
|
||||||
|
Ok(encodedstr) => {
|
||||||
|
match decode_ssh(&encodedstr) {
|
||||||
|
Err(e3) => assert!(false, format!("reparse error: {:?}", e3)),
|
||||||
|
Ok((keypair2,comment2)) => {
|
||||||
|
assert_eq!(keypair,keypair2,"failed to reparse key pair");
|
||||||
|
assert_eq!(comment,comment2,"failed to reparse comment");
|
||||||
|
let ppath = format!("testdata/ssh/{}.pub",file);
|
||||||
|
match load_ssh_pubkeys::<RSAPair,String>(ppath) {
|
||||||
|
Err(e4) => assert!(false, format!("pubkey error: {:?}", e4)),
|
||||||
|
Ok(pubkeys) => {
|
||||||
|
let _ : Vec<(RSAPublic,String)> = pubkeys;
|
||||||
|
for (pubkey, comment3) in pubkeys {
|
||||||
|
assert_eq!(pubkey, keypair.public(), "public key check");
|
||||||
|
assert_eq!(comment, comment3, "public key check comment");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn ecdsa_examples() {
|
||||||
|
let test_files = ["ecdsa256-1", "ecdsa256-2", "ecdsa256-3",
|
||||||
|
"ecdsa384-1", "ecdsa384-2", "ecdsa384-3",
|
||||||
|
"ecdsa521-1", "ecdsa521-2", "ecdsa521-3"];
|
||||||
|
|
||||||
|
for file in test_files.iter() {
|
||||||
|
let path = format!("testdata/ssh/{}",file);
|
||||||
|
match load_ssh_keyfile::<ECDSAPair,String>(path) {
|
||||||
|
Err(e) =>
|
||||||
|
assert!(false, "SSH ECDSA parse error: {:?}", e),
|
||||||
|
Ok((keypair,comment)) => {
|
||||||
|
// first see if this roundtrips
|
||||||
|
let buffer = vec![0,1,2,4,5,6,9];
|
||||||
|
match keypair {
|
||||||
|
ECDSAPair::P192(_,_) =>
|
||||||
|
assert!(false, "Somehow got a P192 in read test"),
|
||||||
|
ECDSAPair::P224(_,_) =>
|
||||||
|
assert!(false, "Somehow got a P224 in read test"),
|
||||||
|
ECDSAPair::P256(ref pu, ref pr) => {
|
||||||
|
let sig = pr.sign::<SHA256>(&buffer);
|
||||||
|
assert!(pu.verify::<SHA256>(&buffer, &sig));
|
||||||
|
}
|
||||||
|
ECDSAPair::P384(ref pu, ref pr) => {
|
||||||
|
let sig = pr.sign::<SHA256>(&buffer);
|
||||||
|
assert!(pu.verify::<SHA256>(&buffer, &sig));
|
||||||
|
}
|
||||||
|
ECDSAPair::P521(ref pu, ref pr) => {
|
||||||
|
let sig = pr.sign::<SHA256>(&buffer);
|
||||||
|
assert!(pu.verify::<SHA256>(&buffer, &sig));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// encode this, parse it again
|
||||||
|
match encode_ssh(&keypair, &comment) {
|
||||||
|
Err(e) =>
|
||||||
|
assert!(false, "SSH ECDSA encoding error: {:?}", e),
|
||||||
|
Ok(coded) => {
|
||||||
|
match (decode_ssh(&coded), keypair) {
|
||||||
|
(Err(e), _) =>
|
||||||
|
assert!(false, "SSSH ECDSA redecoding error: {:?}", e),
|
||||||
|
(Ok((ECDSAPair::P256(pu2, pr2), comment2)), ECDSAPair::P256(pu,pr)) => {
|
||||||
|
assert_eq!(pu, pu2, "public key mismatch");
|
||||||
|
assert_eq!(pr, pr2, "public key mismatch");
|
||||||
|
assert_eq!(comment, comment2, "comment mismatch");
|
||||||
|
}
|
||||||
|
(Ok((ECDSAPair::P384(pu2, pr2), comment2)), ECDSAPair::P384(pu,pr)) => {
|
||||||
|
assert_eq!(pu, pu2, "public key mismatch");
|
||||||
|
assert_eq!(pr, pr2, "public key mismatch");
|
||||||
|
assert_eq!(comment, comment2, "comment mismatch");
|
||||||
|
}
|
||||||
|
(Ok((ECDSAPair::P521(pu2, pr2), comment2)), ECDSAPair::P521(pu,pr)) => {
|
||||||
|
assert_eq!(pu, pu2, "public key mismatch");
|
||||||
|
assert_eq!(pr, pr2, "public key mismatch");
|
||||||
|
assert_eq!(comment, comment2, "comment mismatch");
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
assert!(false, "Failed to accurately re-parse key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn ed25519_examples() {
|
||||||
|
let test_files = ["ed25519-1", "ed25519-2", "ed25519-3"];
|
||||||
|
|
||||||
|
for file in test_files.iter() {
|
||||||
|
let path = format!("testdata/ssh/{}",file);
|
||||||
|
match load_ssh_keyfile::<ED25519KeyPair,String>(path) {
|
||||||
|
Err(e) =>
|
||||||
|
assert!(false, "SSH ED25519 parse error: {:?}", e),
|
||||||
|
Ok((keypair,comment)) => {
|
||||||
|
// first see if this roundtrips
|
||||||
|
let buffer = vec![0,1,2,4,5,6,9];
|
||||||
|
let sig = keypair.private.sign(&buffer);
|
||||||
|
assert!(keypair.public.verify(&buffer, &sig));
|
||||||
|
match encode_ssh(&keypair, &comment) {
|
||||||
|
Err(e) =>
|
||||||
|
assert!(false, "SSH ED25519 encoding error: {:?}", e),
|
||||||
|
Ok(coded) => {
|
||||||
|
match decode_ssh(&coded) {
|
||||||
|
Err(e) =>
|
||||||
|
assert!(false, "SSSH ECDSA redecoding error: {:?}", e),
|
||||||
|
Ok((keypair2, comment2)) => {
|
||||||
|
let _ : ED25519KeyPair = keypair2;
|
||||||
|
assert_eq!(keypair.public, keypair2.public, "public key mismatch");
|
||||||
|
assert_eq!(keypair.private, keypair2.private, "public key mismatch");
|
||||||
|
assert_eq!(comment, comment2, "comment mismatch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
201
src/ssh/rsa.rs
Normal file
201
src/ssh/rsa.rs
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use rsa::{RSAPair,RSAPublic,RSAPublicKey,RSAPrivate,RSAPrivateKey};
|
||||||
|
use std::io::{Read,Write};
|
||||||
|
use ssh::errors::{SSHKeyParseError,SSHKeyRenderError};
|
||||||
|
use ssh::frame::*;
|
||||||
|
use ssh::SSHKey;
|
||||||
|
|
||||||
|
impl SSHKey for RSAPair {
|
||||||
|
fn valid_keytype(s: &str) -> bool {
|
||||||
|
(s == "ssh-rsa") || (s == "rsa")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ssh_public_info<I: Read>(inp: &mut I) -> Result<Self::Public,SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let pubkey_type = parse_openssh_string(inp)?;
|
||||||
|
if !Self::valid_keytype(&pubkey_type) {
|
||||||
|
return Err(SSHKeyParseError::UnknownKeyType(pubkey_type));
|
||||||
|
}
|
||||||
|
// this peaks a little under the cover a bit (it'd be nice to pretend
|
||||||
|
// that we didn't know the number format was the same as the buffer
|
||||||
|
// one), but we need to infer what kind of key this is, and this appears
|
||||||
|
// to be the easiest / fastest way.
|
||||||
|
let mut ebuf = parse_openssh_buffer(inp)?;
|
||||||
|
let mut nbuf = parse_openssh_buffer(inp)?;
|
||||||
|
|
||||||
|
while ebuf[0] == 0 { ebuf.remove(0); }
|
||||||
|
while nbuf[0] == 0 { nbuf.remove(0); }
|
||||||
|
|
||||||
|
if nbuf.len() > (8192 / 8) {
|
||||||
|
let e = U15360::from_bytes(&ebuf);
|
||||||
|
let n = U15360::from_bytes(&nbuf);
|
||||||
|
Ok(RSAPublic::Key15360(RSAPublicKey::<U15360>::new(n, e)))
|
||||||
|
} else if nbuf.len() > (4096 / 8) {
|
||||||
|
let e = U8192::from_bytes(&ebuf);
|
||||||
|
let n = U8192::from_bytes(&nbuf);
|
||||||
|
Ok(RSAPublic::Key8192(RSAPublicKey::<U8192>::new(n, e)))
|
||||||
|
} else if nbuf.len() > (3072 / 8) {
|
||||||
|
let e = U4096::from_bytes(&ebuf);
|
||||||
|
let n = U4096::from_bytes(&nbuf);
|
||||||
|
Ok(RSAPublic::Key4096(RSAPublicKey::<U4096>::new(n, e)))
|
||||||
|
} else if nbuf.len() > (2048 / 8) {
|
||||||
|
let e = U3072::from_bytes(&ebuf);
|
||||||
|
let n = U3072::from_bytes(&nbuf);
|
||||||
|
Ok(RSAPublic::Key3072(RSAPublicKey::<U3072>::new(n, e)))
|
||||||
|
} else if nbuf.len() > (1024 / 8) {
|
||||||
|
let e = U2048::from_bytes(&ebuf);
|
||||||
|
let n = U2048::from_bytes(&nbuf);
|
||||||
|
Ok(RSAPublic::Key2048(RSAPublicKey::<U2048>::new(n, e)))
|
||||||
|
} else if nbuf.len() > (512 / 8) {
|
||||||
|
let e = U1024::from_bytes(&ebuf);
|
||||||
|
let n = U1024::from_bytes(&nbuf);
|
||||||
|
Ok(RSAPublic::Key1024(RSAPublicKey::<U1024>::new(n, e)))
|
||||||
|
} else {
|
||||||
|
let e = U512::from_bytes(&ebuf);
|
||||||
|
let n = U512::from_bytes(&nbuf);
|
||||||
|
Ok(RSAPublic::Key512(RSAPublicKey::<U512>::new(n, e)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ssh_private_info<I: Read>(inp: &mut I) -> Result<(Self::Private,String),SSHKeyParseError>
|
||||||
|
{
|
||||||
|
let check1 = parse_openssh_u32(inp)?;
|
||||||
|
let check2 = parse_openssh_u32(inp)?;
|
||||||
|
if check1 != check2 {
|
||||||
|
return Err(SSHKeyParseError::PrivateKeyCorruption);
|
||||||
|
}
|
||||||
|
let privkey_type = parse_openssh_string(inp)?;
|
||||||
|
if !Self::valid_keytype(&privkey_type) {
|
||||||
|
return Err(SSHKeyParseError::InconsistentKeyTypes("ssh-rsa".to_string(), privkey_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
// See the comment in the public key section.
|
||||||
|
let mut nbuf = parse_openssh_buffer(inp)?;
|
||||||
|
let _ebuf = parse_openssh_buffer(inp)?;
|
||||||
|
let mut dbuf = parse_openssh_buffer(inp)?;
|
||||||
|
let _iqmp = parse_openssh_buffer(inp)?;
|
||||||
|
let _pbuf = parse_openssh_buffer(inp)?;
|
||||||
|
let _qbuf = parse_openssh_buffer(inp)?;
|
||||||
|
let comment = parse_openssh_string(inp)?;
|
||||||
|
for (idx,byte) in inp.bytes().enumerate() {
|
||||||
|
if ((idx+1) as u8) != byte? {
|
||||||
|
return Err(SSHKeyParseError::InvalidPadding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while dbuf[0] == 0 { dbuf.remove(0); }
|
||||||
|
while nbuf[0] == 0 { nbuf.remove(0); }
|
||||||
|
|
||||||
|
if nbuf.len() > (8192 / 8) {
|
||||||
|
let d = U15360::from_bytes(&dbuf);
|
||||||
|
let n = U15360::from_bytes(&nbuf);
|
||||||
|
Ok((RSAPrivate::Key15360(RSAPrivateKey::<U15360>::new(n, d)), comment))
|
||||||
|
} else if nbuf.len() > (4096 / 8) {
|
||||||
|
let d = U8192::from_bytes(&dbuf);
|
||||||
|
let n = U8192::from_bytes(&nbuf);
|
||||||
|
Ok((RSAPrivate::Key8192(RSAPrivateKey::<U8192>::new(n, d)), comment))
|
||||||
|
} else if nbuf.len() > (3072 / 8) {
|
||||||
|
let d = U4096::from_bytes(&dbuf);
|
||||||
|
let n = U4096::from_bytes(&nbuf);
|
||||||
|
Ok((RSAPrivate::Key4096(RSAPrivateKey::<U4096>::new(n, d)), comment))
|
||||||
|
} else if nbuf.len() > (2048 / 8) {
|
||||||
|
let d = U3072::from_bytes(&dbuf);
|
||||||
|
let n = U3072::from_bytes(&nbuf);
|
||||||
|
Ok((RSAPrivate::Key3072(RSAPrivateKey::<U3072>::new(n, d)), comment))
|
||||||
|
} else if nbuf.len() > (1024 / 8) {
|
||||||
|
let d = U2048::from_bytes(&dbuf);
|
||||||
|
let n = U2048::from_bytes(&nbuf);
|
||||||
|
Ok((RSAPrivate::Key2048(RSAPrivateKey::<U2048>::new(n, d)), comment))
|
||||||
|
} else if nbuf.len() > (512 / 8) {
|
||||||
|
let d = U1024::from_bytes(&dbuf);
|
||||||
|
let n = U1024::from_bytes(&nbuf);
|
||||||
|
Ok((RSAPrivate::Key1024(RSAPrivateKey::<U1024>::new(n, d)), comment))
|
||||||
|
} else {
|
||||||
|
let d = U512::from_bytes(&dbuf);
|
||||||
|
let n = U512::from_bytes(&nbuf);
|
||||||
|
Ok((RSAPrivate::Key512(RSAPrivateKey::<U512>::new(n, d)), comment))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ssh_public_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
render_openssh_string(out, "ssh-rsa")?;
|
||||||
|
match self {
|
||||||
|
RSAPair::R512(pbl,_) => {
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
}
|
||||||
|
RSAPair::R1024(pbl,_) => {
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
}
|
||||||
|
RSAPair::R2048(pbl,_) => {
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
}
|
||||||
|
RSAPair::R3072(pbl,_) => {
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
}
|
||||||
|
RSAPair::R4096(pbl,_) => {
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
}
|
||||||
|
RSAPair::R8192(pbl,_) => {
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
}
|
||||||
|
RSAPair::R15360(pbl,_) => {
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_ssh_private_info<O: Write>(&self, out: &mut O) -> Result<(),SSHKeyRenderError>
|
||||||
|
{
|
||||||
|
render_openssh_string(out, "ssh-rsa")?;
|
||||||
|
match self {
|
||||||
|
RSAPair::R512(pbl,prv) => {
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &prv.d)?;
|
||||||
|
}
|
||||||
|
RSAPair::R1024(pbl,prv) => {
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &prv.d)?;
|
||||||
|
}
|
||||||
|
RSAPair::R2048(pbl,prv) => {
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &prv.d)?;
|
||||||
|
}
|
||||||
|
RSAPair::R3072(pbl,prv) => {
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &prv.d)?;
|
||||||
|
}
|
||||||
|
RSAPair::R4096(pbl,prv) => {
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &prv.d)?;
|
||||||
|
}
|
||||||
|
RSAPair::R8192(pbl,prv) => {
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &prv.d)?;
|
||||||
|
}
|
||||||
|
RSAPair::R15360(pbl,prv) => {
|
||||||
|
render_openssh_number(out, &pbl.n)?;
|
||||||
|
render_openssh_number(out, &pbl.e)?;
|
||||||
|
render_openssh_number(out, &prv.d)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* iqmp */ render_openssh_buffer(out, &vec![])?;
|
||||||
|
/* p */ render_openssh_buffer(out, &vec![])?;
|
||||||
|
/* q */ render_openssh_buffer(out, &vec![])?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/testing.rs
Normal file
67
src/testing.rs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::str::Lines;
|
||||||
|
|
||||||
|
pub fn build_test_path(dir: &str, typename: &str) -> String
|
||||||
|
{
|
||||||
|
format!("testdata/{}/{}.test", dir, typename)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_value_set(line: &str) -> (String, bool, Vec<u8>)
|
||||||
|
{
|
||||||
|
assert!(line.is_ascii());
|
||||||
|
let mut items = line.split(": ");
|
||||||
|
let key = items.next().unwrap();
|
||||||
|
let valbits = items.next().unwrap();
|
||||||
|
let neg = valbits.contains('-');
|
||||||
|
let valbitsnoneg = valbits.trim_start_matches("-");
|
||||||
|
|
||||||
|
let mut nibble_iter = valbitsnoneg.chars().rev();
|
||||||
|
let mut val = Vec::new();
|
||||||
|
|
||||||
|
while let Some(c1) = nibble_iter.next() {
|
||||||
|
match nibble_iter.next() {
|
||||||
|
None => {
|
||||||
|
val.push( c1.to_digit(16).expect(&format!("Unexpected character: |{}|", c1)) as u8 );
|
||||||
|
}
|
||||||
|
Some(c2) => {
|
||||||
|
let b1 = c1.to_digit(16).expect(&format!("Unexpected character: |{}|", c1)) as u8;
|
||||||
|
let b2 = c2.to_digit(16).expect(&format!("Unexpected character: |{}|", c2)) as u8;
|
||||||
|
val.push( (b2 << 4) | b1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val.reverse();
|
||||||
|
|
||||||
|
(key.to_string(), neg, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_test_case(contents: &mut Lines, lines: usize) ->
|
||||||
|
Option<HashMap<String,(bool,Vec<u8>)>>
|
||||||
|
{
|
||||||
|
let mut res = HashMap::new();
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
|
while count < lines {
|
||||||
|
let line = contents.next()?;
|
||||||
|
let (key, neg, val) = next_value_set(line);
|
||||||
|
res.insert(key, (neg,val));
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_test<F>(fname: String, i: usize, f: F)
|
||||||
|
where F: Fn(HashMap<String,(bool,Vec<u8>)>)
|
||||||
|
{
|
||||||
|
let mut file = File::open(fname).unwrap();
|
||||||
|
let mut contents = String::new();
|
||||||
|
file.read_to_string(&mut contents).unwrap();
|
||||||
|
let mut iter = contents.lines();
|
||||||
|
|
||||||
|
while let Some(scase) = next_test_case(&mut iter, i) {
|
||||||
|
f(scase);
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/utils.rs
Normal file
57
src/utils.rs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
use cryptonum::unsigned::*;
|
||||||
|
use num::{BigInt,BigUint};
|
||||||
|
use num::bigint::Sign;
|
||||||
|
|
||||||
|
pub trait TranslateNums<N>: Sized {
|
||||||
|
fn from_num(x: &N) -> Option<Self>;
|
||||||
|
fn to_num(&self) -> N;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! from_biguint {
|
||||||
|
($uname: ident, $size: expr) => {
|
||||||
|
impl TranslateNums<BigUint> for $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);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some($uname::from_bytes(&base_vec))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_num(&self) -> BigUint {
|
||||||
|
let bytes = self.to_bytes();
|
||||||
|
BigUint::from_bytes_be(&bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TranslateNums<BigInt> for $uname {
|
||||||
|
fn from_num(x: &BigInt) -> Option<$uname> {
|
||||||
|
let ux = x.to_biguint()?;
|
||||||
|
$uname::from_num(&ux)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_num(&self) -> BigInt {
|
||||||
|
BigInt::from_biguint(Sign::Plus, self.to_num())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
from_biguint!(U192, 192);
|
||||||
|
from_biguint!(U256, 256);
|
||||||
|
from_biguint!(U384, 384);
|
||||||
|
from_biguint!(U512, 512);
|
||||||
|
from_biguint!(U576, 576);
|
||||||
|
from_biguint!(U1024, 1024);
|
||||||
|
from_biguint!(U2048, 2048);
|
||||||
|
from_biguint!(U3072, 3072);
|
||||||
|
from_biguint!(U4096, 4096);
|
||||||
|
from_biguint!(U8192, 8192);
|
||||||
|
from_biguint!(U15360, 15360);
|
||||||
393
src/x509/algident.rs
Normal file
393
src/x509/algident.rs
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
use num::BigUint;
|
||||||
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,FromASN1,OID,ToASN1};
|
||||||
|
use x509::error::X509ParseError;
|
||||||
|
|
||||||
|
/// A supported x509 hash algorithm
|
||||||
|
#[derive(Clone,Copy,Debug,PartialEq)]
|
||||||
|
pub enum HashAlgorithm { SHA1, SHA224, SHA256, SHA384, SHA512 }
|
||||||
|
|
||||||
|
/// A supported x509 asymmetric crypto algorithm
|
||||||
|
#[derive(Clone,Copy,Debug,PartialEq)]
|
||||||
|
pub enum PublicKeyInfo { RSA, DSA, ECDSA }
|
||||||
|
|
||||||
|
/// The algorithm used, either in a certificate or as part of the signing
|
||||||
|
/// process. We only actually support a subset of the possible values,
|
||||||
|
/// here, although we try to catch them all.
|
||||||
|
///
|
||||||
|
/// Specifically, this library supports:
|
||||||
|
///
|
||||||
|
/// | | *RSA* | *DSA* | *ECDSA* |
|
||||||
|
/// |----------|-------|-------|---------|
|
||||||
|
/// | *SHA1* | X | X | X |
|
||||||
|
/// | *SHA224* | X | X | X |
|
||||||
|
/// | *SHA256* | X | X | X |
|
||||||
|
/// | *SHA384* | X | | X |
|
||||||
|
/// | *SHA512* | X | | X |
|
||||||
|
///
|
||||||
|
#[derive(Clone,Debug,PartialEq)]
|
||||||
|
pub struct AlgorithmIdentifier {
|
||||||
|
pub hash: HashAlgorithm,
|
||||||
|
pub algo: PublicKeyInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for AlgorithmIdentifier {
|
||||||
|
type Error = X509ParseError;
|
||||||
|
|
||||||
|
fn from_asn1(v: &[ASN1Block])
|
||||||
|
-> Result<(AlgorithmIdentifier,&[ASN1Block]),X509ParseError>
|
||||||
|
{
|
||||||
|
match v.split_first() {
|
||||||
|
None =>
|
||||||
|
Err(X509ParseError::NotEnoughData),
|
||||||
|
Some((x, rest)) => {
|
||||||
|
let v = decode_algorithm_ident(&x)?;
|
||||||
|
Ok((v, rest))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_algorithm_ident(x: &ASN1Block)
|
||||||
|
-> Result<AlgorithmIdentifier,X509ParseError>
|
||||||
|
{
|
||||||
|
// AlgorithmIdentifier ::= SEQUENCE {
|
||||||
|
// algorithm OBJECT IDENTIFIER,
|
||||||
|
// parameters ANY DEFINED BY algorithm OPTIONAL }
|
||||||
|
match x {
|
||||||
|
&ASN1Block::Sequence(_, _, ref v) if v.len() >= 1 => {
|
||||||
|
match v[0] {
|
||||||
|
ASN1Block::ObjectIdentifier(_, _, ref oid) => {
|
||||||
|
if oid == oid!(1,2,840,113549,1,1,5) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA1,
|
||||||
|
algo: PublicKeyInfo::RSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,113549,1,1,11) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA256,
|
||||||
|
algo: PublicKeyInfo::RSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,113549,1,1,12) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA384,
|
||||||
|
algo: PublicKeyInfo::RSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,113549,1,1,13) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA512,
|
||||||
|
algo: PublicKeyInfo::RSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,113549,1,1,14) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA224,
|
||||||
|
algo: PublicKeyInfo::RSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,10040,4,3) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA1,
|
||||||
|
algo: PublicKeyInfo::DSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,10045,4,1) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA1,
|
||||||
|
algo: PublicKeyInfo::ECDSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,10045,4,3,1) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA224,
|
||||||
|
algo: PublicKeyInfo::ECDSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,10045,4,3,2) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA256,
|
||||||
|
algo: PublicKeyInfo::ECDSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,10045,4,3,3) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA384,
|
||||||
|
algo: PublicKeyInfo::ECDSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,10045,4,3,4) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA512,
|
||||||
|
algo: PublicKeyInfo::ECDSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// if oid == oid!(2,16,840,1,101,3,4,2,1) {
|
||||||
|
// return Ok(AlgorithmIdentifier {
|
||||||
|
// hash: HashAlgorithm::SHA256,
|
||||||
|
// algo: PublicKeyInfo::RSAPSS
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// if oid == oid!(2,16,840,1,101,3,4,2,2) {
|
||||||
|
// return Ok(AlgorithmIdentifier {
|
||||||
|
// hash: HashAlgorithm::SHA384,
|
||||||
|
// algo: PublicKeyInfo::RSAPSS
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// if oid == oid!(2,16,840,1,101,3,4,2,3) {
|
||||||
|
// return Ok(AlgorithmIdentifier {
|
||||||
|
// hash: HashAlgorithm::SHA512,
|
||||||
|
// algo: PublicKeyInfo::RSAPSS
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// if oid == oid!(2,16,840,1,101,3,4,2,4) {
|
||||||
|
// return Ok(AlgorithmIdentifier {
|
||||||
|
// hash: HashAlgorithm::SHA224,
|
||||||
|
// algo: PublicKeyInfo::RSAPSS
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
if oid == oid!(2,16,840,1,101,3,4,3,1) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA224,
|
||||||
|
algo: PublicKeyInfo::DSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if oid == oid!(2,16,840,1,101,3,4,3,2) {
|
||||||
|
return Ok(AlgorithmIdentifier {
|
||||||
|
hash: HashAlgorithm::SHA256,
|
||||||
|
algo: PublicKeyInfo::DSA
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(X509ParseError::UnknownAlgorithm)
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::UnknownAlgorithm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllFormedAlgoInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub enum SigAlgEncodeError {
|
||||||
|
ASN1Error(ASN1EncodeErr),
|
||||||
|
InvalidDSAValue, InvalidHash
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ASN1EncodeErr> for SigAlgEncodeError {
|
||||||
|
fn from(e: ASN1EncodeErr) -> SigAlgEncodeError {
|
||||||
|
SigAlgEncodeError::ASN1Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl ToASN1 for AlgorithmIdentifier {
|
||||||
|
type Error = SigAlgEncodeError;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,SigAlgEncodeError>
|
||||||
|
{
|
||||||
|
let block = encode_algorithm_ident(c, self)?;
|
||||||
|
Ok(vec![block])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_algorithm_ident(c: ASN1Class, x: &AlgorithmIdentifier)
|
||||||
|
-> Result<ASN1Block,SigAlgEncodeError>
|
||||||
|
{
|
||||||
|
match x.algo {
|
||||||
|
PublicKeyInfo::RSA => {
|
||||||
|
match x.hash {
|
||||||
|
HashAlgorithm::SHA1 => {
|
||||||
|
let o = oid!(1,2,840,113549,1,1,5);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
HashAlgorithm::SHA224 => {
|
||||||
|
let o = oid!(1,2,840,113549,1,1,14);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
HashAlgorithm::SHA256 => {
|
||||||
|
let o = oid!(1,2,840,113549,1,1,11);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
HashAlgorithm::SHA384 => {
|
||||||
|
let o = oid!(1,2,840,113549,1,1,12);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
HashAlgorithm::SHA512 => {
|
||||||
|
let o = oid!(1,2,840,113549,1,1,13);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PublicKeyInfo::DSA => {
|
||||||
|
match x.hash {
|
||||||
|
HashAlgorithm::SHA1 => {
|
||||||
|
let o = oid!(1,2,840,10040,4,3);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
HashAlgorithm::SHA224 => {
|
||||||
|
let o = oid!(2,16,840,1,101,3,4,3,1);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
HashAlgorithm::SHA256 => {
|
||||||
|
let o = oid!(2,16,840,1,101,3,4,3,2);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(SigAlgEncodeError::InvalidHash),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PublicKeyInfo::ECDSA=> {
|
||||||
|
match x.hash {
|
||||||
|
HashAlgorithm::SHA1 => {
|
||||||
|
let o = oid!(1,2,840,10045,4,1);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
HashAlgorithm::SHA224 => {
|
||||||
|
let o = oid!(1,2,840,10045,4,3,1);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
HashAlgorithm::SHA256 => {
|
||||||
|
let o = oid!(1,2,840,10045,4,3,2);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
HashAlgorithm::SHA384 => {
|
||||||
|
let o = oid!(1,2,840,10045,4,3,3);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
HashAlgorithm::SHA512 => {
|
||||||
|
let o = oid!(1,2,840,10045,4,3,4);
|
||||||
|
let obj = ASN1Block::ObjectIdentifier(c, 0, o);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![obj]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use quickcheck::{Arbitrary,Gen};
|
||||||
|
use rand::prelude::SliceRandom;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const RSA1: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA1,
|
||||||
|
algo: PublicKeyInfo::RSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const RSA224: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA224,
|
||||||
|
algo: PublicKeyInfo::RSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const RSA256: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA256,
|
||||||
|
algo: PublicKeyInfo::RSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const RSA384: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA384,
|
||||||
|
algo: PublicKeyInfo::RSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const RSA512: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA512,
|
||||||
|
algo: PublicKeyInfo::RSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const DSA1: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA1,
|
||||||
|
algo: PublicKeyInfo::DSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const DSA224: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA224,
|
||||||
|
algo: PublicKeyInfo::DSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const DSA256: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA256,
|
||||||
|
algo: PublicKeyInfo::DSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const EC1: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA1,
|
||||||
|
algo: PublicKeyInfo::ECDSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const EC224: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA224,
|
||||||
|
algo: PublicKeyInfo::ECDSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const EC256: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA256,
|
||||||
|
algo: PublicKeyInfo::ECDSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const EC384: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA384,
|
||||||
|
algo: PublicKeyInfo::ECDSA
|
||||||
|
};
|
||||||
|
|
||||||
|
const EC512: AlgorithmIdentifier =
|
||||||
|
AlgorithmIdentifier{
|
||||||
|
hash: HashAlgorithm::SHA512,
|
||||||
|
algo: PublicKeyInfo::ECDSA
|
||||||
|
};
|
||||||
|
|
||||||
|
impl Arbitrary for AlgorithmIdentifier {
|
||||||
|
fn arbitrary<G: Gen>(g: &mut G) -> AlgorithmIdentifier {
|
||||||
|
let opts = [RSA1, RSA224, RSA256, RSA384, RSA512,
|
||||||
|
DSA1, DSA224, DSA256,
|
||||||
|
EC1, EC224, EC256, EC384, EC512];
|
||||||
|
opts.choose(g).unwrap().clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quickcheck!{
|
||||||
|
fn algident_roundtrips(v: AlgorithmIdentifier) -> bool {
|
||||||
|
match encode_algorithm_ident(ASN1Class::Universal, &v) {
|
||||||
|
Err(_) =>
|
||||||
|
false,
|
||||||
|
Ok(block) => {
|
||||||
|
match decode_algorithm_ident(&block) {
|
||||||
|
Err(_) =>
|
||||||
|
false,
|
||||||
|
Ok(v2) =>
|
||||||
|
v == v2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
370
src/x509/atv.rs
Normal file
370
src/x509/atv.rs
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,FromASN1,ToASN1};
|
||||||
|
use std::ops::Index;
|
||||||
|
use x509::error::X509ParseError;
|
||||||
|
pub use x509::name::X520Name;
|
||||||
|
|
||||||
|
/// All of the various bits of information that are encoded within an x.509
|
||||||
|
/// certificate.
|
||||||
|
#[derive(Clone,Debug)]
|
||||||
|
pub struct InfoBlock {
|
||||||
|
pub fields: Vec<AttributeTypeValue>
|
||||||
|
}
|
||||||
|
|
||||||
|
const EMPTY_STRING: &'static str = "";
|
||||||
|
|
||||||
|
impl Index<X520Name> for InfoBlock {
|
||||||
|
type Output = str;
|
||||||
|
|
||||||
|
fn index(&self, name: X520Name) -> &str {
|
||||||
|
for atv in self.fields.iter() {
|
||||||
|
if name == atv.attrtype {
|
||||||
|
return &atv.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&EMPTY_STRING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for InfoBlock {
|
||||||
|
fn eq(&self, other: &InfoBlock) -> bool {
|
||||||
|
for x in self.fields.iter() {
|
||||||
|
if !other.fields.contains(x) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for x in other.fields.iter() {
|
||||||
|
if !self.fields.contains(x) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_info_block(x: &ASN1Block)
|
||||||
|
-> Result<InfoBlock,X509ParseError>
|
||||||
|
{
|
||||||
|
// Name ::= CHOICE { -- only one possibility for now --
|
||||||
|
// rdnSequence RDNSequence }
|
||||||
|
//
|
||||||
|
// RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
|
||||||
|
//
|
||||||
|
// RelativeDistinguishedName ::=
|
||||||
|
// SET SIZE (1..MAX) OF AttributeTypeAndValue
|
||||||
|
match x {
|
||||||
|
&ASN1Block::Sequence(_, _, ref items) => {
|
||||||
|
let mut atvs = Vec::new();
|
||||||
|
|
||||||
|
for set in items.iter() {
|
||||||
|
match set {
|
||||||
|
&ASN1Block::Set(_, _, ref setitems) => {
|
||||||
|
for atv in setitems.iter() {
|
||||||
|
let v = decode_attribute_type_value(atv)?;
|
||||||
|
atvs.push(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
return Err(X509ParseError::IllFormedInfoBlock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(InfoBlock{ fields: atvs })
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllFormedInfoBlock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for InfoBlock {
|
||||||
|
type Error = X509ParseError;
|
||||||
|
|
||||||
|
fn from_asn1(v: &[ASN1Block])
|
||||||
|
-> Result<(InfoBlock,&[ASN1Block]),X509ParseError>
|
||||||
|
{
|
||||||
|
match v.split_first() {
|
||||||
|
None =>
|
||||||
|
Err(X509ParseError::NotEnoughData),
|
||||||
|
Some((x, rest)) => {
|
||||||
|
let v = decode_info_block(&x)?;
|
||||||
|
Ok((v, rest))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_info_block(c: ASN1Class, b: &InfoBlock)
|
||||||
|
-> Result<ASN1Block,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let mut encoded_fields = Vec::with_capacity(b.fields.len());
|
||||||
|
|
||||||
|
for fld in b.fields.iter() {
|
||||||
|
let val = encode_attribute_type_value(c, fld)?;
|
||||||
|
encoded_fields.push(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
let set = ASN1Block::Set(c, 0, encoded_fields);
|
||||||
|
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![set]))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for InfoBlock {
|
||||||
|
type Error = ASN1EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let block = encode_info_block(c, self)?;
|
||||||
|
Ok(vec![block])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An attribute within an x.509 key and its associated string value.
|
||||||
|
#[derive(Clone,Debug,PartialEq)]
|
||||||
|
pub struct AttributeTypeValue {
|
||||||
|
pub attrtype: X520Name,
|
||||||
|
pub value: String
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_attribute_type_value(x: &ASN1Block)
|
||||||
|
-> Result<AttributeTypeValue,X509ParseError>
|
||||||
|
{
|
||||||
|
// AttributeTypeAndValue ::= SEQUENCE {
|
||||||
|
// type AttributeType,
|
||||||
|
// value AttributeValue }
|
||||||
|
match x {
|
||||||
|
&ASN1Block::Sequence(_, _, ref xs) => {
|
||||||
|
let (name, rest) = X520Name::from_asn1(xs)?;
|
||||||
|
match rest.first() {
|
||||||
|
None => Err(X509ParseError::NotEnoughData),
|
||||||
|
Some(ref x) => {
|
||||||
|
let atvstr = get_atv_string(name, x)?;
|
||||||
|
Ok(AttributeTypeValue{
|
||||||
|
attrtype: name,
|
||||||
|
value: atvstr
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllFormedAttrTypeValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for AttributeTypeValue {
|
||||||
|
type Error = X509ParseError;
|
||||||
|
|
||||||
|
fn from_asn1(v: &[ASN1Block])
|
||||||
|
-> Result<(AttributeTypeValue,&[ASN1Block]),X509ParseError>
|
||||||
|
{
|
||||||
|
match v.split_first() {
|
||||||
|
None =>
|
||||||
|
Err(X509ParseError::NotEnoughData),
|
||||||
|
Some((x, rest)) => {
|
||||||
|
let v = decode_attribute_type_value(&x)?;
|
||||||
|
Ok((v, rest))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_attribute_type_value(c: ASN1Class, x: &AttributeTypeValue)
|
||||||
|
-> Result<ASN1Block,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let mut resvec = x.attrtype.to_asn1_class(c)?;
|
||||||
|
let value = match x.attrtype {
|
||||||
|
X520Name::CountryName =>
|
||||||
|
ASN1Block::PrintableString(c,0,x.value.clone()),
|
||||||
|
X520Name::SerialNumber =>
|
||||||
|
ASN1Block::PrintableString(c,0,x.value.clone()),
|
||||||
|
X520Name::DomainComponent =>
|
||||||
|
ASN1Block::IA5String(c,0,x.value.clone()),
|
||||||
|
X520Name::EmailAddress =>
|
||||||
|
ASN1Block::IA5String(c,0,x.value.clone()),
|
||||||
|
_ =>
|
||||||
|
ASN1Block::UTF8String(c,0,x.value.clone())
|
||||||
|
};
|
||||||
|
resvec.push(value);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, resvec))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for AttributeTypeValue {
|
||||||
|
type Error = ASN1EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let block = encode_attribute_type_value(c, self)?;
|
||||||
|
Ok(vec![block])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_atv_string(n: X520Name, x: &ASN1Block)
|
||||||
|
-> Result<String,X509ParseError>
|
||||||
|
{
|
||||||
|
match n {
|
||||||
|
X520Name::CountryName => {
|
||||||
|
let res = get_printable_val(x)?;
|
||||||
|
if res.len() != 2 {
|
||||||
|
return Err(X509ParseError::IllegalStringValue);
|
||||||
|
}
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
X520Name::SerialNumber => get_printable_val(x),
|
||||||
|
X520Name::DomainComponent => get_ia5_val(x),
|
||||||
|
X520Name::EmailAddress => get_ia5_val(x),
|
||||||
|
_ => get_string_val(x),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_string_val(a: &ASN1Block) -> Result<String,X509ParseError>
|
||||||
|
{
|
||||||
|
match a {
|
||||||
|
&ASN1Block::TeletexString(_,_,ref v) => Ok(v.clone()),
|
||||||
|
&ASN1Block::PrintableString(_,_,ref v) => Ok(v.clone()),
|
||||||
|
&ASN1Block::UniversalString(_,_,ref v) => Ok(v.clone()),
|
||||||
|
&ASN1Block::UTF8String(_,_,ref v) => Ok(v.clone()),
|
||||||
|
&ASN1Block::BMPString(_,_,ref v) => Ok(v.clone()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllegalStringValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_printable_val(a: &ASN1Block) -> Result<String,X509ParseError>
|
||||||
|
{
|
||||||
|
match a {
|
||||||
|
&ASN1Block::PrintableString(_,_,ref v) => Ok(v.clone()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllegalStringValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_ia5_val(a: &ASN1Block) -> Result<String,X509ParseError>
|
||||||
|
{
|
||||||
|
match a {
|
||||||
|
&ASN1Block::IA5String(_,_,ref v) => Ok(v.clone()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllegalStringValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use quickcheck::{Arbitrary,Gen};
|
||||||
|
use rand::Rng;
|
||||||
|
use rand::prelude::SliceRandom;
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
impl Arbitrary for X520Name {
|
||||||
|
fn arbitrary<G: Gen>(g: &mut G) -> X520Name {
|
||||||
|
let names = vec![X520Name::Name,
|
||||||
|
X520Name::Surname,
|
||||||
|
X520Name::GivenName,
|
||||||
|
X520Name::Initials,
|
||||||
|
X520Name::GenerationQualifier,
|
||||||
|
X520Name::CommonName,
|
||||||
|
X520Name::LocalityName,
|
||||||
|
X520Name::StateOrProvinceName,
|
||||||
|
X520Name::OrganizationName,
|
||||||
|
X520Name::OrganizationalUnit,
|
||||||
|
X520Name::Title,
|
||||||
|
X520Name::DNQualifier,
|
||||||
|
X520Name::CountryName,
|
||||||
|
X520Name::SerialNumber,
|
||||||
|
X520Name::Pseudonym,
|
||||||
|
X520Name::DomainComponent,
|
||||||
|
X520Name::EmailAddress];
|
||||||
|
names.choose(g).unwrap().clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Arbitrary for AttributeTypeValue {
|
||||||
|
fn arbitrary<G: Gen>(g: &mut G) -> AttributeTypeValue {
|
||||||
|
let name = X520Name::arbitrary(g);
|
||||||
|
let val = match name {
|
||||||
|
X520Name::CountryName => {
|
||||||
|
let mut base = gen_printable(g);
|
||||||
|
base.push('U');
|
||||||
|
base.push('S');
|
||||||
|
base.truncate(2);
|
||||||
|
base
|
||||||
|
}
|
||||||
|
X520Name::SerialNumber => gen_printable(g),
|
||||||
|
X520Name::DomainComponent => gen_ia5(g),
|
||||||
|
X520Name::EmailAddress => gen_ia5(g),
|
||||||
|
_ => gen_utf8(g)
|
||||||
|
};
|
||||||
|
AttributeTypeValue{ attrtype: name, value: val }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const PRINTABLE_CHARS: &'static str =
|
||||||
|
"ABCDEFGHIJKLMOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+,-./:=? ";
|
||||||
|
|
||||||
|
fn gen_printable<G: Gen>(g: &mut G) -> String {
|
||||||
|
let count = g.gen_range(0, 384);
|
||||||
|
let mut items = Vec::with_capacity(count);
|
||||||
|
|
||||||
|
for _ in 0..count {
|
||||||
|
let v = PRINTABLE_CHARS.as_bytes().choose(g).unwrap();
|
||||||
|
items.push(*v as char);
|
||||||
|
}
|
||||||
|
String::from_iter(items.iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_ia5<G: Gen>(g: &mut G) -> String {
|
||||||
|
let count = g.gen_range(0, 384);
|
||||||
|
let mut items = Vec::with_capacity(count);
|
||||||
|
|
||||||
|
for _ in 0..count {
|
||||||
|
items.push(g.gen::<u8>() as char);
|
||||||
|
}
|
||||||
|
String::from_iter(items.iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_utf8<G: Gen>(g: &mut G) -> String {
|
||||||
|
String::arbitrary(g)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Arbitrary for InfoBlock {
|
||||||
|
fn arbitrary<G: Gen>(g: &mut G) -> InfoBlock {
|
||||||
|
let count = g.gen_range(0,12);
|
||||||
|
let mut items = Vec::with_capacity(count);
|
||||||
|
let mut names = Vec::with_capacity(count);
|
||||||
|
|
||||||
|
while items.len() < count {
|
||||||
|
let atv = AttributeTypeValue::arbitrary(g);
|
||||||
|
if !names.contains(&atv.attrtype) {
|
||||||
|
names.push(atv.attrtype);
|
||||||
|
items.push(atv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InfoBlock{ fields: items }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quickcheck! {
|
||||||
|
fn attrtypeval_roundtrips(v: AttributeTypeValue) -> bool {
|
||||||
|
match encode_attribute_type_value(ASN1Class::Universal, &v) {
|
||||||
|
Err(_) => false,
|
||||||
|
Ok(bstr) =>
|
||||||
|
match decode_attribute_type_value(&bstr) {
|
||||||
|
Err(_) => false,
|
||||||
|
Ok(v2) => v == v2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn infoblock_roundtrips(v: InfoBlock) -> bool {
|
||||||
|
match encode_info_block(ASN1Class::Universal, &v) {
|
||||||
|
Err(_) => false,
|
||||||
|
Ok(bstr) =>
|
||||||
|
match decode_info_block(&bstr) {
|
||||||
|
Err(_) => false,
|
||||||
|
Ok(v2) => v == v2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/x509/error.rs
Normal file
53
src/x509/error.rs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
use dsa::rfc6979::DSADecodeError;
|
||||||
|
use ecdsa::ECDSADecodeErr;
|
||||||
|
use rsa::RSAError;
|
||||||
|
use simple_asn1::{ASN1DecodeErr,ASN1EncodeErr};
|
||||||
|
|
||||||
|
/// The error type for parsing and validating an X.509 certificate.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum X509ParseError {
|
||||||
|
ASN1DecodeError(ASN1DecodeErr), ASN1EncodeError(ASN1EncodeErr),
|
||||||
|
RSAError(RSAError), DSADecodeError(DSADecodeError), ECDSADecodeError(ECDSADecodeErr),
|
||||||
|
RSASignatureWrong, DSASignatureWrong,
|
||||||
|
NotEnoughData,
|
||||||
|
IllFormedName, IllFormedAttrTypeValue, IllFormedInfoBlock,
|
||||||
|
IllFormedValidity, IllFormedCertificateInfo, IllFormedSerialNumber,
|
||||||
|
IllFormedAlgoInfo, IllFormedKey, IllFormedEverything,
|
||||||
|
IllegalStringValue, NoSerialNumber, InvalidDSAInfo, ItemNotFound,
|
||||||
|
UnknownAlgorithm, InvalidRSAKey, InvalidDSAKey, InvalidSignatureData,
|
||||||
|
InvalidSignatureHash, InvalidECDSAKey, InvalidPointForm,
|
||||||
|
UnknownEllipticCurve,
|
||||||
|
CompressedPointUnsupported,
|
||||||
|
KeyNotFound,
|
||||||
|
SignatureNotFound, SignatureVerificationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ASN1DecodeErr> for X509ParseError {
|
||||||
|
fn from(e: ASN1DecodeErr) -> X509ParseError {
|
||||||
|
X509ParseError::ASN1DecodeError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ASN1EncodeErr> for X509ParseError {
|
||||||
|
fn from(e: ASN1EncodeErr) -> X509ParseError {
|
||||||
|
X509ParseError::ASN1EncodeError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RSAError> for X509ParseError {
|
||||||
|
fn from(e: RSAError) -> X509ParseError {
|
||||||
|
X509ParseError::RSAError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ECDSADecodeErr> for X509ParseError {
|
||||||
|
fn from(e: ECDSADecodeErr) -> X509ParseError {
|
||||||
|
X509ParseError::ECDSADecodeError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DSADecodeError> for X509ParseError {
|
||||||
|
fn from(e: DSADecodeError) -> X509ParseError {
|
||||||
|
X509ParseError::DSADecodeError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
197
src/x509/misc.rs
Normal file
197
src/x509/misc.rs
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
use num::{BigInt,BigUint,One,ToPrimitive,Zero};
|
||||||
|
use num::bigint::ToBigInt;
|
||||||
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,FromASN1,ToASN1};
|
||||||
|
use x509::error::X509ParseError;
|
||||||
|
|
||||||
|
/// Which version of x.509 certificate this is.
|
||||||
|
#[derive(Clone,Copy,Debug,PartialEq)]
|
||||||
|
pub enum X509Version { V1, V2, V3 }
|
||||||
|
|
||||||
|
fn decode_version(bs: &[ASN1Block])
|
||||||
|
-> Result<(X509Version,&[ASN1Block]),X509ParseError>
|
||||||
|
{
|
||||||
|
match bs.split_first() {
|
||||||
|
Some((&ASN1Block::Integer(_, _, ref v), rest)) => {
|
||||||
|
match v.to_u8() {
|
||||||
|
Some(0) => Ok((X509Version::V1, rest)),
|
||||||
|
Some(1) => Ok((X509Version::V2, rest)),
|
||||||
|
Some(2) => Ok((X509Version::V3, rest)),
|
||||||
|
_ => Ok((X509Version::V1, &bs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::NotEnoughData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for X509Version {
|
||||||
|
type Error = X509ParseError;
|
||||||
|
|
||||||
|
fn from_asn1(v: &[ASN1Block])
|
||||||
|
-> Result<(X509Version,&[ASN1Block]),X509ParseError>
|
||||||
|
{
|
||||||
|
decode_version(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_version(c: ASN1Class, v: X509Version) -> Vec<ASN1Block> {
|
||||||
|
match v {
|
||||||
|
X509Version::V1 => {
|
||||||
|
let zero: BigInt = Zero::zero();
|
||||||
|
let block = ASN1Block::Integer(c, 0, zero);
|
||||||
|
vec![block]
|
||||||
|
}
|
||||||
|
X509Version::V2 => {
|
||||||
|
let one: BigInt = One::one();
|
||||||
|
let block = ASN1Block::Integer(c, 0, one);
|
||||||
|
vec![block]
|
||||||
|
}
|
||||||
|
X509Version::V3 => {
|
||||||
|
let two: BigInt = BigInt::from(2 as u64);
|
||||||
|
let block = ASN1Block::Integer(c, 0, two);
|
||||||
|
vec![block]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for X509Version {
|
||||||
|
type Error = ASN1EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
Ok(encode_version(c, *self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/// The serial number for this certificate.
|
||||||
|
#[derive(Clone,Debug,PartialEq)]
|
||||||
|
pub struct X509Serial {
|
||||||
|
num: BigUint
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_serial(x: &ASN1Block)
|
||||||
|
-> Result<X509Serial,X509ParseError>
|
||||||
|
{
|
||||||
|
match x {
|
||||||
|
&ASN1Block::Integer(_, _, ref v) => {
|
||||||
|
match v.to_biguint() {
|
||||||
|
None =>
|
||||||
|
Err(X509ParseError::IllFormedSerialNumber),
|
||||||
|
Some(n) =>
|
||||||
|
Ok(X509Serial{ num: n })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::NoSerialNumber)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for X509Serial {
|
||||||
|
type Error = X509ParseError;
|
||||||
|
|
||||||
|
fn from_asn1(v: &[ASN1Block])
|
||||||
|
-> Result<(X509Serial,&[ASN1Block]),X509ParseError>
|
||||||
|
{
|
||||||
|
match v.split_first() {
|
||||||
|
None =>
|
||||||
|
Err(X509ParseError::NoSerialNumber),
|
||||||
|
Some((x, rest)) => {
|
||||||
|
let v = decode_serial(x)?;
|
||||||
|
Ok((v, rest))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum SerialEncodeErr { ASN1Error(ASN1EncodeErr), InvalidSerialNumber }
|
||||||
|
|
||||||
|
impl From<ASN1EncodeErr> for SerialEncodeErr {
|
||||||
|
fn from(e: ASN1EncodeErr) -> SerialEncodeErr {
|
||||||
|
SerialEncodeErr::ASN1Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_serial(c: ASN1Class, serial: &X509Serial)
|
||||||
|
-> Result<ASN1Block,SerialEncodeErr>
|
||||||
|
{
|
||||||
|
match serial.num.to_bigint() {
|
||||||
|
None =>
|
||||||
|
Err(SerialEncodeErr::InvalidSerialNumber),
|
||||||
|
Some(n) =>
|
||||||
|
Ok(ASN1Block::Integer(c, 0, n))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for X509Serial {
|
||||||
|
type Error = SerialEncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,SerialEncodeErr>
|
||||||
|
{
|
||||||
|
let v = encode_serial(c, self)?;
|
||||||
|
Ok(vec![v])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_signature(x: &ASN1Block)
|
||||||
|
-> Result<Vec<u8>,X509ParseError>
|
||||||
|
{
|
||||||
|
match x {
|
||||||
|
&ASN1Block::BitString(_, _, size, ref sig) if size % 8 == 0 => {
|
||||||
|
Ok(sig.to_vec())
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::SignatureNotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use quickcheck::{Arbitrary,Gen};
|
||||||
|
use rand::Rng;
|
||||||
|
use rand::distributions::Uniform;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn check_version_roundtrip(v: X509Version) {
|
||||||
|
let blocks = encode_version(ASN1Class::Universal, v);
|
||||||
|
match decode_version(&blocks) {
|
||||||
|
Err(_) =>
|
||||||
|
assert!(false),
|
||||||
|
Ok((v2,_)) =>
|
||||||
|
assert_eq!(v, v2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn versions_roundtrip() {
|
||||||
|
check_version_roundtrip(X509Version::V1);
|
||||||
|
check_version_roundtrip(X509Version::V2);
|
||||||
|
check_version_roundtrip(X509Version::V3);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Arbitrary for X509Serial {
|
||||||
|
fn arbitrary<G: Gen>(g: &mut G) -> X509Serial {
|
||||||
|
let count = g.gen_range(0,16);
|
||||||
|
let dist = Uniform::new_inclusive(0,255);
|
||||||
|
let bits = g.sample_iter(&dist).take(count).collect();
|
||||||
|
let val = BigUint::new(bits);
|
||||||
|
X509Serial{ num: val }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quickcheck! {
|
||||||
|
fn serial_roundtrips(s: X509Serial) -> bool {
|
||||||
|
match encode_serial(ASN1Class::Universal, &s) {
|
||||||
|
Err(_) => false,
|
||||||
|
Ok(block) =>
|
||||||
|
match decode_serial(&block) {
|
||||||
|
Err(_) => false,
|
||||||
|
Ok(s2) => s == s2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
295
src/x509/mod.rs
Normal file
295
src/x509/mod.rs
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
mod algident;
|
||||||
|
mod atv;
|
||||||
|
mod error;
|
||||||
|
mod misc;
|
||||||
|
mod name;
|
||||||
|
mod publickey;
|
||||||
|
mod validity;
|
||||||
|
|
||||||
|
use dsa::DSAPublic;
|
||||||
|
use ecdsa::ECDSAPublic;
|
||||||
|
use rsa::{SIGNING_HASH_SHA1,SIGNING_HASH_SHA224,SIGNING_HASH_SHA256,SIGNING_HASH_SHA384,SIGNING_HASH_SHA512};
|
||||||
|
use sha::{SHA1,SHA224,SHA256,SHA384,SHA512};
|
||||||
|
use simple_asn1::{ASN1Block,FromASN1,der_decode,from_der};
|
||||||
|
pub use x509::validity::Validity;
|
||||||
|
pub use x509::algident::{AlgorithmIdentifier,HashAlgorithm,PublicKeyInfo};
|
||||||
|
use x509::algident::{decode_algorithm_ident};
|
||||||
|
pub use x509::atv::InfoBlock;
|
||||||
|
use x509::error::X509ParseError;
|
||||||
|
pub use x509::misc::{X509Serial,X509Version};
|
||||||
|
use x509::misc::{decode_signature};
|
||||||
|
pub use x509::publickey::X509PublicKey;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* The actual certificate data type and methods
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/// The type of an X.509 certificate.
|
||||||
|
pub struct GenericCertificate {
|
||||||
|
pub version: X509Version,
|
||||||
|
pub serial: X509Serial,
|
||||||
|
pub signature_alg: AlgorithmIdentifier,
|
||||||
|
pub issuer: InfoBlock,
|
||||||
|
pub subject: InfoBlock,
|
||||||
|
pub validity: Validity,
|
||||||
|
pub subject_key: X509PublicKey,
|
||||||
|
pub extensions: Vec<()>
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_certificate(x: &ASN1Block)
|
||||||
|
-> Result<GenericCertificate,X509ParseError>
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// TBSCertificate ::= SEQUENCE {
|
||||||
|
// version [0] Version DEFAULT v1,
|
||||||
|
// serialNumber CertificateSerialNumber,
|
||||||
|
// signature AlgorithmIdentifier,
|
||||||
|
// issuer Name,
|
||||||
|
// validity Validity,
|
||||||
|
// subject Name,
|
||||||
|
// subjectPublicKeyInfo SubjectPublicKeyInfo,
|
||||||
|
// issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
|
||||||
|
// -- If present, version MUST be v2 or v3
|
||||||
|
// subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
|
||||||
|
// -- If present, version MUST be v2 or v3
|
||||||
|
// extensions [3] Extensions OPTIONAL
|
||||||
|
// -- If present, version MUST be v3 -- }
|
||||||
|
//
|
||||||
|
match x {
|
||||||
|
&ASN1Block::Sequence(_, _, ref b0) => {
|
||||||
|
let (version, b1) = X509Version::from_asn1(b0)?;
|
||||||
|
let (serial, b2) = X509Serial::from_asn1(b1)?;
|
||||||
|
let (ident, b3) = AlgorithmIdentifier::from_asn1(b2)?;
|
||||||
|
let (issuer, b4) = InfoBlock::from_asn1(b3)?;
|
||||||
|
let (validity, b5) = Validity::from_asn1(b4)?;
|
||||||
|
let (subject, b6) = InfoBlock::from_asn1(b5)?;
|
||||||
|
let (subkey, _ ) = X509PublicKey::from_asn1(b6)?;
|
||||||
|
Ok(GenericCertificate {
|
||||||
|
version: version,
|
||||||
|
serial: serial,
|
||||||
|
signature_alg: ident,
|
||||||
|
issuer: issuer,
|
||||||
|
subject: subject,
|
||||||
|
validity: validity,
|
||||||
|
subject_key: subkey,
|
||||||
|
extensions: vec![]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllFormedCertificateInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* X.509 parsing routines
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/// Parse an X.590 certificate in memory into a generic certificate that can
|
||||||
|
/// be used by a program.
|
||||||
|
pub fn parse_x509(buffer: &[u8]) -> Result<GenericCertificate,X509ParseError> {
|
||||||
|
let blocks = from_der(&buffer[..])?;
|
||||||
|
match blocks.first() {
|
||||||
|
None =>
|
||||||
|
Err(X509ParseError::NotEnoughData),
|
||||||
|
Some(&ASN1Block::Sequence(_, _, ref x)) => {
|
||||||
|
let cert = decode_certificate(&x[0])?;
|
||||||
|
let cert_block_start = x[0].offset();
|
||||||
|
let cert_block_end = x[1].offset();
|
||||||
|
let cert_block = &buffer[cert_block_start..cert_block_end];
|
||||||
|
let alginfo = decode_algorithm_ident(&x[1])?;
|
||||||
|
let sig = decode_signature(&x[2])?;
|
||||||
|
check_signature(&alginfo, &cert.subject_key, cert_block, sig)?;
|
||||||
|
Ok(cert)
|
||||||
|
}
|
||||||
|
Some(_) =>
|
||||||
|
Err(X509ParseError::IllFormedEverything)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_signature(alg: &AlgorithmIdentifier,
|
||||||
|
key: &X509PublicKey,
|
||||||
|
block: &[u8],
|
||||||
|
sig: Vec<u8>)
|
||||||
|
-> Result<(),X509ParseError>
|
||||||
|
{
|
||||||
|
match (alg.algo, key) {
|
||||||
|
(PublicKeyInfo::RSA, &X509PublicKey::RSA(ref key)) => {
|
||||||
|
let sighash = match alg.hash {
|
||||||
|
HashAlgorithm::SHA1 => &SIGNING_HASH_SHA1,
|
||||||
|
HashAlgorithm::SHA224 => &SIGNING_HASH_SHA224,
|
||||||
|
HashAlgorithm::SHA256 => &SIGNING_HASH_SHA256,
|
||||||
|
HashAlgorithm::SHA384 => &SIGNING_HASH_SHA384,
|
||||||
|
HashAlgorithm::SHA512 => &SIGNING_HASH_SHA512,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !key.verify(sighash, block, &sig) {
|
||||||
|
return Err(X509ParseError::RSASignatureWrong);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
(PublicKeyInfo::DSA, &X509PublicKey::DSA(DSAPublic::DSAPublicL1024N160(ref key))) => {
|
||||||
|
let dsa_sig = der_decode(&sig)?;
|
||||||
|
match alg.hash {
|
||||||
|
HashAlgorithm::SHA1
|
||||||
|
if key.verify::<SHA1>(block, &dsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA224
|
||||||
|
if key.verify::<SHA224>(block, &dsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &dsa_sig) =>
|
||||||
|
Ok(()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PublicKeyInfo::DSA, &X509PublicKey::DSA(DSAPublic::DSAPublicL2048N224(ref key))) => {
|
||||||
|
let dsa_sig = der_decode(&sig)?;
|
||||||
|
match alg.hash {
|
||||||
|
HashAlgorithm::SHA1
|
||||||
|
if key.verify::<SHA1>(block, &dsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA224
|
||||||
|
if key.verify::<SHA224>(block, &dsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &dsa_sig) =>
|
||||||
|
Ok(()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PublicKeyInfo::DSA, &X509PublicKey::DSA(DSAPublic::DSAPublicL2048N256(ref key))) => {
|
||||||
|
let dsa_sig = der_decode(&sig)?;
|
||||||
|
match alg.hash {
|
||||||
|
HashAlgorithm::SHA1
|
||||||
|
if key.verify::<SHA1>(block, &dsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA224
|
||||||
|
if key.verify::<SHA224>(block, &dsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &dsa_sig) =>
|
||||||
|
Ok(()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PublicKeyInfo::DSA, &X509PublicKey::DSA(DSAPublic::DSAPublicL3072N256(ref key))) => {
|
||||||
|
let dsa_sig = der_decode(&sig)?;
|
||||||
|
match alg.hash {
|
||||||
|
HashAlgorithm::SHA1
|
||||||
|
if key.verify::<SHA1>(block, &dsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA224
|
||||||
|
if key.verify::<SHA224>(block, &dsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &dsa_sig) =>
|
||||||
|
Ok(()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P192(ref key))) => {
|
||||||
|
let ecdsa_sig = der_decode(&sig)?;
|
||||||
|
match alg.hash {
|
||||||
|
HashAlgorithm::SHA1 if key.verify::<SHA1>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA224 if key.verify::<SHA224>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA384 if key.verify::<SHA384>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA512 if key.verify::<SHA512>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P224(ref key))) => {
|
||||||
|
let ecdsa_sig = der_decode(&sig)?;
|
||||||
|
match alg.hash {
|
||||||
|
HashAlgorithm::SHA1 if key.verify::<SHA1>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA224 if key.verify::<SHA224>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA384 if key.verify::<SHA384>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA512 if key.verify::<SHA512>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P256(ref key))) => {
|
||||||
|
let ecdsa_sig = der_decode(&sig)?;
|
||||||
|
match alg.hash {
|
||||||
|
HashAlgorithm::SHA1 if key.verify::<SHA1>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA224 if key.verify::<SHA224>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA384 if key.verify::<SHA384>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA512 if key.verify::<SHA512>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P384(ref key))) => {
|
||||||
|
let ecdsa_sig = der_decode(&sig)?;
|
||||||
|
match alg.hash {
|
||||||
|
HashAlgorithm::SHA1 if key.verify::<SHA1>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA224 if key.verify::<SHA224>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA384 if key.verify::<SHA384>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA512 if key.verify::<SHA512>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(PublicKeyInfo::ECDSA, &X509PublicKey::ECDSA(ECDSAPublic::P521(ref key))) => {
|
||||||
|
let ecdsa_sig = der_decode(&sig)?;
|
||||||
|
match alg.hash {
|
||||||
|
HashAlgorithm::SHA1 if key.verify::<SHA1>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA224 if key.verify::<SHA224>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA256 if key.verify::<SHA256>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA384 if key.verify::<SHA384>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
HashAlgorithm::SHA512 if key.verify::<SHA512>(block, &ecdsa_sig) => Ok(()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidSignatureHash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidSignatureData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* Testing is for winners!
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn can_parse(f: &str) -> Result<GenericCertificate,X509ParseError> {
|
||||||
|
let mut fd = File::open(f).unwrap();
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
let _amt = fd.read_to_end(&mut buffer);
|
||||||
|
parse_x509(&buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rsa_tests() {
|
||||||
|
assert!(can_parse("testdata/x509/rsa2048-1.der").is_ok());
|
||||||
|
assert!(can_parse("testdata/x509/rsa2048-2.der").is_ok());
|
||||||
|
assert!(can_parse("testdata/x509/rsa4096-1.der").is_ok());
|
||||||
|
assert!(can_parse("testdata/x509/rsa4096-2.der").is_ok());
|
||||||
|
assert!(can_parse("testdata/x509/rsa4096-3.der").is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dsa_tests() {
|
||||||
|
assert!(can_parse("testdata/x509/dsa2048-1.der").is_ok());
|
||||||
|
assert!(can_parse("testdata/x509/dsa2048-2.der").is_ok());
|
||||||
|
assert!(can_parse("testdata/x509/dsa3072-1.der").is_ok());
|
||||||
|
assert!(can_parse("testdata/x509/dsa3072-2.der").is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ecc_tests() {
|
||||||
|
assert!(can_parse("testdata/x509/ec384-1.der").is_ok());
|
||||||
|
assert!(can_parse("testdata/x509/ec384-2.der").is_ok());
|
||||||
|
assert!(can_parse("testdata/x509/ec384-3.der").is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
138
src/x509/name.rs
Normal file
138
src/x509/name.rs
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
use num::BigUint;
|
||||||
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,FromASN1,OID,ToASN1};
|
||||||
|
use x509::error::X509ParseError;
|
||||||
|
|
||||||
|
/// One of the various attributes that can be encoded within an x.509 name. To
|
||||||
|
/// see one of these paired with its value, consider `AttributeTypeValue`.
|
||||||
|
#[derive(Copy,Clone,Debug,Eq,Hash,PartialEq)]
|
||||||
|
pub enum X520Name {
|
||||||
|
Name, Surname, GivenName, Initials, GenerationQualifier, CommonName,
|
||||||
|
LocalityName, StateOrProvinceName, OrganizationName, OrganizationalUnit,
|
||||||
|
Title, DNQualifier, CountryName, SerialNumber, Pseudonym, DomainComponent,
|
||||||
|
EmailAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for X520Name {
|
||||||
|
type Error = X509ParseError;
|
||||||
|
|
||||||
|
fn from_asn1(v: &[ASN1Block])
|
||||||
|
-> Result<(X520Name,&[ASN1Block]),X509ParseError>
|
||||||
|
{
|
||||||
|
match v.split_first() {
|
||||||
|
None =>
|
||||||
|
Err(X509ParseError::NotEnoughData),
|
||||||
|
Some((x,rest)) => {
|
||||||
|
let name = decode_name(&x)?;
|
||||||
|
Ok((name,rest))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_name(val: &ASN1Block)
|
||||||
|
-> Result<X520Name,X509ParseError>
|
||||||
|
{
|
||||||
|
match val {
|
||||||
|
&ASN1Block::ObjectIdentifier(_, _, ref oid) => {
|
||||||
|
if oid == oid!(2,5,4,41) {return Ok(X520Name::Name) }
|
||||||
|
if oid == oid!(2,5,4,4) {return Ok(X520Name::Surname) }
|
||||||
|
if oid == oid!(2,5,4,42) {return Ok(X520Name::GivenName) }
|
||||||
|
if oid == oid!(2,5,4,43) {return Ok(X520Name::Initials) }
|
||||||
|
if oid == oid!(2,5,4,44) {return Ok(X520Name::GenerationQualifier)}
|
||||||
|
if oid == oid!(2,5,4,3) {return Ok(X520Name::CommonName) }
|
||||||
|
if oid == oid!(2,5,4,7) {return Ok(X520Name::LocalityName) }
|
||||||
|
if oid == oid!(2,5,4,8) {return Ok(X520Name::StateOrProvinceName)}
|
||||||
|
if oid == oid!(2,5,4,10) {return Ok(X520Name::OrganizationName) }
|
||||||
|
if oid == oid!(2,5,4,11) {return Ok(X520Name::OrganizationalUnit) }
|
||||||
|
if oid == oid!(2,5,4,12) {return Ok(X520Name::Title) }
|
||||||
|
if oid == oid!(2,5,4,46) {return Ok(X520Name::DNQualifier) }
|
||||||
|
if oid == oid!(2,5,4,6) {return Ok(X520Name::CountryName) }
|
||||||
|
if oid == oid!(2,5,4,5) {return Ok(X520Name::SerialNumber) }
|
||||||
|
if oid == oid!(2,5,4,65) {return Ok(X520Name::Pseudonym) }
|
||||||
|
if oid == oid!(0,9,2342,19200300,100,1,25) {
|
||||||
|
return Ok(X520Name::DomainComponent);
|
||||||
|
}
|
||||||
|
if oid == oid!(1,2,840,113549,1,9,1) {
|
||||||
|
return Ok(X520Name::EmailAddress);
|
||||||
|
}
|
||||||
|
Err(X509ParseError::IllFormedName)
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllFormedName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for X520Name {
|
||||||
|
type Error = ASN1EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let block = encode_name(c, *self);
|
||||||
|
Ok(vec![block])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_name(class: ASN1Class, name: X520Name)
|
||||||
|
-> ASN1Block
|
||||||
|
{
|
||||||
|
let oid = match name {
|
||||||
|
X520Name::Name => oid!(2,5,4,41),
|
||||||
|
X520Name::Surname => oid!(2,5,4,4),
|
||||||
|
X520Name::GivenName => oid!(2,5,4,42),
|
||||||
|
X520Name::Initials => oid!(2,5,4,43),
|
||||||
|
X520Name::GenerationQualifier => oid!(2,5,4,44),
|
||||||
|
X520Name::CommonName => oid!(2,5,4,3),
|
||||||
|
X520Name::LocalityName => oid!(2,5,4,7),
|
||||||
|
X520Name::StateOrProvinceName => oid!(2,5,4,8),
|
||||||
|
X520Name::OrganizationName => oid!(2,5,4,10),
|
||||||
|
X520Name::OrganizationalUnit => oid!(2,5,4,11),
|
||||||
|
X520Name::Title => oid!(2,5,4,12),
|
||||||
|
X520Name::DNQualifier => oid!(2,5,4,46),
|
||||||
|
X520Name::CountryName => oid!(2,5,4,6),
|
||||||
|
X520Name::SerialNumber => oid!(2,5,4,5),
|
||||||
|
X520Name::Pseudonym => oid!(2,5,4,65),
|
||||||
|
X520Name::DomainComponent => oid!(0,9,2342,19200300,100,1,25),
|
||||||
|
X520Name::EmailAddress => oid!(1,2,840,113549,1,9,1)
|
||||||
|
};
|
||||||
|
|
||||||
|
ASN1Block::ObjectIdentifier(class, 0, oid)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn encdec_test(n: X520Name) {
|
||||||
|
let block = encode_name(ASN1Class::Universal, n);
|
||||||
|
let vec = vec![block];
|
||||||
|
match X520Name::from_asn1(&vec) {
|
||||||
|
Err(_) =>
|
||||||
|
assert!(false),
|
||||||
|
Ok((m, _)) =>
|
||||||
|
assert_eq!(n,m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn name_encoding_roundtrips() {
|
||||||
|
encdec_test(X520Name::Name);
|
||||||
|
encdec_test(X520Name::Surname);
|
||||||
|
encdec_test(X520Name::GivenName);
|
||||||
|
encdec_test(X520Name::Initials);
|
||||||
|
encdec_test(X520Name::GenerationQualifier);
|
||||||
|
encdec_test(X520Name::CommonName);
|
||||||
|
encdec_test(X520Name::LocalityName);
|
||||||
|
encdec_test(X520Name::StateOrProvinceName);
|
||||||
|
encdec_test(X520Name::OrganizationName);
|
||||||
|
encdec_test(X520Name::OrganizationalUnit);
|
||||||
|
encdec_test(X520Name::Title);
|
||||||
|
encdec_test(X520Name::DNQualifier);
|
||||||
|
encdec_test(X520Name::CountryName);
|
||||||
|
encdec_test(X520Name::SerialNumber);
|
||||||
|
encdec_test(X520Name::Pseudonym);
|
||||||
|
encdec_test(X520Name::DomainComponent);
|
||||||
|
encdec_test(X520Name::EmailAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
330
src/x509/publickey.rs
Normal file
330
src/x509/publickey.rs
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
use cryptonum::unsigned::{U3072,U2048,U1024,U256,U192};
|
||||||
|
use dsa::{DSAPublic,DSAPublicKey,DSAParameters};
|
||||||
|
use dsa::{L3072N256,L2048N256,L2048N224,L1024N160};
|
||||||
|
use ecdsa::{ECDSAEncodeErr,ECDSAPublic,ECCPublicKey};
|
||||||
|
use ecdsa::{P192,P224,P256,P384,P521};
|
||||||
|
use num::BigUint;
|
||||||
|
use rsa::RSAPublic;
|
||||||
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,FromASN1,OID,ToASN1,
|
||||||
|
der_decode,der_encode,from_der};
|
||||||
|
use utils::TranslateNums;
|
||||||
|
use x509::error::X509ParseError;
|
||||||
|
|
||||||
|
/// A general type that includes all the supported public key types that we
|
||||||
|
/// could read in an x.509 certificate.
|
||||||
|
pub enum X509PublicKey {
|
||||||
|
DSA(DSAPublic),
|
||||||
|
RSA(RSAPublic),
|
||||||
|
ECDSA(ECDSAPublic)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<X509PublicKey> for Option<DSAPublic> {
|
||||||
|
fn from(x: X509PublicKey) -> Option<DSAPublic> {
|
||||||
|
match x {
|
||||||
|
X509PublicKey::DSA(x) => Some(x),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<X509PublicKey> for Option<RSAPublic> {
|
||||||
|
fn from(x: X509PublicKey) -> Option<RSAPublic> {
|
||||||
|
match x {
|
||||||
|
X509PublicKey::RSA(x) => Some(x),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<X509PublicKey> for Option<ECDSAPublic> {
|
||||||
|
fn from(x: X509PublicKey) -> Option<ECDSAPublic> {
|
||||||
|
match x {
|
||||||
|
X509PublicKey::ECDSA(x) => Some(x),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum X509EncodeErr {
|
||||||
|
ASN1EncodeErr(ASN1EncodeErr),
|
||||||
|
ECDSAEncodeErr(ECDSAEncodeErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ASN1EncodeErr> for X509EncodeErr {
|
||||||
|
fn from(x: ASN1EncodeErr) -> X509EncodeErr {
|
||||||
|
X509EncodeErr::ASN1EncodeErr(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ECDSAEncodeErr> for X509EncodeErr {
|
||||||
|
fn from(x: ECDSAEncodeErr) -> X509EncodeErr {
|
||||||
|
X509EncodeErr::ECDSAEncodeErr(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for X509PublicKey {
|
||||||
|
type Error = X509EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class) -> Result<Vec<ASN1Block>,X509EncodeErr> {
|
||||||
|
let block = match self {
|
||||||
|
X509PublicKey::RSA(x) => encode_rsa_key(c, x)?,
|
||||||
|
X509PublicKey::DSA(x) => encode_dsa_key(c, x)?,
|
||||||
|
X509PublicKey::ECDSA(x) => encode_ecdsa_key(c, x)?,
|
||||||
|
};
|
||||||
|
Ok(vec![block])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for X509PublicKey {
|
||||||
|
type Error = X509ParseError;
|
||||||
|
|
||||||
|
fn from_asn1(v: &[ASN1Block]) -> Result<(X509PublicKey, &[ASN1Block]), Self::Error>
|
||||||
|
{
|
||||||
|
let (block, rest) = v.split_first().ok_or(X509ParseError::NotEnoughData)?;
|
||||||
|
|
||||||
|
// SubjectPublicKeyInfo ::= SEQUENCE {
|
||||||
|
// algorithm AlgorithmIdentifier,
|
||||||
|
// subjectPublicKey BIT STRING }
|
||||||
|
if let &ASN1Block::Sequence(_, _, ref info) = block {
|
||||||
|
let (id, malginfo) = strip_algident(&info[0])?;
|
||||||
|
|
||||||
|
if id == oid!(1,2,840,113549,1,1,1) {
|
||||||
|
let key = decode_rsa_key(&info[1])?;
|
||||||
|
return Ok((X509PublicKey::RSA(key), rest));
|
||||||
|
}
|
||||||
|
|
||||||
|
if id == oid!(1,2,840,10040,4,1) {
|
||||||
|
if let Some(alginfo) = malginfo {
|
||||||
|
let key = decode_dsa_key(alginfo, &info[1])?;
|
||||||
|
return Ok((X509PublicKey::DSA(key), rest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if id == oid!(1,2,840,10045,2,1) {
|
||||||
|
if let Some(alginfo) = malginfo {
|
||||||
|
let key = decode_ecdsa_key(alginfo, &info[1..])?;
|
||||||
|
return Ok((X509PublicKey::ECDSA(key), rest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(X509ParseError::IllFormedKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// RSA Public Key encoding / decoding
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn encode_rsa_key(c: ASN1Class, x: &RSAPublic) -> Result<ASN1Block,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let objoid = ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,113549,1,1,1));
|
||||||
|
let bstr = der_encode(x)?;
|
||||||
|
let objkey = ASN1Block::BitString(c, 0, bstr.len() * 8, bstr);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![objoid, objkey]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_rsa_key(x: &ASN1Block) -> Result<RSAPublic,X509ParseError>
|
||||||
|
{
|
||||||
|
if let &ASN1Block::BitString(_, _, _, ref bstr) = x {
|
||||||
|
der_decode(bstr).map_err(|x| X509ParseError::RSAError(x))
|
||||||
|
} else {
|
||||||
|
Err(X509ParseError::NotEnoughData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// DSA Public Key encoding / decoding
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn encode_dsa_key(c: ASN1Class, x: &DSAPublic) -> Result<ASN1Block,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let objoid = ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,10040,4,1));
|
||||||
|
let (mut objparams, bstr) = match x {
|
||||||
|
DSAPublic::DSAPublicL1024N160(x) => (x.params.to_asn1_class(c)?, der_encode(x)?),
|
||||||
|
DSAPublic::DSAPublicL2048N224(x) => (x.params.to_asn1_class(c)?, der_encode(x)?),
|
||||||
|
DSAPublic::DSAPublicL2048N256(x) => (x.params.to_asn1_class(c)?, der_encode(x)?),
|
||||||
|
DSAPublic::DSAPublicL3072N256(x) => (x.params.to_asn1_class(c)?, der_encode(x)?)
|
||||||
|
};
|
||||||
|
objparams.insert(0, objoid);
|
||||||
|
let headinfo = ASN1Block::Sequence(c, 0, objparams);
|
||||||
|
let objkey = ASN1Block::BitString(c, 0, bstr.len() * 8, bstr);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, vec![headinfo, objkey]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_dsa_key(info: ASN1Block, key: &ASN1Block) -> Result<DSAPublic,X509ParseError>
|
||||||
|
{
|
||||||
|
if let ASN1Block::Sequence(_, _, pqg) = info {
|
||||||
|
if pqg.len() != 3 { return Err(X509ParseError::InvalidDSAInfo); }
|
||||||
|
|
||||||
|
let puint = decode_biguint(&pqg[0])?;
|
||||||
|
let guint = decode_biguint(&pqg[1])?;
|
||||||
|
let quint = decode_biguint(&pqg[2])?;
|
||||||
|
|
||||||
|
if puint.bits() > 2048 {
|
||||||
|
let p = U3072::from_num(&puint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let q = U3072::from_num(&quint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let g = U256::from_num(&guint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let params = L3072N256::new(p, q, g);
|
||||||
|
|
||||||
|
if let ASN1Block::BitString(_, _, _, ybstr) = key {
|
||||||
|
let blocks = from_der(ybstr)?;
|
||||||
|
let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?;
|
||||||
|
if let ASN1Block::Integer(_,_,ynum) = iblk {
|
||||||
|
let y = U3072::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?;
|
||||||
|
let key = DSAPublicKey::<L3072N256>::new(params, y);
|
||||||
|
let reskey = DSAPublic::DSAPublicL3072N256(key);
|
||||||
|
return Ok(reskey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(X509ParseError::InvalidDSAKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
if puint.bits() > 1024 {
|
||||||
|
if guint.bits() > 224 {
|
||||||
|
let p = U2048::from_num(&puint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let q = U2048::from_num(&quint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let g = U256::from_num(&guint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let params = L2048N256::new(p, q, g);
|
||||||
|
|
||||||
|
if let ASN1Block::BitString(_, _, _, ybstr) = key {
|
||||||
|
let blocks = from_der(ybstr)?;
|
||||||
|
let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?;
|
||||||
|
if let ASN1Block::Integer(_,_,ynum) = iblk {
|
||||||
|
let y = U2048::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?;
|
||||||
|
let key = DSAPublicKey::<L2048N256>::new(params, y);
|
||||||
|
let reskey = DSAPublic::DSAPublicL2048N256(key);
|
||||||
|
return Ok(reskey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(X509ParseError::InvalidDSAKey)
|
||||||
|
} else {
|
||||||
|
let p = U2048::from_num(&puint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let q = U2048::from_num(&quint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let g = U256::from_num(&guint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let params = L2048N224::new(p, q, g);
|
||||||
|
|
||||||
|
if let ASN1Block::BitString(_, _, _, ybstr) = key {
|
||||||
|
let blocks = from_der(ybstr)?;
|
||||||
|
let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?;
|
||||||
|
if let ASN1Block::Integer(_,_,ynum) = iblk {
|
||||||
|
let y = U2048::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?;
|
||||||
|
let key = DSAPublicKey::<L2048N224>::new(params, y);
|
||||||
|
let reskey = DSAPublic::DSAPublicL2048N224(key);
|
||||||
|
return Ok(reskey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(X509ParseError::InvalidDSAKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let p = U1024::from_num(&puint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let q = U1024::from_num(&quint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let g = U192::from_num(&guint).ok_or(X509ParseError::InvalidDSAInfo)?;
|
||||||
|
let params = L1024N160::new(p, q, g);
|
||||||
|
|
||||||
|
if let ASN1Block::BitString(_, _, _, ybstr) = key {
|
||||||
|
let blocks = from_der(ybstr)?;
|
||||||
|
let (iblk,_) = blocks.split_first().ok_or(X509ParseError::InvalidDSAKey)?;
|
||||||
|
if let ASN1Block::Integer(_,_,ynum) = iblk {
|
||||||
|
let y = U1024::from_num(ynum).ok_or(X509ParseError::InvalidDSAKey)?;
|
||||||
|
let key = DSAPublicKey::<L1024N160>::new(params, y);
|
||||||
|
let reskey = DSAPublic::DSAPublicL1024N160(key);
|
||||||
|
return Ok(reskey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(X509ParseError::InvalidDSAKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(X509ParseError::InvalidDSAInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// ECDSA Public Key encoding
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn encode_ecdsa_key(c: ASN1Class, x: &ECDSAPublic) -> Result<ASN1Block,ECDSAEncodeErr>
|
||||||
|
{
|
||||||
|
let objoid = ASN1Block::ObjectIdentifier(c, 0, oid!(1,2,840,10045,2,1));
|
||||||
|
let (base_curve_oid, mut keyvec) = match x {
|
||||||
|
ECDSAPublic::P192(k) => (oid!(1,2,840,10045,3,1,1), k.to_asn1_class(c)?),
|
||||||
|
ECDSAPublic::P224(k) => (oid!(1,3,132,0,33), k.to_asn1_class(c)?),
|
||||||
|
ECDSAPublic::P256(k) => (oid!(1,2,840,10045,3,1,7), k.to_asn1_class(c)?),
|
||||||
|
ECDSAPublic::P384(k) => (oid!(1,3,132,0,34), k.to_asn1_class(c)?),
|
||||||
|
ECDSAPublic::P521(k) => (oid!(1,3,132,0,35), k.to_asn1_class(c)?),
|
||||||
|
};
|
||||||
|
let curve_oid = ASN1Block::ObjectIdentifier(c, 0, base_curve_oid);
|
||||||
|
let header = ASN1Block::Sequence(c, 0, vec![objoid, curve_oid]);
|
||||||
|
keyvec.insert(0, header);
|
||||||
|
Ok(ASN1Block::Sequence(c, 0, keyvec))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_ecdsa_key(info: ASN1Block, keybls: &[ASN1Block]) -> Result<ECDSAPublic,X509ParseError>
|
||||||
|
{
|
||||||
|
if let ASN1Block::ObjectIdentifier(_, _, oid) = info {
|
||||||
|
if oid == oid!(1,2,840,10045,3,1,1) {
|
||||||
|
let (res, _) = ECCPublicKey::<P192>::from_asn1(keybls)?;
|
||||||
|
return Ok(ECDSAPublic::P192(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
if oid == oid!(1,3,132,0,33) {
|
||||||
|
let (res, _) = ECCPublicKey::<P224>::from_asn1(keybls)?;
|
||||||
|
return Ok(ECDSAPublic::P224(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
if oid == oid!(1,2,840,10045,3,1,7) {
|
||||||
|
let (res, _) = ECCPublicKey::<P256>::from_asn1(keybls)?;
|
||||||
|
return Ok(ECDSAPublic::P256(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
if oid == oid!(1,3,132,0,34) {
|
||||||
|
let (res, _) = ECCPublicKey::<P384>::from_asn1(keybls)?;
|
||||||
|
return Ok(ECDSAPublic::P384(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
if oid == oid!(1,3,132,0,35) {
|
||||||
|
let (res, _) = ECCPublicKey::<P521>::from_asn1(keybls)?;
|
||||||
|
return Ok(ECDSAPublic::P521(res));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(X509ParseError::UnknownEllipticCurve)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strip_algident(block: &ASN1Block)
|
||||||
|
-> Result<(OID, Option<ASN1Block>),X509ParseError>
|
||||||
|
{
|
||||||
|
match block {
|
||||||
|
&ASN1Block::ObjectIdentifier(_, _, ref oid) => {
|
||||||
|
Ok((oid.clone(), None))
|
||||||
|
}
|
||||||
|
&ASN1Block::Sequence(_, _, ref items) => {
|
||||||
|
let (oid, _) = strip_algident(&items[0])?;
|
||||||
|
Ok((oid, Some(items[1].clone())))
|
||||||
|
}
|
||||||
|
_ => Err(X509ParseError::IllFormedAlgoInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_biguint(b: &ASN1Block) -> Result<BigUint,X509ParseError> {
|
||||||
|
match b {
|
||||||
|
&ASN1Block::Integer(_, _, ref v) => {
|
||||||
|
match v.to_biguint() {
|
||||||
|
Some(sn) => Ok(sn),
|
||||||
|
_ => Err(X509ParseError::InvalidDSAInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::InvalidDSAInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
119
src/x509/validity.rs
Normal file
119
src/x509/validity.rs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
use chrono::{DateTime,Utc};
|
||||||
|
use simple_asn1::{ASN1Block,ASN1Class,ASN1EncodeErr,FromASN1,ToASN1};
|
||||||
|
use x509::error::X509ParseError;
|
||||||
|
|
||||||
|
/// The range of dates in which this certificate is valid.
|
||||||
|
#[derive(Clone,Debug,PartialEq)]
|
||||||
|
pub struct Validity {
|
||||||
|
pub not_before: DateTime<Utc>,
|
||||||
|
pub not_after: DateTime<Utc>
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_validity_data(bs: &ASN1Block) -> Result<Validity,X509ParseError> {
|
||||||
|
// Validity ::= SEQUENCE {
|
||||||
|
// notBefore Time,
|
||||||
|
// notAfter Time }
|
||||||
|
match bs {
|
||||||
|
&ASN1Block::Sequence(_, _, ref valxs) => {
|
||||||
|
if valxs.len() != 2 {
|
||||||
|
return Err(X509ParseError::IllFormedValidity);
|
||||||
|
}
|
||||||
|
let nb = get_time(&valxs[0])?;
|
||||||
|
let na = get_time(&valxs[1])?;
|
||||||
|
Ok(Validity{ not_before: nb, not_after: na })
|
||||||
|
}
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllFormedValidity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromASN1 for Validity {
|
||||||
|
type Error = X509ParseError;
|
||||||
|
|
||||||
|
fn from_asn1(v: &[ASN1Block])
|
||||||
|
-> Result<(Validity,&[ASN1Block]),X509ParseError>
|
||||||
|
{
|
||||||
|
match v.split_first() {
|
||||||
|
None =>
|
||||||
|
Err(X509ParseError::NotEnoughData),
|
||||||
|
Some((x, rest)) => {
|
||||||
|
let v = decode_validity_data(&x)?;
|
||||||
|
Ok((v, rest))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_validity_data(c: ASN1Class, v: &Validity) -> ASN1Block {
|
||||||
|
let mut vs = Vec::with_capacity(2);
|
||||||
|
vs.push(ASN1Block::GeneralizedTime(c, 0, v.not_before));
|
||||||
|
vs.push(ASN1Block::GeneralizedTime(c, 0, v.not_after));
|
||||||
|
ASN1Block::Sequence(c, 0, vs)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToASN1 for Validity {
|
||||||
|
type Error = ASN1EncodeErr;
|
||||||
|
|
||||||
|
fn to_asn1_class(&self, c: ASN1Class)
|
||||||
|
-> Result<Vec<ASN1Block>,ASN1EncodeErr>
|
||||||
|
{
|
||||||
|
let block = encode_validity_data(c, self);
|
||||||
|
Ok(vec![block])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_time(b: &ASN1Block) -> Result<DateTime<Utc>, X509ParseError> {
|
||||||
|
match b {
|
||||||
|
&ASN1Block::UTCTime(_, _, v) => Ok(v.clone()),
|
||||||
|
&ASN1Block::GeneralizedTime(_, _, v) => Ok(v.clone()),
|
||||||
|
_ =>
|
||||||
|
Err(X509ParseError::IllFormedValidity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use chrono::TimeZone;
|
||||||
|
use chrono::offset::LocalResult;
|
||||||
|
use quickcheck::{Arbitrary,Gen};
|
||||||
|
use rand::Rng;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn arbitrary_date<G: Gen>(g: &mut G) -> DateTime<Utc> {
|
||||||
|
loop {
|
||||||
|
let y = g.gen_range(1900,3000);
|
||||||
|
let mo = g.gen_range(0,12);
|
||||||
|
let d = g.gen_range(0,31);
|
||||||
|
let h = g.gen_range(0,24);
|
||||||
|
let mi = g.gen_range(0,60);
|
||||||
|
let s = g.gen_range(0,60);
|
||||||
|
match Utc.ymd_opt(y,mo,d).and_hms_opt(h,mi,s) {
|
||||||
|
LocalResult::None =>
|
||||||
|
continue,
|
||||||
|
LocalResult::Single(x) =>
|
||||||
|
return x,
|
||||||
|
LocalResult::Ambiguous(x,_) =>
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Arbitrary for Validity {
|
||||||
|
fn arbitrary<G: Gen>(g: &mut G) -> Validity {
|
||||||
|
Validity {
|
||||||
|
not_before: arbitrary_date(g),
|
||||||
|
not_after: arbitrary_date(g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quickcheck! {
|
||||||
|
fn validity_roundtrips(v: Validity) -> bool {
|
||||||
|
let bstr = encode_validity_data(ASN1Class::Universal, &v);
|
||||||
|
match decode_validity_data(&bstr) {
|
||||||
|
Err(_) => false,
|
||||||
|
Ok(v2) => v == v2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
test-generator/.gitignore
vendored
Normal file
2
test-generator/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
dist/
|
||||||
|
dist-newstyle/
|
||||||
84
test-generator/DSA.hs
Normal file
84
test-generator/DSA.hs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
module DSA(dsaTasks)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Codec.Crypto.DSA.Pure
|
||||||
|
import Crypto.Hash(Digest, SHA256, hash)
|
||||||
|
import "cryptonite" Crypto.Random(DRG(..),getRandomBytes,withDRG)
|
||||||
|
import Data.ByteArray(convert)
|
||||||
|
import qualified Data.ByteString as BS
|
||||||
|
import Data.ByteString.Lazy(ByteString)
|
||||||
|
import qualified Data.ByteString.Lazy as BSL
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import Math(showX,showBin)
|
||||||
|
import Task(Task(..),liftTest)
|
||||||
|
import Utils(HashAlg(..),generateHash,showHash)
|
||||||
|
|
||||||
|
dsaSizes :: [(ParameterSizes, Int)]
|
||||||
|
dsaSizes = [(L1024_N160, 400),
|
||||||
|
(L2048_N224, 100),
|
||||||
|
(L2048_N256, 50),
|
||||||
|
(L3072_N256, 25)]
|
||||||
|
|
||||||
|
dsaTasks :: [Task]
|
||||||
|
dsaTasks = concatMap generateTask dsaSizes
|
||||||
|
|
||||||
|
generateTask :: (ParameterSizes, Int) -> [Task]
|
||||||
|
generateTask (s, c) = [signTest s c]
|
||||||
|
|
||||||
|
showParam :: ParameterSizes -> String
|
||||||
|
showParam L1024_N160 = "L1024N160"
|
||||||
|
showParam L2048_N224 = "L2048N224"
|
||||||
|
showParam L2048_N256 = "L2048N256"
|
||||||
|
showParam L3072_N256 = "L3072N256"
|
||||||
|
|
||||||
|
signTest :: ParameterSizes -> Int -> Task
|
||||||
|
signTest sz cnt = Task {
|
||||||
|
taskName = "DSA " ++ show sz ++ " signing",
|
||||||
|
taskFile = "../testdata/dsa/sign" ++ showParam sz ++ ".test",
|
||||||
|
taskTest = liftTest go,
|
||||||
|
taskCount = cnt
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory, drg0) =
|
||||||
|
case generateProbablePrimes sz drg0 sha256 Nothing of
|
||||||
|
Left _ -> goAdvance memory drg0
|
||||||
|
Right (p, q, _, drg1) ->
|
||||||
|
case generateUnverifiableGenerator p q of
|
||||||
|
Nothing -> goAdvance memory drg1
|
||||||
|
Just g ->
|
||||||
|
let params = Params p g q
|
||||||
|
in case generateKeyPairWithParams params drg1 of
|
||||||
|
Left _ -> goAdvance memory drg1
|
||||||
|
Right (pub, priv, drg2) ->
|
||||||
|
let (msg, drg3) = withDRG drg2 $ getRandomBytes =<< ((fromIntegral . BS.head) `fmap` getRandomBytes 1)
|
||||||
|
(hashf, drg4) = withDRG drg3 generateHash
|
||||||
|
in case signMessage' (translateHash hashf) kViaRFC6979 drg4 priv (BSL.fromStrict msg) of
|
||||||
|
Left _ ->
|
||||||
|
go (memory, drg4)
|
||||||
|
Right (sig, drg5) ->
|
||||||
|
let res = Map.fromList [("p", showX p),
|
||||||
|
("q", showX q),
|
||||||
|
("g", showX g),
|
||||||
|
("y", showX (public_y pub)),
|
||||||
|
("x", showX (private_x priv)),
|
||||||
|
("m", showBin msg),
|
||||||
|
("h", showHash hashf),
|
||||||
|
("r", showX (sign_r sig)),
|
||||||
|
("s", showX (sign_s sig))]
|
||||||
|
in (res, p, (memory, drg5))
|
||||||
|
--
|
||||||
|
goAdvance memory drg0 =
|
||||||
|
let (bstr, drg1) = randomBytesGenerate 37 drg0
|
||||||
|
in BS.null bstr `seq` go (memory, drg1)
|
||||||
|
--
|
||||||
|
translateHash Sha224 = Codec.Crypto.DSA.Pure.SHA224
|
||||||
|
translateHash Sha256 = Codec.Crypto.DSA.Pure.SHA256
|
||||||
|
translateHash Sha384 = Codec.Crypto.DSA.Pure.SHA384
|
||||||
|
translateHash Sha512 = Codec.Crypto.DSA.Pure.SHA512
|
||||||
|
|
||||||
|
sha256 :: ByteString -> ByteString
|
||||||
|
sha256 = BSL.fromStrict . convert' . hash . BSL.toStrict
|
||||||
|
where
|
||||||
|
convert' :: Digest SHA256 -> BS.ByteString
|
||||||
|
convert' = convert
|
||||||
50
test-generator/Database.hs
Normal file
50
test-generator/Database.hs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
module Database(
|
||||||
|
Database,
|
||||||
|
emptyDatabase,
|
||||||
|
generateNum, genSign
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import "crypto-api" Crypto.Random(CryptoRandomGen(..),SystemRandom)
|
||||||
|
import "cryptonite" Crypto.Random(DRG(..))
|
||||||
|
import Data.ByteArray(convert)
|
||||||
|
import Data.Bits(shiftL,testBit)
|
||||||
|
import qualified Data.ByteString as S
|
||||||
|
import Data.Map.Strict(Map)
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
|
||||||
|
type Database = (Map String [Integer], SystemRandom)
|
||||||
|
|
||||||
|
instance DRG SystemRandom where
|
||||||
|
randomBytesGenerate x g =
|
||||||
|
case genBytes x g of
|
||||||
|
Left e -> error ("Data generation error: " ++ show e)
|
||||||
|
Right (res, g') -> (convert res, g')
|
||||||
|
|
||||||
|
emptyDatabase :: SystemRandom -> Database
|
||||||
|
emptyDatabase g0 = (Map.empty, g0)
|
||||||
|
|
||||||
|
generateNum :: Database -> String -> Int -> (Integer, Database)
|
||||||
|
generateNum (db, rng0) varname size =
|
||||||
|
let (x, rng1) = randomBytesGenerate (size `div` 8) rng0
|
||||||
|
x' = integerize x
|
||||||
|
before = Map.findWithDefault [] varname db
|
||||||
|
in if length (filter (== x') before) < 10
|
||||||
|
then (x', (Map.insert varname (x':before) db, rng1))
|
||||||
|
else generateNum (db, rng1) varname size
|
||||||
|
|
||||||
|
genSign :: (Integer, Database) -> (Integer, Database)
|
||||||
|
genSign (x, (db, rng0)) =
|
||||||
|
let (n, rng1) = randomBytesGenerate 1 rng0
|
||||||
|
n' = integerize n
|
||||||
|
in if testBit n' 0 then (0 - x, (db, rng1)) else (x, (db, rng1))
|
||||||
|
|
||||||
|
integerize :: S.ByteString -> Integer
|
||||||
|
integerize = go 0
|
||||||
|
where
|
||||||
|
go acc bstr =
|
||||||
|
case S.uncons bstr of
|
||||||
|
Nothing -> acc
|
||||||
|
Just (v,rest) ->
|
||||||
|
go ((acc `shiftL` 8) + fromIntegral v) rest
|
||||||
193
test-generator/ECDSATesting.hs
Normal file
193
test-generator/ECDSATesting.hs
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
module ECDSATesting(
|
||||||
|
ecdsaTasks
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Crypto.Hash(SHA224(..),SHA256(..),SHA384(..),SHA512(..))
|
||||||
|
import Crypto.Number.Generate(generateBetween)
|
||||||
|
import Crypto.PubKey.ECC.ECDSA(PrivateKey(..),PublicKey(..),Signature(..),signWith)
|
||||||
|
import Crypto.PubKey.ECC.Generate(generate)
|
||||||
|
import Crypto.PubKey.ECC.Prim(scalarGenerate,pointAdd,pointNegate,pointDouble,pointBaseMul,pointMul,pointAddTwoMuls)
|
||||||
|
import Crypto.PubKey.ECC.Types(Curve,CurveName(..),Point(..),common_curve,curveSizeBits,ecc_n,getCurveByName)
|
||||||
|
import "cryptonite" Crypto.Random(DRG(..),getRandomBytes,withDRG)
|
||||||
|
import qualified Data.ByteString as S
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import Math(showX,showBin)
|
||||||
|
import RFC6979(generateKStream)
|
||||||
|
import Task(Task(..),liftTest)
|
||||||
|
import Utils(HashAlg(..),generateHash,runHash,showHash)
|
||||||
|
|
||||||
|
curves :: [(String, Curve)]
|
||||||
|
curves = [("P192", getCurveByName SEC_p192r1),
|
||||||
|
("P224", getCurveByName SEC_p224r1),
|
||||||
|
("P256", getCurveByName SEC_p256r1),
|
||||||
|
("P384", getCurveByName SEC_p384r1),
|
||||||
|
("P521", getCurveByName SEC_p521r1)]
|
||||||
|
|
||||||
|
negateTest :: String -> Curve -> Task
|
||||||
|
negateTest name curve = Task {
|
||||||
|
taskName = name ++ " point negation",
|
||||||
|
taskFile = "../testdata/ecc/negate/" ++ name ++ ".test",
|
||||||
|
taskTest = liftTest go,
|
||||||
|
taskCount = 1000
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg) =
|
||||||
|
let (scalar, drg') = withDRG drg (scalarGenerate curve)
|
||||||
|
point = pointBaseMul curve scalar
|
||||||
|
dbl = pointNegate curve point
|
||||||
|
in case (point, dbl) of
|
||||||
|
(PointO, _) -> go (memory0, drg')
|
||||||
|
(_, PointO) -> go (memory0, drg')
|
||||||
|
(Point basex basey, Point dblx dbly) ->
|
||||||
|
let res = Map.fromList [("x", showX basex), ("y", showX basey),
|
||||||
|
("a", showX dblx), ("b", showX dbly)]
|
||||||
|
in (res, scalar, (memory0, drg'))
|
||||||
|
|
||||||
|
doubleTest :: String -> Curve -> Task
|
||||||
|
doubleTest name curve = Task {
|
||||||
|
taskName = name ++ " point doubling",
|
||||||
|
taskFile = "../testdata/ecc/double/" ++ name ++ ".test",
|
||||||
|
taskTest = liftTest go,
|
||||||
|
taskCount = 1000
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg) =
|
||||||
|
let (scalar, drg') = withDRG drg (scalarGenerate curve)
|
||||||
|
point = pointBaseMul curve scalar
|
||||||
|
dbl = pointDouble curve point
|
||||||
|
in case (point, dbl) of
|
||||||
|
(PointO, _) -> go (memory0, drg')
|
||||||
|
(_, PointO) -> go (memory0, drg')
|
||||||
|
(Point basex basey, Point dblx dbly) ->
|
||||||
|
let res = Map.fromList [("x", showX basex), ("y", showX basey),
|
||||||
|
("a", showX dblx), ("b", showX dbly)]
|
||||||
|
in (res, scalar, (memory0, drg'))
|
||||||
|
|
||||||
|
addTest :: String -> Curve -> Task
|
||||||
|
addTest name curve = Task {
|
||||||
|
taskName = name ++ " point addition",
|
||||||
|
taskFile = "../testdata/ecc/add/" ++ name ++ ".test",
|
||||||
|
taskTest = liftTest go,
|
||||||
|
taskCount = 1000
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
let (scalar1, drg1) = withDRG drg0 (scalarGenerate curve)
|
||||||
|
(scalar2, drg2) = withDRG drg1 (scalarGenerate curve)
|
||||||
|
point1 = pointBaseMul curve scalar1
|
||||||
|
point2 = pointBaseMul curve scalar2
|
||||||
|
pointr = pointAdd curve point1 point2
|
||||||
|
in case (point1, point2, pointr) of
|
||||||
|
(Point x1 y1, Point x2 y2, Point xr yr) ->
|
||||||
|
let res = Map.fromList [("x", showX x1), ("y", showX y1),
|
||||||
|
("u", showX x2), ("v", showX y2),
|
||||||
|
("a", showX xr), ("b", showX yr)]
|
||||||
|
in (res, scalar1, (memory0, drg2))
|
||||||
|
_ ->
|
||||||
|
go (memory0, drg2)
|
||||||
|
|
||||||
|
scaleTest :: String -> Curve -> Task
|
||||||
|
scaleTest name curve = Task {
|
||||||
|
taskName = name ++ " point scaling",
|
||||||
|
taskFile = "../testdata/ecc/scale/" ++ name ++ ".test",
|
||||||
|
taskTest = liftTest go,
|
||||||
|
taskCount = 1000
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
let (scalar0, drg1) = withDRG drg0 (scalarGenerate curve)
|
||||||
|
(scalar1, drg2) = withDRG drg1 (scalarGenerate curve)
|
||||||
|
(negbs, drg3) = randomBytesGenerate 1 drg2
|
||||||
|
[negbyte] = S.unpack negbs
|
||||||
|
k = if odd negbyte then scalar1 else -scalar1
|
||||||
|
point = pointBaseMul curve scalar0
|
||||||
|
respnt = pointMul curve k point
|
||||||
|
in case (point, respnt) of
|
||||||
|
(PointO, _) -> go (memory0, drg3)
|
||||||
|
(_, PointO) -> go (memory0, drg3)
|
||||||
|
(Point basex basey, Point resx resy) ->
|
||||||
|
let res = Map.fromList [("x", showX basex), ("y", showX basey),
|
||||||
|
("k", showX k),
|
||||||
|
("a", showX resx), ("b", showX resy)]
|
||||||
|
in (res, scalar0, (memory0, drg3))
|
||||||
|
|
||||||
|
addScaleTest :: String -> Curve -> Task
|
||||||
|
addScaleTest name curve = Task {
|
||||||
|
taskName = name ++ " point addition of two scalings",
|
||||||
|
taskFile = "../testdata/ecc/add_scale2/" ++ name ++ ".test",
|
||||||
|
taskTest = liftTest go,
|
||||||
|
taskCount = 1000
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
let (scalar1, drg1) = withDRG drg0 (scalarGenerate curve)
|
||||||
|
(scalar2, drg2) = withDRG drg1 (scalarGenerate curve)
|
||||||
|
(n, drg3) = withDRG drg2 (scalarGenerate curve)
|
||||||
|
(m, drg4) = withDRG drg3 (scalarGenerate curve)
|
||||||
|
point1 = pointBaseMul curve scalar1
|
||||||
|
point2 = pointBaseMul curve scalar2
|
||||||
|
pointr = pointAddTwoMuls curve n point1 m point2
|
||||||
|
in case (point1, point2, pointr) of
|
||||||
|
(Point x1 y1, Point x2 y2, Point xr yr) ->
|
||||||
|
let res = Map.fromList [("x", showX x1), ("y", showX y1),
|
||||||
|
("p", showX x2), ("q", showX y2),
|
||||||
|
("n", showX n), ("m", showX m),
|
||||||
|
("r", showX xr), ("s", showX yr)]
|
||||||
|
in (res, scalar1, (memory0, drg4))
|
||||||
|
_ ->
|
||||||
|
go (memory0, drg4)
|
||||||
|
|
||||||
|
|
||||||
|
signTest :: String -> Curve -> Task
|
||||||
|
signTest name curve = Task {
|
||||||
|
taskName = name ++ " curve signing",
|
||||||
|
taskFile = "../testdata/ecc/sign/" ++ name ++ ".test",
|
||||||
|
taskTest = liftTest go,
|
||||||
|
taskCount = 1000
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
let ((pub, priv), drg1) = withDRG drg0 (generate curve)
|
||||||
|
(msg, drg2) = withDRG drg1 $ do x <- generateBetween 0 256
|
||||||
|
getRandomBytes (fromIntegral x)
|
||||||
|
(hash, drg3) = withDRG drg2 generateHash
|
||||||
|
n = ecc_n (common_curve curve)
|
||||||
|
PrivateKey _ d = priv
|
||||||
|
kStream = generateKStream hash msg d n (curveSizeBits curve)
|
||||||
|
findGoodK stream =
|
||||||
|
case stream of
|
||||||
|
[] ->
|
||||||
|
go (memory0, drg3)
|
||||||
|
(k : restks) ->
|
||||||
|
case signWith' k priv hash msg of
|
||||||
|
Nothing ->
|
||||||
|
findGoodK restks
|
||||||
|
Just sig ->
|
||||||
|
let PublicKey _ (Point x y) = pub
|
||||||
|
res = Map.fromList [("d", showX d), ("k", showX k),
|
||||||
|
("x", showX x), ("y", showX y),
|
||||||
|
("m", showBin msg), ("h", showHash hash),
|
||||||
|
("n", showBin (runHash hash msg)),
|
||||||
|
("r", showX (sign_r sig)),
|
||||||
|
("s", showX (sign_s sig))]
|
||||||
|
in (res, d, (memory0, drg3))
|
||||||
|
in findGoodK kStream
|
||||||
|
|
||||||
|
signWith' :: Integer -> PrivateKey -> HashAlg -> S.ByteString -> Maybe Signature
|
||||||
|
signWith' k priv Sha224 msg = signWith k priv SHA224 msg
|
||||||
|
signWith' k priv Sha256 msg = signWith k priv SHA256 msg
|
||||||
|
signWith' k priv Sha384 msg = signWith k priv SHA384 msg
|
||||||
|
signWith' k priv Sha512 msg = signWith k priv SHA512 msg
|
||||||
|
|
||||||
|
generateTasks :: (String, Curve) -> [Task]
|
||||||
|
generateTasks (name, curve) = [negateTest name curve,
|
||||||
|
doubleTest name curve,
|
||||||
|
addTest name curve,
|
||||||
|
scaleTest name curve,
|
||||||
|
addScaleTest name curve,
|
||||||
|
signTest name curve]
|
||||||
|
|
||||||
|
ecdsaTasks :: [Task]
|
||||||
|
ecdsaTasks = concatMap generateTasks curves
|
||||||
735
test-generator/ED25519.hs
Normal file
735
test-generator/ED25519.hs
Normal file
@@ -0,0 +1,735 @@
|
|||||||
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
module ED25519(ed25519Tasks)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Control.Monad(unless)
|
||||||
|
import Crypto.Error(CryptoFailable(CryptoPassed))
|
||||||
|
import "crypto-api" Crypto.Random(SystemRandom)
|
||||||
|
import "cryptonite" Crypto.Random(getRandomBytes,withDRG)
|
||||||
|
import Crypto.PubKey.Ed25519
|
||||||
|
import Data.ByteArray(convert)
|
||||||
|
import Data.ByteString(ByteString,pack,useAsCString)
|
||||||
|
import qualified Data.ByteString as BS
|
||||||
|
import Data.Int(Int32)
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import Data.Word(Word8,Word32,Word64)
|
||||||
|
import ED25519.PrecompPoints
|
||||||
|
import Foreign.C.Types(CChar)
|
||||||
|
import Foreign.Marshal.Alloc(alloca)
|
||||||
|
import Foreign.Marshal.Array(allocaArray,peekArray,pokeArray)
|
||||||
|
import Foreign.Ptr(Ptr,castPtr)
|
||||||
|
import Foreign.Storable(Storable(..))
|
||||||
|
import Math(showX,showBin)
|
||||||
|
import Task(Task(..))
|
||||||
|
|
||||||
|
cTEST_COUNT :: Int
|
||||||
|
cTEST_COUNT = 1000
|
||||||
|
|
||||||
|
ed25519Tasks :: [Task]
|
||||||
|
ed25519Tasks = [ loadTests, byteTests, addsubTests, mulTests,
|
||||||
|
squaringTests, inversionTests, negateTests,
|
||||||
|
cmovTests, isTests, square2Tests,
|
||||||
|
pow22523Tests, fbvTests, conversionTests,
|
||||||
|
ptDoubleTests, maddsubTests, ptAddSubTests,
|
||||||
|
scalarMultBaseTests, slideTests, scalarMultTests,
|
||||||
|
reduceTests, muladdTests, pubPrivTests,
|
||||||
|
signTest ]
|
||||||
|
|
||||||
|
loadTests :: Task
|
||||||
|
loadTests = Task {
|
||||||
|
taskName = "ed25519 byte loading",
|
||||||
|
taskFile = "../testdata/ed25519/load.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
do let (bytes, drg1) = withDRG drg0 (getRandomBytes 4)
|
||||||
|
res3 <- useAsCString bytes (\ptr -> load_3 ptr)
|
||||||
|
res4 <- useAsCString bytes (\ptr -> load_4 ptr)
|
||||||
|
let res = Map.fromList [("x", showBin bytes), ("a", showX res3), ("b", showX res4)]
|
||||||
|
return (res, fromIntegral res4, (memory0, drg1))
|
||||||
|
|
||||||
|
byteTests :: Task
|
||||||
|
byteTests = Task {
|
||||||
|
taskName = "ed25519 byte / element conversion",
|
||||||
|
taskFile = "../testdata/ed25519/bytes.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomPackedBytes drg0 $ \ ptra drg1 ->
|
||||||
|
alloca $ \ ptrc ->
|
||||||
|
allocaArray 32 $ \ rptr ->
|
||||||
|
do clearSpace ptrc
|
||||||
|
pokeArray (rptr :: Ptr Word8) (replicate 32 0)
|
||||||
|
fe_frombytes ptrc ptra
|
||||||
|
b <- convertFE ptrc
|
||||||
|
fe_tobytes (castPtr rptr) ptrc
|
||||||
|
start <- peek ptra
|
||||||
|
end <- peek (castPtr rptr)
|
||||||
|
unless (start == end) $
|
||||||
|
fail "field element tobytes/frombytes doesn't round trip"
|
||||||
|
bytes' <- pack `fmap` peekArray 32 (castPtr ptra :: Ptr Word8)
|
||||||
|
let res = Map.fromList [("a", showBin bytes'),
|
||||||
|
("b", showBin b)]
|
||||||
|
return (res, toNumber b, (memory0, drg1))
|
||||||
|
|
||||||
|
addsubTests :: Task
|
||||||
|
addsubTests = Task {
|
||||||
|
taskName = "ed25519 addition/subtraction tests",
|
||||||
|
taskFile = "../testdata/ed25519/addsub.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomElement drg0 $ \ ptrel1 drg1 ->
|
||||||
|
randomElement drg1 $ \ ptrel2 drg2 ->
|
||||||
|
alloca $ \ ptrc ->
|
||||||
|
alloca $ \ ptrd ->
|
||||||
|
do fe_add ptrc ptrel1 ptrel2
|
||||||
|
fe_sub ptrd ptrel1 ptrel2
|
||||||
|
[a, b, c, d] <- mapM convertFE [ptrel1, ptrel2, ptrc, ptrd]
|
||||||
|
let res = Map.fromList [("a", showBin a),
|
||||||
|
("b", showBin b),
|
||||||
|
("c", showBin c),
|
||||||
|
("d", showBin d)]
|
||||||
|
return (res, toNumber c, (memory0, drg2))
|
||||||
|
|
||||||
|
mulTests :: Task
|
||||||
|
mulTests = Task {
|
||||||
|
taskName = "ed25519 multiplication tests",
|
||||||
|
taskFile = "../testdata/ed25519/mul.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomElement drg0 $ \ ptrel1 drg1 ->
|
||||||
|
randomElement drg1 $ \ ptrel2 drg2 ->
|
||||||
|
alloca $ \ ptrc ->
|
||||||
|
do fe_mul ptrc ptrel1 ptrel2
|
||||||
|
[a, b, c] <- mapM convertFE [ptrel1, ptrel2, ptrc]
|
||||||
|
let res = Map.fromList [("a", showBin a),
|
||||||
|
("b", showBin b),
|
||||||
|
("c", showBin c)]
|
||||||
|
return (res, toNumber c, (memory0, drg2))
|
||||||
|
|
||||||
|
squaringTests :: Task
|
||||||
|
squaringTests = Task {
|
||||||
|
taskName = "ed25519 squaring tests",
|
||||||
|
taskFile = "../testdata/ed25519/square.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomElement drg0 $ \ ptrel drg1 ->
|
||||||
|
alloca $ \ ptrc ->
|
||||||
|
do fe_square ptrc ptrel
|
||||||
|
[a, c] <- mapM convertFE [ptrel, ptrc]
|
||||||
|
let res = Map.fromList [("a", showBin a),
|
||||||
|
("c", showBin c)]
|
||||||
|
return (res, toNumber c, (memory0, drg1))
|
||||||
|
|
||||||
|
inversionTests :: Task
|
||||||
|
inversionTests = Task {
|
||||||
|
taskName = "ed25519 inversion tests",
|
||||||
|
taskFile = "../testdata/ed25519/invert.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomElement drg0 $ \ ptrel drg1 ->
|
||||||
|
alloca $ \ ptrc ->
|
||||||
|
do fe_invert ptrc ptrel
|
||||||
|
a <- convertFE ptrel
|
||||||
|
c <- convertFE ptrc
|
||||||
|
let res = Map.fromList [("a", showBin a),
|
||||||
|
("c", showBin c)]
|
||||||
|
return (res, toNumber a, (memory0, drg1))
|
||||||
|
|
||||||
|
negateTests :: Task
|
||||||
|
negateTests = Task {
|
||||||
|
taskName = "ed25519 negation tests",
|
||||||
|
taskFile = "../testdata/ed25519/negate.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomElement drg0 $ \ ptrel drg1 ->
|
||||||
|
alloca $ \ ptrc ->
|
||||||
|
do fe_negate ptrc ptrel
|
||||||
|
a <- convertFE ptrel
|
||||||
|
c <- convertFE ptrc
|
||||||
|
let res = Map.fromList [("a", showBin a),
|
||||||
|
("c", showBin c)]
|
||||||
|
return (res, toNumber a, (memory0, drg1))
|
||||||
|
|
||||||
|
cmovTests :: Task
|
||||||
|
cmovTests = Task {
|
||||||
|
taskName = "ed25519 conditional mov tests",
|
||||||
|
taskFile = "../testdata/ed25519/cmov.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomElement drg0 $ \ aelptr drg1 ->
|
||||||
|
do let (bbytes, drg2) = withDRG drg1 (getRandomBytes 1)
|
||||||
|
b = even (BS.head bbytes)
|
||||||
|
bvalLib = if b then 0 else 1
|
||||||
|
bvalOut = if b then 0 else 0xFFFFFF :: Word32
|
||||||
|
alloca $ \ celptr ->
|
||||||
|
do clearSpace celptr
|
||||||
|
fe_cmov celptr aelptr bvalLib
|
||||||
|
a <- convertFE aelptr
|
||||||
|
c <- convertFE celptr
|
||||||
|
let res = Map.fromList [("a", showBin a),
|
||||||
|
("b", showX bvalOut),
|
||||||
|
("c", showBin c)]
|
||||||
|
return (res, toNumber a, (memory0, drg2))
|
||||||
|
|
||||||
|
isTests :: Task
|
||||||
|
isTests = Task {
|
||||||
|
taskName = "ed25519 predicate tests",
|
||||||
|
taskFile = "../testdata/ed25519/istests.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomElement drg0 $ \ aptr drg1 ->
|
||||||
|
do a <- convertFE aptr
|
||||||
|
z <- fe_isnonzero aptr
|
||||||
|
n <- fe_isnegative aptr
|
||||||
|
let res = Map.fromList [("a", showBin a),
|
||||||
|
("z", showX (if z == 0 then 0 :: Word32 else 0xFFFFFF)),
|
||||||
|
("n", showX (if n == 0 then 0 :: Word32 else 0xFFFFFF))]
|
||||||
|
return (res, toNumber a, (memory0, drg1))
|
||||||
|
|
||||||
|
square2Tests :: Task
|
||||||
|
square2Tests = Task {
|
||||||
|
taskName = "ed25519 square2 tests",
|
||||||
|
taskFile = "../testdata/ed25519/square2.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomElement drg0 $ \ aptr drg1 ->
|
||||||
|
alloca $ \ cptr ->
|
||||||
|
do clearSpace cptr
|
||||||
|
fe_square2 cptr aptr
|
||||||
|
a <- convertFE aptr
|
||||||
|
c <- convertFE cptr
|
||||||
|
let res = Map.fromList [("a", showBin a), ("c", showBin c)]
|
||||||
|
return (res, toNumber a, (memory0, drg1))
|
||||||
|
|
||||||
|
pow22523Tests :: Task
|
||||||
|
pow22523Tests = Task {
|
||||||
|
taskName = "ed25519 pow22523 tests",
|
||||||
|
taskFile = "../testdata/ed25519/pow22523.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomElement drg0 $ \ aptr drg1 ->
|
||||||
|
alloca $ \ cptr ->
|
||||||
|
do clearSpace cptr
|
||||||
|
fe_pow22523 cptr aptr
|
||||||
|
a <- convertFE aptr
|
||||||
|
c <- convertFE cptr
|
||||||
|
let res = Map.fromList [("a", showBin a), ("c", showBin c)]
|
||||||
|
return (res, toNumber a, (memory0, drg1))
|
||||||
|
|
||||||
|
fbvTests :: Task
|
||||||
|
fbvTests = Task {
|
||||||
|
taskName = "ed25519 from bytes (vartime) tests",
|
||||||
|
taskFile = "../testdata/ed25519/fbv.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
do let (abytes, drg1) = withDRG drg0 (getRandomBytes 32)
|
||||||
|
useAsCString abytes $ \ aptr ->
|
||||||
|
do let aptr' = castPtr aptr :: Ptr PackedBytes
|
||||||
|
curve25519_scalar_mask aptr'
|
||||||
|
alloca $ \ dest ->
|
||||||
|
do clearSpace dest
|
||||||
|
ok <- point_frombytes dest aptr'
|
||||||
|
a <- pack `fmap` peekArray 32 (castPtr aptr)
|
||||||
|
c <- pack `fmap` peekArray (4 * 10 * 4) (castPtr dest)
|
||||||
|
let c' | ok = c
|
||||||
|
| otherwise = BS.empty
|
||||||
|
let res = Map.fromList [("a", showBin a),
|
||||||
|
("b", showBin c'),
|
||||||
|
("c", showBin c)]
|
||||||
|
return (res, if ok then (toNumber abytes) else 0, (memory0, drg1))
|
||||||
|
|
||||||
|
conversionTests :: Task
|
||||||
|
conversionTests = Task {
|
||||||
|
taskName = "ed25519 point form conversion tests",
|
||||||
|
taskFile = "../testdata/ed25519/conversion.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomPoint3 drg0 $ \ ptr3 drg' ->
|
||||||
|
alloca $ \ ptrCached ->
|
||||||
|
alloca $ \ ptr2 ->
|
||||||
|
alloca $ \ ptrP1P1 ->
|
||||||
|
alloca $ \ ptr2' ->
|
||||||
|
alloca $ \ ptr3' ->
|
||||||
|
do clearSpace ptrCached
|
||||||
|
clearSpace ptr2
|
||||||
|
clearSpace ptrP1P1
|
||||||
|
clearSpace ptr2'
|
||||||
|
clearSpace ptr3'
|
||||||
|
p3_to_cached ptrCached ptr3
|
||||||
|
ge_p3_to_p2 ptr2 ptr3
|
||||||
|
ge_p3_dbl ptrP1P1 ptr3
|
||||||
|
p1p1_to_p2 ptr2' ptrP1P1
|
||||||
|
p1p1_to_p3 ptr3' ptrP1P1
|
||||||
|
a <- convertPoint ptr3
|
||||||
|
c <- convertPoint ptrCached
|
||||||
|
t <- convertPoint ptr2
|
||||||
|
o <- convertPoint ptrP1P1
|
||||||
|
d <- convertPoint ptr2'
|
||||||
|
b <- convertPoint ptr3'
|
||||||
|
let res = Map.fromList [("a", showBin a), ("c", showBin c),
|
||||||
|
("t", showBin t), ("o", showBin o),
|
||||||
|
("d", showBin d), ("b", showBin b)]
|
||||||
|
return (res, toNumber a, (memory0, drg'))
|
||||||
|
|
||||||
|
ptDoubleTests :: Task
|
||||||
|
ptDoubleTests = Task {
|
||||||
|
taskName = "ed25519 point doubling tests",
|
||||||
|
taskFile = "../testdata/ed25519/pt_double.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomPoint3 drg0 $ \ ptra drg1 ->
|
||||||
|
randomPoint2 drg1 $ \ ptrc drg2 ->
|
||||||
|
alloca $ \ ptrb ->
|
||||||
|
alloca $ \ ptrd ->
|
||||||
|
do clearSpace ptrb
|
||||||
|
clearSpace ptrd
|
||||||
|
ge_p3_dbl ptrb ptra
|
||||||
|
ge_p2_dbl ptrd ptrc
|
||||||
|
a <- convertPoint ptra
|
||||||
|
b <- convertPoint ptrb
|
||||||
|
c <- convertPoint ptrc
|
||||||
|
d <- convertPoint ptrd
|
||||||
|
let res = Map.fromList [("a", showBin a), ("b", showBin b),
|
||||||
|
("c", showBin c), ("d", showBin d)]
|
||||||
|
return (res, toNumber a, (memory0, drg2))
|
||||||
|
|
||||||
|
maddsubTests :: Task
|
||||||
|
maddsubTests = Task {
|
||||||
|
taskName = "ed25519 point madd/msub tests",
|
||||||
|
taskFile = "../testdata/ed25519/maddsub.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomPoint3 drg0 $ \ ptra drg1 ->
|
||||||
|
randomPointPrecomp drg1 $ \ ptrc drg2 ->
|
||||||
|
alloca $ \ ptrb ->
|
||||||
|
alloca $ \ ptrd ->
|
||||||
|
do clearSpace ptrb
|
||||||
|
clearSpace ptrd
|
||||||
|
ge_madd ptrb ptra ptrc
|
||||||
|
ge_msub ptrd ptra ptrc
|
||||||
|
a <- convertPoint ptra
|
||||||
|
b <- convertPoint ptrb
|
||||||
|
c <- convertPoint ptrc
|
||||||
|
d <- convertPoint ptrd
|
||||||
|
let res = Map.fromList [("a", showBin a), ("b", showBin b),
|
||||||
|
("c", showBin c), ("d", showBin d)]
|
||||||
|
return (res, toNumber a, (memory0, drg2))
|
||||||
|
|
||||||
|
ptAddSubTests :: Task
|
||||||
|
ptAddSubTests = Task {
|
||||||
|
taskName = "ed25519 point add/sub tests",
|
||||||
|
taskFile = "../testdata/ed25519/ptaddsub.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomPoint3 drg0 $ \ ptra drg1 ->
|
||||||
|
randomPointCached drg1 $ \ ptrc drg2 ->
|
||||||
|
alloca $ \ ptrb ->
|
||||||
|
alloca $ \ ptrd ->
|
||||||
|
do clearSpace ptrb
|
||||||
|
clearSpace ptrd
|
||||||
|
ge_add ptrb ptra ptrc
|
||||||
|
ge_sub ptrd ptra ptrc
|
||||||
|
a <- convertPoint ptra
|
||||||
|
b <- convertPoint ptrb
|
||||||
|
c <- convertPoint ptrc
|
||||||
|
d <- convertPoint ptrd
|
||||||
|
let res = Map.fromList [("a", showBin a), ("b", showBin b),
|
||||||
|
("c", showBin c), ("d", showBin d)]
|
||||||
|
return (res, toNumber a, (memory0, drg2))
|
||||||
|
|
||||||
|
scalarMultBaseTests :: Task
|
||||||
|
scalarMultBaseTests = Task {
|
||||||
|
taskName = "ed25519 point add/sub tests",
|
||||||
|
taskFile = "../testdata/ed25519/scalar_mult.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomPackedBytes drg0 $ \ ptra drg1 ->
|
||||||
|
alloca $ \ ptrb ->
|
||||||
|
do clearSpace ptrb
|
||||||
|
x25519_ge_scalarmult_base ptrb ptra
|
||||||
|
PB abytes <- peek ptra
|
||||||
|
let a = pack abytes
|
||||||
|
b <- convertPoint ptrb
|
||||||
|
let res = Map.fromList [("a", showBin a), ("b", showBin b)]
|
||||||
|
return (res, toNumber a, (memory0, drg1))
|
||||||
|
|
||||||
|
slideTests :: Task
|
||||||
|
slideTests = Task {
|
||||||
|
taskName = "ed25519 slide helper function tests",
|
||||||
|
taskFile = "../testdata/ed25519/slide.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomPackedBytes drg0 $ \ ptra drg1 ->
|
||||||
|
allocaArray 256 $ \ ptrb ->
|
||||||
|
do pokeArray ptrb (replicate 256 0)
|
||||||
|
slide ptrb ptra
|
||||||
|
a <- pack `fmap` peekArray 32 (castPtr ptra)
|
||||||
|
b <- pack `fmap` peekArray 356 ptrb
|
||||||
|
let res = Map.fromList [("a", showBin a), ("b", showBin b)]
|
||||||
|
return (res, toNumber a, (memory0, drg1))
|
||||||
|
|
||||||
|
scalarMultTests :: Task
|
||||||
|
scalarMultTests = Task {
|
||||||
|
taskName = "ed25519 point general scalar multiplication tests",
|
||||||
|
taskFile = "../testdata/ed25519/scalar_mult_gen.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomPackedBytes drg0 $ \ ptra drg1 ->
|
||||||
|
randomPoint3 drg1 $ \ ptrb drg2 ->
|
||||||
|
randomPackedBytes drg2 $ \ ptrc drg3 ->
|
||||||
|
alloca $ \ ptrd ->
|
||||||
|
do clearSpace ptrd
|
||||||
|
ge_double_scalarmult_vartime ptrd ptra ptrb ptrc
|
||||||
|
PB abytes <- peek ptra
|
||||||
|
let a = pack abytes
|
||||||
|
b <- convertPoint ptrb
|
||||||
|
PB cbytes <- peek ptrc
|
||||||
|
let c = pack cbytes
|
||||||
|
d <- convertPoint ptrd
|
||||||
|
let res = Map.fromList [("a", showBin a), ("b", showBin b),
|
||||||
|
("c", showBin c), ("d", showBin d)]
|
||||||
|
return (res, toNumber a, (memory0, drg3))
|
||||||
|
|
||||||
|
reduceTests :: Task
|
||||||
|
reduceTests = Task {
|
||||||
|
taskName = "ed25519 reduce tests",
|
||||||
|
taskFile = "../testdata/ed25519/reduce.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
do let (a, drg1) = withDRG drg0 (getRandomBytes 64)
|
||||||
|
allocaArray 64 $ \ target ->
|
||||||
|
do pokeArray target (BS.unpack a)
|
||||||
|
sc_reduce target
|
||||||
|
b <- pack `fmap` peekArray 32 target
|
||||||
|
let res = Map.fromList [("a", showBin a), ("b", showBin b)]
|
||||||
|
return (res, toNumber a, (memory0, drg1))
|
||||||
|
|
||||||
|
muladdTests :: Task
|
||||||
|
muladdTests = Task {
|
||||||
|
taskName = "ed25519 multiplication+addition tests",
|
||||||
|
taskFile = "../testdata/ed25519/muladd.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomPackedBytes drg0 $ \ ptra drg1 ->
|
||||||
|
randomPackedBytes drg1 $ \ ptrb drg2 ->
|
||||||
|
randomPackedBytes drg2 $ \ ptrc drg3 ->
|
||||||
|
alloca $ \ ptrd ->
|
||||||
|
do clearSpace ptrd
|
||||||
|
sc_muladd ptrd ptra ptrb ptrc
|
||||||
|
a <- repackBytes ptra
|
||||||
|
b <- repackBytes ptrb
|
||||||
|
c <- repackBytes ptrc
|
||||||
|
d <- repackBytes ptrd
|
||||||
|
let res = Map.fromList [("a", showBin a), ("b", showBin b),
|
||||||
|
("c", showBin c), ("d", showBin d)]
|
||||||
|
return (res, toNumber a, (memory0, drg3))
|
||||||
|
|
||||||
|
pubPrivTests :: Task
|
||||||
|
pubPrivTests = Task {
|
||||||
|
taskName = "ed25519 private -> public conversion tests",
|
||||||
|
taskFile = "../testdata/ed25519/pubfrompriv.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
randomPackedBytes drg0 $ \ ptra drg1 ->
|
||||||
|
alloca $ \ ptrb ->
|
||||||
|
do clearSpace ptrb
|
||||||
|
public_from_private ptrb ptra
|
||||||
|
a <- repackBytes ptra
|
||||||
|
b <- repackBytes ptrb
|
||||||
|
let res = Map.fromList [("a", showBin a), ("b", showBin b)]
|
||||||
|
return (res, toNumber a, (memory0, drg1))
|
||||||
|
|
||||||
|
signTest :: Task
|
||||||
|
signTest = Task {
|
||||||
|
taskName = "ed25519 signing tests",
|
||||||
|
taskFile = "../testdata/ed25519/sign.test",
|
||||||
|
taskTest = go,
|
||||||
|
taskCount = cTEST_COUNT
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go (memory0, drg0) =
|
||||||
|
let (priv, drg1) = withDRG drg0 generateSecretKey
|
||||||
|
(msg, drg2) = withDRG drg1 $ getRandomBytes =<< ((fromIntegral . BS.head) `fmap` getRandomBytes 1)
|
||||||
|
pub = toPublic priv
|
||||||
|
privBytes = convert priv
|
||||||
|
pubBytes = convert pub
|
||||||
|
sig = convert (sign priv pub msg)
|
||||||
|
res = Map.fromList [("u", showBin pubBytes), ("r", showBin privBytes),
|
||||||
|
("m", showBin msg), ("s", showBin sig)]
|
||||||
|
in return (res, toNumber privBytes, (memory0, drg2))
|
||||||
|
|
||||||
|
|
||||||
|
data PackedBytes = PB [Word8]
|
||||||
|
deriving (Eq)
|
||||||
|
|
||||||
|
instance Storable PackedBytes where
|
||||||
|
sizeOf _ = 32
|
||||||
|
alignment _ = 8
|
||||||
|
peek p = PB `fmap` peekArray 32 (castPtr p)
|
||||||
|
poke p (PB v) = pokeArray (castPtr p) v
|
||||||
|
|
||||||
|
randomPackedBytes :: SystemRandom -> (Ptr PackedBytes -> SystemRandom -> IO a) -> IO a
|
||||||
|
randomPackedBytes drg action =
|
||||||
|
do let (bytes, drg') = withDRG drg (getRandomBytes 32)
|
||||||
|
useAsCString bytes $ \ ptr ->
|
||||||
|
do let ptr' = castPtr ptr :: Ptr PackedBytes
|
||||||
|
curve25519_scalar_mask ptr'
|
||||||
|
action ptr' drg'
|
||||||
|
|
||||||
|
repackBytes :: Ptr PackedBytes -> IO ByteString
|
||||||
|
repackBytes ptr =
|
||||||
|
do PB xs <- peek ptr
|
||||||
|
return (pack xs)
|
||||||
|
|
||||||
|
data Element = FE [Int32]
|
||||||
|
|
||||||
|
instance Storable Element where
|
||||||
|
sizeOf _ = 10 * sizeOf (undefined :: Int32)
|
||||||
|
alignment _ = 8
|
||||||
|
peek p = FE `fmap` peekArray 10 (castPtr p)
|
||||||
|
poke p (FE v) = pokeArray (castPtr p) v
|
||||||
|
|
||||||
|
randomElement :: SystemRandom -> (Ptr Element -> SystemRandom -> IO a) -> IO a
|
||||||
|
randomElement drg action =
|
||||||
|
randomPackedBytes drg $ \ ptrpb drg' -> alloca $ \ ptrel ->
|
||||||
|
do clearSpace ptrel
|
||||||
|
fe_frombytes ptrel ptrpb
|
||||||
|
action ptrel drg'
|
||||||
|
|
||||||
|
data Point3 = P3 [Element]
|
||||||
|
|
||||||
|
instance Storable Point3 where
|
||||||
|
sizeOf _ = 4 * sizeOf (undefined :: Element)
|
||||||
|
alignment _ = 8
|
||||||
|
peek p = P3 `fmap` peekArray 4 (castPtr p)
|
||||||
|
poke p (P3 v) = pokeArray (castPtr p) v
|
||||||
|
|
||||||
|
randomPoint3 :: SystemRandom -> (Ptr Point3 -> SystemRandom -> IO a) -> IO a
|
||||||
|
randomPoint3 drg0 action = allocaArray (4 * 10) (go drg0)
|
||||||
|
where
|
||||||
|
go drg dest =
|
||||||
|
do mres <- randomPackedBytes drg $ \ aptr drg' ->
|
||||||
|
do clearSpace dest
|
||||||
|
worked <- point_frombytes dest aptr
|
||||||
|
if worked
|
||||||
|
then Right `fmap` action (castPtr dest) drg'
|
||||||
|
else return (Left drg')
|
||||||
|
case mres of
|
||||||
|
Right x -> return x
|
||||||
|
Left drg' -> go drg' dest
|
||||||
|
|
||||||
|
data PointCached = PC [Element]
|
||||||
|
|
||||||
|
instance Storable PointCached where
|
||||||
|
sizeOf _ = 4 * sizeOf (undefined :: Element)
|
||||||
|
alignment _ = 8
|
||||||
|
peek p = PC `fmap` peekArray 4 (castPtr p)
|
||||||
|
poke p (PC v) = pokeArray (castPtr p) v
|
||||||
|
|
||||||
|
randomPointCached :: SystemRandom -> (Ptr PointCached -> SystemRandom -> IO a) -> IO a
|
||||||
|
randomPointCached drg action =
|
||||||
|
randomPoint3 drg $ \ ptr drg' ->
|
||||||
|
allocaArray (4 * 10) $ \ dest ->
|
||||||
|
do pokeArray (castPtr dest :: Ptr Int32) (replicate (4 * 10) 0)
|
||||||
|
p3_to_cached dest ptr
|
||||||
|
action (castPtr dest) drg'
|
||||||
|
|
||||||
|
data Point2 = P2 [Element]
|
||||||
|
|
||||||
|
instance Storable Point2 where
|
||||||
|
sizeOf _ = 3 * sizeOf (undefined :: Element)
|
||||||
|
alignment _ = 8
|
||||||
|
peek p = P2 `fmap` peekArray 3 (castPtr p)
|
||||||
|
poke p (P2 v) = pokeArray (castPtr p) v
|
||||||
|
|
||||||
|
randomPoint2 :: SystemRandom -> (Ptr Point2 -> SystemRandom -> IO a) -> IO a
|
||||||
|
randomPoint2 drg action =
|
||||||
|
randomPoint3 drg $ \ ptr3 drg' ->
|
||||||
|
allocaArray (3 * 10) $ \ dest ->
|
||||||
|
do pokeArray (castPtr dest :: Ptr Int32) (replicate (3 * 10) 0)
|
||||||
|
ge_p3_to_p2 dest ptr3
|
||||||
|
action (castPtr dest) drg'
|
||||||
|
|
||||||
|
data PointP1P1 = P1P1 [Element]
|
||||||
|
|
||||||
|
instance Storable PointP1P1 where
|
||||||
|
sizeOf _ = 4 * sizeOf (undefined :: Element)
|
||||||
|
alignment _ = 8
|
||||||
|
peek p = P1P1 `fmap` peekArray 4 (castPtr p)
|
||||||
|
poke p (P1P1 v) = pokeArray (castPtr p) v
|
||||||
|
|
||||||
|
_randomPointP1P1 :: SystemRandom -> (Ptr PointP1P1 -> SystemRandom -> IO a) -> IO a
|
||||||
|
_randomPointP1P1 drg action =
|
||||||
|
randomPoint3 drg $ \ ptr3 drg' ->
|
||||||
|
allocaArray (4 * 10) $ \ dest ->
|
||||||
|
do pokeArray (castPtr dest :: Ptr Int32) (replicate (4 * 10) 0)
|
||||||
|
ge_p3_dbl dest ptr3
|
||||||
|
action (castPtr dest) drg'
|
||||||
|
|
||||||
|
data PointPrecomp = PP [Element]
|
||||||
|
|
||||||
|
instance Storable PointPrecomp where
|
||||||
|
sizeOf _ = 4 * sizeOf (undefined :: Element)
|
||||||
|
alignment _ = 8
|
||||||
|
peek p = PP `fmap` peekArray 4 (castPtr p)
|
||||||
|
poke p (PP v) = pokeArray (castPtr p) v
|
||||||
|
|
||||||
|
randomPointPrecomp :: SystemRandom -> (Ptr PointPrecomp -> SystemRandom -> IO a) -> IO a
|
||||||
|
randomPointPrecomp drg action =
|
||||||
|
do let ([a,b,c,d], drg') = withDRG drg (BS.unpack `fmap` getRandomBytes 4)
|
||||||
|
mix = fromIntegral a + fromIntegral b + fromIntegral c + fromIntegral d
|
||||||
|
idx = mix `mod` (length precompPoints)
|
||||||
|
val = PP (map FE (precompPoints !! idx))
|
||||||
|
alloca $ \ ptr ->
|
||||||
|
do poke ptr val
|
||||||
|
action ptr drg'
|
||||||
|
|
||||||
|
clearSpace :: Storable a => Ptr a -> IO ()
|
||||||
|
clearSpace x = meh x undefined
|
||||||
|
where
|
||||||
|
meh :: Storable a => Ptr a -> a -> IO ()
|
||||||
|
meh p v = pokeArray (castPtr p) (replicate (sizeOf v) (0 :: Word8))
|
||||||
|
|
||||||
|
convertFE :: Ptr Element -> IO ByteString
|
||||||
|
convertFE feptr = pack `fmap` peekArray 40 (castPtr feptr :: Ptr Word8)
|
||||||
|
|
||||||
|
convertPoint :: Storable a => Ptr a -> IO ByteString
|
||||||
|
convertPoint x = meh x undefined
|
||||||
|
where
|
||||||
|
meh :: Storable a => Ptr a -> a -> IO ByteString
|
||||||
|
meh p v = pack `fmap` peekArray (sizeOf v) (castPtr p)
|
||||||
|
|
||||||
|
toNumber :: ByteString -> Integer
|
||||||
|
toNumber = BS.foldr (\ x a -> fromIntegral x + a) 0
|
||||||
|
|
||||||
|
foreign import ccall unsafe "load_3"
|
||||||
|
load_3 :: Ptr CChar -> IO Word64
|
||||||
|
foreign import ccall unsafe "load_4"
|
||||||
|
load_4 :: Ptr CChar -> IO Word64
|
||||||
|
foreign import ccall unsafe "GFp_curve25519_scalar_mask"
|
||||||
|
curve25519_scalar_mask :: Ptr PackedBytes -> IO ()
|
||||||
|
foreign import ccall unsafe "fe_frombytes"
|
||||||
|
fe_frombytes :: Ptr Element -> Ptr PackedBytes -> IO ()
|
||||||
|
foreign import ccall unsafe "GFp_fe_tobytes"
|
||||||
|
fe_tobytes :: Ptr PackedBytes -> Ptr Element -> IO ()
|
||||||
|
foreign import ccall unsafe "fe_add"
|
||||||
|
fe_add :: Ptr Element -> Ptr Element -> Ptr Element -> IO ()
|
||||||
|
foreign import ccall unsafe "fe_sub"
|
||||||
|
fe_sub :: Ptr Element -> Ptr Element -> Ptr Element -> IO ()
|
||||||
|
foreign import ccall unsafe "GFp_fe_mul"
|
||||||
|
fe_mul :: Ptr Element -> Ptr Element -> Ptr Element -> IO ()
|
||||||
|
foreign import ccall unsafe "fe_sq"
|
||||||
|
fe_square :: Ptr Element -> Ptr Element -> IO ()
|
||||||
|
foreign import ccall unsafe "GFp_fe_invert"
|
||||||
|
fe_invert :: Ptr Element -> Ptr Element -> IO ()
|
||||||
|
foreign import ccall unsafe "fe_neg"
|
||||||
|
fe_negate :: Ptr Element -> Ptr Element -> IO ()
|
||||||
|
foreign import ccall unsafe "fe_cmov"
|
||||||
|
fe_cmov :: Ptr Element -> Ptr Element -> Word32 -> IO ()
|
||||||
|
foreign import ccall unsafe "fe_isnonzero"
|
||||||
|
fe_isnonzero :: Ptr Element -> IO Int32
|
||||||
|
foreign import ccall unsafe "GFp_fe_isnegative"
|
||||||
|
fe_isnegative :: Ptr Element -> IO Word8
|
||||||
|
foreign import ccall unsafe "fe_sq2"
|
||||||
|
fe_square2 :: Ptr Element -> Ptr Element -> IO ()
|
||||||
|
foreign import ccall unsafe "fe_pow22523"
|
||||||
|
fe_pow22523 :: Ptr Element -> Ptr Element -> IO ()
|
||||||
|
foreign import ccall unsafe "GFp_x25519_ge_frombytes_vartime"
|
||||||
|
point_frombytes :: Ptr Point3 -> Ptr PackedBytes -> IO Bool
|
||||||
|
foreign import ccall unsafe "x25519_ge_p3_to_cached"
|
||||||
|
p3_to_cached :: Ptr PointCached -> Ptr Point3 -> IO ()
|
||||||
|
foreign import ccall unsafe "x25519_ge_p1p1_to_p2"
|
||||||
|
p1p1_to_p2 :: Ptr Point2 -> Ptr PointP1P1 -> IO ()
|
||||||
|
foreign import ccall unsafe "x25519_ge_p1p1_to_p3"
|
||||||
|
p1p1_to_p3 :: Ptr Point3 -> Ptr PointP1P1 -> IO ()
|
||||||
|
foreign import ccall unsafe "ge_p2_dbl"
|
||||||
|
ge_p2_dbl :: Ptr PointP1P1 -> Ptr Point2 -> IO ()
|
||||||
|
foreign import ccall unsafe "ge_p3_dbl"
|
||||||
|
ge_p3_dbl :: Ptr PointP1P1 -> Ptr Point3 -> IO ()
|
||||||
|
foreign import ccall unsafe "ge_p3_to_p2"
|
||||||
|
ge_p3_to_p2 :: Ptr Point2 -> Ptr Point3 -> IO ()
|
||||||
|
foreign import ccall unsafe "ge_madd"
|
||||||
|
ge_madd :: Ptr PointP1P1 -> Ptr Point3 -> Ptr PointPrecomp -> IO ()
|
||||||
|
foreign import ccall unsafe "ge_msub"
|
||||||
|
ge_msub :: Ptr PointP1P1 -> Ptr Point3 -> Ptr PointPrecomp -> IO ()
|
||||||
|
foreign import ccall unsafe "x25519_ge_add"
|
||||||
|
ge_add :: Ptr PointP1P1 -> Ptr Point3 -> Ptr PointCached -> IO ()
|
||||||
|
foreign import ccall unsafe "x25519_ge_sub"
|
||||||
|
ge_sub :: Ptr PointP1P1 -> Ptr Point3 -> Ptr PointCached -> IO ()
|
||||||
|
foreign import ccall unsafe "GFp_x25519_ge_scalarmult_base"
|
||||||
|
x25519_ge_scalarmult_base :: Ptr Point3 -> Ptr PackedBytes -> IO ()
|
||||||
|
foreign import ccall unsafe "slide"
|
||||||
|
slide :: Ptr Word8 -> Ptr PackedBytes -> IO ()
|
||||||
|
foreign import ccall unsafe "GFp_ge_double_scalarmult_vartime"
|
||||||
|
ge_double_scalarmult_vartime :: Ptr Point2 -> Ptr PackedBytes -> Ptr Point3 -> Ptr PackedBytes -> IO ()
|
||||||
|
foreign import ccall unsafe "GFp_x25519_sc_reduce"
|
||||||
|
sc_reduce :: Ptr Word8 -> IO ()
|
||||||
|
foreign import ccall unsafe "GFp_x25519_sc_muladd"
|
||||||
|
sc_muladd :: Ptr PackedBytes -> Ptr PackedBytes -> Ptr PackedBytes -> Ptr PackedBytes -> IO ()
|
||||||
|
foreign import ccall unsafe "GFp_x25519_public_from_private"
|
||||||
|
public_from_private :: Ptr PackedBytes -> Ptr PackedBytes -> IO ()
|
||||||
2120
test-generator/ED25519/PrecompPoints.hs
Normal file
2120
test-generator/ED25519/PrecompPoints.hs
Normal file
File diff suppressed because it is too large
Load Diff
44
test-generator/Main.hs
Normal file
44
test-generator/Main.hs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
import Control.Concurrent(forkIO)
|
||||||
|
import Control.Concurrent.Chan(Chan,newChan,readChan,writeChan)
|
||||||
|
import Control.Concurrent.MVar(MVar,newMVar,modifyMVar)
|
||||||
|
import Control.Exception(SomeException,catch)
|
||||||
|
import Control.Monad(replicateM_,void)
|
||||||
|
import "crypto-api" Crypto.Random(CryptoRandomGen(..),SystemRandom)
|
||||||
|
import DSA(dsaTasks)
|
||||||
|
import ECDSATesting(ecdsaTasks)
|
||||||
|
import ED25519(ed25519Tasks)
|
||||||
|
import GHC.Conc(getNumCapabilities)
|
||||||
|
import RFC6979(rfcTasks)
|
||||||
|
import RSA(rsaTasks)
|
||||||
|
import System.Console.AsciiProgress
|
||||||
|
import Task(Task, runTask)
|
||||||
|
|
||||||
|
taskExecutor :: MVar [Task] -> Chan () -> SystemRandom -> IO SystemRandom
|
||||||
|
taskExecutor taskList done gen =
|
||||||
|
do mnext <- modifyMVar taskList (\case
|
||||||
|
[] -> return ([], Nothing)
|
||||||
|
(x:xs) -> return (xs, Just x))
|
||||||
|
case mnext of
|
||||||
|
Nothing -> do writeChan done ()
|
||||||
|
return gen
|
||||||
|
Just x -> do gen' <- runTask gen x
|
||||||
|
taskExecutor taskList done gen'
|
||||||
|
|
||||||
|
spawnExecutor :: MVar [Task] -> Chan () -> IO ()
|
||||||
|
spawnExecutor tasks done =
|
||||||
|
do gen <- newGenIO
|
||||||
|
void (forkIO (catch (void (taskExecutor tasks done gen)) handler))
|
||||||
|
where
|
||||||
|
handler :: SomeException -> IO ()
|
||||||
|
handler e = putStrLn ("ERROR: " ++ show e)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = displayConsoleRegions $
|
||||||
|
do
|
||||||
|
executors <- getNumCapabilities
|
||||||
|
done <- newChan
|
||||||
|
tasks <- newMVar (dsaTasks ++ ecdsaTasks ++ rfcTasks ++ rsaTasks ++ ed25519Tasks)
|
||||||
|
replicateM_ executors (spawnExecutor tasks done)
|
||||||
|
replicateM_ executors (void $ readChan done)
|
||||||
166
test-generator/Math.hs
Normal file
166
test-generator/Math.hs
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
module Math(
|
||||||
|
extendedGCD
|
||||||
|
, barrett, computeK, base
|
||||||
|
, modulate, modulate'
|
||||||
|
, isqrt
|
||||||
|
, divmod
|
||||||
|
, showX, showB, showBin
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Data.Bits(shiftL,shiftR,(.&.))
|
||||||
|
import qualified Data.ByteString as S
|
||||||
|
import GHC.Integer.GMP.Internals(recipModInteger)
|
||||||
|
import Numeric(showHex)
|
||||||
|
|
||||||
|
data AlgState = AlgState {
|
||||||
|
u :: Integer,
|
||||||
|
v :: Integer,
|
||||||
|
bigA :: Integer,
|
||||||
|
bigB :: Integer,
|
||||||
|
bigC :: Integer,
|
||||||
|
bigD :: Integer
|
||||||
|
}
|
||||||
|
|
||||||
|
printState :: AlgState -> IO ()
|
||||||
|
printState a =
|
||||||
|
do putStrLn ("u: " ++ showX (u a))
|
||||||
|
putStrLn ("v: " ++ showX (v a))
|
||||||
|
putStrLn ("A: " ++ showX (bigA a))
|
||||||
|
putStrLn ("B: " ++ showX (bigB a))
|
||||||
|
putStrLn ("C: " ++ showX (bigC a))
|
||||||
|
putStrLn ("D: " ++ showX (bigD a))
|
||||||
|
|
||||||
|
extendedGCD :: Integer -> Integer -> (Integer, Integer, Integer)
|
||||||
|
extendedGCD x y = (a, b, g * (v finalState))
|
||||||
|
where
|
||||||
|
(x', y', g, initState) = initialState x y 1
|
||||||
|
finalState = runAlgorithm x' y' initState
|
||||||
|
a = bigC finalState
|
||||||
|
b = bigD finalState
|
||||||
|
|
||||||
|
initialState :: Integer -> Integer -> Integer -> (Integer, Integer, Integer, AlgState)
|
||||||
|
initialState x y g | even x && even y = initialState (x `div` 2) (y `div` 2) (g * 2)
|
||||||
|
| otherwise = (x, y, g, AlgState x y 1 0 0 1)
|
||||||
|
|
||||||
|
runAlgorithm :: Integer -> Integer -> AlgState -> AlgState
|
||||||
|
runAlgorithm x y state | u state == 0 = state
|
||||||
|
| otherwise = runAlgorithm x y state6
|
||||||
|
where
|
||||||
|
state4 = step4 x y state
|
||||||
|
state5 = step5 x y state4
|
||||||
|
state6 = step6 state5
|
||||||
|
|
||||||
|
step4 :: Integer -> Integer -> AlgState -> AlgState
|
||||||
|
step4 x y input@AlgState{..} | even u = step4 x y input'
|
||||||
|
| otherwise = input
|
||||||
|
where
|
||||||
|
input' = AlgState u' v bigA' bigB' bigC bigD
|
||||||
|
u' = u `div` 2
|
||||||
|
bigA' | even bigA && even bigB = bigA `div` 2
|
||||||
|
| otherwise = (bigA + y) `div` 2
|
||||||
|
bigB' | even bigA && even bigB = bigB `div` 2
|
||||||
|
| otherwise = (bigB - x) `div` 2
|
||||||
|
|
||||||
|
step5 :: Integer -> Integer -> AlgState -> AlgState
|
||||||
|
step5 x y input@AlgState{..} | even v = step5 x y input'
|
||||||
|
| otherwise = input
|
||||||
|
where
|
||||||
|
input' = AlgState u v' bigA bigB bigC' bigD'
|
||||||
|
v' = v `div` 2
|
||||||
|
bigC' | even bigC && even bigD = bigC `div` 2
|
||||||
|
| otherwise = (bigC + y) `div` 2
|
||||||
|
bigD' | even bigC && even bigD = bigD `div` 2
|
||||||
|
| otherwise = (bigD - x) `div` 2
|
||||||
|
|
||||||
|
step6 :: AlgState -> AlgState
|
||||||
|
step6 AlgState{..}
|
||||||
|
| u >= v = AlgState (u - v) v (bigA - bigC) (bigB - bigD) bigC bigD
|
||||||
|
| otherwise = AlgState u (v - u) bigA bigB (bigC - bigA) (bigD - bigB)
|
||||||
|
|
||||||
|
barrett :: Integer -> Integer
|
||||||
|
barrett m = (base ^ (2 * k)) `div` m
|
||||||
|
where
|
||||||
|
k = computeK m
|
||||||
|
|
||||||
|
computeK :: Integer -> Int
|
||||||
|
computeK v = go 0 1
|
||||||
|
where
|
||||||
|
go k acc | v <= acc = k
|
||||||
|
| otherwise = go (k + 1) (acc * base)
|
||||||
|
|
||||||
|
base :: Integer
|
||||||
|
base = 2 ^ (64 :: Integer)
|
||||||
|
|
||||||
|
modulate :: Integer -> Int -> Integer
|
||||||
|
modulate x size = x `mod` (2 ^ size)
|
||||||
|
|
||||||
|
modulate' :: Integer -> Int -> Integer
|
||||||
|
modulate' x size = signum x * (abs x `mod` (2 ^ size))
|
||||||
|
|
||||||
|
showX :: (Integral a, Show a) => a -> String
|
||||||
|
showX x | x < 0 = "-" ++ showX (abs x)
|
||||||
|
| otherwise = showHex x ""
|
||||||
|
|
||||||
|
showB :: Bool -> String
|
||||||
|
showB False = "0"
|
||||||
|
showB True = "1"
|
||||||
|
|
||||||
|
showBin :: S.ByteString -> String
|
||||||
|
showBin bstr =
|
||||||
|
case S.uncons bstr of
|
||||||
|
Nothing -> ""
|
||||||
|
Just (x,rest) ->
|
||||||
|
showX (x `shiftR` 4) ++ showX (x .&. 0xF) ++ showBin rest
|
||||||
|
|
||||||
|
isqrt :: Int -> Integer -> Integer
|
||||||
|
isqrt bits val = final
|
||||||
|
where
|
||||||
|
bit' = part1 (1 `shiftL` (bits - 2))
|
||||||
|
--
|
||||||
|
part1 x | x > val = part1 (x `shiftR` 2)
|
||||||
|
| otherwise = x
|
||||||
|
--
|
||||||
|
final = loop val 0 bit'
|
||||||
|
--
|
||||||
|
loop num res bit
|
||||||
|
| bit == 0 = res
|
||||||
|
| otherwise = let (num', res') = adjust num res bit
|
||||||
|
in loop num' (res' `shiftR` 1) (bit `shiftR` 2)
|
||||||
|
adjust num res bit
|
||||||
|
| num >= (res + bit) = (num - (res + bit), res + (bit `shiftL` 1))
|
||||||
|
| otherwise = (num, res)
|
||||||
|
|
||||||
|
divmod :: Integer -> Integer -> Integer -> Maybe Integer
|
||||||
|
divmod x y m =
|
||||||
|
let y' = y `mod` m
|
||||||
|
in case recipModInteger y' m of
|
||||||
|
0 -> Nothing
|
||||||
|
i -> Just ((x * i) `mod` m)
|
||||||
|
|
||||||
|
_run :: Integer -> Integer -> IO ()
|
||||||
|
_run inputx inputy =
|
||||||
|
do let (x, y, g, initState) = initialState inputx inputy 1
|
||||||
|
finalState <- go x y initState
|
||||||
|
putStrLn ("-- FINAL STATE -----------------------")
|
||||||
|
printState finalState
|
||||||
|
putStrLn ("Final value: " ++ showX (g * v finalState))
|
||||||
|
putStrLn ("-- RUN ------")
|
||||||
|
printState (runAlgorithm x y initState)
|
||||||
|
putStrLn ("-- NORMAL ------")
|
||||||
|
let (a, b, v) = extendedGCD inputx inputy
|
||||||
|
putStrLn ("a: " ++ showX a)
|
||||||
|
putStrLn ("b: " ++ showX b)
|
||||||
|
putStrLn ("v: " ++ showX v)
|
||||||
|
|
||||||
|
where
|
||||||
|
go x y state =
|
||||||
|
do putStrLn "-- STATE -----------------------------"
|
||||||
|
printState state
|
||||||
|
if u state == 0
|
||||||
|
then return state
|
||||||
|
else do let state' = step4 x y state
|
||||||
|
state'' = step5 x y state'
|
||||||
|
state''' = step6 state''
|
||||||
|
go x y state'''
|
||||||
113
test-generator/RFC6979.hs
Normal file
113
test-generator/RFC6979.hs
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
module RFC6979
|
||||||
|
-- (
|
||||||
|
-- rfcTasks
|
||||||
|
-- )
|
||||||
|
where
|
||||||
|
|
||||||
|
import Crypto.Hash(SHA224(..),SHA256(..),SHA384(..),SHA512(..))
|
||||||
|
import Crypto.MAC.HMAC(HMAC,hmac)
|
||||||
|
import Crypto.Number.Generate(generateBetween)
|
||||||
|
import "cryptonite" Crypto.Random(getRandomBytes,withDRG)
|
||||||
|
import Data.Bits(shiftL,shiftR,(.&.))
|
||||||
|
import qualified Data.ByteArray as B
|
||||||
|
import qualified Data.ByteString as S
|
||||||
|
import Data.Char(toUpper)
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import Math(showBin,showX)
|
||||||
|
import Task(Task(..),liftTest)
|
||||||
|
import Utils(HashAlg(..), runHash)
|
||||||
|
|
||||||
|
|
||||||
|
runHMAC :: HashAlg -> S.ByteString -> S.ByteString -> S.ByteString
|
||||||
|
runHMAC Sha224 key msg = S.pack (B.unpack (hmac key msg :: HMAC SHA224))
|
||||||
|
runHMAC Sha256 key msg = S.pack (B.unpack (hmac key msg :: HMAC SHA256))
|
||||||
|
runHMAC Sha384 key msg = S.pack (B.unpack (hmac key msg :: HMAC SHA384))
|
||||||
|
runHMAC Sha512 key msg = S.pack (B.unpack (hmac key msg :: HMAC SHA512))
|
||||||
|
|
||||||
|
generateKStream :: HashAlg -> S.ByteString -> Integer -> Integer -> Int -> [Integer]
|
||||||
|
generateKStream alg m x q qlen = nextK bigK2 bigV2
|
||||||
|
where
|
||||||
|
h1 = runHash alg m
|
||||||
|
bigV0 = S.replicate (S.length h1) 0x01
|
||||||
|
bigK0 = S.replicate (S.length h1) 0x00
|
||||||
|
seed1 = S.concat [bigV0, S.singleton 0x00, int2octets qlen x, bits2octets qlen q h1]
|
||||||
|
bigK1 = runHMAC alg bigK0 seed1
|
||||||
|
bigV1 = runHMAC alg bigK1 bigV0
|
||||||
|
seed2 = S.concat [bigV1, S.singleton 0x01, int2octets qlen x, bits2octets qlen q h1]
|
||||||
|
bigK2 = runHMAC alg bigK1 seed2
|
||||||
|
bigV2 = runHMAC alg bigK2 bigV1
|
||||||
|
--
|
||||||
|
nextK bigK bigV =
|
||||||
|
let (bigV', bigT) = buildT bigK bigV S.empty
|
||||||
|
k = bits2int qlen bigT
|
||||||
|
bigK' = runHMAC alg bigK (bigV' `S.append` S.singleton 0)
|
||||||
|
bigV'' = runHMAC alg bigK' bigV'
|
||||||
|
in if k < q then (k : nextK bigK' bigV'') else nextK bigK' bigV''
|
||||||
|
buildT bigK bigV bigT
|
||||||
|
| S.length bigT * 8 >= qlen = (bigV, bigT)
|
||||||
|
| otherwise =
|
||||||
|
let bigV' = runHMAC alg bigK bigV
|
||||||
|
in buildT bigK bigV' (bigT `S.append` bigV')
|
||||||
|
|
||||||
|
bits2int :: Int -> S.ByteString -> Integer
|
||||||
|
bits2int qlen bstr = reduce (go bstr 0)
|
||||||
|
where
|
||||||
|
reduce x =
|
||||||
|
let vlen = S.length bstr * 8
|
||||||
|
in if vlen > qlen
|
||||||
|
then x `shiftR` (vlen - qlen)
|
||||||
|
else x
|
||||||
|
--
|
||||||
|
go x acc =
|
||||||
|
case S.uncons x of
|
||||||
|
Nothing -> acc
|
||||||
|
Just (v, rest) ->
|
||||||
|
go rest ((acc `shiftL` 8) + fromIntegral v)
|
||||||
|
|
||||||
|
int2octets :: Int -> Integer -> S.ByteString
|
||||||
|
int2octets lenBits x =
|
||||||
|
S.pack (pad (rlen `div` 8) (reverse (go x)))
|
||||||
|
where
|
||||||
|
rlen = 8 * ((lenBits + 7) `div` 8)
|
||||||
|
pad target ls
|
||||||
|
| length ls > target = drop (length ls - target) ls
|
||||||
|
| length ls < target = pad target (0 : ls)
|
||||||
|
| otherwise = ls
|
||||||
|
--
|
||||||
|
go 0 = []
|
||||||
|
go v = (fromIntegral (v .&. 0xFF)) : go (v `shiftR` 8)
|
||||||
|
|
||||||
|
bits2octets :: Int -> Integer -> S.ByteString -> S.ByteString
|
||||||
|
bits2octets qlen q bstr =
|
||||||
|
let z1 = bits2int qlen bstr
|
||||||
|
z2 = if z1 > q then z1 - q else z1
|
||||||
|
in int2octets qlen z2
|
||||||
|
|
||||||
|
rfc6979Test :: HashAlg -> Task
|
||||||
|
rfc6979Test alg = Task {
|
||||||
|
taskName = name ++ " RFC 6979 deterministic k-generation",
|
||||||
|
taskFile = "../testdata/rfc6979/" ++ name ++ ".test",
|
||||||
|
taskTest = liftTest go,
|
||||||
|
taskCount = 1000
|
||||||
|
}
|
||||||
|
where
|
||||||
|
name = map toUpper (show alg)
|
||||||
|
go (memory0, drg0) =
|
||||||
|
let (qlen, drg1) = withDRG drg0 $ generateBetween 160 521
|
||||||
|
(key, drg2) = withDRG drg1 $ generateBetween 1 ((2 ^ qlen) - 1)
|
||||||
|
(q, drg3) = withDRG drg2 $ generateBetween 1 ((2 ^ qlen) - 1)
|
||||||
|
(dataSize, drg4) = withDRG drg3 $ generateBetween 1 1024
|
||||||
|
(msg, drg5) = withDRG drg4 $ getRandomBytes (fromIntegral dataSize)
|
||||||
|
h1 = runHash alg msg
|
||||||
|
ks = generateKStream alg msg key q (fromIntegral qlen)
|
||||||
|
res = Map.fromList [("q", showX q), ("l", showX qlen),
|
||||||
|
("x", showX key), ("h", showBin h1),
|
||||||
|
("k", showX (ks !! 0)),
|
||||||
|
("y", showX (ks !! 1)),
|
||||||
|
("z", showX (ks !! 2))]
|
||||||
|
in (res, qlen, (memory0, drg5))
|
||||||
|
|
||||||
|
rfcTasks :: [Task]
|
||||||
|
rfcTasks = [rfc6979Test Sha224, rfc6979Test Sha256,
|
||||||
|
rfc6979Test Sha384, rfc6979Test Sha512]
|
||||||
126
test-generator/RSA.hs
Normal file
126
test-generator/RSA.hs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
module RSA(rsaTasks)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Crypto.Hash(SHA224(..),SHA256(..),SHA384(..),SHA512(..))
|
||||||
|
import "cryptonite" Crypto.Random(MonadRandom,MonadPseudoRandom,getRandomBytes,withDRG)
|
||||||
|
import "crypto-api" Crypto.Random(SystemRandom)
|
||||||
|
import Crypto.PubKey.MaskGenFunction(mgf1)
|
||||||
|
import Crypto.PubKey.RSA
|
||||||
|
import Crypto.PubKey.RSA.PKCS15(sign)
|
||||||
|
import Crypto.PubKey.RSA.OAEP(OAEPParams(..),encrypt)
|
||||||
|
import qualified Data.ByteString as BS
|
||||||
|
import qualified Data.ByteString.Char8 as BSC
|
||||||
|
import Data.Char(chr,isPrint)
|
||||||
|
import Data.Map.Strict(Map)
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import Data.Maybe(fromMaybe,isJust)
|
||||||
|
import Data.Word(Word8)
|
||||||
|
import Database(Database)
|
||||||
|
import Math(barrett,computeK,showX,showBin)
|
||||||
|
import Task(Task(..),liftTest)
|
||||||
|
import Utils(HashAlg(..),generateHash,showHash)
|
||||||
|
|
||||||
|
rsaSizes :: [(Int, Int)]
|
||||||
|
rsaSizes = [(512, 400),
|
||||||
|
(1024, 200),
|
||||||
|
(2048, 100),
|
||||||
|
(3072, 50),
|
||||||
|
(4096, 50),
|
||||||
|
(8192, 10),
|
||||||
|
(15360, 5)]
|
||||||
|
|
||||||
|
rsaTasks :: [Task]
|
||||||
|
rsaTasks = concatMap generateTask rsaSizes
|
||||||
|
|
||||||
|
generateTask :: (Int, Int) -> [Task]
|
||||||
|
generateTask (s, c) = [signTest s c, encryptTest s c]
|
||||||
|
|
||||||
|
signTest :: Int -> Int -> Task
|
||||||
|
signTest sz cnt = Task {
|
||||||
|
taskName = "RSA " ++ show sz ++ " signing",
|
||||||
|
taskFile = "../testdata/rsa/sign" ++ show sz ++ ".test",
|
||||||
|
taskTest = liftTest go,
|
||||||
|
taskCount = cnt
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go db = withDRG' db go2
|
||||||
|
--
|
||||||
|
go2 :: MonadRandom m => m (Map String String, Integer)
|
||||||
|
go2 = do (public, private) <- generate (sz `div` 8) 65537
|
||||||
|
let d = private_d private
|
||||||
|
let n = public_n public
|
||||||
|
msg <- getRandomBytes =<< ((fromIntegral . BS.head) `fmap` getRandomBytes 1)
|
||||||
|
hash <- generateHash
|
||||||
|
case signWith hash private msg of
|
||||||
|
Left _ -> go2
|
||||||
|
Right sig -> return $ (Map.fromList [("d", showX d),
|
||||||
|
("n", showX n),
|
||||||
|
("k", showX (computeK n)),
|
||||||
|
("u", showX (barrett n)),
|
||||||
|
("h", showHash hash),
|
||||||
|
("m", showBin msg),
|
||||||
|
("s", showBin sig)], n)
|
||||||
|
|
||||||
|
withDRG' :: Database -> MonadPseudoRandom SystemRandom (Map String String, Integer) ->
|
||||||
|
(Map String String, Integer, Database)
|
||||||
|
withDRG' (memory, drg) action =
|
||||||
|
let ((res, n), drg') = withDRG drg action
|
||||||
|
in (res, n, (memory, drg'))
|
||||||
|
|
||||||
|
signWith :: HashAlg -> PrivateKey -> BS.ByteString -> Either Error BS.ByteString
|
||||||
|
signWith Sha224 = sign Nothing (Just SHA224)
|
||||||
|
signWith Sha256 = sign Nothing (Just SHA256)
|
||||||
|
signWith Sha384 = sign Nothing (Just SHA384)
|
||||||
|
signWith Sha512 = sign Nothing (Just SHA512)
|
||||||
|
|
||||||
|
encryptTest :: Int -> Int -> Task
|
||||||
|
encryptTest sz cnt = Task {
|
||||||
|
taskName = "RSA " ++ show sz ++ " encryption",
|
||||||
|
taskFile = "../testdata/rsa/encrypt" ++ show sz ++ ".test",
|
||||||
|
taskTest = liftTest go,
|
||||||
|
taskCount = cnt
|
||||||
|
}
|
||||||
|
where
|
||||||
|
go db = withDRG' db go2
|
||||||
|
go2 = do (public, private) <- generate (sz `div` 8) 65537
|
||||||
|
let d = private_d private
|
||||||
|
let n = public_n public
|
||||||
|
msg <- getRandomBytes =<< ((fromIntegral . BS.head) `fmap` getRandomBytes 1)
|
||||||
|
hash <- generateHash
|
||||||
|
label <- do len <- BS.head `fmap` getRandomBytes 1
|
||||||
|
if odd len
|
||||||
|
then return Nothing
|
||||||
|
else Just `fmap` genASCII (len `div` 2)
|
||||||
|
let labelbstr = fromMaybe BS.empty (BSC.pack `fmap` label)
|
||||||
|
labelAlive = if isJust label then 1 else (0 :: Integer)
|
||||||
|
res <- encryptWith hash (BSC.pack `fmap` label) public msg
|
||||||
|
case res of
|
||||||
|
Left _ -> go2
|
||||||
|
Right cipher ->
|
||||||
|
return $ (Map.fromList [("d", showX d),
|
||||||
|
("n", showX n),
|
||||||
|
("k", showX (computeK n)),
|
||||||
|
("u", showX (barrett n)),
|
||||||
|
("h", showHash hash),
|
||||||
|
("m", showBin msg),
|
||||||
|
("l", showBin labelbstr),
|
||||||
|
("e", showX labelAlive),
|
||||||
|
("c", showBin cipher)], n)
|
||||||
|
|
||||||
|
genASCII :: MonadRandom m => Word8 -> m String
|
||||||
|
genASCII 0 = return ""
|
||||||
|
genASCII x =
|
||||||
|
do v <- (BS.head `fmap` getRandomBytes 1)
|
||||||
|
let c = chr (fromIntegral v)
|
||||||
|
if (v < 128) && isPrint c
|
||||||
|
then (c :) `fmap` genASCII (x - 1)
|
||||||
|
else genASCII x
|
||||||
|
|
||||||
|
encryptWith :: MonadRandom m =>
|
||||||
|
HashAlg -> Maybe BS.ByteString -> PublicKey -> BS.ByteString ->
|
||||||
|
m (Either Error BS.ByteString)
|
||||||
|
encryptWith Sha224 mlabel = encrypt (OAEPParams SHA224 (mgf1 SHA224) mlabel)
|
||||||
|
encryptWith Sha256 mlabel = encrypt (OAEPParams SHA256 (mgf1 SHA256) mlabel)
|
||||||
|
encryptWith Sha384 mlabel = encrypt (OAEPParams SHA384 (mgf1 SHA384) mlabel)
|
||||||
|
encryptWith Sha512 mlabel = encrypt (OAEPParams SHA512 (mgf1 SHA512) mlabel)
|
||||||
56
test-generator/Task.hs
Normal file
56
test-generator/Task.hs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
module Task(
|
||||||
|
Test,
|
||||||
|
Task(..),
|
||||||
|
runTask,
|
||||||
|
liftTest
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Control.Monad(foldM, forM_)
|
||||||
|
import "crypto-api" Crypto.Random(SystemRandom)
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import Database
|
||||||
|
import System.Console.AsciiProgress
|
||||||
|
import System.Directory(createDirectoryIfMissing,doesFileExist)
|
||||||
|
import System.FilePath(takeDirectory)
|
||||||
|
import System.IO(Handle,IOMode(..),hPutStrLn,withFile)
|
||||||
|
|
||||||
|
type Test = Database -> IO (Map.Map String String, Integer, Database)
|
||||||
|
|
||||||
|
data Task = Task {
|
||||||
|
taskName :: String,
|
||||||
|
taskFile :: FilePath,
|
||||||
|
taskTest :: Test,
|
||||||
|
taskCount :: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
liftTest :: (Database -> (Map.Map String String, Integer, Database)) ->
|
||||||
|
(Database -> IO (Map.Map String String, Integer, Database))
|
||||||
|
liftTest f db = return (f db)
|
||||||
|
|
||||||
|
runTask :: SystemRandom -> Task -> IO SystemRandom
|
||||||
|
runTask gen task =
|
||||||
|
do createDirectoryIfMissing True (takeDirectory (taskFile task))
|
||||||
|
alreadyDone <- doesFileExist (taskFile task)
|
||||||
|
if alreadyDone
|
||||||
|
then return gen
|
||||||
|
else withFile (taskFile task) WriteMode $ \ hndl ->
|
||||||
|
do pg <- newProgressBar def{ pgOnCompletion = Just ("Finished " ++ taskName task),
|
||||||
|
pgFormat = taskName task ++ " " ++ pgFormat def,
|
||||||
|
pgTotal = fromIntegral (taskCount task) }
|
||||||
|
let initval = emptyDatabase gen
|
||||||
|
(_, gen') <- foldM (writer hndl pg (taskTest task)) initval [0..taskCount task]
|
||||||
|
return gen'
|
||||||
|
where
|
||||||
|
writer :: Handle -> ProgressBar -> Test -> Database -> Int -> IO Database
|
||||||
|
writer hndl pg runner db x =
|
||||||
|
do (output, key, acc@(db',gen')) <- runner db
|
||||||
|
let before = Map.findWithDefault [] "RESULT" db'
|
||||||
|
if length (filter (== key) before) >= 10
|
||||||
|
then writer hndl pg runner acc x
|
||||||
|
else do forM_ (Map.toList output) $ \ (outkey, val) ->
|
||||||
|
hPutStrLn hndl (outkey ++ ": " ++ val)
|
||||||
|
tick pg
|
||||||
|
return (Map.insert "RESULT" (key : before) db', gen')
|
||||||
|
|
||||||
35
test-generator/Utils.hs
Normal file
35
test-generator/Utils.hs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{-# LANGUAGE PackageImports #-}
|
||||||
|
module Utils(HashAlg(..), generateHash, runHash, showHash)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Crypto.Hash(Digest,SHA224(..),SHA256(..),SHA384(..),SHA512(..),hash)
|
||||||
|
import Crypto.Number.Generate(generateBetween)
|
||||||
|
import "cryptonite" Crypto.Random(MonadRandom)
|
||||||
|
import qualified Data.ByteArray as B
|
||||||
|
import qualified Data.ByteString as S
|
||||||
|
import Math(showX)
|
||||||
|
|
||||||
|
data HashAlg = Sha224 | Sha256 | Sha384 | Sha512
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
||||||
|
runHash :: HashAlg -> S.ByteString -> S.ByteString
|
||||||
|
runHash Sha224 x = S.pack (B.unpack (hash x :: Digest SHA224))
|
||||||
|
runHash Sha256 x = S.pack (B.unpack (hash x :: Digest SHA256))
|
||||||
|
runHash Sha384 x = S.pack (B.unpack (hash x :: Digest SHA384))
|
||||||
|
runHash Sha512 x = S.pack (B.unpack (hash x :: Digest SHA512))
|
||||||
|
|
||||||
|
showHash :: HashAlg -> String
|
||||||
|
showHash Sha224 = showX (224 :: Int)
|
||||||
|
showHash Sha256 = showX (256 :: Int)
|
||||||
|
showHash Sha384 = showX (384 :: Int)
|
||||||
|
showHash Sha512 = showX (512 :: Int)
|
||||||
|
|
||||||
|
generateHash :: MonadRandom m => m HashAlg
|
||||||
|
generateHash =
|
||||||
|
do x <- generateBetween 0 3
|
||||||
|
case x of
|
||||||
|
0 -> return Sha224
|
||||||
|
1 -> return Sha256
|
||||||
|
2 -> return Sha384
|
||||||
|
3 -> return Sha512
|
||||||
|
_ -> fail "Incompatible random number"
|
||||||
96
test-generator/cbits/GFp/aes.h
Normal file
96
test-generator/cbits/GFp/aes.h
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
* Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* 3. All advertising materials mentioning features or use of this
|
||||||
|
* software must display the following acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* prior written permission. For written permission, please contact
|
||||||
|
* openssl-core@openssl.org.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called "OpenSSL"
|
||||||
|
* nor may "OpenSSL" appear in their names without prior written
|
||||||
|
* permission of the OpenSSL Project.
|
||||||
|
*
|
||||||
|
* 6. Redistributions of any form whatsoever must retain the following
|
||||||
|
* acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||||
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||||
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
* ==================================================================== */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_AES_H
|
||||||
|
#define OPENSSL_HEADER_AES_H
|
||||||
|
|
||||||
|
#include <GFp/base.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Raw AES functions. */
|
||||||
|
|
||||||
|
|
||||||
|
#define AES_ENCRYPT 1
|
||||||
|
#define AES_DECRYPT 0
|
||||||
|
|
||||||
|
/* AES_MAXNR is the maximum number of AES rounds. */
|
||||||
|
#define AES_MAXNR 14
|
||||||
|
|
||||||
|
#define AES_BLOCK_SIZE 16
|
||||||
|
|
||||||
|
/* aes_key_st should be an opaque type, but EVP requires that the size be
|
||||||
|
* known. */
|
||||||
|
struct aes_key_st {
|
||||||
|
uint32_t rd_key[4 * (AES_MAXNR + 1)];
|
||||||
|
unsigned rounds;
|
||||||
|
};
|
||||||
|
typedef struct aes_key_st AES_KEY;
|
||||||
|
|
||||||
|
/* GFp_AES_set_encrypt_key configures |aeskey| to encrypt with the |bits|-bit
|
||||||
|
* key, |key|.
|
||||||
|
*
|
||||||
|
* WARNING: unlike other OpenSSL functions, this returns zero on success and a
|
||||||
|
* negative number on error. */
|
||||||
|
OPENSSL_EXPORT int GFp_AES_set_encrypt_key(const uint8_t *key, unsigned bits,
|
||||||
|
AES_KEY *aeskey);
|
||||||
|
|
||||||
|
/* AES_encrypt encrypts a single block from |in| to |out| with |key|. The |in|
|
||||||
|
* and |out| pointers may overlap. */
|
||||||
|
OPENSSL_EXPORT void GFp_AES_encrypt(const uint8_t *in, uint8_t *out,
|
||||||
|
const AES_KEY *key);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} /* extern C */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* OPENSSL_HEADER_AES_H */
|
||||||
123
test-generator/cbits/GFp/arm_arch.h
Normal file
123
test-generator/cbits/GFp/arm_arch.h
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
* Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* 3. All advertising materials mentioning features or use of this
|
||||||
|
* software must display the following acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* prior written permission. For written permission, please contact
|
||||||
|
* openssl-core@openssl.org.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called "OpenSSL"
|
||||||
|
* nor may "OpenSSL" appear in their names without prior written
|
||||||
|
* permission of the OpenSSL Project.
|
||||||
|
*
|
||||||
|
* 6. Redistributions of any form whatsoever must retain the following
|
||||||
|
* acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||||
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||||
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This product includes cryptographic software written by Eric Young
|
||||||
|
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||||
|
* Hudson (tjh@cryptsoft.com). */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_ARM_ARCH_H
|
||||||
|
#define OPENSSL_HEADER_ARM_ARCH_H
|
||||||
|
|
||||||
|
#if !defined(__ARM_ARCH__)
|
||||||
|
# if defined(__CC_ARM)
|
||||||
|
# define __ARM_ARCH__ __TARGET_ARCH_ARM
|
||||||
|
# if defined(__BIG_ENDIAN)
|
||||||
|
# define __ARMEB__
|
||||||
|
# else
|
||||||
|
# define __ARMEL__
|
||||||
|
# endif
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
# if defined(__aarch64__)
|
||||||
|
# define __ARM_ARCH__ 8
|
||||||
|
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
# define __ARMEB__
|
||||||
|
# else
|
||||||
|
# define __ARMEL__
|
||||||
|
# endif
|
||||||
|
/* Why doesn't gcc define __ARM_ARCH__? Instead it defines
|
||||||
|
* bunch of below macros. See all_architectires[] table in
|
||||||
|
* gcc/config/arm/arm.c. On a side note it defines
|
||||||
|
* __ARMEL__/__ARMEB__ for little-/big-endian. */
|
||||||
|
# elif defined(__ARM_ARCH)
|
||||||
|
# define __ARM_ARCH__ __ARM_ARCH
|
||||||
|
# elif defined(__ARM_ARCH_8A__)
|
||||||
|
# define __ARM_ARCH__ 8
|
||||||
|
# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
|
||||||
|
defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \
|
||||||
|
defined(__ARM_ARCH_7EM__)
|
||||||
|
# define __ARM_ARCH__ 7
|
||||||
|
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
|
||||||
|
defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__) || \
|
||||||
|
defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__) || \
|
||||||
|
defined(__ARM_ARCH_6T2__)
|
||||||
|
# define __ARM_ARCH__ 6
|
||||||
|
# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \
|
||||||
|
defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__) || \
|
||||||
|
defined(__ARM_ARCH_5TEJ__)
|
||||||
|
# define __ARM_ARCH__ 5
|
||||||
|
# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
|
||||||
|
# define __ARM_ARCH__ 4
|
||||||
|
# else
|
||||||
|
# error "unsupported ARM architecture"
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Even when building for 32-bit ARM, support for aarch64 crypto instructions
|
||||||
|
* will be included. */
|
||||||
|
#if !defined(__ARM_MAX_ARCH__)
|
||||||
|
#define __ARM_MAX_ARCH__ 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ARMV7_NEON is true when a NEON unit is present in the current CPU. */
|
||||||
|
#define ARMV7_NEON (1 << 0)
|
||||||
|
|
||||||
|
/* ARMV8_AES indicates support for hardware AES instructions. */
|
||||||
|
#define ARMV8_AES (1 << 2)
|
||||||
|
|
||||||
|
/* ARMV8_SHA1 indicates support for hardware SHA-1 instructions. */
|
||||||
|
#define ARMV8_SHA1 (1 << 3)
|
||||||
|
|
||||||
|
/* ARMV8_SHA256 indicates support for hardware SHA-256 instructions. */
|
||||||
|
#define ARMV8_SHA256 (1 << 4)
|
||||||
|
|
||||||
|
/* ARMV8_PMULL indicates support for carryless multiplication. */
|
||||||
|
#define ARMV8_PMULL (1 << 5)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* OPENSSL_HEADER_ARM_ARCH_H */
|
||||||
122
test-generator/cbits/GFp/base.h
Normal file
122
test-generator/cbits/GFp/base.h
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* 3. All advertising materials mentioning features or use of this
|
||||||
|
* software must display the following acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* prior written permission. For written permission, please contact
|
||||||
|
* openssl-core@openssl.org.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called "OpenSSL"
|
||||||
|
* nor may "OpenSSL" appear in their names without prior written
|
||||||
|
* permission of the OpenSSL Project.
|
||||||
|
*
|
||||||
|
* 6. Redistributions of any form whatsoever must retain the following
|
||||||
|
* acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||||
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||||
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This product includes cryptographic software written by Eric Young
|
||||||
|
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||||
|
* Hudson (tjh@cryptsoft.com). */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_BASE_H
|
||||||
|
#define OPENSSL_HEADER_BASE_H
|
||||||
|
|
||||||
|
|
||||||
|
/* This file should be the first included by all BoringSSL headers. */
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64)
|
||||||
|
#define OPENSSL_64_BIT
|
||||||
|
#define OPENSSL_X86_64
|
||||||
|
#elif defined(__x86) || defined(__i386) || defined(__i386__) || defined(_M_IX86)
|
||||||
|
#define OPENSSL_32_BIT
|
||||||
|
#define OPENSSL_X86
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
#define OPENSSL_64_BIT
|
||||||
|
#define OPENSSL_AARCH64
|
||||||
|
#elif defined(__arm) || defined(__arm__) || defined(_M_ARM)
|
||||||
|
#define OPENSSL_32_BIT
|
||||||
|
#define OPENSSL_ARM
|
||||||
|
#elif (defined(__PPC64__) || defined(__powerpc64__)) && defined(_LITTLE_ENDIAN)
|
||||||
|
#define OPENSSL_64_BIT
|
||||||
|
#define OPENSSL_PPC64LE
|
||||||
|
#elif defined(__mips__) && !defined(__LP64__)
|
||||||
|
#define OPENSSL_32_BIT
|
||||||
|
#define OPENSSL_MIPS
|
||||||
|
#elif defined(__mips__) && defined(__LP64__)
|
||||||
|
#define OPENSSL_64_BIT
|
||||||
|
#define OPENSSL_MIPS64
|
||||||
|
#elif defined(__pnacl__)
|
||||||
|
#define OPENSSL_32_BIT
|
||||||
|
#define OPENSSL_PNACL
|
||||||
|
#elif defined(__myriad2__)
|
||||||
|
#define OPENSSL_32_BIT
|
||||||
|
#else
|
||||||
|
#error "Unknown target CPU"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#define OPENSSL_APPLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define OPENSSL_WINDOWS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OPENSSL_IS_BORINGSSL
|
||||||
|
#define OPENSSL_IS_RING
|
||||||
|
#define OPENSSL_VERSION_NUMBER 0x10002000
|
||||||
|
|
||||||
|
/* *ring* doesn't support the `BORINGSSL_SHARED_LIBRARY` configuration, so
|
||||||
|
* the default (usually "hidden") visibility is always used, even for exported
|
||||||
|
* items. */
|
||||||
|
#define OPENSSL_EXPORT
|
||||||
|
|
||||||
|
typedef struct bignum_st BIGNUM;
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} /* extern C */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* OPENSSL_HEADER_BASE_H */
|
||||||
256
test-generator/cbits/GFp/bn.h
Normal file
256
test-generator/cbits/GFp/bn.h
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This package is an SSL implementation written
|
||||||
|
* by Eric Young (eay@cryptsoft.com).
|
||||||
|
* The implementation was written so as to conform with Netscapes SSL.
|
||||||
|
*
|
||||||
|
* This library is free for commercial and non-commercial use as long as
|
||||||
|
* the following conditions are aheared to. The following conditions
|
||||||
|
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||||
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||||
|
* included with this distribution is covered by the same copyright terms
|
||||||
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||||
|
*
|
||||||
|
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||||
|
* the code are not to be removed.
|
||||||
|
* If this package is used in a product, Eric Young should be given attribution
|
||||||
|
* as the author of the parts of the library used.
|
||||||
|
* This can be in the form of a textual message at program startup or
|
||||||
|
* in documentation (online or textual) provided with the package.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* "This product includes cryptographic software written by
|
||||||
|
* Eric Young (eay@cryptsoft.com)"
|
||||||
|
* The word 'cryptographic' can be left out if the rouines from the library
|
||||||
|
* being used are not cryptographic related :-).
|
||||||
|
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||||
|
* the apps directory (application code) you must include an acknowledgement:
|
||||||
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The licence and distribution terms for any publically available version or
|
||||||
|
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||||
|
* copied and put under another distribution licence
|
||||||
|
* [including the GNU Public Licence.]
|
||||||
|
*/
|
||||||
|
/* ====================================================================
|
||||||
|
* Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* 3. All advertising materials mentioning features or use of this
|
||||||
|
* software must display the following acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* prior written permission. For written permission, please contact
|
||||||
|
* openssl-core@openssl.org.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called "OpenSSL"
|
||||||
|
* nor may "OpenSSL" appear in their names without prior written
|
||||||
|
* permission of the OpenSSL Project.
|
||||||
|
*
|
||||||
|
* 6. Redistributions of any form whatsoever must retain the following
|
||||||
|
* acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||||
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||||
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This product includes cryptographic software written by Eric Young
|
||||||
|
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||||
|
* Hudson (tjh@cryptsoft.com).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/* ====================================================================
|
||||||
|
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||||
|
*
|
||||||
|
* Portions of the attached software ("Contribution") are developed by
|
||||||
|
* SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
|
||||||
|
*
|
||||||
|
* The Contribution is licensed pursuant to the Eric Young open source
|
||||||
|
* license provided above.
|
||||||
|
*
|
||||||
|
* The binary polynomial arithmetic software is originally written by
|
||||||
|
* Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
|
||||||
|
* Laboratories. */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_BN_H
|
||||||
|
#define OPENSSL_HEADER_BN_H
|
||||||
|
|
||||||
|
#include <GFp/base.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* BN provides support for working with arbitrary sized integers. For example,
|
||||||
|
* although the largest integer supported by the compiler might be 64 bits, BN
|
||||||
|
* will allow you to work with numbers until you run out of memory. */
|
||||||
|
|
||||||
|
|
||||||
|
/* BN_ULONG is the native word size when working with big integers.
|
||||||
|
*
|
||||||
|
* Note: on some platforms, inttypes.h does not define print format macros in
|
||||||
|
* C++ unless |__STDC_FORMAT_MACROS| defined. As this is a public header, bn.h
|
||||||
|
* does not define |__STDC_FORMAT_MACROS| itself. C++ source files which use the
|
||||||
|
* FMT macros must define it externally. */
|
||||||
|
#if defined(OPENSSL_64_BIT)
|
||||||
|
#define BN_ULONG uint64_t
|
||||||
|
#define BN_BITS2 64
|
||||||
|
#elif defined(OPENSSL_32_BIT)
|
||||||
|
#define BN_ULONG uint32_t
|
||||||
|
#define BN_BITS2 32
|
||||||
|
#else
|
||||||
|
#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Allocation and freeing. */
|
||||||
|
|
||||||
|
/* GFp_BN_init initialises a stack allocated |BIGNUM|. */
|
||||||
|
OPENSSL_EXPORT void GFp_BN_init(BIGNUM *bn);
|
||||||
|
|
||||||
|
/* GFp_BN_free frees the data referenced by |bn| and, if |bn| was originally
|
||||||
|
* allocated on the heap, frees |bn| also. */
|
||||||
|
OPENSSL_EXPORT void GFp_BN_free(BIGNUM *bn);
|
||||||
|
|
||||||
|
/* GFp_BN_copy sets |dest| equal to |src| and returns one on success or zero on
|
||||||
|
* failure. */
|
||||||
|
OPENSSL_EXPORT int GFp_BN_copy(BIGNUM *dest, const BIGNUM *src);
|
||||||
|
|
||||||
|
|
||||||
|
/* Basic functions. */
|
||||||
|
|
||||||
|
/* GFp_BN_zero sets |bn| to zero. */
|
||||||
|
OPENSSL_EXPORT void GFp_BN_zero(BIGNUM *bn);
|
||||||
|
|
||||||
|
|
||||||
|
/* Internal functions.
|
||||||
|
*
|
||||||
|
* These functions are useful for code that is doing low-level manipulations of
|
||||||
|
* BIGNUM values. However, be sure that no other function in this file does
|
||||||
|
* what you want before turning to these. */
|
||||||
|
|
||||||
|
/* bn_correct_top decrements |bn->top| until |bn->d[top-1]| is non-zero or
|
||||||
|
* until |top| is zero. */
|
||||||
|
OPENSSL_EXPORT void GFp_bn_correct_top(BIGNUM *bn);
|
||||||
|
|
||||||
|
/* bn_wexpand ensures that |bn| has at least |words| works of space without
|
||||||
|
* altering its value. It returns one on success and zero on allocation
|
||||||
|
* failure. */
|
||||||
|
OPENSSL_EXPORT int GFp_bn_wexpand(BIGNUM *bn, size_t words);
|
||||||
|
|
||||||
|
|
||||||
|
/* Simple arithmetic */
|
||||||
|
|
||||||
|
/* GFp_BN_mul_no_alias sets |r| = |a| * |b|, where |r| must not be the same pointer
|
||||||
|
* as |a| or |b|. Returns one on success and zero otherwise. */
|
||||||
|
OPENSSL_EXPORT int GFp_BN_mul_no_alias(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
|
||||||
|
|
||||||
|
|
||||||
|
/* Comparison functions */
|
||||||
|
|
||||||
|
/* GFp_BN_is_odd returns one if |bn| is odd and zero otherwise. */
|
||||||
|
OPENSSL_EXPORT int GFp_BN_is_odd(const BIGNUM *bn);
|
||||||
|
|
||||||
|
|
||||||
|
/* Bitwise operations. */
|
||||||
|
|
||||||
|
/* GFp_BN_is_bit_set returns the value of the |n|th, least-significant bit in
|
||||||
|
* |a|, or zero if the bit doesn't exist. */
|
||||||
|
OPENSSL_EXPORT int GFp_BN_is_bit_set(const BIGNUM *a, int n);
|
||||||
|
|
||||||
|
|
||||||
|
/* Modulo arithmetic. */
|
||||||
|
|
||||||
|
/* GFp_BN_mod_mul_mont set |r| equal to |a| * |b|, in the Montgomery domain.
|
||||||
|
* Both |a| and |b| must already be in the Montgomery domain (by
|
||||||
|
* |GFp_BN_to_mont|). In particular, |a| and |b| are assumed to be in the range
|
||||||
|
* [0, n), where |n| is the Montgomery modulus. It returns one on success or
|
||||||
|
* zero on error. */
|
||||||
|
OPENSSL_EXPORT int GFp_BN_mod_mul_mont(
|
||||||
|
BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *n,
|
||||||
|
const BN_ULONG n0[/*BN_MONT_CTX_N0_LIMBS*/]);
|
||||||
|
|
||||||
|
/* GFp_BN_reduce_montgomery returns |a % n| in constant-ish time using
|
||||||
|
* Montgomery reduction. |a| is assumed to be in the range [0, n**2), where |n|
|
||||||
|
* is the Montgomery modulus. It returns one on success or zero on error. */
|
||||||
|
int GFp_BN_reduce_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *n,
|
||||||
|
const BN_ULONG n0[/*BN_MONT_CTX_N0_LIMBS*/]);
|
||||||
|
|
||||||
|
|
||||||
|
/* Exponentiation. */
|
||||||
|
|
||||||
|
OPENSSL_EXPORT int GFp_BN_mod_exp_mont_consttime(
|
||||||
|
BIGNUM *rr, const BIGNUM *a_mont, const BIGNUM *p, size_t p_bits,
|
||||||
|
const BIGNUM *one_mont, const BIGNUM *n,
|
||||||
|
const BN_ULONG n0[/*BN_MONT_CTX_N0_LIMBS*/]);
|
||||||
|
|
||||||
|
|
||||||
|
/* Private functions */
|
||||||
|
|
||||||
|
/* Keep in sync with `BIGNUM` in `ring::rsa::bigint`. */
|
||||||
|
struct bignum_st {
|
||||||
|
BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks in little-endian
|
||||||
|
order. */
|
||||||
|
int top; /* Index of last used element in |d|, plus one. */
|
||||||
|
int dmax; /* Size of |d|, in words. */
|
||||||
|
int flags; /* bitmask of BN_FLG_* values */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BN_FLG_MALLOCED 0x01
|
||||||
|
#define BN_FLG_STATIC_DATA 0x02
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} /* extern C */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* OPENSSL_HEADER_BN_H */
|
||||||
189
test-generator/cbits/GFp/cpu.h
Normal file
189
test-generator/cbits/GFp/cpu.h
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This package is an SSL implementation written
|
||||||
|
* by Eric Young (eay@cryptsoft.com).
|
||||||
|
* The implementation was written so as to conform with Netscapes SSL.
|
||||||
|
*
|
||||||
|
* This library is free for commercial and non-commercial use as long as
|
||||||
|
* the following conditions are aheared to. The following conditions
|
||||||
|
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||||
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||||
|
* included with this distribution is covered by the same copyright terms
|
||||||
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||||
|
*
|
||||||
|
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||||
|
* the code are not to be removed.
|
||||||
|
* If this package is used in a product, Eric Young should be given attribution
|
||||||
|
* as the author of the parts of the library used.
|
||||||
|
* This can be in the form of a textual message at program startup or
|
||||||
|
* in documentation (online or textual) provided with the package.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* "This product includes cryptographic software written by
|
||||||
|
* Eric Young (eay@cryptsoft.com)"
|
||||||
|
* The word 'cryptographic' can be left out if the rouines from the library
|
||||||
|
* being used are not cryptographic related :-).
|
||||||
|
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||||
|
* the apps directory (application code) you must include an acknowledgement:
|
||||||
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The licence and distribution terms for any publically available version or
|
||||||
|
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||||
|
* copied and put under another distribution licence
|
||||||
|
* [including the GNU Public Licence.]
|
||||||
|
*
|
||||||
|
* This product includes cryptographic software written by Eric Young
|
||||||
|
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||||
|
* Hudson (tjh@cryptsoft.com). */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_CPU_H
|
||||||
|
#define OPENSSL_HEADER_CPU_H
|
||||||
|
|
||||||
|
#include <GFp/base.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Runtime CPU feature support */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
|
||||||
|
/* GFp_ia32cap_P contains the Intel CPUID bits when running on an x86 or
|
||||||
|
* x86-64 system.
|
||||||
|
*
|
||||||
|
* Index 0:
|
||||||
|
* EDX for CPUID where EAX = 1
|
||||||
|
* Bit 20 is always zero
|
||||||
|
* Bit 28 is adjusted to reflect whether the data cache is shared between
|
||||||
|
* multiple logical cores
|
||||||
|
* Bit 30 is used to indicate an Intel CPU
|
||||||
|
* Index 1:
|
||||||
|
* ECX for CPUID where EAX = 1
|
||||||
|
* Bit 11 is used to indicate AMD XOP support, not SDBG
|
||||||
|
* Index 2:
|
||||||
|
* EBX for CPUID where EAX = 7
|
||||||
|
* Index 3 is set to zero.
|
||||||
|
*
|
||||||
|
* Note: the CPUID bits are pre-adjusted for the OSXSAVE bit and the YMM and XMM
|
||||||
|
* bits in XCR0, so it is not necessary to check those. */
|
||||||
|
extern uint32_t GFp_ia32cap_P[4];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
|
||||||
|
|
||||||
|
#if defined(OPENSSL_APPLE)
|
||||||
|
/* iOS builds use the static ARM configuration. */
|
||||||
|
#define OPENSSL_STATIC_ARMCAP
|
||||||
|
|
||||||
|
#if defined(OPENSSL_AARCH64)
|
||||||
|
#define OPENSSL_STATIC_ARMCAP_AES
|
||||||
|
#define OPENSSL_STATIC_ARMCAP_SHA1
|
||||||
|
#define OPENSSL_STATIC_ARMCAP_SHA256
|
||||||
|
#define OPENSSL_STATIC_ARMCAP_PMULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(OPENSSL_STATIC_ARMCAP)
|
||||||
|
|
||||||
|
/* GFp_is_NEON_capable_at_runtime returns true if the current CPU has a NEON
|
||||||
|
* unit. Note that |OPENSSL_armcap_P| also exists and contains the same
|
||||||
|
* information in a form that's easier for assembly to use. */
|
||||||
|
OPENSSL_EXPORT uint8_t GFp_is_NEON_capable_at_runtime(void);
|
||||||
|
|
||||||
|
/* GFp_is_NEON_capable returns true if the current CPU has a NEON unit. If
|
||||||
|
* this is known statically then it returns one immediately. */
|
||||||
|
static inline int GFp_is_NEON_capable(void) {
|
||||||
|
/* On 32-bit ARM, one CPU is known to have a broken NEON unit which is known
|
||||||
|
* to fail with on some hand-written NEON assembly. Assume that non-Android
|
||||||
|
* applications will not use that buggy CPU but still support Android users
|
||||||
|
* that do, even when the compiler is instructed to freely emit NEON code.
|
||||||
|
* See https://crbug.com/341598 and https://crbug.com/606629. */
|
||||||
|
#if defined(__ARM_NEON__) && (!defined(OPENSSL_ARM) || !defined(__ANDROID__))
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return GFp_is_NEON_capable_at_runtime();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(OPENSSL_ARM)
|
||||||
|
/* GFp_has_broken_NEON returns one if the current CPU is known to have a
|
||||||
|
* broken NEON unit. See https://crbug.com/341598. */
|
||||||
|
OPENSSL_EXPORT int GFp_has_broken_NEON(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* GFp_is_ARMv8_AES_capable returns true if the current CPU supports the
|
||||||
|
* ARMv8 AES instruction. */
|
||||||
|
int GFp_is_ARMv8_AES_capable(void);
|
||||||
|
|
||||||
|
/* GFp_is_ARMv8_PMULL_capable returns true if the current CPU supports the
|
||||||
|
* ARMv8 PMULL instruction. */
|
||||||
|
int GFp_is_ARMv8_PMULL_capable(void);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static inline int GFp_is_NEON_capable(void) {
|
||||||
|
#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__)
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int GFp_is_ARMv8_AES_capable(void) {
|
||||||
|
#if defined(OPENSSL_STATIC_ARMCAP_AES)
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int GFp_is_ARMv8_PMULL_capable(void) {
|
||||||
|
#if defined(OPENSSL_STATIC_ARMCAP_PMULL)
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* OPENSSL_STATIC_ARMCAP */
|
||||||
|
#endif /* OPENSSL_ARM || OPENSSL_AARCH64 */
|
||||||
|
|
||||||
|
#if defined(OPENSSL_PPC64LE)
|
||||||
|
|
||||||
|
/* CRYPTO_is_PPC64LE_vcrypto_capable returns true iff the current CPU supports
|
||||||
|
* the Vector.AES category of instructions. */
|
||||||
|
int CRYPTO_is_PPC64LE_vcrypto_capable(void);
|
||||||
|
|
||||||
|
#endif /* OPENSSL_PPC64LE */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} /* extern C */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* OPENSSL_HEADER_CPU_H */
|
||||||
93
test-generator/cbits/GFp/mem.h
Normal file
93
test-generator/cbits/GFp/mem.h
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This package is an SSL implementation written
|
||||||
|
* by Eric Young (eay@cryptsoft.com).
|
||||||
|
* The implementation was written so as to conform with Netscapes SSL.
|
||||||
|
*
|
||||||
|
* This library is free for commercial and non-commercial use as long as
|
||||||
|
* the following conditions are aheared to. The following conditions
|
||||||
|
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||||
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||||
|
* included with this distribution is covered by the same copyright terms
|
||||||
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||||
|
*
|
||||||
|
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||||
|
* the code are not to be removed.
|
||||||
|
* If this package is used in a product, Eric Young should be given attribution
|
||||||
|
* as the author of the parts of the library used.
|
||||||
|
* This can be in the form of a textual message at program startup or
|
||||||
|
* in documentation (online or textual) provided with the package.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* "This product includes cryptographic software written by
|
||||||
|
* Eric Young (eay@cryptsoft.com)"
|
||||||
|
* The word 'cryptographic' can be left out if the rouines from the library
|
||||||
|
* being used are not cryptographic related :-).
|
||||||
|
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||||
|
* the apps directory (application code) you must include an acknowledgement:
|
||||||
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The licence and distribution terms for any publically available version or
|
||||||
|
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||||
|
* copied and put under another distribution licence
|
||||||
|
* [including the GNU Public Licence.] */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_MEM_H
|
||||||
|
#define OPENSSL_HEADER_MEM_H
|
||||||
|
|
||||||
|
#include <GFp/base.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Memory and string functions, see also buf.h.
|
||||||
|
*
|
||||||
|
* OpenSSL has, historically, had a complex set of malloc debugging options.
|
||||||
|
* However, that was written in a time before Valgrind and ASAN. Since we now
|
||||||
|
* have those tools, the OpenSSL allocation functions are simply macros around
|
||||||
|
* the standard memory functions. */
|
||||||
|
|
||||||
|
|
||||||
|
#define OPENSSL_malloc malloc
|
||||||
|
#define OPENSSL_realloc realloc
|
||||||
|
#define OPENSSL_free free
|
||||||
|
|
||||||
|
/* GFp_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. It
|
||||||
|
* takes an amount of time dependent on |len|, but independent of the contents
|
||||||
|
* of |a| and |b|. Unlike memcmp, it cannot be used to put elements into a
|
||||||
|
* defined order as the return value when a != b is undefined, other than to be
|
||||||
|
* non-zero. */
|
||||||
|
OPENSSL_EXPORT int GFp_memcmp(const void *a, const void *b, size_t len);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} /* extern C */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* OPENSSL_HEADER_MEM_H */
|
||||||
75
test-generator/cbits/GFp/type_check.h
Normal file
75
test-generator/cbits/GFp/type_check.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This package is an SSL implementation written
|
||||||
|
* by Eric Young (eay@cryptsoft.com).
|
||||||
|
* The implementation was written so as to conform with Netscapes SSL.
|
||||||
|
*
|
||||||
|
* This library is free for commercial and non-commercial use as long as
|
||||||
|
* the following conditions are aheared to. The following conditions
|
||||||
|
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||||
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||||
|
* included with this distribution is covered by the same copyright terms
|
||||||
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||||
|
*
|
||||||
|
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||||
|
* the code are not to be removed.
|
||||||
|
* If this package is used in a product, Eric Young should be given attribution
|
||||||
|
* as the author of the parts of the library used.
|
||||||
|
* This can be in the form of a textual message at program startup or
|
||||||
|
* in documentation (online or textual) provided with the package.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* "This product includes cryptographic software written by
|
||||||
|
* Eric Young (eay@cryptsoft.com)"
|
||||||
|
* The word 'cryptographic' can be left out if the rouines from the library
|
||||||
|
* being used are not cryptographic related :-).
|
||||||
|
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||||
|
* the apps directory (application code) you must include an acknowledgement:
|
||||||
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The licence and distribution terms for any publically available version or
|
||||||
|
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||||
|
* copied and put under another distribution licence
|
||||||
|
* [including the GNU Public Licence.] */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_TYPE_CHECK_H
|
||||||
|
#define OPENSSL_HEADER_TYPE_CHECK_H
|
||||||
|
|
||||||
|
#include <GFp/base.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||||
|
#define OPENSSL_COMPILE_ASSERT(cond, msg) _Static_assert(cond, #msg)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define OPENSSL_COMPILE_ASSERT(cond, msg) \
|
||||||
|
typedef char OPENSSL_COMPILE_ASSERT_##msg[((cond) ? 1 : -1)] \
|
||||||
|
__attribute__((unused))
|
||||||
|
#else
|
||||||
|
#define OPENSSL_COMPILE_ASSERT(cond, msg) \
|
||||||
|
typedef char OPENSSL_COMPILE_ASSERT_##msg[((cond) ? 1 : -1)]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* OPENSSL_HEADER_TYPE_CHECK_H */
|
||||||
2133
test-generator/cbits/asm/x25519-asm-arm.S
Normal file
2133
test-generator/cbits/asm/x25519-asm-arm.S
Normal file
File diff suppressed because it is too large
Load Diff
1921
test-generator/cbits/asm/x25519-asm-x86_64.S
Normal file
1921
test-generator/cbits/asm/x25519-asm-x86_64.S
Normal file
File diff suppressed because it is too large
Load Diff
4726
test-generator/cbits/curve25519.c
Normal file
4726
test-generator/cbits/curve25519.c
Normal file
File diff suppressed because it is too large
Load Diff
109
test-generator/cbits/internal.h
Normal file
109
test-generator/cbits/internal.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/* Copyright (c) 2015, Google Inc.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_CURVE25519_INTERNAL_H
|
||||||
|
#define OPENSSL_HEADER_CURVE25519_INTERNAL_H
|
||||||
|
|
||||||
|
#include <GFp/base.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_SMALL) && \
|
||||||
|
!defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_ASM)
|
||||||
|
/* This isn't compatible with Windows because the asm code makes use of the red
|
||||||
|
* zone, which Windows doesn't support. */
|
||||||
|
#define BORINGSSL_X25519_X86_64
|
||||||
|
|
||||||
|
void GFp_x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
|
||||||
|
const uint8_t point[32]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
|
||||||
|
#define BORINGSSL_X25519_NEON
|
||||||
|
|
||||||
|
/* x25519_NEON is defined in asm/x25519-arm.S. */
|
||||||
|
void GFp_x25519_NEON(uint8_t out[32], const uint8_t scalar[32],
|
||||||
|
const uint8_t point[32]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* fe means field element. Here the field is \Z/(2^255-19). An element t,
|
||||||
|
* entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
|
||||||
|
* t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
|
||||||
|
* context.
|
||||||
|
*
|
||||||
|
* Keep in sync with `Elem` and `ELEM_LIMBS` in curve25519/ops.rs. */
|
||||||
|
typedef int32_t fe[10];
|
||||||
|
|
||||||
|
/* ge means group element.
|
||||||
|
|
||||||
|
* Here the group is the set of pairs (x,y) of field elements (see fe.h)
|
||||||
|
* satisfying -x^2 + y^2 = 1 + d x^2y^2
|
||||||
|
* where d = -121665/121666.
|
||||||
|
*
|
||||||
|
* Representations:
|
||||||
|
* ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
|
||||||
|
* ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
|
||||||
|
* ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
|
||||||
|
* ge_precomp (Duif): (y+x,y-x,2dxy)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Keep in sync with `Point` in curve25519/ops.rs. */
|
||||||
|
typedef struct {
|
||||||
|
fe X;
|
||||||
|
fe Y;
|
||||||
|
fe Z;
|
||||||
|
} ge_p2;
|
||||||
|
|
||||||
|
|
||||||
|
/* Keep in sync with `ExtPoint` in curve25519/ops.rs. */
|
||||||
|
typedef struct {
|
||||||
|
fe X;
|
||||||
|
fe Y;
|
||||||
|
fe Z;
|
||||||
|
fe T;
|
||||||
|
} ge_p3;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
fe X;
|
||||||
|
fe Y;
|
||||||
|
fe Z;
|
||||||
|
fe T;
|
||||||
|
} ge_p1p1;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
fe yplusx;
|
||||||
|
fe yminusx;
|
||||||
|
fe xy2d;
|
||||||
|
} ge_precomp;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
fe YplusX;
|
||||||
|
fe YminusX;
|
||||||
|
fe Z;
|
||||||
|
fe T2d;
|
||||||
|
} ge_cached;
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} /* extern C */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* OPENSSL_HEADER_CURVE25519_INTERNAL_H */
|
||||||
361
test-generator/cbits/internal2.h
Normal file
361
test-generator/cbits/internal2.h
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This package is an SSL implementation written
|
||||||
|
* by Eric Young (eay@cryptsoft.com).
|
||||||
|
* The implementation was written so as to conform with Netscapes SSL.
|
||||||
|
*
|
||||||
|
* This library is free for commercial and non-commercial use as long as
|
||||||
|
* the following conditions are aheared to. The following conditions
|
||||||
|
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||||
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||||
|
* included with this distribution is covered by the same copyright terms
|
||||||
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||||
|
*
|
||||||
|
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||||
|
* the code are not to be removed.
|
||||||
|
* If this package is used in a product, Eric Young should be given attribution
|
||||||
|
* as the author of the parts of the library used.
|
||||||
|
* This can be in the form of a textual message at program startup or
|
||||||
|
* in documentation (online or textual) provided with the package.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* "This product includes cryptographic software written by
|
||||||
|
* Eric Young (eay@cryptsoft.com)"
|
||||||
|
* The word 'cryptographic' can be left out if the rouines from the library
|
||||||
|
* being used are not cryptographic related :-).
|
||||||
|
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||||
|
* the apps directory (application code) you must include an acknowledgement:
|
||||||
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The licence and distribution terms for any publically available version or
|
||||||
|
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||||
|
* copied and put under another distribution licence
|
||||||
|
* [including the GNU Public Licence.]
|
||||||
|
*/
|
||||||
|
/* ====================================================================
|
||||||
|
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* 3. All advertising materials mentioning features or use of this
|
||||||
|
* software must display the following acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||||
|
* endorse or promote products derived from this software without
|
||||||
|
* prior written permission. For written permission, please contact
|
||||||
|
* openssl-core@openssl.org.
|
||||||
|
*
|
||||||
|
* 5. Products derived from this software may not be called "OpenSSL"
|
||||||
|
* nor may "OpenSSL" appear in their names without prior written
|
||||||
|
* permission of the OpenSSL Project.
|
||||||
|
*
|
||||||
|
* 6. Redistributions of any form whatsoever must retain the following
|
||||||
|
* acknowledgment:
|
||||||
|
* "This product includes software developed by the OpenSSL Project
|
||||||
|
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||||
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||||
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
* ====================================================================
|
||||||
|
*
|
||||||
|
* This product includes cryptographic software written by Eric Young
|
||||||
|
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||||
|
* Hudson (tjh@cryptsoft.com). */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_CRYPTO_INTERNAL_H
|
||||||
|
#define OPENSSL_HEADER_CRYPTO_INTERNAL_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if defined(__clang__) || defined(_MSC_VER)
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <GFp/base.h>
|
||||||
|
#include <GFp/type_check.h>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push, 3)
|
||||||
|
#include <intrin.h>
|
||||||
|
#pragma warning(pop)
|
||||||
|
#if !defined(__cplusplus)
|
||||||
|
#define alignas(x) __declspec(align(x))
|
||||||
|
#define alignof __alignof
|
||||||
|
#endif
|
||||||
|
#elif !defined(__clang__) && defined(__GNUC__) && __GNUC__ == 4 && \
|
||||||
|
__GNUC_MINOR__ <= 6
|
||||||
|
#define alignas(x) __attribute__((aligned (x)))
|
||||||
|
#define alignof __alignof__
|
||||||
|
#else
|
||||||
|
#include <stdalign.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM) || \
|
||||||
|
defined(OPENSSL_AARCH64) || defined(OPENSSL_PPC64LE)
|
||||||
|
/* OPENSSL_cpuid_setup initializes the platform-specific feature cache. */
|
||||||
|
void GFp_cpuid_setup(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OPENSSL_LITTLE_ENDIAN 1
|
||||||
|
#define OPENSSL_BIG_ENDIAN 2
|
||||||
|
|
||||||
|
#if defined(OPENSSL_X86_64) || defined(OPENSSL_X86) || \
|
||||||
|
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
|
||||||
|
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||||
|
#define OPENSSL_ENDIAN OPENSSL_LITTLE_ENDIAN
|
||||||
|
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
|
||||||
|
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||||
|
#define OPENSSL_ENDIAN OPENSSL_BIG_ENDIAN
|
||||||
|
#else
|
||||||
|
#error "Cannot determine endianness"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define bswap_u32(x) __builtin_bswap32(x)
|
||||||
|
#define bswap_u64(x) __builtin_bswap64(x)
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#pragma intrinsic(_byteswap_ulong, _byteswap_uint64)
|
||||||
|
#define bswap_u32(x) _byteswap_ulong(x)
|
||||||
|
#define bswap_u64(x) _byteswap_uint64(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(_MSC_VER) && defined(OPENSSL_64_BIT)
|
||||||
|
typedef __int128_t int128_t;
|
||||||
|
typedef __uint128_t uint128_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Constant-time utility functions.
|
||||||
|
*
|
||||||
|
* The following methods return a bitmask of all ones (0xff...f) for true and 0
|
||||||
|
* for false. This is useful for choosing a value based on the result of a
|
||||||
|
* conditional in constant time. */
|
||||||
|
|
||||||
|
/* constant_time_msb returns the given value with the MSB copied to all the
|
||||||
|
* other bits. */
|
||||||
|
static inline unsigned int constant_time_msb_unsigned(unsigned int a) {
|
||||||
|
return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
OPENSSL_COMPILE_ASSERT(sizeof(ptrdiff_t) == sizeof(size_t),
|
||||||
|
ptrdiff_t_and_size_t_are_different_sizes);
|
||||||
|
|
||||||
|
static inline size_t constant_time_msb_size_t(size_t a) {
|
||||||
|
return (size_t)((ptrdiff_t)(a) >> (sizeof(ptrdiff_t) * 8 - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* constant_time_is_zero returns 0xff..f if a == 0 and 0 otherwise. */
|
||||||
|
static inline unsigned int constant_time_is_zero_unsigned(unsigned int a) {
|
||||||
|
/* Here is an SMT-LIB verification of this formula:
|
||||||
|
*
|
||||||
|
* (define-fun is_zero ((a (_ BitVec 32))) (_ BitVec 32)
|
||||||
|
* (bvand (bvnot a) (bvsub a #x00000001))
|
||||||
|
* )
|
||||||
|
*
|
||||||
|
* (declare-fun a () (_ BitVec 32))
|
||||||
|
*
|
||||||
|
* (assert (not (= (= #x00000001 (bvlshr (is_zero a) #x0000001f)) (= a #x00000000))))
|
||||||
|
* (check-sat)
|
||||||
|
* (get-model)
|
||||||
|
*/
|
||||||
|
return constant_time_msb_unsigned(~a & (a - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* constant_time_is_zero_size_t is like |constant_time_is_zero_unsigned| but
|
||||||
|
* operates on |size_t|. */
|
||||||
|
static inline size_t constant_time_is_zero_size_t(size_t a) {
|
||||||
|
return constant_time_msb_size_t(~a & (a - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t constant_time_is_nonzero_size_t(size_t a) {
|
||||||
|
return constant_time_is_zero_size_t(constant_time_is_zero_size_t(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* constant_time_eq_int returns 0xff..f if a == b and 0 otherwise. */
|
||||||
|
static inline unsigned int constant_time_eq_int(int a, int b) {
|
||||||
|
return constant_time_is_zero_unsigned((unsigned)(a) ^ (unsigned)(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* constant_time_eq_size_t acts like |constant_time_eq_int| but operates on
|
||||||
|
* |size_t|. */
|
||||||
|
static inline size_t constant_time_eq_size_t(size_t a, size_t b) {
|
||||||
|
return constant_time_is_zero_size_t(a ^ b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* constant_time_select_size_t returns (mask & a) | (~mask & b). When |mask| is
|
||||||
|
* all 1s or all 0s (as returned by the methods above), the select methods
|
||||||
|
* return either |a| (if |mask| is nonzero) or |b| (if |mask| is zero). it is
|
||||||
|
* derived from BoringSSL's |constant_time_select|. */
|
||||||
|
static inline size_t constant_time_select_size_t(size_t mask, size_t a,
|
||||||
|
size_t b) {
|
||||||
|
return (mask & a) | (~mask & b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* from_be_u32_ptr returns the 32-bit big-endian-encoded value at |data|. */
|
||||||
|
static inline uint32_t from_be_u32_ptr(const uint8_t *data) {
|
||||||
|
#if defined(__clang__) || defined(_MSC_VER)
|
||||||
|
/* XXX: Unlike GCC, Clang doesn't optimize compliant access to unaligned data
|
||||||
|
* well. See https://llvm.org/bugs/show_bug.cgi?id=20605,
|
||||||
|
* https://llvm.org/bugs/show_bug.cgi?id=17603,
|
||||||
|
* http://blog.regehr.org/archives/702, and
|
||||||
|
* http://blog.regehr.org/archives/1055. MSVC seems to have similar problems.
|
||||||
|
*/
|
||||||
|
uint32_t value;
|
||||||
|
memcpy(&value, data, sizeof(value));
|
||||||
|
#if OPENSSL_ENDIAN != OPENSSL_BIG_ENDIAN
|
||||||
|
value = bswap_u32(value);
|
||||||
|
#endif
|
||||||
|
return value;
|
||||||
|
#else
|
||||||
|
return ((uint32_t)data[0] << 24) |
|
||||||
|
((uint32_t)data[1] << 16) |
|
||||||
|
((uint32_t)data[2] << 8) |
|
||||||
|
((uint32_t)data[3]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* from_be_u64_ptr returns the 64-bit big-endian-encoded value at |data|. */
|
||||||
|
static inline uint64_t from_be_u64_ptr(const uint8_t *data) {
|
||||||
|
#if defined(__clang__) || defined(_MSC_VER)
|
||||||
|
/* XXX: Unlike GCC, Clang doesn't optimize compliant access to unaligned data
|
||||||
|
* well. See https://llvm.org/bugs/show_bug.cgi?id=20605,
|
||||||
|
* https://llvm.org/bugs/show_bug.cgi?id=17603,
|
||||||
|
* http://blog.regehr.org/archives/702, and
|
||||||
|
* http://blog.regehr.org/archives/1055. MSVC seems to have similar problems.
|
||||||
|
*/
|
||||||
|
uint64_t value;
|
||||||
|
memcpy(&value, data, sizeof(value));
|
||||||
|
#if OPENSSL_ENDIAN != OPENSSL_BIG_ENDIAN
|
||||||
|
value = bswap_u64(value);
|
||||||
|
#endif
|
||||||
|
return value;
|
||||||
|
#else
|
||||||
|
return ((uint64_t)data[0] << 56) |
|
||||||
|
((uint64_t)data[1] << 48) |
|
||||||
|
((uint64_t)data[2] << 40) |
|
||||||
|
((uint64_t)data[3] << 32) |
|
||||||
|
((uint64_t)data[4] << 24) |
|
||||||
|
((uint64_t)data[5] << 16) |
|
||||||
|
((uint64_t)data[6] << 8) |
|
||||||
|
((uint64_t)data[7]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* to_be_u32_ptr writes the value |x| to the location |out| in big-endian
|
||||||
|
order. */
|
||||||
|
static inline void to_be_u32_ptr(uint8_t *out, uint32_t value) {
|
||||||
|
#if defined(__clang__) || defined(_MSC_VER)
|
||||||
|
/* XXX: Unlike GCC, Clang doesn't optimize compliant access to unaligned data
|
||||||
|
* well. See https://llvm.org/bugs/show_bug.cgi?id=20605,
|
||||||
|
* https://llvm.org/bugs/show_bug.cgi?id=17603,
|
||||||
|
* http://blog.regehr.org/archives/702, and
|
||||||
|
* http://blog.regehr.org/archives/1055. MSVC seems to have similar problems.
|
||||||
|
*/
|
||||||
|
#if OPENSSL_ENDIAN != OPENSSL_BIG_ENDIAN
|
||||||
|
value = bswap_u32(value);
|
||||||
|
#endif
|
||||||
|
memcpy(out, &value, sizeof(value));
|
||||||
|
#else
|
||||||
|
out[0] = (uint8_t)(value >> 24);
|
||||||
|
out[1] = (uint8_t)(value >> 16);
|
||||||
|
out[2] = (uint8_t)(value >> 8);
|
||||||
|
out[3] = (uint8_t)value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* to_be_u64_ptr writes the value |value| to the location |out| in big-endian
|
||||||
|
order. */
|
||||||
|
static inline void to_be_u64_ptr(uint8_t *out, uint64_t value) {
|
||||||
|
#if defined(__clang__) || defined(_MSC_VER)
|
||||||
|
/* XXX: Unlike GCC, Clang doesn't optimize compliant access to unaligned data
|
||||||
|
* well. See https://llvm.org/bugs/show_bug.cgi?id=20605,
|
||||||
|
* https://llvm.org/bugs/show_bug.cgi?id=17603,
|
||||||
|
* http://blog.regehr.org/archives/702, and
|
||||||
|
* http://blog.regehr.org/archives/1055. MSVC seems to have similar problems.
|
||||||
|
*/
|
||||||
|
#if OPENSSL_ENDIAN != OPENSSL_BIG_ENDIAN
|
||||||
|
value = bswap_u64(value);
|
||||||
|
#endif
|
||||||
|
memcpy(out, &value, sizeof(value));
|
||||||
|
#else
|
||||||
|
out[0] = (uint8_t)(value >> 56);
|
||||||
|
out[1] = (uint8_t)(value >> 48);
|
||||||
|
out[2] = (uint8_t)(value >> 40);
|
||||||
|
out[3] = (uint8_t)(value >> 32);
|
||||||
|
out[4] = (uint8_t)(value >> 24);
|
||||||
|
out[5] = (uint8_t)(value >> 16);
|
||||||
|
out[6] = (uint8_t)(value >> 8);
|
||||||
|
out[7] = (uint8_t)value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* from_be_u64 returns the native representation of the 64-bit
|
||||||
|
* big-endian-encoded value |x|. */
|
||||||
|
static inline uint64_t from_be_u64(uint64_t x) {
|
||||||
|
#if OPENSSL_ENDIAN != OPENSSL_BIG_ENDIAN
|
||||||
|
x = bswap_u64(x);
|
||||||
|
#endif
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} /* extern C */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* OPENSSL_HEADER_CRYPTO_INTERNAL_H */
|
||||||
1921
test-generator/cbits/x25519-asm-x86_64.S
Normal file
1921
test-generator/cbits/x25519-asm-x86_64.S
Normal file
File diff suppressed because it is too large
Load Diff
244
test-generator/cbits/x25519-x86_64.c
Normal file
244
test-generator/cbits/x25519-x86_64.c
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
/* Copyright (c) 2015, Google Inc.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||||
|
|
||||||
|
/* This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
|
||||||
|
* 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as
|
||||||
|
* public domain but this file has the ISC license just to keep licencing
|
||||||
|
* simple.
|
||||||
|
*
|
||||||
|
* The field functions are shared by Ed25519 and X25519 where possible. */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(BORINGSSL_X25519_X86_64)
|
||||||
|
|
||||||
|
typedef struct { uint64_t v[5]; } fe25519;
|
||||||
|
|
||||||
|
/* These functions are defined in asm/x25519-x86_64.S */
|
||||||
|
void GFp_x25519_x86_64_work_cswap(fe25519 *, uint64_t);
|
||||||
|
void GFp_x25519_x86_64_mul(fe25519 *out, const fe25519 *a, const fe25519 *b);
|
||||||
|
void GFp_x25519_x86_64_square(fe25519 *out, const fe25519 *a);
|
||||||
|
void GFp_x25519_x86_64_freeze(fe25519 *);
|
||||||
|
void GFp_x25519_x86_64_ladderstep(fe25519 *work);
|
||||||
|
|
||||||
|
static void fe25519_setint(fe25519 *r, unsigned v) {
|
||||||
|
r->v[0] = v;
|
||||||
|
r->v[1] = 0;
|
||||||
|
r->v[2] = 0;
|
||||||
|
r->v[3] = 0;
|
||||||
|
r->v[4] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assumes input x being reduced below 2^255 */
|
||||||
|
static void fe25519_pack(unsigned char r[32], const fe25519 *x) {
|
||||||
|
fe25519 t;
|
||||||
|
t = *x;
|
||||||
|
GFp_x25519_x86_64_freeze(&t);
|
||||||
|
|
||||||
|
r[0] = (uint8_t)(t.v[0] & 0xff);
|
||||||
|
r[1] = (uint8_t)((t.v[0] >> 8) & 0xff);
|
||||||
|
r[2] = (uint8_t)((t.v[0] >> 16) & 0xff);
|
||||||
|
r[3] = (uint8_t)((t.v[0] >> 24) & 0xff);
|
||||||
|
r[4] = (uint8_t)((t.v[0] >> 32) & 0xff);
|
||||||
|
r[5] = (uint8_t)((t.v[0] >> 40) & 0xff);
|
||||||
|
r[6] = (uint8_t)((t.v[0] >> 48));
|
||||||
|
|
||||||
|
r[6] ^= (uint8_t)((t.v[1] << 3) & 0xf8);
|
||||||
|
r[7] = (uint8_t)((t.v[1] >> 5) & 0xff);
|
||||||
|
r[8] = (uint8_t)((t.v[1] >> 13) & 0xff);
|
||||||
|
r[9] = (uint8_t)((t.v[1] >> 21) & 0xff);
|
||||||
|
r[10] = (uint8_t)((t.v[1] >> 29) & 0xff);
|
||||||
|
r[11] = (uint8_t)((t.v[1] >> 37) & 0xff);
|
||||||
|
r[12] = (uint8_t)((t.v[1] >> 45));
|
||||||
|
|
||||||
|
r[12] ^= (uint8_t)((t.v[2] << 6) & 0xc0);
|
||||||
|
r[13] = (uint8_t)((t.v[2] >> 2) & 0xff);
|
||||||
|
r[14] = (uint8_t)((t.v[2] >> 10) & 0xff);
|
||||||
|
r[15] = (uint8_t)((t.v[2] >> 18) & 0xff);
|
||||||
|
r[16] = (uint8_t)((t.v[2] >> 26) & 0xff);
|
||||||
|
r[17] = (uint8_t)((t.v[2] >> 34) & 0xff);
|
||||||
|
r[18] = (uint8_t)((t.v[2] >> 42) & 0xff);
|
||||||
|
r[19] = (uint8_t)((t.v[2] >> 50));
|
||||||
|
|
||||||
|
r[19] ^= (uint8_t)((t.v[3] << 1) & 0xfe);
|
||||||
|
r[20] = (uint8_t)((t.v[3] >> 7) & 0xff);
|
||||||
|
r[21] = (uint8_t)((t.v[3] >> 15) & 0xff);
|
||||||
|
r[22] = (uint8_t)((t.v[3] >> 23) & 0xff);
|
||||||
|
r[23] = (uint8_t)((t.v[3] >> 31) & 0xff);
|
||||||
|
r[24] = (uint8_t)((t.v[3] >> 39) & 0xff);
|
||||||
|
r[25] = (uint8_t)((t.v[3] >> 47));
|
||||||
|
|
||||||
|
r[25] ^= (uint8_t)((t.v[4] << 4) & 0xf0);
|
||||||
|
r[26] = (uint8_t)((t.v[4] >> 4) & 0xff);
|
||||||
|
r[27] = (uint8_t)((t.v[4] >> 12) & 0xff);
|
||||||
|
r[28] = (uint8_t)((t.v[4] >> 20) & 0xff);
|
||||||
|
r[29] = (uint8_t)((t.v[4] >> 28) & 0xff);
|
||||||
|
r[30] = (uint8_t)((t.v[4] >> 36) & 0xff);
|
||||||
|
r[31] = (uint8_t)((t.v[4] >> 44));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fe25519_unpack(fe25519 *r, const uint8_t x[32]) {
|
||||||
|
r->v[0] = x[0];
|
||||||
|
r->v[0] += (uint64_t)x[1] << 8;
|
||||||
|
r->v[0] += (uint64_t)x[2] << 16;
|
||||||
|
r->v[0] += (uint64_t)x[3] << 24;
|
||||||
|
r->v[0] += (uint64_t)x[4] << 32;
|
||||||
|
r->v[0] += (uint64_t)x[5] << 40;
|
||||||
|
r->v[0] += ((uint64_t)x[6] & 7) << 48;
|
||||||
|
|
||||||
|
r->v[1] = x[6] >> 3;
|
||||||
|
r->v[1] += (uint64_t)x[7] << 5;
|
||||||
|
r->v[1] += (uint64_t)x[8] << 13;
|
||||||
|
r->v[1] += (uint64_t)x[9] << 21;
|
||||||
|
r->v[1] += (uint64_t)x[10] << 29;
|
||||||
|
r->v[1] += (uint64_t)x[11] << 37;
|
||||||
|
r->v[1] += ((uint64_t)x[12] & 63) << 45;
|
||||||
|
|
||||||
|
r->v[2] = x[12] >> 6;
|
||||||
|
r->v[2] += (uint64_t)x[13] << 2;
|
||||||
|
r->v[2] += (uint64_t)x[14] << 10;
|
||||||
|
r->v[2] += (uint64_t)x[15] << 18;
|
||||||
|
r->v[2] += (uint64_t)x[16] << 26;
|
||||||
|
r->v[2] += (uint64_t)x[17] << 34;
|
||||||
|
r->v[2] += (uint64_t)x[18] << 42;
|
||||||
|
r->v[2] += ((uint64_t)x[19] & 1) << 50;
|
||||||
|
|
||||||
|
r->v[3] = x[19] >> 1;
|
||||||
|
r->v[3] += (uint64_t)x[20] << 7;
|
||||||
|
r->v[3] += (uint64_t)x[21] << 15;
|
||||||
|
r->v[3] += (uint64_t)x[22] << 23;
|
||||||
|
r->v[3] += (uint64_t)x[23] << 31;
|
||||||
|
r->v[3] += (uint64_t)x[24] << 39;
|
||||||
|
r->v[3] += ((uint64_t)x[25] & 15) << 47;
|
||||||
|
|
||||||
|
r->v[4] = x[25] >> 4;
|
||||||
|
r->v[4] += (uint64_t)x[26] << 4;
|
||||||
|
r->v[4] += (uint64_t)x[27] << 12;
|
||||||
|
r->v[4] += (uint64_t)x[28] << 20;
|
||||||
|
r->v[4] += (uint64_t)x[29] << 28;
|
||||||
|
r->v[4] += (uint64_t)x[30] << 36;
|
||||||
|
r->v[4] += ((uint64_t)x[31] & 127) << 44;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fe25519_invert(fe25519 *r, const fe25519 *x) {
|
||||||
|
fe25519 z2;
|
||||||
|
fe25519 z9;
|
||||||
|
fe25519 z11;
|
||||||
|
fe25519 z2_5_0;
|
||||||
|
fe25519 z2_10_0;
|
||||||
|
fe25519 z2_20_0;
|
||||||
|
fe25519 z2_50_0;
|
||||||
|
fe25519 z2_100_0;
|
||||||
|
fe25519 t;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* 2 */ GFp_x25519_x86_64_square(&z2, x);
|
||||||
|
/* 4 */ GFp_x25519_x86_64_square(&t, &z2);
|
||||||
|
/* 8 */ GFp_x25519_x86_64_square(&t, &t);
|
||||||
|
/* 9 */ GFp_x25519_x86_64_mul(&z9, &t, x);
|
||||||
|
/* 11 */ GFp_x25519_x86_64_mul(&z11, &z9, &z2);
|
||||||
|
/* 22 */ GFp_x25519_x86_64_square(&t, &z11);
|
||||||
|
/* 2^5 - 2^0 = 31 */ GFp_x25519_x86_64_mul(&z2_5_0, &t, &z9);
|
||||||
|
|
||||||
|
/* 2^6 - 2^1 */ GFp_x25519_x86_64_square(&t, &z2_5_0);
|
||||||
|
/* 2^20 - 2^10 */ for (i = 1; i < 5; i++) { GFp_x25519_x86_64_square(&t, &t); }
|
||||||
|
/* 2^10 - 2^0 */ GFp_x25519_x86_64_mul(&z2_10_0, &t, &z2_5_0);
|
||||||
|
|
||||||
|
/* 2^11 - 2^1 */ GFp_x25519_x86_64_square(&t, &z2_10_0);
|
||||||
|
/* 2^20 - 2^10 */ for (i = 1; i < 10; i++) { GFp_x25519_x86_64_square(&t, &t); }
|
||||||
|
/* 2^20 - 2^0 */ GFp_x25519_x86_64_mul(&z2_20_0, &t, &z2_10_0);
|
||||||
|
|
||||||
|
/* 2^21 - 2^1 */ GFp_x25519_x86_64_square(&t, &z2_20_0);
|
||||||
|
/* 2^40 - 2^20 */ for (i = 1; i < 20; i++) { GFp_x25519_x86_64_square(&t, &t); }
|
||||||
|
/* 2^40 - 2^0 */ GFp_x25519_x86_64_mul(&t, &t, &z2_20_0);
|
||||||
|
|
||||||
|
/* 2^41 - 2^1 */ GFp_x25519_x86_64_square(&t, &t);
|
||||||
|
/* 2^50 - 2^10 */ for (i = 1; i < 10; i++) { GFp_x25519_x86_64_square(&t, &t); }
|
||||||
|
/* 2^50 - 2^0 */ GFp_x25519_x86_64_mul(&z2_50_0, &t, &z2_10_0);
|
||||||
|
|
||||||
|
/* 2^51 - 2^1 */ GFp_x25519_x86_64_square(&t, &z2_50_0);
|
||||||
|
/* 2^100 - 2^50 */ for (i = 1; i < 50; i++) { GFp_x25519_x86_64_square(&t, &t); }
|
||||||
|
/* 2^100 - 2^0 */ GFp_x25519_x86_64_mul(&z2_100_0, &t, &z2_50_0);
|
||||||
|
|
||||||
|
/* 2^101 - 2^1 */ GFp_x25519_x86_64_square(&t, &z2_100_0);
|
||||||
|
/* 2^200 - 2^100 */ for (i = 1; i < 100; i++) {
|
||||||
|
GFp_x25519_x86_64_square(&t, &t);
|
||||||
|
}
|
||||||
|
/* 2^200 - 2^0 */ GFp_x25519_x86_64_mul(&t, &t, &z2_100_0);
|
||||||
|
|
||||||
|
/* 2^201 - 2^1 */ GFp_x25519_x86_64_square(&t, &t);
|
||||||
|
/* 2^250 - 2^50 */ for (i = 1; i < 50; i++) { GFp_x25519_x86_64_square(&t, &t); }
|
||||||
|
/* 2^250 - 2^0 */ GFp_x25519_x86_64_mul(&t, &t, &z2_50_0);
|
||||||
|
|
||||||
|
/* 2^251 - 2^1 */ GFp_x25519_x86_64_square(&t, &t);
|
||||||
|
/* 2^252 - 2^2 */ GFp_x25519_x86_64_square(&t, &t);
|
||||||
|
/* 2^253 - 2^3 */ GFp_x25519_x86_64_square(&t, &t);
|
||||||
|
|
||||||
|
/* 2^254 - 2^4 */ GFp_x25519_x86_64_square(&t, &t);
|
||||||
|
|
||||||
|
/* 2^255 - 2^5 */ GFp_x25519_x86_64_square(&t, &t);
|
||||||
|
/* 2^255 - 21 */ GFp_x25519_x86_64_mul(r, &t, &z11);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mladder(fe25519 *xr, fe25519 *zr, const uint8_t s[32]) {
|
||||||
|
fe25519 work[5];
|
||||||
|
|
||||||
|
work[0] = *xr;
|
||||||
|
fe25519_setint(work + 1, 1);
|
||||||
|
fe25519_setint(work + 2, 0);
|
||||||
|
work[3] = *xr;
|
||||||
|
fe25519_setint(work + 4, 1);
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
uint8_t prevbit = 0;
|
||||||
|
|
||||||
|
j = 6;
|
||||||
|
for (i = 31; i >= 0; i--) {
|
||||||
|
while (j >= 0) {
|
||||||
|
const uint8_t bit = 1 & (s[i] >> j);
|
||||||
|
const uint64_t swap = bit ^ prevbit;
|
||||||
|
prevbit = bit;
|
||||||
|
GFp_x25519_x86_64_work_cswap(work + 1, swap);
|
||||||
|
GFp_x25519_x86_64_ladderstep(work);
|
||||||
|
j -= 1;
|
||||||
|
}
|
||||||
|
j = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
*xr = work[1];
|
||||||
|
*zr = work[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFp_x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
|
||||||
|
const uint8_t point[32]) {
|
||||||
|
uint8_t e[32];
|
||||||
|
memcpy(e, scalar, sizeof(e));
|
||||||
|
|
||||||
|
e[0] &= 248;
|
||||||
|
e[31] &= 127;
|
||||||
|
e[31] |= 64;
|
||||||
|
|
||||||
|
fe25519 t;
|
||||||
|
fe25519 z;
|
||||||
|
fe25519_unpack(&t, point);
|
||||||
|
mladder(&t, &z, e);
|
||||||
|
fe25519_invert(&z, &z);
|
||||||
|
GFp_x25519_x86_64_mul(&t, &t, &z);
|
||||||
|
fe25519_pack(out, &t);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* BORINGSSL_X25519_X86_64 */
|
||||||
34
test-generator/gcd.hs
Normal file
34
test-generator/gcd.hs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import Numeric
|
||||||
|
|
||||||
|
data Set = Set { r :: Integer, s :: Integer, t :: Integer }
|
||||||
|
|
||||||
|
step :: Set -> Set -> Set
|
||||||
|
step old new = Set r' s' t'
|
||||||
|
where
|
||||||
|
quotient = r old `div` r new
|
||||||
|
r' = r old - (r new * quotient)
|
||||||
|
s' = s old - (s new * quotient)
|
||||||
|
t' = t old - (t new * quotient)
|
||||||
|
|
||||||
|
run :: Integer -> Integer -> IO Set
|
||||||
|
run self rhs = go (Set self 1 0) (Set rhs 0 1)
|
||||||
|
where
|
||||||
|
go old new | r new == 0 =
|
||||||
|
do putStrLn "------------------------------"
|
||||||
|
putStrLn ("res_r: " ++ showX (r old))
|
||||||
|
putStrLn ("res_s: " ++ showX (s old))
|
||||||
|
putStrLn ("res_t: " ++ showX (t old))
|
||||||
|
return old
|
||||||
|
| otherwise =
|
||||||
|
do putStrLn "------------------------------"
|
||||||
|
putStrLn ("old_r: " ++ showX (r old))
|
||||||
|
putStrLn ("old_s: " ++ showX (s old))
|
||||||
|
putStrLn ("old_t: " ++ showX (t old))
|
||||||
|
putStrLn ("new_r: " ++ showX (r new))
|
||||||
|
putStrLn ("new_s: " ++ showX (s new))
|
||||||
|
putStrLn ("new_t: " ++ showX (t new))
|
||||||
|
go new (step old new)
|
||||||
|
|
||||||
|
showX :: Integer -> String
|
||||||
|
showX x | x < 0 = "-" ++ showX (abs x)
|
||||||
|
| otherwise = showHex x ""
|
||||||
32
test-generator/test-generator.cabal
Normal file
32
test-generator/test-generator.cabal
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
cabal-version: >=1.10
|
||||||
|
-- Initial package description 'test-generator.cabal' generated by 'cabal
|
||||||
|
-- init'. For further documentation, see
|
||||||
|
-- http://haskell.org/cabal/users-guide/
|
||||||
|
|
||||||
|
name: test-generator
|
||||||
|
version: 0.1.0.0
|
||||||
|
synopsis: Test generation helper
|
||||||
|
-- description:
|
||||||
|
homepage: http://github.com/acw
|
||||||
|
-- bug-reports:
|
||||||
|
license: ISC
|
||||||
|
license-file: ../LICENSE
|
||||||
|
author: Adam Wick
|
||||||
|
maintainer: awick@uhsure.com
|
||||||
|
-- copyright:
|
||||||
|
category: Testing
|
||||||
|
build-type: Simple
|
||||||
|
extra-source-files: CHANGELOG.md
|
||||||
|
|
||||||
|
executable gen-tests
|
||||||
|
main-is: Main.hs
|
||||||
|
other-modules: Database, DSA, ECDSATesting, ED25519, ED25519.PrecompPoints, Math, RFC6979, RSA, Task, Utils
|
||||||
|
-- other-extensions:
|
||||||
|
build-depends: base >=4.11 && < 4.14, ascii-progress, bytestring, containers, crypto-api, cryptonite, directory, DSA, filepath, integer-gmp, memory, random
|
||||||
|
hs-source-dirs: .
|
||||||
|
c-sources: cbits/curve25519.c cbits/x25519-x86_64.c cbits/x25519-asm-x86_64.S
|
||||||
|
include-dirs: cbits
|
||||||
|
default-language: Haskell2010
|
||||||
|
ghc-options: -Wall -O2 -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
if os(Windows) || !arch(x86_64)
|
||||||
|
buildable: False
|
||||||
3609
testdata/dsa/signL1024N160.test
vendored
Normal file
3609
testdata/dsa/signL1024N160.test
vendored
Normal file
File diff suppressed because it is too large
Load Diff
909
testdata/dsa/signL2048N224.test
vendored
Normal file
909
testdata/dsa/signL2048N224.test
vendored
Normal file
@@ -0,0 +1,909 @@
|
|||||||
|
g: 6907a072b81862e4621de1cf1173e5d7b26a0da7eb3877a3fd8e5160e1f3958287f25b8e55635bdea4b3a94282a49b0b89cd962dcd61643bd2a8da0017b85476f951101581c893d67058f0ca37d7bebbfad0857a5f791fed2f505585cefd0839ba2628bcf409e6ea5fc7d2fb709dfd248876051807c0e1dcb5eee9b96c43e17db13f0548b8e0416a764240a33352050f7fd06c1f3fe3492050a6bd1e5432b03b2af8aead27ef9dac53134021478c9b521a41f52f1dd52a6a7883816535ac4057032555c9991992ce65e185fdbb488f9bd6b8ec0d5425df81ec9403b2412e7b620ccd82b0858467902f60d7e0df054da343bb30129bec45ab73ef62f0971fc45d
|
||||||
|
h: e0
|
||||||
|
m: 5b9e51587484af8c2957348f419848441ba271829bf358115919d834092df9e2a350af38c64d0e1406aad9e2af9affd112a22420e4230700b8d4579adf6b02f2368eb676a8682506a6c5bf21519605ae47963372eb2cbbab375c7841b7432da5d13ca4b002be02b9be001deec4d7083599b0226e5e7cbaa43f2d22556761a2cae25eff4cd819084a68fb4573dc46c2663e9ce12b0d648e4f1eca3b8197470361a2ee2d284a099feebec8a377662f38443007a9fb1498fd1f179627ff0ab300c2ec2e2050a8f109d8b28d295d983ef88568996b3642eb2757f3daed5109a94fa426cde7d4d281d84bc0190617cb86
|
||||||
|
p: a4da0f697eed92e72fabb0a538fbf690b7809086a59c7f119ca18dff733699f80f9caa59e9630d9aaf90c2dc17add835ce54197cb95269c3f767d68e5d5e3dd454fccc7a01816a588ca1f4cc7344b20e457c32c4557061f46f6736d932cd5eac60c05ded929dc8ebd9082bf685e478b6bd497f653611e9f8a8c10aaf2409136ab5b5a2563363ded71303e66c03f9a6aa70c19b73def6868c40ed94da2cb296f3f36ca060884c634b69c5e3622767ca6e8b7c8fb81991a5ffabd7aea867b0edfdba5e6cfecc13262a290ed4069116150b25321390bcc19c95c3ca42d0bca04e9012f4f828964fc31f094c032235464a6649f0b222ad86fba3ad6ceab8d3c4c5c7
|
||||||
|
q: e09ad72fa8ea898997ab1894288e16803641f7f539089414bbf93165
|
||||||
|
r: 5dc513689b5bc9cda535bf07b3c06214ae12b7b2bb512496445689db
|
||||||
|
s: c463bd68fe6d7afe144dd62530ecb62c0b084252fedbd3a92b8473b
|
||||||
|
x: 1427aa251a0b4ed1c664134bd4e7a69e5169ebd225b16de51febb5ca
|
||||||
|
y: 641c6c8808db6498a3ada4fbf9b3bb84071f2d5b5da68296fdde7f6274713a3ea244e0a6b9da75941d8f36a706df3384d473edd5681e9f9ffa6c6aa3bfd4ad77d8c1164fa2e4f46b3cb07e12dda96c2cdbe80521c459a1c5c0a80ab8f8b5505bf70666b56abfe21ea5f787bd9473f36cafd457c413c9d96bc24d29ac8f1d5defa6307c0bbc45ed11b65ad094257de972691e7dca315bc0054d6ee61bf2577fb190b13f0d4b07bd25a19d6b0913c47844175b09ff0af0344abb08e17736df0e61e16f924c04d9e9b990103ba2926dfed2451c2c79e91b8f863333207ebfa3237be0af3661abbf4f4a98cbb64d1f233a3033fce05006ab41d30072348439a38475
|
||||||
|
g: c768c234f7113f2d1631b5642275bcafe0a819d744ab8bd4f2f1d4852873b5c7ce22cde75119922239dbc3c6164835efcccb9a1c41d8f2db1bb5e43806ea1940d69e6439f5015fdf58f638d83b57f5f1095d460fe33fb07dca787cc02e21d890cf80e4f13f70925f19416568f90721e1d1ebadb1d6ba40ec528f13b2b2a91b85fdfc3cccb18d49b604b6d93ac61b092e7c094000ed34970ee12934512c394f0813f5be8556c595c2d550c2dbc35730134673541180a757917af95dfacc2550795cf53ccc6a37cc81bb8c68001198cea59dc908c5222b8533e22c08cfebc1d2355f64ae7bed6a4883c60c5aeb3226d0ef2703051d978af5d972318a5fef4d14c
|
||||||
|
h: 180
|
||||||
|
m: ba984e8297d8acde096f55bd1fa2b4aed9e5c9dbb3160d5dcf23fd6c29a5e7b71b4e120d3ea07c908c57d0e0104d0ed67c2d41db541c0e19076c6b490cc55cfcc6ca8bdd39f5f38c4200bb15671cf9a0bebfba5d98f76306f436b9ad8b90545402943457895e3543add17f8a
|
||||||
|
p: c2b3b3adb34dde06655d9dfa8f1f24f909c21a04dccbc33be3c31ec0a0878790aff2e59c8ef8a62e0a50a255569c20a5d38ffe80b876026ec0bb5aa49fe194ffa517b30400dd67b85eb37af2026bc66f659ed4fd60c271351e4992889b163f236e96b2bd9ad5fef239d32afd7699fb8447745ef6c26b4d66cd0c5eba1713d952b752f81a1bef5ffa72e6402497b0be3c88811808161d43f90ee8c8460ef7d5aa52959d8239c29d1f531872f021a9131d0f39120bec78624b159a3a4f96add0664729b549d03403498f81c4a7023301c1b3c4aa385b6c303225027eccf1dc010547eb497976b0c7f6563e37630b241195b5acb7ceaf29cba227d85906d4d10935
|
||||||
|
q: a8bd009d9dbe5b8768019df747b7e38a5ce16d1a0aee09a7c6dec609
|
||||||
|
r: 3b9d8fbc9cb3797092f2ad0344adf53484b8fd67eff765d7a68a3822
|
||||||
|
s: 2817e0ed023d5bf966e8d88fb561ccc3b13297230ff7f2c5594ed961
|
||||||
|
x: 9163bc5989a16068b8893e0b5e2b72b39f65f5f016c690dadc7f95e4
|
||||||
|
y: 6577c5494f307facc9f559769e2c8a771afb746a1bd5d479d3e754bf6e5a8385ca92b0e610266af4a910535a26642ff6c9c56bdc366a2e4de634699b9725e523c44c6fe3cf12107cf8cd341be17916377a69e4733dd079ff03de844bc2c1e76e650292cc946a6905ede6c0ce0efdbbe22061d7b15acf3c477a81a098fc80fedb9c0a70a12b9ee78b5059fda201c80a547d5357e3dfa7fea7e3b5e72680297552dfbf5e78da3cb9c2b9bcf94714e3e419ef07348f16ed7dd1dc84a613b2a468a1568e3c9e970c8623f15df26d2e9c3d65646e1f23dffc993e49128b8c74b1542a921268a66e9563b370f6f64d274630525778e2e9ae8124d1f899bd81eeb2d621
|
||||||
|
g: 7d427bf9f9882dbf7481d2d039e35e120b3648e91ee188104328408a712d8e4a0577be1142c924298e202abd753c0446a76ba79623db7bf25da465e9b289b9123b670b618d2bdace45205494737485398e73805fa929727ce8a6c7ade0395883f058a29767d67f48527bea1979b2c406e790f1676ed97ee5f23d4c231dd41b54d695fbc80916e5ee5e773cf33ee4ebff916c4cfdb47ace8471839e5a238d382095da9b4b278a64bc574cbc9fa6f255ce593489147c847f3a81856396ed344a0c42dfae9652fb5b2e72c9fb04af9a5d35b336293b5cc5f66f554618a7d01a4b2828690b106a60825309dc5dbad5052f9cd67095ed70457ef3c2a29c6a5c56f4a0
|
||||||
|
h: 180
|
||||||
|
m: 4ffbe6d0764ab2c15c2f75de350d864c7fc415e018ba66074edba720cc216072c9873ebcc24d7a31ba509bdec09df116e4a8d0110d105f0e67987865ecd71e89d96dade9715c89e74fae3a825cbe2f32e8fe3adabcb2ed202378dedbf2e047b19598aba595198c73d9d4d41c522f2f458ba2feda71916685d1a71f6c1452465a88fc698668b740ec47cf6b6b09936fb5fd4c38cca863c6928d00a050d3a6c8d844137f76518932726b1daf928ea5f1dea7d627ae28e0baf5c79925
|
||||||
|
p: 88187c27193ff47f07217ddec8a2a5f8f1f8f7cd3b7e4a3a55377a72046a3f7c73cfa7074b063cbdf37623b620fa689350b134fce801e6425978e392896523e510f52e9b6e91b69540c864171ff9125ba1324f81e54f61d1d6763aa6800c999073c4376001e0c11c5bc0f6ed40a670cbab29952d6143621e5f89d84c4e507d32c9dbae5f9a469dff0550769e243700735256bc0454a57754a03354a3ec17d8c90b5e3136846ef5cfa9105fde352820e7df1801253988a0bb89dc083d7925ea6a6d88f80010638e74492d28009f1cd43ba7c645b61281f7dad9ca79f12430183d57768567081bf4c0e78dec0933d0d3059ac4d7c9e9e45ced192f4d37ea2b8229
|
||||||
|
q: c10ad68517578153a8c1017498bc9d1dc6e57d6ac35a7c44dc4c7465
|
||||||
|
r: 5d0d48a16093a71905e49909d987552b377ffab255bfda2329467125
|
||||||
|
s: b2510cac9390e93268343a5fa44d1fdb1ade28507fc50022f69b433e
|
||||||
|
x: 261d755051573c27c936e9d9fcd3f166258f03eb85b597af373ee9cb
|
||||||
|
y: 78f47e1998cf8d3af9c5398ad2b0f9f58f2e8e85428bf19cd9fa77446eaa58aecf2a5c33c7b017bdc4877694845b86243d4a8fe451276139c4976b0ffc402f7b2c8b160350d03257ed27be57961d3aac3b603b898345e1bf0e6c1ba92215339b3333a6a5de65b634e004b431026fe8061ab0986f73d59c36c99f63ef890bdbbcdc0af97b27bdc729d5dbd352070cb973b7d9cdcbff94ddad421099d7158c7bb949d87712b21e02d7d32666b402c60736780f3a223482426cbf2da6ab42766617fce3811cd9ca680e972736758e795496c1b4b8d8f577b21517dac2986074c029785373cd91dfa554e13235e237c35f9fcc768f7e5670bb7a0a91d798c94b98ae
|
||||||
|
g: 78bc8a7893ba31c723f2da3d0b692faf29d7fbd99dccad2ddfb5ae5c413164eda415e7fe79d871c7f93a88b5a26db029c589f3d1d24d766a31ff5a29a85de53e50c183b89f79e84b0d68802afb26e908275a9ce7e226f2fb8eda25f0d1b4294483389567dafd8fccd579f8e76510605b5ae0586fcf7bde4c9822abffbcd5cffe40cc0795e1c5def5ac44acc1851e103c85a7d359d11c7f9fc947b4f57f815196e37a61acb5aeec5e0ddf2fcce5c6d73638657375a4b0a0fe10b0a0002e3530c6b8ee77981e00fa788c57625ef939432203c59e3dd7df9418e752253507c04b99052d1309fa0a11660be9dc8ed7933b090b9ac662b7f15b3a8dd56463b6a78726
|
||||||
|
h: e0
|
||||||
|
m: 0106de135125a367dc073135e6e1dda2eb382640278e744084ffde08b11207c6565ea2f71fcc1ad1a01e91203d04604b1281535b89
|
||||||
|
p: a3a1d7b36890afea91ce89277c435d91010cfee2912360245eed827c8ee1bd495edb53840716b05baff2ece3fbd1838d50546b8d4fbd7c6ccaefa02a7cd97951a47538133f6a4d11242245d94bbeec515c4514d0a60889b9e5dbe404f9d709b1dc05eb027a48b6ce5317c7ee13cb4657452a2842c0ce641588a12c5e267c3c66665e831967137e0c0ae8554302a4d3a8a3cd4f21ed714cfd1b64b2c6aadf3670ca788f0f1e114db1fd498ba95b559fb7a0872833b81ed420125b044bf015c92fff092235450b840c664e9568dbb150bcb69abfe29c588def8250c87ab850d13dfa92296035270b8c5895101658e863db71689047eaf9a742780ad56ee7e37e41
|
||||||
|
q: f2c374f3963bb3122ade6644fdfe852f3d22d2a4d500e1a07355d673
|
||||||
|
r: 1e411dbe74af08fc6fbf2df5caeff5ecd2189f6ec48a2edb45b2e5d2
|
||||||
|
s: cc68f6d65d8055dba5846b6878dbdaecf55697856df1606886257d50
|
||||||
|
x: e330987fe0fc1c57ddc7fdf7e6a831d9cf2de435de9a2daa4dba4d7b
|
||||||
|
y: a1fd8b07e7c63c5ccf22467bd773db51d0ab5697da191a5183c56c9f0e3689822eb827ee37b051cc4e7b388ba131d4601508e935d2be54d8ecf646eb9cf547710d9702e507fbefa0c011fb34faa8c66c3dbe49d9119a89f9fa1a963959612b21e27d3552d25a60568d04791f820dca1088754a281ce7592c52487caad52b31eeb750626ef084520a0bf7d930b21da95b43fe5923b9e3ad168d4ed3bc1db16cf7dfda9d847c28f799e0c825bff3ffcbd9883aabe219adbc698896107ff60422d7860d12ab2b85ed7624e89dc79e637790722559e3206c3c40be5fb6d735a9451d538018cb218fe7d93497e2f67e66dccffdb8335df4bb2967d1390d08798fbc7c
|
||||||
|
g: d1763360ffcf6795a1b5a5b2f8497c7dfc5e71249be4fa1ed71ff73685775855cc893f6d2d4cb2facb60fee81bc3af511e453f7cb062dcb402667c3a46de52c813afa83463eb58bd626aa796d11498cd6d21826f5f2db796c407d27906dda4e4d01c74590a45c0b46e1087bdbfec91ab23649a530cb7d307bb56eaa4c21882d0c58e9a13c911fd97713302a4fddb9f68b17d4cefbcee5276b1a94f3e0418d72daea19987795d5855f7da8a3f0cad900331512df25191eb8037420137d16c5aba07d374e6f5ac0a089bdb45c134a33a3fd7f168b794fb86dce33d8a69d1971e8249621cf7d9aece68bf7fb81c108e89123a9c1947ef8567346c0bd8774ebf4d40
|
||||||
|
h: 180
|
||||||
|
m: cfa7665db0c47e11189de1fa549cd0ac5bbb9eae1807f7d372f1f42a2f66640b78e69668127a9f006d6fc6b706a41c60da876081548200fd8f231415fd58653fbdf443446ba527e603bfaeef39eaa07cab
|
||||||
|
p: ddf469ed437a720b152d52902bb83993a1022105ac817447788719422c674a943dd3a6d645682fd1b034abea529ab4921514148f8f2dd0b5f3ab7ff39e051b82c643f4976608e2d01967b3465e9c52e3621e01682a884a8348d4ac015e4fdd2d5f82aba74f1d3666cdccc0907205f00866e67390fbf990c5163bd9ac825aaf01483c1cfe1c9db81379d9f924926815bc8031adfbd75c2941cad60855f8c5c6182a72b217a8e79f296ae85257f88b8147cef3aee7d5d260647a68ecf3ae44c273b5a1b0b39b1e9aa4b7487d209ee181bef77fe028487de520661ea985432e95d4d91f2e5a62b976319370ba0eee99c728b59a7d50c0e547615e836fb27ba5482b
|
||||||
|
q: e4a7617f540cbdef0762db0c3418d811e41b22111890413ac23ff39f
|
||||||
|
r: c71e133201ac408d458ac991af0bf5b874ff7ce8c8e168440b9a687f
|
||||||
|
s: b43b4f41f0557f48f2832590482afe48a08724befdf6efe0945a7717
|
||||||
|
x: 8f784a294cb67e1feb9d4bcc3c882045befd8b65d8982640e82f586c
|
||||||
|
y: c5ca9cc76ce80b5cf48f87726fa1cd43ce2815b536d69551f81ca135001f5e7622d5062fe3e08bc6d58dc57ff925828beb3b2815edb8dc6d9659b5733561488220290f6b319ec7ad328b615b1f91d686eaf03b7a4a0773befb4a03b71932269f7bc6a06b222ef66deb66c7089db6d03ab38c4192333106cd1bef2eecb6a6bab158d666aa415455cc274be6e88cf8e35abe0ec0ddff82adf7a50584e8a2fdde1f139e7a71d63d4abbfc408feb039ff48da9a096b87213bb51902220c840f11873ff922a8aa17aa19c1a945da345d7f66ffe91639070961e145fef3e4ff364dee336330b6f00f7206268d5744da309421e3829f7a22cc20299e01c5b677e1aaa79
|
||||||
|
g: 3458c42d21eebb814d6fb13de88ce72da42a9ef0c2ed54a782c4bd241fa5974ed892a500b886696f0f83ce744d893bc65dbb1b61f6827739b9ac9ee33d7f8fe2c04a9fd0cec1b4014988f2bb53347f210796ff829f42704ecd54d62185c26d961f4da1c41283fd47aed672cd1fd7bda0b28aa445bf8fc12747cb8b446a87c237b1da49f17c316e541dcb25013dcf32af99292a4bab3092906a2e6030060da150ef37b71beea078158350f86ecdec84eb71de76280156adb06d59267792416e6f0acd5e1343f6ded51d93b28e5616df3048200a7138643b4c471c3b70c325bfef33335f8ef308dc6ed32cfd686a2eddd61fe8311db5e3b73a34701b38e2e6e190
|
||||||
|
h: e0
|
||||||
|
m: 96c67b8bb4b501d75f27dcfdad9373794f094911d389f3835e30401a1dca55a3c709595719e7829037f709b2f69a96407afd3d0e3c809552bbe06224d5f6a792e1f1fa6cfc9c5f7912de6025565e432730b367b4076298244a930e92d288c979e4dfefa426ef95042ec158308011eeb23f75441ee1f460a02b6332d6015e9253b03b6ea9b82bfcdb5da4bc7d14306b361bf807964e93ba129dfecef67ad19ec58e00cc94b24d8aada963e450c792ba518d4cd341705c95724a76ecaae54a8b05a671f2c83bc461da4587e4288e41d2df5ed0b73dc284a72be2ea360a32fe84f07f9f35074b7923e5d99f2b8f49c2744fccff9a7b00c904a50b92566ec6
|
||||||
|
p: bddea458eebe5a8e4c56e3f8a0947527ccf0fd9d2fbc5d911e50c14c3f1eb42a2629cb168df27ea8965cbfdb839fc6d09a9b3255ea4e2797f40162c6bd04e92c575c32a54f97239219004f3eccd9c0fd81603a9d9857d0679a5f4d907432f3c519a9141bca37acb5364643d5621c2661c01bf2d13b77fbb9a80797cc83cb9b709796f8761edd1c6365bef02dce356c2ac8e0c499a12f05cccb1f0701611113493fdb0c3a23a3b16548207d057bb66c53c1f3323f29102c507f12a134731c2e36f9537c2230ca48181e63c90607fc9d72bf8c26cf0cafe10f4f48ceabe9fb62b298da0fa0c09395343fd963ae068524c48435489b591e54d2a40de37bc918891f
|
||||||
|
q: f59d2f09bfa964dbc0f75c4ace3e5cf76467ba4992903e4f57d40dad
|
||||||
|
r: b151d2bc3d717468e7afe96d3240b0e04451e83d18b1175f356a8322
|
||||||
|
s: ea1b98ba9c3d1db3d2a39d12a6e072590bd3c1cf9c13f41dec37b665
|
||||||
|
x: 3cab737b8a9152846d415eb7d12e0a58a3921873dfb5c0b0f655e6b4
|
||||||
|
y: 9e778c13495f4366591a73ac40ad60fbe20be19e0f5c94c2f199c77a7dada74fa664509008a2c84bb5e5539570e2fa6111cc5737999c6f9aa54518aeda5b15577000f73f95c020d952a43bbfa85da8706d1557db5e7f38e037827d86984587df1ecd30e959e15d4b5a5c2bdd2242c08d267eda61e336b347bfeed9af5e5ff8c93a8141f85cdb4da78457cbd582aa95b86006cc8da3acca75e62fa5c1c091c82a88b247c3c8841b2d2fc5edf86496e71a986a5a8c63e878307c95098be4d0ea54049a4cd20935ed8a67c2aa7b76ccdfd39da27ae5f837e631bb6efd266f01db05bffbd7ab326fc393698c4efa5a12232a8184e67c62628989148ca02c6421a8
|
||||||
|
g: 15f4ee8c927a4d6d34bb475aece2ec3c98c4a8638b00df91cd35e7bf1e4396312e415ca1e235741fb174680c48bdff9ab22bf6fc34589f40b1b8cc8d4fba685f73e34fc5fda8a2c59d3e7e65d7d7c889d6f55db2c8902c98e79112b733d207538f1a5d47c37c8b7cccfec28cc1bf77145dcc491724cd7373165d9097675ab9611ea77a694d494c0c85e80dbc15e0681a7b7502e884e37a41c465268e2bcecfbf1df5fde45323e37b6b0d505be66bd7ba7f51d61277b9e595c79f5d87dd2a19dc99b76f1036c2eb560544e0bd122790a342b0e6fb150c2671c714659f2d3185b41d9a676dcc01277915c06c0ca9f01b7b4a988c6efcc3e48b280607f396c12f36
|
||||||
|
h: 200
|
||||||
|
m: 13fc4c9c095c832ef248f8156ffe24ceb6c7566149e0ed9000a59a5dc40e14a365f54ab36f37de938a848feb1f5fcb9c825d4a436c4da4adcaf0d81de0489bf6f76e280772fb9596d599ad99c0c879a302dd28c45ba2fc24947d06f072bfd2c5f786b1114d1fc24dedd0ad60b6aed4958ea3d38ded60720f7f0291e888c9bfdaa327b0ee94f4ca179c278cb1cae9e6c3bc88c6b0c13542d2396478b1b53eb014a862119dcc39b4c0210d6a7ae25072ce9c62ef64ce5bc11037976a8ef8f3607bfa177d8c453240896121f197b05d7f73de14a88b5f2a1b268915d32f710169a45c8de18bf160567f15b753
|
||||||
|
p: ae763b0d058aeb7340b9dbdddd3b293fcea5a3aecd0e9a040da0aaa50af8e23b61d702a50a2dac94246fd072bc1cbfb392caa751050bf2b6b1dceeb0203992875e2c58964b6c700b012cd1892d49832f3d5b7ca89bc14f76e39fc907a023d8be7b4ab3c0718036a1d7aaa9088f122a7bad91116db3d003c2bc631956f2ec36a5968a502977fc700df1c9722af40ad68a6c35e0a60dd8203d8c8f188639c68f6ed9cc2807dc2f0a7db8bc51055b1813d88018d8084f68b79352ea414e18eb2dc2e955434e53816540201dac1313f00b5c653e42e5247fd61e649c5b1c2a801189a70d3bd91f52a6fd9fb155b2b8747f80b85784497547fc1aa06e974b62a961f5
|
||||||
|
q: d0b2c733663e539712204ee1222e5544660ffb6442706ed2232eca39
|
||||||
|
r: 6d3720851b5f6bf357db368f90ae422979a71b082639ec2c1e4afa
|
||||||
|
s: d0231900db79b9d703045ecb7952e8519706aace60880d49a253b064
|
||||||
|
x: 668a3d8e2f3a6f43ebc4875bf17bc3b2214d09717f4609c79bbdeb29
|
||||||
|
y: 6b08999e6aaad6fd5fd164807807cda47fcd26e5989c309ff125f5b9567d4e2a828d5ebfe5e6ca18bb0f61c9ebca4a90dd5a9a683a4f8691a28394a702a4bf66527b48481350e0ea7f8c182c56ac150782fa6564a8eb9808886fd7173bc256490c0575d865741db69667496ac0fa7f60215735447efea631f3fc703fe0ead05fb5ae79a919efcf9fa26cfa2b2d6052478c82905b4f57061617224d5e067bc0ceca0f1e31a1ba62f51f675964872798495522ed0b164338bece568f6c60f8b6923c8454ba29c09287db0dc62460e1e93b334394216bf7bf08ae6adee8d34ea387786cac0195af0169cd0c4af8d62a393c8f2fe1dcbeb9c800b33cbc76adfeb118
|
||||||
|
g: 56277772a87001d18e8f82a7f0505ced957509d734ada4254d41d12bcd5f08940a03878084f84a391d3e05861c89930b969fd0b2d20357814bf18d8264ea74eb0ab7340f07f73374f284f4b4f839099646bf5164dc24658695825380eef0268ec2c23417e4211e58709ea9e0ac3d614800b5172b1f57b4ff1a25f3a7ae27eedb660804910c5614b8b9dbe186e9551e98a5cc085b252abfca757cca0c1ea04472ebf37ded59f21a20b5d553f8d4a1b8fde1956e0ab524d176c82d173103fe16a69870209b3803ef5d3ece9d6e8ce2e5b2df3f192d7e55cce41fba1a6c43cf35d96047a4207cdeb6c136ff0a191e1abf434791615acf30b76b8526760dcc6cd33f
|
||||||
|
h: e0
|
||||||
|
m: 8157b242
|
||||||
|
p: d4c994b7c237829bbce90b5e5a57c6c5b100e8b1b910d95753123b7516e4aee80584f4f9b5f1fd1995a472af28d4ee8c9d765c6532fa91ae68a18b801145f18626542c32cdcb3d1aba136be39bf2943057259da6447ad010a4af30b90130f69d55863d2853a429e2d5e6337690126bd8d111629e77f2d383fddd498491fae709e75fbb7c2c9e0290cdea2ee9b6d457cbdf24cf4a9db923d901d439b2ef4033a89d5bc7921ba5580bca2b6df4dbabfc72af813fe951a1ccf4486c975e50259aa9a55fd3493eb3151749b5496fdf9a970f23a85355573d3c57d8fce8ebe47139c1a9045ee6053977bfc3e9e3ae16625dfedf0197300c8e66076821fab5b67ffd63
|
||||||
|
q: 8f926164d95fb8192ab91392d0dca1614c7498cdb6ae7a8a21cfe2cb
|
||||||
|
r: 878afa4e315752102f1293429c233850c741f5c71a595e521b6c4a1e
|
||||||
|
s: 8e2f4a720594781eb0243b6eab0baf4557ba4f4540c7818f91878ff2
|
||||||
|
x: 4983fc5e78698d863e274caa663e1c89f45c8e6a4c0948a8f493f99b
|
||||||
|
y: c23cecd73b0c1aa2d9023c9ddd1bf00379eeb905bf65f119a093acc11f14bf8f5f5fa13ad0b67e41d7fa84445696cdee5bceb349bc7c91942f0b4b83ddbe19e5543f2f272926d2d5589884285093af893113bd90632aecdfff1be94d7bc63d85104adf4db392b5fab1b20e70b136a24a5bb46b8c3ba643ef57af594252ec3725f8c90041583db7ec945efb459eb83a1a9bb5c7063bdfa9331e189cf5bcf09f5f85464efe1c1ff8c54f375ff15c7df50d25e1e881fc483e5abf96f4e1df2080fd1164a88d5815439a1aa0a35785890c650babd4ed9a43b1d5c2ca1f2faa7e431d949e0304c56c2d8b915b7d3e280f50b20d0a482bcaafa58979bd99e56d9e5003
|
||||||
|
g: da2e54efb7e2026ea65bd56e711a6b8c1084162515d420b5660b3f1787137289bc3496bc94f56414a74cbfac4b1758279b2d793a47a8200c2ea4441128b3c90c64181993aa41002d32f02e252a8183f29cacab842685a5c52c72c952d798d1e33ec67460cb4bcc55de15787d5d902de4238e354c24e74860912d7785e3647454be060f98d64a92804851ad4978c3d295b2653ba1fba2991e2f8947b7a4ace37e8d331554b59889fe5327a8cd365dffd8f44b983005715896d76c6f20471c707064b90fcf42aa8deaf6a089927760fc1a313b7b60dd2cfbb2c78f475313f1f9677f80d66858d6cdb934fda4db96301044e889d52c49e9f0ae967b8203935485a
|
||||||
|
h: 100
|
||||||
|
m: cfb318c85f8ce25678d71d89d580d08a99d40bfe1244b5c9215da177ac85e1d700a023f2c2c589ae909e092d4bbd65d6bd14cdc708cd5fef2a125bfaf360c98657a7f127aa6e3a2841699384af023a729b75c9fc97173b577ae9cdd7966fb055f77dbd646a2c844ea3e6321a708509073b593359523dca1b1851464f004c72ad76059347
|
||||||
|
p: 994957ed456355257d990c606284083d1b22e60a7032f418382794249c6cb75ba0fa02f6f13007bbae58c29b5b4be0276c25f24e98c8826e1cb6aa559460ed878a787ff641905afa4e5c65ed054ae521ec50a6377b1d366cea6c8255539acfc4ab66ec20784e9a8ffbd735448b40959f13228f477ed6bdc149d736763ba3c3533873ae587b9d1aa08ed105847e81934c55c3a285c9dfa52662407acc47cb9c128c989a52e052e35eb21eb1f86bd31f1f4debda27648838ca0a1b76b73f0eedd9708c24d5506fdb9f4872fe7963c804a859cb14432a7775ae35d1c6566e1b5fcd56c2a7d618a944921133e757a981e99bf3448d42df97e4e01b761dbe2e57218b
|
||||||
|
q: b1a6f6afce2768814ed36567ee873f5e8ac74c1456968f3f453c5b71
|
||||||
|
r: 34f23ce17b7db4fcc11549354c7e8444c56c864d855a0c5aa8c1b819
|
||||||
|
s: 32fd0a7926f2d153f5dc3d223936c48a454afb0af6c869242dc7c9ce
|
||||||
|
x: 62184cf9cbc96a78ba1f59e45521cabe2b84eefc166d76885fba040b
|
||||||
|
y: 26ba1bf6e4e63a0a1c4314780939119904fb7696978aea62db4bb7d784b2d9cb0b8a04eea3112a0b267a7049281f35cb6d154e05f8831ff120b16821d8d3ba07d4b3bb1c164192f24873619cf0dddb96cbf641ec49dfce7497f4ffba9c28b2cd0cd8e8ee9615e6db13d47db71ec767da8b86f9f6f4242cc8d37c0ca87638c4d19b5c24aff40af45580704b89f617e9c8fb40f4180789b8d1383aa956e3371b877e9d0da257cf07d3270d2d1b33f04cbcd414b1cb6c884d898a05ccc1fee967a4f57b809dd8f4783c4bcf2e02a2fc02a8a33f1ffdec71d03e804066285d889bf950b82c9c8c658ef7a145cf62e9e50d652a1351f5e38850d41b7259a70da5c72b
|
||||||
|
g: f151f776685c600062aebdf313d7c9213528e650c64ef864ff04d84165011722e282a787073200c98124ca93d770702acb9df26119b3b676e6b5d8d967f2ebaf51400eed1f40aa22887b2e5870d15646c1df235cb88dce1dee6986229835a5d5f5095b3c0ed9ebcd06a757b5bd08adae8f747a6e2aa763c259ed6d6cc704fbb733b692d121e00fdb0cb4009c2791e8c44e14ac88e903c59f2e8328837f45f4655b7afb2cf35b5fbd0cb6f75a54802fa499bbf6b5ada3dde23fa58de74d0d90cc9a621c74e2071e09fdfb5bb600ef3e74c18bdc985f7ffce2274a78cd73655f1acc8008b328a37bd10a915c1b22bd6870a4e5106da252357a377325c87b5c1f74
|
||||||
|
h: e0
|
||||||
|
m: 4f93dc748351fe63f11070f67c9958676f6bc1a7d049974cde581fcd123c779ddbba5c99ed6b49d15e649033c4f978e02969e4d0475219c3b003e5666d91b17520b76bc31fd641a0e6e69a9104e0c3f3082b698619ee69f97909b84abfef3940f607cb240011f82ca4f06896128d24d0cd44ea12a98409ff630110828a23718d65876c38ab0bf4ca0572ec6a2dd72035919099e7a08bb6bb86e353065de10a9ebbbc53998fe2cf91bd03df96f4903d0f32bc25c29e98bc8f80691541db39473a6f20c3a6f259
|
||||||
|
p: f7cdb3ef93c29b6d8c658e1ad8ba33a15af4c27d9ad61fb8bb3da052476848017a8d5d4039e424f6935996384f8c785f2660c311c604252e1ebf21e0baef3b0aefbcabc55b454757040955f4136f2b1b8a53cb2aedadbb0fe0a83e7f3d1ce6292908a750f8eff73f253656d5dc3d9da6e4d0f9592fa3d284e458070cbd2b969e54957cfa3b0df383ec0ad2cc7a2e90eb5b4b119acae07ce5ee20e1a276f6ff191afb9b7b572e48f375a6d40b94ecb84e1cd08573327bd8b2ec6fc0781a4aac89c09ea50660fbb1778e49b8c927e7dda28470d7567451b0721909a6587ccd1a66113dd38b7d3112d596402147effdc953d594665f946e7935a82e1d9009cf39b5
|
||||||
|
q: 8fce73c7d3262f590691379e56c012904c9d71e255f8e7cd2b54941f
|
||||||
|
r: 8e4ee117bfdfa307fe29682ce97795be60a6eb3aff2cb6d87baff34c
|
||||||
|
s: b97b95197aaa4ea707af995c7e7934695f7bfd971b24d9c33865f09
|
||||||
|
x: 133f7e86aa4e8b26ce7a06f7758f0b469efe860cdbc740f86ef13a47
|
||||||
|
y: c1e1d6dd155eb0bdf303f2011216795acf597ceb6357a8f861575f31e4f07b8fa75681a43cf221713dd9c090f3781bb0b3cb7e1b938cb5f82b64b1d12cc6082bd412dfd2f40e7bf71a505e418376ade9ef4c177c0aca34a592b10d4e7d2a4c5b45b834a23830a7b30116da00734c1e1e0c890c17b9aed43cc03d2493451717faf04bc969d9c8c49b098f87378d3b381e7e76400a56369734972810ceb2ec8dadbc512c473e87c0e5b52e673aac7efd9535558dfc9e498d764cc0984a95f0b3a5436b3a902efad5c5165bc14c200960fffeacd9b7b3b4139260bba68c72d8ab71992e29f52766fec5759d34327f6b4be929c4680ed9e1ba8e74300c3e030f08cc
|
||||||
|
g: 5ef368b11ad0c366bf944c15cfd4c70fa8f1fe90e9e058758203cca00a8e244887ddc0026bc1b7541668f72a8ca7aecb538e62f194b245cb9bba45f61ad0ecdbe045312714b38fac454c891c3415aa6eed8a98d4f9c4f3f61dc1505aaccc527847be612d157f3667178a6ed2b61d311eb4c8b76e559d9be57066de92fb973c2c8241e940bcefe5cf2d6c679fb33022d41d742532a073757286cc68f69ce2ad998f8a68fe89d542f7cd7cb15adc3bb6d36d0009aeddb1461ce5f2ffffa670e6f3bf29d00d7bf5f26bbf13281dbf2f7196553602975ea34603af2334069c0caa8e413b7e5ab87b6bfd0c3081561ec5361ff54eca7c2f33d315bb7067a167dddf0d
|
||||||
|
h: e0
|
||||||
|
m: 7fb453f703cfb4ac0cd58c459cacce3e28b1bfd61bd64dc9f41a144644bbc07c3f413dd486b67f1f2185ea2a69b994881235356f6dc0357fe1af0526b77b472c16c428aab07494447ba4ade171914098ed4e45b267fe03e2a11604cd3def8e97c22c1ccce2c80cb195707a442e93bcc37329ddbea2b43393babdf0a556c1cef800d7454bd190b6ca2b6f7bc97a0b5a14d757d258825cbd02fba9c54168c03e0ea2d611b8e4486dab547f44ae73e4b6bda08e88ea1c09a7018289e0de28d816
|
||||||
|
p: edce55217dc9c0d6b452debb21d239726e94ccf408dd46c4d297aa8bb82dc57c1587df50e8f175de3b56bdd16430ce7514fac777b881598e6e315802c3111c51842ff48e5e814341f433f49d6c90bc9fd54656244252c075399db08b8b16634fdc92adcc5a1dba18f96a7fe19274e05d4cb2c18bfbc83fb4878f0116776b6eb374c4a31b8bb8ad4e7efeff152b426c080f2995ee6342120724143e933d66f147b630e655faef568877c04612e6462350c2e5ce8814668f22b78b41dad71e0ee5ca9a5f7d6b1c06642c098fc114ebb3eaf16a3e3c365b5d50403a239d0b80f6f8da6c6a6936cd26e54dd76bf3735e748d5ec557ade521afeb2f610d163241367f
|
||||||
|
q: b4cb15be8eef2b1f681cad74d4199defcd74b56ae88478a2295ed3cd
|
||||||
|
r: 8a6c3138d0700b78fe43913d4327a4018c04e0c87faca7b21fad7605
|
||||||
|
s: 779de55d2b9988f98149ca5eddd4bd0ebb337419e99d619196374849
|
||||||
|
x: 6ae841f465d3299d5a2b49c24bad536841bce0f4df63bf3aa1b850b0
|
||||||
|
y: 4b93a4e4d6d9519d98599277cb327ffda47a8656777394badb6cb40c341252b789f4b662baa3a400a1848fa9a763f06063b03b5f9b13291f86ce3b843a7607d4ecd243588caf16c4c802276a415b26f10d608664d1540fd850d9244c5ba943f60f2ff31d7081dfcc55ab236216ae150fba8eed42175e669364372c8edf7118270cb666d838b12fd8d809bfb2e1df3924047d9c5344a0c661764a5aaf2496a1afe807d38a592237968a749334f192a734af11807b522b74601ed164f9a5ae46501add1b083a5666197b0bb747aeca5822f4538c1aa8a0a6452acd56d1a90208a7ac0080b3be6c91b9fa59eb1642cab13e354e8e973997b19249d7b9425d3d408f
|
||||||
|
g: 9ee298305aeef3f239956729b303e7ffeb87f694920418d1cf4c68f796448537fe0dea6b8691a0678782d1bf281ee3adf74331d762990f76215e8c06a68d062fda1956200928a46f6121c6af1bcffaaceed1fe8393b432f868fe892920c656b792e2fed8dc5337f502278851ce949106308a9220079e7a2b53caf5f3be77803e0947d08dae62bc43d5e2a81dbe127761fe77bdaceb21a8f7d9f205d58105063e999328af5ad4f06677acf7ac1d972fad0e57df4916298cf3af12e67c26895a295093ac9753b0df758527458834d9aa76ddc282ff1284791ff6c4eaaaf868312c17d939baa70dd1e2f256002f199a757e3726ec0badf8cd676241382e54dde988
|
||||||
|
h: 200
|
||||||
|
m: 2b41e5342f9c4fc117a575cb933104cfbae195e672af58afe75e9d20edc7d4d685a032f9c2ca8df20580634d688a58c8c13cfcfb9ded2e4f3711c986364773e09bfe33fc8ed2d0463411c993cef870fa72aa8601c2fcde211a733caedf8de994ec2c04336e1a8cf6b8ae26a38db33fcfa4f1dd314d8c571ef13f411b973e87b43ef6a528fefc397cafeac7e48da382cb76ab7d38d24261dbac697073ba624306c2085e8ccb6a832a7a3f
|
||||||
|
p: dfbef7a74456b64a7649197d4193f14af9359dc3ed9eb2d0d0960d23039ea221304013c5c2e93c99e320ea978b2c1283ff4fe9e26910f79960d21898f3e9ae449124fc765ee4c52d73aeaddba41e900ce0857da2ab727c81da612edf46ea203ff9be39712d1b6827eaa8515667bbf85b8cd0007c0ce55b0fdbb81d98d866df661b1e97fbc55075c2df562052d2600b5a2e9d5c2e28af568f39f8456100e651a67f301f8e446d72c84360c70f07edb9f83dee1f91c7f8aa3e6e6fe42c2d4a0d67388e51f128ef9a528be9b4badaac524d3bf5d443f4cc4a980e7ceaaf7bf0ac5fa10bd0f0547d0907a48d40aacb874d926c36e99fb350bb2ebe8a75fe94cead75
|
||||||
|
q: 8636d99401dcc62bc8ef2aaaf9eac1576f49e0c7794e8c3420489f95
|
||||||
|
r: 18633587afa9097818a08f0c48dad5fcd8e1c4a37b07af8158e5b2d4
|
||||||
|
s: 3164a29ad416fae98c98084cbd70e25c146082c71e62e551de25d796
|
||||||
|
x: 4238a427de56b23d6585e7878c4f5c96b408721073b4dc1b5b995387
|
||||||
|
y: ba48870958b29b3a353729e8bdc25612f1942aaaa482c7af2e0aeca884abf1a6148473eef7595b884e57e7b0ab612741bfdb35c5c9a4cfd8c0b1fae8c3dfa1750495eac13bc5a747b9e155375512672adc06bfa0301d2d18b72749a4d37172cd66deb823f51ae06c7a7710490372c9222eea5e05ab2745762ecbeac446b54b5ca3ee5a731b0817840b5591561b781db93e3432a1b4b2a4170609ee7f336f08c619ced35d92a7f87ddaf0a1fd67ebc19cb8e7219c18a9b395870efdc788d0afc51dfca18d709aafe9472455e0329549a6753c45c97d5561481e0c8f8f0a2fbc6204a58f2b1c537475e351876c726134b3c92439f08311b92d1a5522c33e214c36
|
||||||
|
g: de8455517e4ef1a07d094e3acc4a0445ff4e3eb0e14f9c1a2cbf9e5c307dcf1d31b3a3aee6776c145315caf9ece314cbcebc72de824929e5c5e287e2e47610199459abe4ea5a5ea023fdbf06afd8feab2b92908a44564802cb90ed0f5d3b5251d3c19bcfd99f72feff70f6bca38f8aef8a2e811290b4a9a977665ed8c91dcc4ec5a389750a412ac1f154efdac00e47f147c8f585506d6849cdc017ad8b070e5f7f175051297fd05933bc4c302a2059e1d63a2bfbe0b07f497714e81374f961aa23c6b8e92e711f6fb7bd67f95dee844d5ec2474e1091a15e54fcf68916b72606f36425722d8a7231ce00075326b27f6048250a96f700674ada91f6aa4f6b2ff1
|
||||||
|
h: 180
|
||||||
|
m: 09ead7ae2b8bdb6a67735bcccd65b6cd8d2870c72b2712f98523a645547af259f47221d34dcece1c5c84d690eb5054f38e661cdf36626a5f98cca1f1e19ad341e3737b19309dc87152950b549beb52afd901861d2b3884afaca1345fcbcb5be6354b2e25083fc7823ed4d2bb336072827016bbcd4cd718dc1fe7da708f43d565d0b2eca13e216e3ee5a443a841916f74525f6c941a5ed5764a235dc78669ab5de05448335bcb01fabb159285efccab52fe156783ac558c0a4053f6a316921ff123ae5c9b9dbfe1697793cec72612ada8d244f6b8ce64b01d07b6e0479f93
|
||||||
|
p: f3ca4b159c95bb71a49ff43481957a2e40ec1a82d484aad27ff4ff8bdc5e7550695253bfbe5c93ec6df799ac13696aa6e22ec839cfcf5fd0c5abfa756bfdcca5f6da52cd3b7cdc4cbf1f803812d356ecda89d3307bd3a4090ac8755623a1e54c85a507589274a4120d2d604052ec792fe47fbdfe48d1ed9eca5b1335cdb470279729b0f14d586a7c4dc143936a59cc79d189346fd4d67d56cbbdbcb8d323105474cd13b3103501c35e0e22d8bfec32949a5d112da299a60ca806737c8782523903fe6241ac4e96da37e1c9ca1a4da38e70a549dd25692869980139b2058e95cb6d3439f21bf0958537a7a11d9f5a316c596c036d66593d14843d5f3e53b1fbeb
|
||||||
|
q: 8b9ab58a48cfb9176c8afe98922dc188b0f1b53722d8135f6c402449
|
||||||
|
r: 6ef011128d69ebb9124fffda4a3eeafa0a3f536153bcf98a38f25b2a
|
||||||
|
s: 177f1bde758e8a484e37fc8bd0af1652069727dcbb489cc399119c8
|
||||||
|
x: 5595f26f65958f794390d4568c2cc904790861674ac80bc5a58ff4d5
|
||||||
|
y: bbe635c1a563a64573803624b953b002e97ae8268cb37d7faff1f386cad05d9f4d2cb49789645af374d79709dfe7472395ea3274aac73742b707918c620d4214b56bf122cc68c2ea7a4ecf9f582413a3f5500babc79cafddf1033c9fed762844b1c08c054f8798a5c00f20585b940e552c91bb162ae09dda7f25e98844fc1ec7c913691eafad922287080c2d05cd93391598c743893c37215e78e6c2d120efdfc7c3654b5ec3b7a7aaf43d4ef8c4a72a1a9af6f54738351a123b3effa3ed71621fa40ac2cb62e05cd392ea1137ccefbf519e6789e7ae3a478ffdf85aaff2635b679ac934f26e9a45e5bbddeb6e21fbb3ef47c580de3e097294c91af69fcb4199
|
||||||
|
g: 917c405a9f89b25636886aa1f82b8a2e68b2bcad17735a5be42b42f491fc7f93fa6bba606aa9525a82831cf961791b6b4a4e6ae8a2aebd80b168075a15045701520aa5c5f4494dab7ab506c47691a2a729a6340473d0d621ad59f3b2c397c4d3d91d99c91e48adfc641617f5765c8f9c229e88be9388dfbab7f484a88d817d921645985d3874d0f7586c8f0354932c329c140af6e03728cea4467e4fa5aaf0db354aaa2679410fd1803f9cecae08df8ad5d60cf916b53d3536da88735aaa662ef79db261b16e8eead2f3561e35aba6c595027053d2b95d8d292a2f3cdd4c9ea414ba2a61b5f6ccbbad6f64dd6e140c47015369a74b10e3c1fb2de91084ded855
|
||||||
|
h: e0
|
||||||
|
m: f00e6b042477b1b2c4274074a77a138ef76d55bb43fc761588ffa21b3b9562fb69bfde489b5e5624a00943ba8c01c5cbece35eb857bd852a853e1cb9501c53070c1a958b51fe9d95ac7681b9d2050cb0df1cd4fd52ce26d81fc9bdd3ff891ba1de639c0b6bf748f6047d78b3c2d9fd8d0d826dc24b86ddb6dac25ebf71520c5b849813755b7115d7b9f4ed35a67e838c39f7881930b1275f2c0a03c1a37d083e33654c
|
||||||
|
p: 993c963c70849a6bb531058a5af8f900ed83e024ed200fab07bc73c2de6c1e1ad062fc7dd944d6f24d94fe1fb44b0668a617b4c4fb10effcb6b399c1f489acff5882ac9980bfcbe9036861280fbcba6134f9931ec39365d50704416d63b395d7a7449326db7c6034b5d430cb3d3a7a973fbdfcd6844100749f93d616e94412ba56144586fc2289ca639f2f9c6554132e73f568ae17130aa7b22af121e9b6fd0d1bbd192f2b21ed0cade13d4764d8d04b407ff312f8aa4f00af17ab0de04e249d228a2b7c9cd214ddf67d13014572d8b4867464615aa3db7ffeb24c57cced95b76f3e79a2a8a80d7f6ed0e47de0b33d85bd65ae607d16a969cb22339c12a6cf5f
|
||||||
|
q: aeb0a320204ac1baf1ca158f766ed7b33e899cb1d89e66d32ddf4cbf
|
||||||
|
r: 6e6dd782bcc0c52ac77fe203da455c4baf24607598ec1fbdca6e905b
|
||||||
|
s: 30f0617a24f2a7367c22aa959ae5e1ff7f87990bb8d704ea88125df8
|
||||||
|
x: 969c467dea2510779cadd959723e04f5ea2368e5203de2e7ec933c7
|
||||||
|
y: 48fb337e8254834298cac488f5216dd9fb9b61a381366ae9378bc78f5cc435c6f371f61357226cdd6a55fa7a007d544bd515358b31f0f7dc7d44bed29d5a6973966cb13fab3951676aa714f25f5f148bb8864b19d664346b0e45288d3e75b9c04ec2b5866029a5d3b2c62f03b0aa3b3242ae8426e0dcd6e42eb2561dd75a0de7af7599d8f984f55b86db9c8dc8918f5324a8f1b568c6881426038f70e81df6aadc46cbdebbec505e1682d8038932cf1ff4539928b054263f2ee651b71ed379f25f7d93b28bee9f259779d2b234b949e39db7655e6f1d8a201f4573b13e59200e6c3c3d90cc330d4d17fb6485b004def0c071c65158b2b87b99f021d7c735dcd7
|
||||||
|
g: 86fcf370fda50f695e9caeb2b6639096842c052a4f4843181e51c7e8111e9d334bcf0db3fe2e8b268810d067ff5958ee29c53407b061ff2fec8f91b638e096bbaa8d4b377ae6ecacd57afe9fa2d3faa6a883e95712c1d42262b6c935401104422469be3463c8edd990a39661ac49e1e3fd524c0f6fd605e9b8f5ca99cd9a1bd905e5a04ec5ded4e04688451bf3e0d34da74911e3bf43d597e287d28d0ff162a1dd8f919476484da8e0e108cf96d2b58252b8e8bd450b3aac91b6a9de82118954889970d0631f7563102d959642b4f885ab5433358dc3e24aaa62313541edacabe19b53f14efedfe5ea36a4b0543e4b9f8a0badec7506558a452aff9131b47655
|
||||||
|
h: 180
|
||||||
|
m: b337690fa5fc7c9bd62cdcb941d0a64b12b8489895e54e0dc223cd63fef3f73a68d3bcdc7c21fa8ef311cac6ca536127790f16cc4af0d6a7e7864aa5fc25cecaccdbdac7e0a47e0fdbcb29ab28f234fb330c3d1e9ec8dd4ad8781eeacbed60bd83a4bb2635f92f3e1b640474acd33f55c0f070441ec56db72d0b798c4e895a12a816bdd069f0a6ef6567
|
||||||
|
p: 9d8d4646c8cf6d8dc8f1356fc44204684af7817ad23479ea2ae98763732ea048fd461a422d2d8dd45284758af1ca7aa8100431b8e46618fa08996eb64ea1f62ec4f75e16297cc511920a4731f55eb7b82398572162d2e0b971069af0de4e201c9e71b7abb46a9b9d06913981a5ee5f12c02ebcbb584d15b27ddd19068369d26e9825a596295353f7fcf9e2026f0d5d52303f50b8b06255d6a8494f61e3a8678cb4786c19e0a0faa3a4c5016c525dc3f7e45c2bd307e129f087777c36d68bac38498d30362b49e648807f78118761fe0c2509e127f9ebeabba37f20339fea7157c8c88d9acdc0ac3d7218e9547b5cda5d0df514df7e9216ce31b887dbc469769f
|
||||||
|
q: b715df304d2200a8f37c04abcae398d85d801f211c502c995da3b2d3
|
||||||
|
r: 9d1ad56684c4926bf9a48f34186aa9d1a89257639071236247ec86f4
|
||||||
|
s: 85229b131a67eecd9755bf0b8c76523d1d9af11ff310b8177bac7dc2
|
||||||
|
x: 48e82d075c93ae881c13024cf3007f79182f2d1327586e67360812e1
|
||||||
|
y: 3e72e5abef7d3d0aaf53817ce1ffd7afdddeab27631d31dc60be6e9379b1d08c415cb2939e0ca09fcf24d26d0295269f061e81e2c92f6f88c059338160939b25733f285922a4cf2c637d9463b749c9c85ea5110fd2bc4c4e2ad4f4f43b30b0f8a3acae8af35c3745520934c0a6771a3b6f2384a150d8e0b849110f68b7a7121e5d695decd4ba28a8f080b10860dff410dd65d4f004f892249693ac1a760e9c1b59141cba4dd1eaa275f12d6ab70f5acc1323b5939a88289064f45b90c557385dad7fef3f94bda573b5337e3a59aff2c2355527839b7b01813674e1a3ddf3b1aa6cba25611699a36cbfa52c857f6cfec0afec206ae3369103d20f4069b0c04fba
|
||||||
|
g: 3b6d588b9fec113a6ff2aaa275ca4299100415bb56492bfc983b13c41d55e71182599e0bc64044d0a42e37f373723f4d243a80692827628d414b8b79dc0e767c9e1233a30245edd7866823c33ea9045826c7bd674ac9b29d6187d5069eff6b798c91d3e8ded61f925728a479811c86308d822d13769976c46d0e44f4cb86b22ba9ee2a52a94c250c0d4ecd826f6e1ddd8433429b2e151524b5357f71d18d4681b9a49969490483ccd2569c0fe4ee4e4267f08ff26521ba6a408f1a3f82bcb5978ff20e13f2aca7c20cdbd51052d0e397501d5cfbeac8388a50e2be6e7800e5f9d747d9cfec6d82cd3d6ef70753c7fe41e766142ae4a242bc32e459f06a1c0bcf
|
||||||
|
h: 100
|
||||||
|
m: 9b728e1cff164f294b0b076356eb
|
||||||
|
p: e2d3b45a4035ff720a751d486730c508d8621d60f9f9793fe3d74ed4e45bee113bdefd2cee4ce9e0ffb89fe06af2cd154a6c13b2e2f6e36cb9803cf0cd6b91267e26e8ff3c837e9c9df95109880f6888086c615efcc3777ca7a033832ac9b6adb2b244124c29d8041edc28a343ed699beaa668571c027ee55aad0d8bd0b0cbaea17f2416a84de912c9966c511798004217ad520a3eb09cb318c274ea93da7c79211977bc1d3fe6078c1284304676130c37948f0b627b85adae56f60eff0cbd3d27282c2e024fe0fb47fb2afaba73dfc248a8650cedf38aa6fb0f9a723b5b468fe5a7be435d9ffa81482ce2143e67d08865677604fee0e1741d6e90f31f71bf09
|
||||||
|
q: 8fd517c975c4b949d75d7623ab955d38e1e8721f0c27792dc2f0a893
|
||||||
|
r: 57d9baffc630971f47e20009e6776153318adf57981a60071f98775c
|
||||||
|
s: 872249bf9a961be1aa2f5471670a1c268ecf2ea02381d1d81f4a30f6
|
||||||
|
x: 109e14f53cbaa6d1a8b6570633a801751dc1965326e7c1fbc5dfb5e7
|
||||||
|
y: 73fffa4fe5276014f9ac175ac46f46395370db576ea49d83c188889ca2030efb3a0ca57ba026897ca63708483705f6d9e1a81d1e3aa3762b760aecc04ca41b68731bcccc0446c3301c5c5aa1719f2885efac860ab92e29cd78ab846f80b43a52321184cf39444eef379d41bc71c8412ded1c8b346f12e8885a0190b4b17d270fc632655c4d8d7395fd36235adc6f247120e988bef14efe446a56362d77181837a3ca3f40c3d7697b167350ee540100bf66fc2b0f9f2ac5cf09b37968913d82d7f6ca3aeb7df56ed76229dcbeadc448cce7e9533f543f49bd808cd832acc205d63b85a428dfedabd4a54973950bf67a904972da5aa7e620360e2fea5e543cbad7
|
||||||
|
g: 912fc3a0c1a61718c9f02c3d01d226d320c1cd19f8c039603e70f1fa9b96678bc3dd459d6dcb0c19b11b29bd387c10d21105248cee9302ebd712897a40423d5982412706aed8b6e4711d48cf10cde866c0604f6dda5a6aca3297791156aa7b7267e8c709e861ae0b4dbd6541755ea5d0c8e2c878740fac4c79a40c253e1563f58946d8ee199253d2150daf4928be93cc232e17a0ee991ea8dbe9ab57edfab127b05013dfb304fcd42a15788e4cda79c9912ad99aad24db8f6e294d0b8efd606356a260432f06704d3d1ca3e5c2cb36bcc04e2314107d751fd82ce4af3112cbb17afbd6faa108c15e276763363d2126d1a54bb7177e6413bfde1dea663811b0e5
|
||||||
|
h: 100
|
||||||
|
m: 36bd1993ff7d1a10c157b7c4c4eba829e7546b050df1534618e85221df1c1f02184720dadde7c38b80d2d11192e4a262b171e4085243bb3cb6772fe199b9b9a223d3763b16fa568ac738179ebf8503d6f53cb1b7f13ca831057d5562c38ef1260d936e0f80d932f91eb19c727dd98bfc68252bd1
|
||||||
|
p: 981a1bd7ba432c5b12e83a3bcfbc18474e8ce9a667301782e9b329e65b2db1824628d6253a57a0da647c45aef3b14aed7578c83e3b7a6c5e55f32bb28dfa86b17272dd5c20e519fe55dc26fd8be827642fe41ccc5b0e3ac34880cb93965af777a18d1ea920cbdd351afb58becac8f135bbbc93df6a8751a7bc6433b4ac7a0866c307a077e70846dab6d1d346dff68aa27e08be32a140ee0317b165456683a5aaeb2f92c95881292326121dd3d3aa957bd158391077837872880f146fd1f4426c9fb8d67c74abe2538422d8f8d4c3a425102a8653ca85a71afaf66373b11e0da7d9dd0ddd96d8848afa800789e88d940785f8ee6acfca57ace233dce65656ab17
|
||||||
|
q: be105c46a4e713c87bbbecdfae0ba4c5f9615189ce6a513c44c38011
|
||||||
|
r: 599495d3297b51bbc8cab06a00e1d46b7bb766e66f62a34077087095
|
||||||
|
s: 5d5c4d4d3412eb458e8e5ad681b1c4c2b12e45455445da12855907fb
|
||||||
|
x: 12f4a64fbd200f921385fae808e891234e4c3513ee95209db2b273a2
|
||||||
|
y: 2c6b7db4a113ee6933f15ff2063d2145fa803547b8648f828e73c18d548554d73a5a9b3247c8f2fa857209ed46c35e18fc5ae4db2752d199d30767e88bbd1c8ef6b6a7910fe15945ad10a0d1f2cd6cb67c2a1794fa309a4ef00a54e218ea020fab7d7f5a7ef07871388eefe297935fbc1a512241228e281738a8f48fb98da06b5ed06cbc4c59682b6eeb882d51659f58fa79ff2dfb0a924915b19097a66987116aaccc8648e38c976fb64fa3fa1c59a0735be2def2f776dd4900c46345241f51ee0c583932673b7827f3ec5cd7b3a3794d90e19fb9214e9b1a6221f7f63e4aef3ea194b5ee3e39a79dcb4c8cb48195947f62c37670260f48681b79a1d4a4ea8a
|
||||||
|
g: 593a789eb79089a5d2c2b8f0801aa6d3a31f53bd55e635f99b0104bafd35d3a8570b3ffe2d6d589443e42842b05a2f01a8b63f33624c6758ec1d43384c15c0092e11ea940afa53b24431ba780ee42e386d41627044a7d1204fa2a7062993fd280bd5a3a91cb6e6b8de1f5f09a91b559f21ff7f84ad8f61bbfea544666c30eeb4cdccff841dd81d3b8f60d7448cb18d6eba9fdc02eb580c4af56f3e27f10078f5d326df2c35f98c73b304835dee42bcb47c7023b8532454b6704413e4d1f9118d8d735678001a2530587bdadc213d0db9bd89b2211ea751e278c7360078257deef5d4ce28f8486b674c5ba6b65c430383b57484b03371792c9059cac7a0aec067
|
||||||
|
h: 180
|
||||||
|
m: fed4be180727cfb598dc363713fbbd7c7fdaa178585280
|
||||||
|
p: f6bd6c0d013d23ca3b5079cd8579aa8ccbc9933c7e33f0036c9b1628a8bda002190d8f8c7414dc438dec0ecf77e3d2327c993521638ad569256bbe69ac62347b3127feb14dbd0d7aadb95d5bae30ae6b6044253113e50055a6aaca8da3dc9dcf4d7c8032427f44db49127516e5fe0f28a32c7077bab15062f427cae0a6d9e176a8719939940c8919d7614137b35db8fab167c8ca2c0e73ad84a1a0842ee2789b23963f449f4b80447f07e4dd77b485143d3465caec4e79bcdbed1acd4528d3fc2bcf77a8e6c30a24dd55effdf743d92888ae7b6a48ae8ad75cd6f4ef2b92d5b1145a24277278427338fa18d4e7068a293e4058ce4e9482695173897309f0f8ed
|
||||||
|
q: 8bc9ec7d332642a0d90e0085ee5c68befde929d6e3de1e69ba6a4625
|
||||||
|
r: 162a3b83b191efb844bcbd39240df7bd5d06bb27b5410855b49ef8c4
|
||||||
|
s: 8145ca6cca9e0d04b7603d666bae46078c1da9f10802a719fd5e6716
|
||||||
|
x: 25ff471174921d840b3b58c9ee6399b69ebc0a1d171fa720e888fb3f
|
||||||
|
y: 39b0e78f7a72e89cbd63267693b16a6f960dca7abd6e9fe75d22602876e8731141665835fe9141cd418d7b73f028da4aeb4b6d1e2aca3698b97ab37d63a9c2f3ff81bb37e786477e27a79dd3af02584068c4fdde938e635256dd2097e8531eed5f92f89cb71d13d2ffd298ccd8393065f39cf0fc9ea2c90eeff1d4a8bf0030e94b8a19aaa3b677dbf96c4b1583c468d6e5fda7e662c3b0824d418589629c2d9c55a83384c1bc1ade0fd1a4bb8fba46e92146e6dd239d948962cc38bdb96361cf934a1aed8229ccbd7e6eb0825982f41ac4e4a5d76ffc9e8ab95563e2a647ec086bfc1edfdc932bb36c475811593db1a3911245b2b530202da8744e6d3e857751
|
||||||
|
g: af72ea87c13ee7ab3923d1d9296fe2a0eddf1e1bc48687de608fae485f72d694cb73dc14fefbb1ef855ab463dd8068201126dff1c3e7d0f2c622f1f1d8bffdcccc44193ee8adcecc35193e30ca36695a8a9a1625b937e5ea82e78bf3feafc2bb82dda8638262090f9a0523d448c68941e85b64591fca63c61464901765c48aab6ed2daff54ceab7d05a828a7e02b57177fd3b992191d520959aeb20926a4ba8c22587ecbc8b6bc5bd01c3e5c84a75409ad80b1271c7b4563357639f45505d4adfef88c29df01497f7e1472c125771bdf09605542aaaa6467ccaeba399a0dad9eda90feabbdaab99cc88300985e298da166490264095b9eef3ff4a5420d226b9b
|
||||||
|
h: 100
|
||||||
|
m: 703696715c8d31135848e66d8c2a6bdf7925ef0489093e5075ca59aacfc772e2666685a6ff799de4f59e26668ddc2f87d45fb0262c0a1f2a4f4cfcb65ff85319e0f86b095b9cb6bc3321154f180bdb1eadb00730640df30d4225ee8d031d3538b7adaf3cda9d0f8c7148947854e2d86bcdf60b9748ebc51e2508521220945ff1b1fd52c690d95e7ca0bf6339275f669fc78e3f43189c0d72236d70377a6b149f0acb6263926c7ab2392f02561da119d80efcae305d9a860932be5f7b26a5c366d420ca66ebd51d24a210b009b873d3949e3f4061b31057692a9c120d83b81ae8e0747362f1189fa8351ea2bcfd61425d1004e0537c5f
|
||||||
|
p: bcc3c31321eb2e21c10028a987f09f5346afeac2e2e9fcc9174d333f332ecc2bbbf7b29e81c8c0a4e113babd61ed3d9212d659bb336aa105215a15f795319af5a9c20fe9a1c963a674f73d7bf7efda95188c9a0024e05116de02356a81bc7bb67dbc5d36a1e903052034ac36d40f22eb71869434edb63c324afaf5248d77b1ac8f8239e9c0bf4b4d13627277f710ec18b17d363e01b7bb5e53570b070fa48a9c42ac1ff54e40744d4120be8f2abd01e47184f49ad81924f2f4f4f9a55f530250a34c2720a8cbb1cda2a192a7624a257f62b57eece71323ca332abea557f84a4e80539ee25eb584517c6de364509c4ca5c33060464d26428088338ebcbcb09a35
|
||||||
|
q: a82df7fc9ea48029cfcdb28c062ac1ce63d3dad7e64effcb20130bfd
|
||||||
|
r: 61a0d24b7b3721f493d1b392aafc9697ab62d4738fcf6d62e88e11be
|
||||||
|
s: 7fc7ccd912d48b8279bb3ce7a8ae357aed7abfce8baaeca53f86b85d
|
||||||
|
x: 1531c423cb564a85fdde6dd896869e886fed9263fd1659dfd4bd1bce
|
||||||
|
y: 99b6c9d5eafbfa07db1ebf7a3b29409d3aaa34d189d64c28ba3bfebb895f2b392052a50fc60a6636b87c4da6840795877f9b9cd7ed281533e783246bb7e6558d4ae7ea7896e89fe0f22332ff26a1e6028c6b6698df980e1c10d6f356df4cefffa1cab676593af7840b0533cea3b22f25fbba04b7ad5e5cd326a03ddbbb854b787e1f3ed56d947f6cf990ebe2e3786f2d4f167752370c92e46c32632021769d1ee8618ccd8d86e6736797f02aea89d54b3e7d8ed8eb0341a89851117036db04904b516f1501aef8ae2eaa7b7f9399d00a808da3b12b0607e5247bfa88c9930fe20fee5a8a35ebffa9df73f7e9eb7ac8f9429f985190024433cf7cd1ca67d47cec
|
||||||
|
g: 25f6ce36e41338202267e8c0f57d0c9b459056ad3b0e1f5c3dade9cdfafb7bc401696a3b40c09a0e8d547ddb7c270017f111ea703dd4496bf65f8efd50f8660fb35ce79bf1c74b299ad86cc31d1164e1fa1062531e2879bd42ddce94a7e32ed76de6282ea3c54ff3e11436e3a5537384edc55811a726fc8e0f330c903c2a98e75f48dbc183be583fa20000fd6f104a6fc53548f9d5b4496782d24d2c1226589c757a257892e7e29dc3aa2f9e78bc5bc589a44b1edc4a07e1601bd2ef8c60adc5a726cd5089f5ffe7df806b66bcf525fb65fea57aa468390f8e408bbcb5abc16982c2f8a5d214d7958cebdb693cc7f2a36d8ca3749949ef59504f264141826be6
|
||||||
|
h: e0
|
||||||
|
m: 92df7077542fd6cc480a67465a911087706ac3a62a9be72781af054b9b6f9f58d0e18f919d398574afafe1740b91a471aa3098763c686687bb02ab45059fdc1d3b7ce37a3248b2a209f8600d321e9be5b5b1105c8f6085e8a536079b8fee7b31aa9b7df9ab9442738ae9e5651441967ed07ff214812eaa4f0ebbcbb1a35f851a74758dd4ccbfa6f7ad0b64d7e8c1513b6d3ca784caf8580bff403e62b103391ae68c463c82602e5ceecdd01e75e86dd82a3f93e6b17f5d014e0c7be034b746461cc09583a87b58cd8b1b79faf51310f6ea1a32085bad038e91380e
|
||||||
|
p: 98833ecb12acc9b5376d36ecbdad45311cfd2b847a79ad5e45c68ccebbc7107ab897fa7027457bf19470907cef8e400423aee7f662105986934bd08a18b89cba7e2a2c9fe12166f5e955a723f9db2379e65ea6fb54adcb1e8d169f2a097156ff804d9342820e99f22bd6b2e23400635ebdb8b3a9231c6fd51f9c27bae18ff0fb16c0bab91c5e663196ee000cdf8d063748e607ed109613c2625b719b7fe53487d6f308af87be99ced8447681ee10844539f16a32019fdcce933ad288b6eec3e0d41a1d1416dc7e9e1755ddaccfdb3cb8f973a793d1ae2b608706b0faad800f8a2d2267b19eb358d611ddf4790bc94fa1c6594294dc7af7fc6bf171b39b7833d3
|
||||||
|
q: e9ac0229b685c49b6ab6d17acc399d8a6839f5b0b459310322d76f19
|
||||||
|
r: 473ebd5631802582fbbb885f6a7a16116e0955e72a3c41bd851c03bd
|
||||||
|
s: 8ddf46d58c4cbbfe9a0bcb4814bd7bdf25ff640b5772cca2eee1351c
|
||||||
|
x: e78fd849400a6f743c1c7db13abe8faa3e8ddc53f08c9ad6f33ffd6d
|
||||||
|
y: 65a15c5e897ad5452c30e85a2b995c91f258189c3b209b00bfb0d71861ac46350b24a8f5a1286f5d696d3a55f06c010473159bac182a1648a75449771981020cbc7df9715476bdda704123a9958f6d5096ee0109cb1ffd36980c78cf49f2b6833530bb57789d6da675a14bde4f07221f88cbf0991a45e6510c6514440bf3909f9c892575fcb477a45f0fbaf46b074108104918f25b809d651b38c1dea9f1f3bbfdf3b9ae60aaeb30a5a1f2f6f3465bdb4f2e982ec312f9cc81f5156662181ac0c3ffda8d4bfe530b84054f52ce4c781269946ed4f10f7259c15eb24755282a534395a34c5b07a767545e1f26a10ecf0fac5f6bed3ecfa804683f27f3eca919cf
|
||||||
|
g: 22b59c4b1153e0bc923534262d2a23112ed8979859ca3ef0e549937e5305e2e5599bb963d672056f18d1dcd3b2fab3433894ac417096ed4a4944a00c4c1a139f61a1fa9bc854c7a6167bec7df7a62d1e303d97b217cb81bf735e9bbe45ca12383ae46829cc8a50753a2ce8357ef453b714af196c6d9ee7b0915b12b5994803f26bcf4309b0e608706e03a36f65adc0fa9cc4cd04b617865af1ed3142a15e409a8bb6efaa23da77ba6af52d0b27de7d8d4bcd623b58d1fa8c87b7c1043128f5155f30b30f504c14d19332ae35ac31d2be0f0281a97a389ea1bb12826b6e16364cb99064ce6ad413feb98581fc702a2fa6614be55967a28506ae55d84575da12f7
|
||||||
|
h: 100
|
||||||
|
m: 68d1
|
||||||
|
p: 8e6b74d1df71a5fb988ecb8fc7f47f1e8cde9c3cdd4229a3a82f24a869f2f2cabe6fd6e4cb808f8d94ef56a50ae60dcc93ec619ad109cd7e0e195416c6dd46c34d59050424f56405536c7c571c31d4b81fb79da08d59179769ad5aacfebbd1c5d019fe61907d4bbc8914a34106418d81360eb122972a3edfc29b270444c4fe5e5cdd1587a064c8cebab7cdf47e3ae3eed5ee825d51a3a558ee6ea43f1d79e069dbffd51fc941ce30cf1454d11c9a2fc0c9a76393b52f7f11e51ae580bafdf4b10e0ab4494d5acf8aeb6fe38e039f53200370697e00585cefbe118920fde6b95dd004634e6e941b900c81fae878dd94fdbde52120da84c4a6f5ccdc0063e59605
|
||||||
|
q: b0bb72eee2fb0c3b52b3b5bbcac8ab2214ee726d355e55931c36b371
|
||||||
|
r: 2ac98c521a10fec2d04da7ff8a2c775d0b20b167870724c36f82ec0e
|
||||||
|
s: 324a6f8ba8c58dd8c70cc6dec279e17d62069633254b2a1513456f82
|
||||||
|
x: 3277affff64d42a70e5c49e3f03873f455c6fb4eec020b8e0153e5bf
|
||||||
|
y: 6a6695c99483e5144fb46e415390f0c756ccae821420ac080dfb8811ccde45df8ac834c25297df1851d24ae6485d5730278403cfe975760501ef96628a278274638401fe9b2a5aa772e00093d954c2ab588104566156152e1e745f9ad1a4ae1e0ccd5f7d8946ce299c0d0a5bcd0502d8d5445d20c60959654be392e04b4135090dff2a751a2995e1e2b877d3f67e2d326a9a445f194979a79db46b26093edb9743a404e10cb4b27750649504a410be329e8a5fff023ac23234e7be78f88495ddb82850230f770193cc73e49a12d228df276198fa6131d2ed04405de6a33a4a419306e5941c91cbd9572b63e15847cb8fcfdd4e80de393c57a667dca6324a25a5
|
||||||
|
g: 648a2773d52552c96fed01fd63c067ba8ccf6c3dd5b877ec5764fbc5f81286bc7dad25a56088dc85c596136f22d683b9155df8e459a820c98e4701b3e3a5793e3f36769b60dbcb119c2e64c7fb1622c32db9b36d65f6d5d5a4ff86461871f8c9a1eec9b0f7eeccb82e0e54b8e0fb6d304ee75da9943ae61bb1bfadf7c0df2fd26093f0f3d7b135f4908bb924e27c9d87594dc4730aeb058bc65e317f92d61f00fe31ea654db39f0da772abb7e0578975762e094234c612c64a97cbdbc5685d108da7cad60134142d3565d83b04569972e4e3a961f152f25f33f623ceb4435d6492491a4330cbde0f40958a69ea1aa0ed4ef88bfc755fc67175ad804574e54654
|
||||||
|
h: e0
|
||||||
|
m: 7541d261a1c5f1cbd7df6bd1872a3ac98caf95669f8aaaf3d386874c0cfb173b63b283d8da85119b7ad0a237e3b2b55d4290703ee1b4e4d03d504bba102beda23c
|
||||||
|
p: ad3865b9c1c13b84ef773f3b8d4eefc1ca5c3630b8ae3a496cee26ab78b60c0915483ce2aa2bcefe947ba38b4daea877ad9e1e36e258555e5477157f7005eadcc69da336b15e032a608caf4c6e81c86ab6d892060d809eeec34a364faa3fc14f3815d2d19684f3ece3739ec25d501bcb8e80d060d99b4a59f187d9980a02bc00d797d14a8653ac8f02364e04a7c270bb818122257a7bf949ed80aa4fa60cc881192721358b2260d6302e49003a57d24ded33c68577deeca73ef7437ef1c30c0a4e87b66dc9e59abbab783ee735f79439a115727c40291fc622cd2f4adbae5dbb8606edb1a94a96d489a8853d07714fd77908dc4cda17e746a14d501de96f92af
|
||||||
|
q: dbb867dc0e56aa48b4dd1ab567d1457f5bc6e5ff8b838c9dad218509
|
||||||
|
r: 2889263370b7cbdbc933144e05852c121f62361f156f23124d1dfc2a
|
||||||
|
s: 28e2c3145bcd24e52d05574ac28bfcc77f856b803eda5b455079bf28
|
||||||
|
x: 9484ee47d91746cd355e6ccdd0aabb18754a180734724b80d9ad82f5
|
||||||
|
y: 21bb8b5cf74ee51b1b8720d9b90976b3f07a7daf30b8b62dcb1698851410a69b0ed041fa73e8dde17ad50ef8acd3459aad405266116ae555cea1c9491333a89bb346b59fb4c64b1d04f560074b1757e81c91c06b209bbb1040b00302e65fdfe23e81937d20424a795c2b392784ac4f7e7000de81f4e0e52ea2e825302e95872d28a01c173c4564678fc84634dddd38496f2fc3e41b667401563d2484460929f5065fa777bec4e8e22f8543eba9efbef61b695eb35b9450d309f7f203c0e1150a2a1a655ca6278d3afc61e564ca6a96bb50ca17122420475bc2bb2ec164c5a045f712dccde83311bd4bcf0616977e6f0c51e86e87e467c8d36ae3259c67be9d4d
|
||||||
|
g: 60b67122ad17ce091d5d8bb2ad235b7de0f18c254d1de9d472384f7551a37f84c2b7299c6853a7545642f397fb99a70bbc6808f0d3afd626cc578ef69b46c5a169432fea6eaeb7bc60d32f9ada1d7145e6124059d55e2efcb72632ccd4142bf2b3c58ea2ed4cf76c61e9d57fdfb326f0d0cdfdf3d6781d3b7e17abb74ccf746845118f7086246c49eac4df3a6494af575d933d711283db0e0c13cdc7b53cdc8def3515e6add56a0cc1e4ed2e87eaf8622f7f2664a24afb3cda91f2b4cb1b185876327606a63cb5db6c65622fc7cd66e923d12b7d9bc1c0fcf7d9c52682f058e285aee044f7963e5a769339b09b42aef9c423f8dcae80be913d6075e64d002edf
|
||||||
|
h: e0
|
||||||
|
m: 1de638e1f3ef07a62af620f5555ab7b158a5ebc03a544c45107352cd5bcdf1180099ed6b3057f37eef61fc0756929f50d85dcbcab8ea10d23d967a4bc62ad7d057e23a708c8cc4b1e94cbd5599d8ac1547c67df0e166e949f2409e14a830948b96df1fd771db5c1bf4e03c3559dd54639b9be038c74fa2878b2bd127dcedc6af650efc5dfc9ac59db78e773d9277993abd492be923f25dc497ddbec7d44af961fc0210d7fdd7c4653a98215060448cbf65eca3b7c41494fac12a52e59cc75113fb9cee3c2da34b97c58a
|
||||||
|
p: 80802c75612fdff5c7e6517745ae3df2b7dc7ed90ab17f082f1ce5882163172415d1c710815bbd4ad2f421085d75ce7d1b8e8ace04c7d96c6f4de5f577289ae8f2ea2a9149a5584f12d95648a7c287e8bf7d97706a0cd9c6f6221a78fece78654556efcbf90c9b81a68d4f2b53a6873af004a4f4e658bc3f9af19a148cd21f740662b017e0cc598d39ccdad7eb8630eb8d6869b08a017ea590620e15131569e914fed8da61a6ff0d1d3e2af83a3d58cf208be622f501086022e5a1c4efe959bf4831cfdc232bc477420627e98a4a8b2e69523520a902990bd1e45bddaeb8346c1777238643ba64d36f38ac503b15b5fa011b69d1dbfc373afab6713d5adde815
|
||||||
|
q: bd3c358a1baec377bbb2b3c5424da2a080a56d830cb7e14636e781a3
|
||||||
|
r: 6140321c6142d643aaade303e20e70c11cb44903d913c3506b3130bf
|
||||||
|
s: 9e60de19a7d536aee5175005151e570b7613c7605460471f260b6130
|
||||||
|
x: 22e4fe758e368c9997f3f380c9975eeab46c68dce9ded344a51b873f
|
||||||
|
y: 671bf8bdd551ceab91cdce1518d2d44410f9ef481adcfd9101156d376c3df6079de85ee60eb80b342d25c4b12567e6d9c46c021beef0a7a9f4deb2ae101c1f39a778afca988fd49bb699b13720be5d429ccbe3682babfd18e4760e556e3e75313fb138e745d3f4a4c7426e2de0fdf40c72b446f4dbb8b2d9afd04a2707387ab505d216cb5d39275eb792b33dc419df1531506fa5f54a4517272e71ce6aeb56abc8d4d7b2f4d112b312520ac97f1a363ea7eba53e6b3df727f728d8a88d960622d6404da9007d3c07483e14c1b92ae35586e665bbe271600ce061f41174a904026bd6b140fbd952438791b14f75b8ec643785167c078640c43806909d70a72884
|
||||||
|
g: 257746e903ac167732fb4fbe682b42113f566742883e6893e7efbc73aafc7cffb044f4fd4b185268a0f24715bd205655c21af803ba91d09cf76e9944fcfe4721f90656385e905216b0a5bf9eb634f0096854bd6fa1a507241e82836afd4fb354c53f312e794845ffae2392179a7b9926fd5e3b5a152223a65767d549bed22acc0947cd43c7de7ba13f422d9ccd4a6c0e58529585cd0cbc2ef6d11cab106dcb6268774251c860e3af2eb9f6b0e68e28632d430feeada26ed542ab095068de7ee8476d390e6634b4c4074004676005950e2b1d1ea26440842199ce62ca03e392fb12b43fd90acb8e165216c633e04ff16d64410cb734d2845de8e039759b42fe8
|
||||||
|
h: 180
|
||||||
|
m: 6d826b53c55c421336a7948c72c0eca395412b4eacd1326427adb6f868c58e92984a6ff8f3121f27200b24053347c582b8649f8683f05380a181d9370e60bd008daf8433df95259491b11465bae397836094229d1665bc5e855b151023a4825b4252f0ea569e39e7d06c09a6bb64c8be98
|
||||||
|
p: b0786459b659a2e86263cd817b6733177e95a7ab9f1efbeb2414320ec1391486447c287d55789fdcbc07a65fd8302f6966a681eb7a0727814dcf3bbb83ecf62b5f156dc413f52e90331e235bbda51653e293d1b26a9b14ccf581e2711ca4d98edbde20f9ff6086572075b4a60b44448105e1a569e061fa23ae7a34776ebc25daeccefc72232b53afecd59878f0903f6e20c25355b792222f27ce8376cf104777bca7ea9e226984ebec71fbbcc6b309fe77dc877a1a826bf8cd95621c03bf8fafc555fb7476f0610cec8ab7c6ff4b2f547efda139cbd0e1906f6da018beec9b7c1a03dde981cdb98d85ade99f01a7e3313444f642d872878be4a3ad361077812d
|
||||||
|
q: ffaab7a8245bac019458c9351bf5248df74c08219da802e05d6aa2dd
|
||||||
|
r: a489cb7f840fc909c01e2f5dbf56dd71bf8b80ac6bf445a50faa52
|
||||||
|
s: 5835cfe67ef6a3b7062e6b0293b2e38919a61002ae75fb0ddf321538
|
||||||
|
x: 6eff90edffba20cdd1b6d3f5f2b833befe71bd6246269b6e2c24b27a
|
||||||
|
y: 5fdaa398ab81276dcf1594de8ffdc295f1c00cb65b7c721da46e4ef17fad82039acea821701b4c1cb86b7b20794fb13c1d35e5e792433ea1795ed3163e59732ab090f6a3f87e00f63d708e4d8d2bae1bcc55b72023d3545883b92d6a527375b2fd265a895ad96f856b50ba0b403a1fefc0de4954dc05e8896ded337397a8fe0eef1934025f9a005e0529ba64d7efde86ce5a5a7eeafde765ef5030e536ae9ab7a8c62b6111c598d6e82e23159a356a09f15fc28a4f4f5580e89e6fa00cf02009c9d886fa28d629a1efd2d4563d3f85b2f8fcc0db8b6f5487354e54f85367ecffeb005863a6d12bb980fe2a96737359f3f52ac9de679a9122ae7987895499e26b
|
||||||
|
g: bf1eb1613ea3cb694ab4c777c5f3805bed7a07bb0565f822ad4366b3d0731173349f80eaf4afd7ecde01cdb7337d35695a981959b91aab179fa5b50f16d19398ec3e41010c573706ad59b6f98d32f9ec92fa159ad1fe133f54e3174ddfc8f2b855f9bbe196933c3c8b7b9248959c3e351858da0c68dc7aec49703d4ee6693fbfd137b254509e78b4838c1570b322fe3618354d884f23e79898512576265fb270431e73213dafc3379ef004ddff329843afa901cc7a22ac8335fc8b1276b9f1441af5d292586ba2b4a28ce753b8d736eb781a30ec90f12e38505171182c05aca8f1ab4dab36314374c65e2afe79f674d3595ee54cefbd14be4b8c26421e2c65cd
|
||||||
|
h: 100
|
||||||
|
m: d3ea008623e60e26e7197b1d8165d5438a94fda258714eaa86d9344e05292915e7e4a1c58eee14d44b0d102e723ccb1cd3db82aff212dcb29a370f6870f78de4efe55f6de587518e9258f0f61403bb17082aff9a71fb39315df37d5ff104245350bd8c4e4358b933eb7b0efe21a3a2ea2e4f0d60f40ba300041e15d7bba78fde52c9bbdb0a225ce74754afd573c1689366f0e96edabe589fa6496fca9c16a0379b656dbf7fa6aee3a0999d10cfb03a824cf5ef30374a4fd15fdaa40155fe924be99ba3ea58abf965226e6344d8cb82b7fa3ed9b1d494197abe3d081e0f6d4ecf918d84b975be8a2e
|
||||||
|
p: cf64b03f0e616eaf7a1b4b7e0a42aa5613455aa157e6fa3b7939f372ebbece8d6b6654423215f7641cd25eaf3453dbc2c02cde8571ab362e425824e6cb6e5c78cbc2327a2e8b4c22fad6766ce426ad18b347c2b064fe32c5e77f75b98f784baac22b6274865a1bcc236190a60d3d5c7d4e3085a3ebf581a31c2fca597494029ad04c17f7ea4fa318518f3b104d1ace6fbe0db2a17cbacb9e8cd69d09bff203d7fd4d19f3095a456019d0346f4aa4df7e29e7cfa346b7c52929bbd7ba89cad7bb1cf194679acf5458cb60e8075b0499e954d45a8e9cc5bbeccd548c95a9a206ebacd885c65410d273a69aa7f4997cde52c100a8c4e7816da658926ce83848993d
|
||||||
|
q: 898ba0a00e5b2fbc8522a895cb2de4a1d7d7de2aa3662273c0fbb183
|
||||||
|
r: 41ca6a3f0dd8b7d2ac8c57203bc4e99e3265f8b5f5c0aabee9cf0175
|
||||||
|
s: 4fe9fde8350388693d8b2e76903858c99403e2adb127023d6e1197cf
|
||||||
|
x: 3801f472df984ab311fcf040a513eb5d816379f395ef92e18ffb7a5e
|
||||||
|
y: 68c159a9384c7a1eade817db453d98290a38e2c416f83cd1b6ad75878917def3db8a7ce910acfcf644becb2484df9342f8c86027153dc20b52b412c0d4460ffe62101f02c1c60fa69469bf29180d1219a79886c942f6600ba011894e90e46a88fca3e11129326594b593f79e74969af1c22929a71088da802488103c3e2395c8c835f9991f196fdf4017e8d495ce014b105e3d1670c0b3d91891ef4cb8c26a7b1c2c86672a2d99f052facebf4d2105f779dd0185b7f1cc426747f866a075da52f8b9e1f5cc1f06b93647cc40e355e00b858ade53b20dfe72220e10e2a3376d282302ffac5094d39e94b5918a980203d88dcae27ab5a45cc92fe654408c2c4751
|
||||||
|
g: 1584727688781178f6aecbcd3ddefe19aee49e26340c7be928ffdfe1e9f79608cb57fe10cd67a98e8db554a22386e4fadd3a379950d31933b904cea4e29409c9f0e4619e0408447d5d7d60bb5c6d5819557bfa5763bbac7517e915a0da32857664eaa1f60a008db2e84d35376da11f40e339c2fd05d1bcd17c8051e6849425e91058ad0f190b9b12e90b1cca789b4e4cc22ea7862464d3f92f9c423bf0d41d34a9438fa39f1f70db772b33aab0b13e4ff0f565a2ea5f0da1537bbb8ff909ff32e2ec4a97dcfbfe34dac266340804bea72de4555563144f053b0016e62e2360a9075d7eb34f7879149c3d579dd7dcc6d3096373a0f8649d6587efe291c73aea77
|
||||||
|
h: 200
|
||||||
|
m: 771c0510c70a779f9f57f2145abc7eb483f86404715b669ed508e36238597c86c12d0ce25b092b665ea070f5b9413450f381e95ea641a6d746702d7bb893c85e1a92e22a58f6f04e40f3c251f0f515bcf212afdda3af7539c2c5add40108407fd74bf0ef4ea9f3fd43a6c33d6b9fbadf3cff81d59736aafa6dc4999bf29c43773ad1ba47b941b55f874184f1eccb01e23f02259b1af1b97ee49ceca5ddccee07406044150ee76d171c8d1883a9a9bc4a7b039412fce8bc1d782ac2ef490c294db35262d24ef3db78fd89276f8d8987bacc64edd0327cbbb4d3e9
|
||||||
|
p: a1749ab6c0bef4c46217232c9712e90d76dbeaf4818ac7e138bff366686e22194bc3993548968bdef892a34902719c868cbe9037ffd4acc74524fa8a5857ba9d0238fd3a2c7a7073048bb53d3e8455c4bc556b981486b2a5dcad4f2006d00ac992e37f677f9e7b660681a9572e3bbdce0d68a9577f1296e1c60b070a567e99b432240199565cccb8191982758814e3777e5db0b88cae82f8a1ed05ae5514bd7e68f47cebf4e38e7c80bfe5debded1bff420a5569c42b4ef02101da5623d16ace95fca025ea0ee7c282207dec498225d0cd27ff86b73cb2757efba58de340d4d3fca8bab627c3d6eea7813871305ac96247e6576538ac655f54d8daef40076b9d
|
||||||
|
q: 98b9b8d5d699eb67863acf54dc585515f8556c4c8e797aa80ca29981
|
||||||
|
r: 59f8d7276262dd6be4fa772987a7354f403290d5b5f54d8ee445ec91
|
||||||
|
s: 716b0946762416682e47c7fb8e66684a5e41b53ed3c5e1d179379ee4
|
||||||
|
x: 278bcfb6ebabcf5fdb4d7ca2d34f747dd772b0c39b985b7c89b387af
|
||||||
|
y: 3dc886e8c4367c7d55b8b2fc075ca954991ed69e11ecbfffc5cc1b207e1ec2d316fa9645603cf1078f8cf369d5743fe96cb88a6d119ea2a7e647c84881d1642abe540b65d6f5ec3903c21692f069a01fb4ee450f7d173dd2bc5b264e29930bdfdf235b2f7b998aec6e0e8840f112049ace527271da785ba51dd9d02e7710696df12709db35caf35ccaf8c7deedfbdb9752b82648183d81569a896f45ab9d7dcac55927df6df34c8a222feaf0729dce21a748abfbbcf8b7d176510b9871ba9906ce3c729aacbc392031c8cbf346b9e473e1fffd1f811ff572896f02039b143f04a148400d680ab8567be2ca1f0d046557996f4a413f19b2b8b12498d6bd792117
|
||||||
|
g: 811e541eeddd0f9fd4e29431757e4b78f8d96365e6643b5642f5e0c6930ab60d590f9f7af065d12a62fca4ed8c92fac2c8d2de0c4ef8e8fb2aa56d2b115bb45a34d468353e0d3a29a0d46e40f4ecccee11e7164dc4751bbfe371b17e0a5ddbee7676ebf505f82c39d89f78d2140d23a8abe92d37031e33b1776d807c4fdd5538ffa86dc8433cd91683eaa744315adc402454f95f25b6df9b2443dd7e39b365a8377c17d5d51e2f3b62129b221db9c9bc75ae212636923d92a412b8c30e91d570fe041a76d49d959772ab952d1eb5642b12738ea05377c297ab221e9444bb35e8ee4c706de3db285bcbba2e67bb8a239bf3c129497c46b00ad44bab011e5a94e4
|
||||||
|
h: 180
|
||||||
|
m: b21199eed176784bbdc0f0003cf7376e8b502fbad79d16a2
|
||||||
|
p: cc89f83c9d4b7572be0956a4f303b47d9d6b1456913b7fa362c7b7956080df35b1302099b2a00ef04a07383346c8c80cd6a6593a546ebbbc01791eda0e270185132043dd06a3c5826f147ba784005e4965bc3185273a69f9ecc4a9ed06fba59f61145131f7b206c9eadb000e7070c10472fee16c8d0596d68894355d4891888c578505835bce44ef9b5c679bb5f9ec4f7345037683cc3b32dae9b0504d37125fe9fbf8a8860fdb92645c644ff0b36298e3b3c2e44ed2fd5f4c2b60f7c50029285e8033be43c270739ec466ebcafd1a69cfabeb5f8348d9ceb1aa73934eb867645ad4196f78faa654ed35908594e9f56d658c22f512d599801927da6f156188ff
|
||||||
|
q: 9dff5ff90a7103cd59d3edaf681f99f65204e7d5714ec9fad7c414a3
|
||||||
|
r: 7cc4e937ee082f6f5a7239640af805b20199f67835964a6e1f27e8ad
|
||||||
|
s: 6a7941a5844414d34427879e8d90cfab84a06ac93c731d139d6b0b8
|
||||||
|
x: 67a20f4ffaa369d2e24eb2ba879a8481c8cfc18c1cfbba8b77e615a7
|
||||||
|
y: 6c5ca61e32f9e9603ee29c10534e1c827811311e2b062a689649b94179816baf043aed44cc095ca770611c580cc6f339a6361ded866503db710ea058ef8ca4e47ff90bec3e71a77d679580e9279c553a9c12cc9b06d74f94e2146fd70cdfa4da0e5e528743d0e0e3606a267fbd4ef633c8c13637ad34a5b7cc6d0d385d305703d74bf594991a399e02b638b7937d8b7a599b8cc72635ea40f199c5a6528cfeef418a0ac1d9a34292d5a51eff8a08abdc56571f9e121a801e19ef7f7b8c31ca74faba06c56d49ae8d1a21702f7ee36cea85f5adfb62ff8c5e3396c20eceb0e31149c37abfcb4445443cf43c92267188ab0f9db08c7c272d93709905760db6b2e1
|
||||||
|
g: 4833bdf57b69b6bf9abcad681342406937cebf732e1daaef3d34f07396c6aea9079e057744690410aff26d6c963e9760e50b11961a9450a84e9fbf56bea18321c8c699085aee436760c2faffefd03657242674c4ea464b06c035ef64577227ec72d52f152c877e61ab8159bfa3c12fde85f7c4ea31f610fd383b55b3ba8f193120d363346d84ba5fd177afb4c4eb7235afaff31b94d69cc336924b1cc61e39dd41d422d533a4adcc79054eb22aebe4d633ad5da2a01860a97bba867b783c5793b7f2924247da18b2033dd049123fd2941e03658fdb7bba94bea127a3e8c66b6cf25c711949892527df17171acc57c357b48939e7a0c44702942ad5d552999f96
|
||||||
|
h: e0
|
||||||
|
m: 37fa3721338c7ad4344aac8dc50187f92278f7631187de1bae981c34c09c53ca10ea23a2f92644012311c46bd8403f008aa02fa2bede0fb35d182ca632d29d6ff64fea595ef35054ea8d915964e7f89c37416b85f0d64723a6e1df5c39314ba6999ef80288c95569f27072d82e9f520754fb55e4a7d1af2ba2addbeb1010570a2ef39d722b4959c88f3e3f79f63fce6689184957d35f8f80ec078a92a5157f70c16d7f37edfc26f0ad824bc13e8ade98ab909a1e087199e2d0aa0a15d0cea70b413cb6c61887acee1a51c358b4bcaf60d2ad4dbf7be97d422eb375b27ec3e28a8e0f8e38
|
||||||
|
p: d415a669ee6551d331b12a62ba7748b6d6996a358ec511b70c9525c22a58a3adb38be871f70b4115f709c9c62ed7fced65497344d05705cfe45883a785494dfac0f5223540088f7229234a6182a4fda917b19145b029f4230ac30a3bca3fd144076c42e04bfbc8c57944d693b2a17a30bf9edde05ceb1be41b0abc52ddc9c72320acfa95ba883741df186afbe10db865dd0ad540ecfc1e654fc9816598c8b29fdb5d1aafff6fe178db3aba9d5b850d0238a3262f4d001395c96db92379e76daf089444e575015946f62656738f1231812cd756fd7a92db4dcad7414dc176231a895eac194e8e27dfe895d501e32cf87a9b88af7ed0f900712a337c2af6eaf837
|
||||||
|
q: 87a2a55e0d1c59fccb6f5073c594356370b9b8ad619bb8d079e16077
|
||||||
|
r: 581422c06b69b5548061b419492ef80d659bcc2ec17b064ca7fb6fa5
|
||||||
|
s: 4d5efec20f7ac1b7d192ddce0f2ee79c9626f046835f6db106ee2911
|
||||||
|
x: 4fe21fc25a1e963df906747e4fc0313ed585d5f5d23c5af81e68a44b
|
||||||
|
y: acca364adf286020dea6c75bf542488ef57060db16a194307063ac7d96e24ef2d46fd678429f8b9ba4bcf3052c78a4494a959c82bffa2b3784a62198463fa1785243ea8723839b1a3b3952bc8b442e1eb7440fb421b3bc5100f38406a11eb6b67112bed18bb9ad1f2524af3606d74f9f763a9374a67a5f2f9399cdc8c02e0033ba5d3cb6a91be7eff7f13ed9fb1cb5486da97ea4f26f242695403512f77b07d0ecd9333b6c0e923722cf3934b014ad55bf2d50ef836110841d38c4ffc8fe2f47a073152a7b6f764be4556982c2bc1d058f7a6838a72377fd26d02d76178be863f60b4039deacf3cc12672dece4d26bc9c9ad63b433ad6c092471a8156b09b9bb
|
||||||
|
g: 267bffdd72e9581c333dcbfbf1b6f60e89b495f79ede81e8584e1175b84c6e87e1e0b904ebebdaea4c9916557a652c44ee683ef3d8e984c9fb6b7c5ecef3c4121fc32c68d5595035d2b9e5ea942a19ab019151e551813229dd4fc281b127629d53a811993e0e56af8d9032432aabac547549dd7f1ed8606310d84ea190d81920f06e2b1a2b4bf41858f73864f67bbc69ae4e25bbf15159043a2d85192c5c85673e0c726ada0349692ac1b47b6619be492c5f4cc1f5731aaa6c2b8a6ee0b2172218df603c4e5e1aa274266fe64f26fbaf252ab1b7bdbd43c4660375fe253c1ac2dab8006d77c73bfb553723576399d160aba9a473b4eb8c408261b21a8427eb41
|
||||||
|
h: 180
|
||||||
|
m: 6b1c237a16d62320227ba897a69e0730f28d1e7914749719f48d8a83c84fc6733219
|
||||||
|
p: a1b6ed918a8285a65c44c5bd4e435cf198a43cb74052a98e124ea1e7a1f1ecbfa69cc7827796063a601e33fda97916f39e69a051047db9b88b21bbf5bc88cd79cdfdbe862a372ed0309c8f4ff5b72d66fd28539aecbaba9a59e3215ed26e1bb7de440118832c553dae9ebeda50bcec677d10f6ba7051eb3978390673c9aca8bfaaf9fbe50900598302e8be3bc63f577417243b2c834e50ea46a693d75c4febdd409675f4163354c139006c675aaecb9949739b4d3f41b1059838542c1a5fb04785d9f90466bae5b70112082ef0640218ac892ebafaa3124c279d1e89eb3b5c599b5ad770751da1c00a7173313ce38f0ae0af5dc8f7541da0aeb365b7a9a6b71b
|
||||||
|
q: 8939cf3ce028a618dd8757132a58602d08e267b1118ebb46156840cf
|
||||||
|
r: 689e94a9a3990c214df888513170ca0a30371a448c44fed80254e9cd
|
||||||
|
s: 3dd683bc3e102247d6889074d12599de3101a78a9ee806db2258becd
|
||||||
|
x: 581bae3ef6b1d9cd92dbbf9f37ce560af5a440d1596a3a2432a792e2
|
||||||
|
y: 74f2f4b654f483b843ae41ae78fe5b69e48fe8bc289fae6917e063588ecb9e1f2d0324aafe2a761c826522ff7505401690d1b016a366bdd9039d359b2a83830a80eac338a4f67c1c5136c4d3c46829fcc1f2c948427affe7b28c3368be6dc31f8780c31600f8e9ef6b2467171e9bf8fd00f1711e04b19c394d723a7933895c252a2718c5c11d409b8f40b28b39a0015198a49c09e287f4dc4393d78ececcef55019236cfc3e9eaa460f9c89911eb133b752e0f3f996abb80f79c6be85044350797a7755f45bf82196284ce32b9544a286fea7932be52143c15bdace01a3da409a8b85b11c97d0c0d9f4f9caa822a1a2c2c89b4680aba6a4acd65acff9eb924ff
|
||||||
|
g: c4556043144dcc79548928969f15ae1eceb171e7f96dee0a0a41627d1573e3d74ffd99af66fd8f6a5347e00a5332353426bfbe7bab37a387331c44047890af2a21228e5c00128fef7354049f7173b862ccaa0041639252a66ca3eb19914929d96131b90386100939b99493142c8dfb2cb35dd9d166064fce1b1b91f639bd8510eaf6f509a0e2e96cce642e28231dec781f2ff3789882ad869b787b4d765cab47a90d5d451dfe8fcdeb9419b3e0c4adfa5c8aa02bc622314f43469140ffe5a04df7d080a5042b82af1b559228d39ee74a72fa25df2a200607b8e3f79bfe53997e3d98714f4107b73deacb04adf4aedcaccf786238ae6a5e39e5a0adb1bab3dafd
|
||||||
|
h: 100
|
||||||
|
m: 82ad6eb15e872132c38a9f5e7baab68c2b117ee1651a42048d431b461afc6ab2efbf0540d6b9de8d7960fe48d3bf137143e5758f1e78b3f669bc1a3240719b54645db694f59161202c642cf06f89af5dbe79bef1070837ed6c0c496df1604d8605480c47a6a6ccbe47a74f8cdfbde831f694fab676e29d26a2f820f2206f55a3e2c8f23c91ff4b525955bb6939e40a003f4c9cddd75e558d94cefdacf7a10bf3d3e8257484bbe3b258cc6ab4b1a49df95ff16b33aab5f59e8e7c163c7ec938f3a4a7861913171b5c5169c62b994ef36bb8505b70b2e1ffc06273856f7f1e80775b06a45698077cd8e6128eabfa2f67b747b3a01b
|
||||||
|
p: d1747c3236717b4915a6f5e63c42576a69f5975d41ebd0421b23f95b004ee9231848fc086703305c19108f3d580ad4f1a8e42052a6e93e5495f873cdaea274eb54b8960d7dc28b56b68184ef2418dfb0c84b0f56d4ff797f5c24470cde44037b74c976854d931069a9d400acf8c54495de171485b013e94ab5721c7d5b8989f98acc26f71cc622741db67b9929667f75235ad8988950dca0a34eb2465c64dd8187d6755f138f7104a220fdb47085beeb8561e5149676ef398e1d6e5d6336175e4ccb1b617319af384b0b068acf6cea64aeb0e112095b98271f612ed765c3d03dbb924b1dc7bdc117a1b26f435f95cf9acda153113a13e8c3fa78c5db9563e95d
|
||||||
|
q: 93bf777b59d7c7814b218674b817de2c64ab448d6696928fca1a4a61
|
||||||
|
r: 250da6ef1b17e7bb480becbae472a0c626d8621bbb8d3662e4ce2cd6
|
||||||
|
s: 5f2eeec78d768d1e757a5eaf1d8e01d7455e7d380555599d20dbe85b
|
||||||
|
x: 669b019864e18ac1435d6be8a3cd19b421bc2a122b29149ae098497b
|
||||||
|
y: bdccd40964ba1cf8d7e5bf23a61d6a5e789bc3b4263912303f5c794cd9b171e662474293b46a0ca8a6d77752123466a2d5058efb517a5b85578da9909be6f9d578127de4b43bd30c377bb68099a2cc159c2c2d4ba2cc1204e8bdbcf56851148f489438cee580c72071daa9e1b3894424af23733e13280839ef2cff633db4a92b673334640513c0ee5b6dde31848c9aa7a713bd1f93ae12fbe53e9cafab731d2edc95b3923209ba20512e9afabdd4895eedf2c3dd9250cbc1a3829a7b8c346e2db13b10e5f4cd88753fd4f462148b195d98cfdce73d1495f7a4aa0e34c86e89fd4cc59618e5c0619ae4bff3c70823b92b65dc234fd39fb8abd6748e5e134fd75e
|
||||||
|
g: 25e417d0e8a928027b7d1fb57842d606fa286c585ce1328c7ce0d0df3dd92e3eb76acb2077adb0b02946da2b76fee3ba8a26895e044edfc7ebd03cd684ee2989dcc1a3b30374e4cefa6f37484a9c9bd39e687aebbb7978df2e75c9830eb45bfa3e10c9bd7b22ec3a8709c84bdd272d77f2208be5f1c0aa248e5af43e26041826bd4601dfa0dd47417b6771bd7036a346048421f4553be135f1458e8fe377188f9b497561646aba53548da8d6289108809b7b348ed23562e0efcb5d0c4cf456c116ddc89cf59965cc1a4e3b9e33a23e053c028d90ba34539ef5ea3ca11ed78a8cb1edd710d043fdf5780b0f19dfc7c41c17c735725cd94110c270f3c3ac6035f9
|
||||||
|
h: e0
|
||||||
|
m: 59d1dcc21a5d90ff2dd706e97ed42e03b9787a27418cd4a8974545b9d8b354874f5d681e6c66a6d6b9970c860aa8957c0bd8dcbd4fe32c42e6e09fb3c04acb08495ae611387645b3bd0d22f947257a8a7aed723608d58254b291bfcee26e2289d5d7b24532904e77f2fa26911ce576a4b28956efd1c2d172787d7a4221d91e753813bdcb37d0fa67cd8e7d38387d7c1a0cf69b3da2cb1edd38907297803476ddafc85c8e6cce452a62e890b9ffbc1bee643abdfbe4dc192b0be19e23c6801e45b1e7
|
||||||
|
p: bb7954df68f66ba149cfae385fdf32a273b05913aa879be1f89e9ec700f378ec72a5411866c2eb2edad4700ecc77223842c0d4af37eb1f8206bfa1df761baac9714a54f38468b41c3a333bb174820d54245659f0e613c1f43c922d06aec24844b3a3ff5251994e2e9e90f37e0c64bb60d74a9c42812710cd7c62b850a98e9a5b887266e4afdc0d6c4f65887719730c2b7790311562a9a7c1a9fe1d64959a457e669630cd7e49f9aef709934f496a060114eb7d5a004e566fee8609f560137733cde5b2b6c85a5aef613404838d70087d97a2184975abae8760eb68959ac61e4c003214b63f3a0e89606b8119cf0a29b3bf16080e528e3e1384e87615365a088f
|
||||||
|
q: 958e8b68d86bba3500fc209cbac79a459c19c350601d80a9774b7ab7
|
||||||
|
r: 945b8cf9de2aba9427c74d7fc4411a03781bba73db3a1cc149a590b5
|
||||||
|
s: 91f0f0acc8ec2963071669e22256f03c8192b947e47fd0a8402bca10
|
||||||
|
x: 87aefcacc712b1c0764e9a4dab6cd997252f4b120061379627a207db
|
||||||
|
y: 460e197f316d78967d94172bfec9d50ab14d12aa663997c32a08ac62d80885e2623660d390468c12036a31beb7f0f451728a28017b1841fff0a0644415c2b8b7d61256657d3dd6d59821ff996cca41cd419a3221047a37bd8648d352e0fdcdf6239d2c0b091b4382b8aa21a7665d228d11cf846123d235fa5492206c06e3e2f31f51cc72925d2ab030e6b55ef1b07520f9a25ec94f3157b2d3d637d5c257fa97a62459bdeeb9eb30edfcc1f7afe204c5baae17158e0672c484015ce86d27fd903ce91d0e37bad3a73c34dfb0fd4a0567a5b2e84b8741cdb4a7e5db118339cccd87a203cff875983638dc51f864f8cf33174afec59ef893d814eb7185d690935a
|
||||||
|
g: 1fd2c90c4805186226c6be779c58b4a1f2b10495a94ec48d8c3e9b5686fecbeb19b50aaea65ef0602b293a017d9a1000c0fe75b74adeb6015c03ba2bdb6f2a642c75a1e312f3567df169e84d837c6bd5e176b5999bef0a0da4102892c7ff128947fbf503822052bf3f80920591a0324be830630132d7d5d7c5b7de8471655c6595b2deb45a93490180b42dafc079664fcfcca29e651d828381e7848a55ba0c5307da00883d8515e88e4998f49ef5a3294e73744afd89988801de1c6776d1de7326f39a9e9c808b813f6507b7de3ae1b75e3098c61fdfb3ac3eb539d00f88976ad65f0533b978c3c24a866de86d2773e875a931667a3b56f90d563e680c33010
|
||||||
|
h: 180
|
||||||
|
m: 1391d8e30f6a5c5857ed117a3e2468a2a0101e358d765fbc24023eb01eb7861653cd
|
||||||
|
p: 8a9d5b34a9c009889820c3de356a6570379a908806fc6923e9caca7a0dd9a536dbabcb8771535fba173f554b95c32ba506ffa915d74b3c1a3eb26b71e69416782be569f711f83aa4525a7b9a4e4a42e8608940224659ca88046f31e4c10f15b87195e160743a0b3226194e6e472575dfa198e16b2d4e3fd780afde56a536211c7ac245d2da89b0a2289116823676eb63d06119f6c1de0fecd11d6fc51f5f84371e6adb3963fc49884de3f2fd73e0a7fdc27880b97af20a950df6082af7e99f709feb3690021ce33d6723158921f2b64f995c286f25f7df4c60917eddcbb5ad000f7d3bc3107cb13b16cb578e4411440685e9087f5e88c577c1280106f452a1a5
|
||||||
|
q: eb3156fa9b703b4fc81a88d73b8b1027e5aa190b4e027bee5b4bcf5f
|
||||||
|
r: 191023b3891a99f9be78f157609dda119bef122b0d13f5bd593c8d8b
|
||||||
|
s: 98bb266b279f35abd8c48b7bea8391c9c3edb12cf85bb88b14013ca3
|
||||||
|
x: 5dc96a783ee46e6478793a2a03fcd71d46b4c2c1a9842978bc4db39c
|
||||||
|
y: 4509874fb9ec7e6207a3ba2f40533f59a8cb594f77a200ddf2b8c6ce43b476996898072eb4d0e403be0a4cefcedcd3dbd2d3b6343b26819fd3b08c28253069e09f97253fdd8094555ddc94d375c84b905a960b02b6dfc71d455bcf3820bab25d8d52c83f287510e5cfd0cd29ced2efd9546509c17f2cd5a258afbfe59e2a2569490d6879e4c968224dc072603a7255224f910d9d8b72cb6c95a0466f1050b2796d346089335cb89e0222f9c4525b4b10467397c8fb073dc3fa05856ec9e196d0c40019320ac49d9ca5daee371d674e43f8ad2a23f213bb4fb01d84afb8934c4bc251907003f30636b73ab9fc32850cd9b8547db930aba9462cc20fded6e89364
|
||||||
|
g: 83c70f14c85ab511142edcbb17593c8b26bf2ff126f6e4d215963ed10b05a014bc8da277fb3f9412940e9fcc8f8eb5a09f2f017d98c7d7f5a08359bd0480716fb0157109d33d810fd0d5e94c7721739d2bad7e155df9452911becbebbe42b3202182de415fc761fb3b30a2f929d0818626ad6a83473c44c832e5abd3efac4cc1afe0a1364322f2a07d6f3b0603e8480be9f5dd974f8231cc302f2d27646b552684773b16ac69b7fb255200574a74b7d64819aeff7b7c8c7f1dffdbf4078e445b12bc090abf5aecf83b4b16ae3823b808214814f91fad1daaf94647d09ad97061bec0af07b7189b6fb386e7611e73443f38027080b769a7118d31fa39bceea854
|
||||||
|
h: 100
|
||||||
|
m: ed7952cd586d36447d66c12646aaefe45c7684fb4c1c2ef92a250023c6fc36ee8d4c0615a2baf4499809e89c43d3e630e52feaecd1e33d0ce1ee440c4a9b8847f0cf39b0b45817713d7e80bcc2f95a2c12af79a205b1f07da0e9c314afe1694ac3c858a5696e75d09042a260e96d26f3e51296c68d1bf9e569aa4b468572e95ee7363f5e52c618bbb0f66286058e1207bbfc510e35b536a5c26dd6735a04166bc9d08c0d06fa97b4b8b101218b10e01832cc07d19c7d372ccca8d8cc7a6de55bf9032eac200b7deb1edc1867d65a8b987410e73b5abab0394ac1fdc93a3e4f90396c3df8ee83e22eafd110
|
||||||
|
p: b5996f897bd23f28306a1ebc72a3b226d3405484962b125732eb3af659aef385e260ac5db1f15b4e574bd3a6920fccab6e2a3a330a65f29254ff3cc7774867a9c66a7eb47140900e6864e54a35eaae78badb17eba89732148d78715ca0c13ea9addaac257c761c304e5d09d01aea14ae3beaaae8aacd8102fd932f3ad35161b7dedc20e1deca727d4496deff89a92e72d508e310c1937878ec4677ca610ba56d8a037524c428463dd7f777bb76e5b711d4fd4aded7625afbaa1dc1c2e29b1a574c3a07b2b208b93d5dff2e1960e7c9208e03af5bfff7a592c4b6e56bb041f23f1cbfeea2e39d155beb737a11468b52fb05639b409859d887658b3626c6c63361
|
||||||
|
q: d9aa50d49312085f55f86e24e8ef83b8398f0a23cf46aa508534243d
|
||||||
|
r: 631acca69f50f898828e9e4e97f69c07f501260db4e3651a90302c09
|
||||||
|
s: 43f59d5cd84a6c01f6850d817dc851553a9568bbaf0b160895439e6b
|
||||||
|
x: 2814abf1b12d69faabb1df4998d28402569addffa9f2d382777e48ec
|
||||||
|
y: 97a4c7ac05154295293f3abe22f0ab777f8c93a75139cf4fac4c1b41d6077d028ba14cd65aefdb16c6075b063bea7a7897f521d473371ded8a4802e83d10c0e7b3dcd00887fd885c7711f42b1ef6e04d4a7aced8d795fd181f37545af4bbe7477938ff444b5f4068a9c09137e43d056c420dcb3419e20969baf08bbab0b6e2021c87f1d22cfd7d16a8de9d645fe81a7427cbe389815040dc6d6537a62e88404872f4c44e0f9b40f7c575fbcb14ad9379660a6ccfcfed24c8f92e2c41016daf9ef7c9659d941320be5fda4f0264fdc08855afe2d7a49ab749770ac6d13ece1ddc4c14dd31c1a9fd211041f7887ae6f6a22f62292d0a1d757f319d1f087cb9ba91
|
||||||
|
g: 6a45134e14f0f89d69b01bafaf43a0dc19c7c6c69385627aac47d81bf2334f0c2d466bec936f42ceb0ce4c116488bb158b0b408e19bf55fa756ee525ca4afa10cd6a7b4c01373bed9c833b208e4a61ce312c233f804a1b7d6eaaa2065d94e3b80fb3bf69f02a3ed800f658be570835f76e98f2c9f9e12f3b72053256ec6d3819d6afb5f7315dd0f0bab12f683fa8d0ea03e9a8674e83c86571f618f818cc70c37f28b0f53895f877718a480c9322d92daba02f2e269b43ff0f7ea71cb5ce0dffa6d7756b3f328935ce4324a09ee07b552a382cb18ee82deb68a444b11073b45d6a08af784f59d3fd1cbb039a79ccf1b503186feb1fbbe34de5d08a82b3b7474
|
||||||
|
h: 180
|
||||||
|
m: eab7ce44f602e5e46c7387c31136b04c2444de3e3e4babc6e77fcc8582e7b0b2e32d96764048075c852a6624e797b82c05e479035ffa7753a92815405b6c29b905d129975fe782c5a46a5e91bb
|
||||||
|
p: 8c464bff7e870c496ce105973c5b1e76011943249afd8ba65a9de2b11ae751b1b9b804e2e3004fcc5252c35578c9e2f94123f27aa57e2cc0dcbcf75da07729bd6bb0067b6e467d7df84c68e19b8f8256ef4d518834e1f0415aef0e7770a0e93ac6822d677c01257ef30870d9fa95fe74d41caeb0d73b3846dbb3b93af9f1ca79bde8ff6854bfed0ab2b4bb92735c65c340c8b85bdc9a8c996f6d2203f6f0690d97f9194f79e18fc7095abd45508bc0ab83e62802dfb05d699e0eac4918a2d835b485b20f6578f6c7f31cb44bcbea273cf0057c283b696b73b27711d1a157a2d463510186d6ea54aef189e7b4b1f4babe54b46c4664f3c938dc5cb6098ee114b1
|
||||||
|
q: 860e8232356998d738fc5396e736c1f3f9ea3ea1d454c6375a69eaa9
|
||||||
|
r: 562baf5d92f7f4f0ce3bde1dfe59c28a80950c734cd104ba55509f24
|
||||||
|
s: 81a27c444abc842e0a169fc14ca51c2cdc1a953fca3587908e07da98
|
||||||
|
x: 122da28d28802a2e221596e372eda8b4a99647a7439dc0af23d9c082
|
||||||
|
y: c16917a7ef98fbc4b4b418ef627eafaa48c0351659ce2b9340bf06d768898d059985699b6f1643adc323f58a286c17a0a03ceee65ad6a15cb9410b677e915ab63b163bc698c45c8c17111809dfb37b40da712b4207c614c9704b698f02523064cdf11135d7a01050695667685a2554590a4a39be97bbb7c1edf125f0151d1ae6376775463623e574ac5757a2f812064bb7b529dfc9a2cbf9aaf62a072e6455ace8ec21508d0cd586e3383577d9beead1899db2027d691aba126c39a40e49e469b940d0bb08c8936b97d01665c94beab4ee66c96fbc6656c46faecfaa369e9db1219288a430469de7abda0e591277a04e834c00000540300194cedd545829b20
|
||||||
|
g: ae0d1fc9326a1174a37170a9eea83a8278670d29a9d24671e061c73e8de80727a6cf098134aa2b9c85031dd5b0c3bb84c05ba5f832c6f79f06f22262430b924a3c9b26ad851e38d45fb0328c37ede5ee73e0677936303af4a0be4687f5f620fe44279b2418d2e0a44f8cc9b92a067908dddf657ddcd3fcf6db887141cfcfa2ffb8d20d502314d519877ba077989d30295c6d64b0d4d372090ed791859800893f397903aa9f8d7e1cbaf1dd340bcdf53f651ea8defd25006bdba2a84e70384986569c8d8aa7f89a49c50ddbf2b9a58aaac4ade267835fdb5c2c3ccf1747e12533391240b7a93bcc0dcc361cc52373f80f13ebbe4a7753bb0856ed2047d5feb4f8
|
||||||
|
h: 100
|
||||||
|
m: 9f11d784f8e47e86719b56f9cd024f1a4446ace1cba3b14e757932f302e9ffd8d5a8386a3c2f427bf0d8f2b7c090b396cd950ce437acd076b91441815fd02c1ffafa5f
|
||||||
|
p: da02cff45c76fa856d3a4438a1bb11170bcde1316a560e438bfbf82fb23ed5277dcbabd5a7999b5f624179cff00a91b54b61d2754a99867e627711bf2b71dbbcc7a72ca5a8c034f844b4aecccacf6cfab0806418a882ba15861bd911d7550dc8f230efa785d44a92f7ad0cd8465a25875b0d6bdfcf5cf004080aa29e5e31f2e34f9e39d1a86ecaa3133ab5d30fb1db2b6166a4eab27b86642ed8a7ffa8ea14655be63dbb7d6913be0f1ef014ffa067b0e529f199a73838ef9309110961fe6d0b47e68629bde64320bcf22a6c470c65662a811112a49116958238569f2c513c203f20d7c9ba3d4ddfe52333e6108d24758cd1fdecbb025bef927d5b7de5a170c3
|
||||||
|
q: 88084dd8a05e65a7d2ccad8bf291c3cfe359d86275fa00d0f6bbfe7b
|
||||||
|
r: 1177cf0f51ccd66e410637d27369659b9b9fba311315769618fbcc04
|
||||||
|
s: fde95ca6b8e2a304411b60f948055d1224c160f7ef54c49acf02f70
|
||||||
|
x: 21ddadcc538d76b1534ccf7d49d33e0386c695739e4d1aed1dab246a
|
||||||
|
y: 3ace1b3bf51f5dc9116b8145394558831999bbed64b9bc67b86f0bec08a5d4999fb3787b44888272e480c32c98d2c5d10dfcb51c73226398b0e4e52c34d36beb4d68c48cb4ffd4bdaa915b6e88c2cea851215130024fcaeba568f0e4a6ddd12c6f42a632f42a8c4dacf1bd99ed273a7031f0b264a51ab85e5421f75d1682c50793b5d6bdaa7c287b1fec37ee9a1da5cec2343b79faebc2c9905e1ef8062847a925daeb401040b87031f95137a28b4631862c330c41615539066caf87b3bcbe18aea923b7cf0ca20ccb24185534fb0d2aa5840b89bc2d0e4c81b2ba0855537a13a95bb97f73fdb0eb6846e176751ece53d29788a33f35f1a14b558d433431dd63
|
||||||
|
g: 2e68806e9c519d334d339a560ca4c50c84cfa1a0089ac9e05d227a670d8c467be4d9f135c0bed9ebeeca3639669bb70d037ae7b23666eab8d0d852e4c57dfde9ac01a208a36d676817a6981468e2884fdd172b91023c2b94002b33e263bd5e4ef8d449c0a54e4b31767073a4e90035825f0577159521af7b0f57ad5d118de1a3bd1f306bcdb5738ed83cc3a5636154276eab02db87a7220a9aa7981bdafd4231c9aed0a0c5073b5acd60ea359e6495741278254c7f38a48624a6fd65924e327349927f0d323beab69fadf79e7f776f18391c2bbb7f6540d1debfd41c4e5474ec4dfd5271cc688711e291c108ba16d16b35551e448714218bafc7c63a3b6f1512
|
||||||
|
h: 100
|
||||||
|
m: 56bdf9fcf431424707f1f95f8e41d5ae8d233b76ac123ba2a80254890c42a7d630f867695b20845fb7b812a2f6ddc3c6eb80e62af4951370bbd0d5d03bda6729d940f645b5db219aa70753d91f122f3632446ff4d5374930c226c2e67b1e8bce3c5342a61d2c5a743b007da87f91c28632f1356bc7b5105849539573c2400bdb3f63c16ef501a0c3c4b28ae5dbae1d60009c75f6b37b0e882cc50fc0d6613f683c241e9ebbfd1762b123127ec279ca96f73b23
|
||||||
|
p: b176d1c2ff6123e71ead83b0e53d774ab4819411d51d49374f827c7be67cfd76763a972147e650d7ee2b58b1a424787a1ba5cfcc57885d8fc20d892755ae1b5db7fe0231a4d6726ee0a9473b62f04521bc1fe1e5cb58f6b071f0d1718538901324f01a7391c91385bfee311de7134fa5139a8cc1ddead314c7fb88f923fbd0c203f6858f673bd3af9b2b0756a221e7fb5a4b0aa39a2d6d9a6ee46eeaad9c278decfe8557f496c5956a371691c916bcbe3ab43214ff563a70dcd0db1f374974498c4c138dbf97e54996c4b1791c09f02309ff9483c9aec3e1b8530b9ab6f08ed4290a120db642f02954d3e32ee96f56a813faab1443f8d5c3e998841f61ef21c3
|
||||||
|
q: fd9b04dc79b9261c1dada8e16ab993209d51cb2baa977b67b25ca4eb
|
||||||
|
r: 2ffa07252f12b3908608d524295901d2a3ea1245966d919e4cc288f1
|
||||||
|
s: a003a4ba156cc38c6f68a2732d380cbee66d86cbb6743d7b954649d6
|
||||||
|
x: f9989142a66b0306295616c27e0f527a8b0424a68ce793b1888ca68b
|
||||||
|
y: 886c8b64d073beabbb0ff8d23d05ed19951e71e530d998c834c6dc326e787030651ceffd120b2b97ad551155fe00ac9096f4c1d2eaab9529d87309ba8ac5d3d7b7ef056ccffa03b8412d01ca9652cb9fabed1d320aa4469c675af8419b1ac9f59f00b9e836dc714384df193ed824836fef75a2372fd0bec1fe8fa9d8ea09b91b3e2751b87f50fdca8828d87f6a741c4b89ccd5eb1b741b6b9bfc717d1fc05b2056cc9ae9d3219c78038bedc459116e03ca3a86cdede897c818a257ec843f34391e7c7441f746060009e0183ac592e1fb714ced5dcd8091d9fd49c1fc598c627958607d25ec17dc57bdeacc139e960f605448e28620c391331a9d34439e0ec937
|
||||||
|
g: 20b4663ae2a4f2229a799f174dc895c6cd940c9327ddde58b76bcf6e1975e0f0bd453ad576fc95961dc5e0c9aa5179448776fd83605daea304685bf21c61f374214444250c85c2add2e71af33afaf4a28daba107f3869a0118cc776fc653603604a77b25318e03374c00a56b789131d4ddd6b6addbd62275152f0cbfbd1a7e9ec6805606f72290955dd1753247c164558f2090657943e31e54bfd98accdaccf5ba8f8fd01cbf210cb77f1bfbde62cf4bfde04b6f10e7f394ed8e044125f0d43365f19bcbc6bef14a116a8cbe08328f82f845214b4c45f22643b080049b1b6e55e3021dbb90a2820c10f6a6a0cd29c13300acd0c3afd0ccd3606e7dadc7f937e1
|
||||||
|
h: 180
|
||||||
|
m: e63fc61bfc5818aef082f97419329b8adb42be9635ec7715c55614df0b12248c4f5a949785e375c937cc619cf1451a0541a9e96d939e95f76793ca01706d287c178f4224135535b5b816638bea9191ec623da6f564091f1f0c43fc164f4fa85033b287ddfbe358707bdf6bc360b210323d0219b835fc1f0f6c8e0a9f00e5003dfe206611dc758d8cac4b1142acae34a1a17c09bc46c9b67b5e68c8a84238399b3a0a1e0ddada5665
|
||||||
|
p: eb81f1c0701fbe8a7bfb4de40d577203ca5ca10fd7b2552f25b21861e834b15f7b1698affd6cdf0d8a20e8be52ef8438085b0b90709e047d62ccce7663aae1ba509f0585bf5d4d69560fceec116c8a357f2a9e1f3f5490b178a9050658458b09e14d7995d0a439dfa32348c4f273d3a13912307887067b745eb1895beb819ca407325dbc316192da05cda4f83c1a7fc45f9290e94960752c010289c52a9abde848c2d89816d19c15f77846b0eb66ad97d2744f618af77e40765bcb02ca3a1994435dc29fe5e5d592dc2d4eb6bdfb4dbc6f6b7283d919b0d943d0b75b11bd74c337b0dd2ac638e1c8ef1dff8f448744affdcf58848a2ab7fb3f0198b01e05e85b
|
||||||
|
q: a106b7dabd59d3fc0a77337ff8aee12dd41c5d5b087a06c1b9316309
|
||||||
|
r: 50da9d43fbb6ebb59e9b4f89c1c356215b078d88e00608ac3e084a64
|
||||||
|
s: 2087720ea3501f07fe32112ef4ff5eb029b0620eba4c2c68fccb0847
|
||||||
|
x: 2d231de663900e2f4cc1c87f8addcbf745e2ab18f31221707368a2d1
|
||||||
|
y: d9df92ed7c82e6da8ad7cea76226f1f8ee5d24d7897bb915ec69d0e778511d9f6ef9461049c367f21c6dc646db61f489c7048015e82f351a4c57e90bbe1ebd5b5ccb8b3ea6bd477ab8859589f48a2f69e16c03f6816da7572a7f6e59ec3f2f8b102ed070ed46db2fc475d9c325201d295e07fa425d604d26c9f572357c15c6e6d5f5bdbea77cceaf3d7f49bb2ae7fadbf857666cfd47b61c590e16947dc4d4c03c3d04e156d4f68b412fd3bfa07686bf88c8b9bedba7206f7c3527bb22f3e400333087a89007b499c36ea0d16dd32539f56c160d1f6e40798820bc6168354821d2757f34dbf17cbd9bef9fea3891b525bf581fdde0cd030e3b90d133087abc5e
|
||||||
|
g: 17f4c01edcb16c83ff2a183c9079a74b767cad4c2fb234714d3dc3a9a55938e3e81c05102356b21f024733a04174d04c46c781ebf31b2909a22d42fdede81caab1e627ca1540ed6a802a25376d0c7f3af9a60a4c64af806494c753b937a25eeace16c19eb9a142ec5da70c4c5b843b332db8407e157dafc998cb39e9a67556c6318210872e922d84938619f70060ed5a8196f660d58ff23fffc9981c44f76b5ec0c580b424f04fc6adc13a391cfa1be64d14246612a902c4fb5156e08d2ad23dfd1a0a8c84ce50fe59ebda0e9a842d03608156809d7812a8cc14f920a5434d8f6b0db697dbcb8606fe0f38be0b221dc7b6dd5d143c2f67276358f9578584870f
|
||||||
|
h: 180
|
||||||
|
m: 875c4cb3a08b5bc478d925356de76d05
|
||||||
|
p: 90326d8cee672a0b3ff9fcef581a182cd84b8c97ce86a960f094708e00d8f7d0417c74735f2c65a0569a60e1f17759b0359303a5a1319a3352883be4008c00afc2ba50f897620fcc2a337037abc9447428f91e107901760c3c6a9fc05f142387ccbd823fcb2a0d2aa5c55203f961a8ed68fb94d2ff6aedc5ee0d32930fa6076406b940e50e1aa4b46140d6bce87348f971da55cc3f24a82ee032583d81287dd50264103f5afb82e76ec81ebb3127a136a6c06653075c485bc033c1c09636e4f4b0a22f5430ce8aa4ce2e8a3dc3dbad5b241531730412fff4a5164a8b908b7beadd9922144b8d4c43dcde1f45abfd6b66ef66bb1d16eaabf05847014d659a419b
|
||||||
|
q: ea85349913754eea1d0c7f5d17fc9d73c0e64a0be281d503e44fa927
|
||||||
|
r: 925a996eeb5e8c3be19f872114133066fdd68e67fec7e37e4c96e887
|
||||||
|
s: 8d523959af54ed2c557aea35a3dc4da5267dd6d7a4d796bd585019bb
|
||||||
|
x: 24a7333c34fb47c3e54290b64b679730b0e6ea00417aa82c08c156f8
|
||||||
|
y: 88c0777479a23d5fd944e098b0a3dba04b7aabca2a066e43e504ea74e3398417c960474d2ed194152eae7450cbaf4f0a0b06e2d79b4a64788fee3d7d4f122442d3d353f1f62e3b3dedf2f87956c3b849497891ed8335c4092a54ef0c5baa2169d696414f3b9d5dfe2436d99c52156ccaa3453685382a3aaf7c47060bbca32273cc998a9f3cfd6f28d1f997ebb4569e4134d0602fabd1a7f716de552de6e9dc59b7d1716e814cd9f0a1f4c967e447c9d666f295e5421a9e70dfca7ab1d8e57f20c952471d5fedeb266ce5889354ef05f97751e9e8c214138f5a0129fbdb54f1c835773791e8c660b43755df56d942267efe0af2a526ca68cfe6e04d2ae5fdc6eb
|
||||||
|
g: 5b9a6be90c0f87d8dad70dfae94b6d943ddb3c8e0fca3f0f4afc6eb14109c611aee162f4f168224749cc8d3ee09fd5cad3f7eb309a0528c748187fa841bdd8d44586cd44e6afd1b1110423ee0d46051799b446c59d2f1ce8b06f78aa4675b31a99abc0b014ee85030d60aba14c01340d686ede6bdf6f9d53eff33cf831d6076999d6b4c4679e0955d5481b9dc6288171c77b645cd38139f3e87f8f14db77e3e90cb6df1e3ffff9cff84c258b994d7799ba4563146f146146f1880fc9db1b046d7383c388829f90047b08ba32b7e8b2a4119bee8973f0a894e85c1a7f06ba2eff45e1800255403205e1fee19fd6d70eb7773ca5820586e214562a27ca859c8b3e
|
||||||
|
h: 200
|
||||||
|
m: 988af38061c4a11029d5307b92d337a61702232860f3722627db830985282c755ed5ecb15bf2789c4b970342640dfbfde370325977ed8cc111e068da3bc49541fa28702ba98949e09727da7609555dd34194b63b9d1f19105138f4bc9d60d0c348548cd1594a82a94a517461db1f1fe852e3afbf6bcb4a6249a742a6b90a23b8181e07e2ce6f5194a9a5cd16a94862ab27a660fecbdc8a268b
|
||||||
|
p: bc2392b05907cbef35dee577e735f7ef7b16c2c0d4f0d9d824038ebca5692c412821650cf9e3c5908bbbf2d33d6210491b14f839cc5faaa66adfa37de49bfe022eb2e79141f2954495cb7fb0c0f64549219065a0f9795b87bf3ef6e5c6903f3fabd95fcba0fd58277ad6411d50a456b6f7b8442e1c5c64381ad3c3071db322d4d44e90178f1a72f8b2fdaf89bf57572ca36f72b549ffac4cbe3b121c46f0e65a13191e8f78e4d6867c3003da47ab42491574fdc75fba00c55ead6cdbce078971013d0610f18fdb6a49dd5ad3e96fdf92747d3ddfece0684d597e93fb4384c7b80e267eb31d2ef5021a4577c1348f2e468ad80f85a3c4c1367ee34ee7337c89ab
|
||||||
|
q: df8ead593056702e1f8cb93ab08b039d3049ac2c96956bc7c772816d
|
||||||
|
r: a8fdc1da276efcf5fcec4eac7021b1b8634991200363d3d1e32f9029
|
||||||
|
s: 717cc41555e9f7eac8bdfc7940b62878d6294e7b50cd5f4be03485a
|
||||||
|
x: 9f04977681f073dca482c945997e213494194ab4b77e72d1eaa956e
|
||||||
|
y: 1aea5d97768d610c0edd637781b5c5b204f7f8f58088badc7ecd648000d2a1c569b05e4a549a01e9150652c9e8243ab989d1c642d6a4ff9bee6e00d8fc304a2f0abc99c7618d4e83ae4a2da3bef9647e4caf998c99a3581d55326670baf698cf6b97343f015680859cec755987627b0f84ce389bc20f862d758968b1e9655f388445a0cc76b472155eb3936cef3bd31f206ef03a7b03208b6686adb55dfcedeaae8206ae350cc2deafdd65700f8a5b554fb2d2ebb0f01cd2554cff5f98b3738659279fdbb5433e85d5d28ac2b0332b3660eb71f53b723ad09cd624eb95d8751e40f2e1c0dd53029bad6c8509b2452dedcc47190f76eb02a58f4538014f8ee5b3
|
||||||
|
g: dcb43f91c33f29334f634f868f870ef57c0a53a0a2fe1140ff0bda361e13d870bf30ec5184cc33ba961b584322e192131a819118186aea9898d8fe46889121b4f4d1d739fa04114d1b18b3e0768030afbd9efcc73942e0d57c91764e5e0f4fec8d17b3a72ed5deabb821779654699b9244b609e34ada7f870e07d1004905a6d39b2edb45fbd8708a248e74a32cbda5d1e1cd719f949f07479285f77c6fafbed2948a19cb451544a7b2593451e46c19e8303e378c1ed026b116a49077f5d460f2bb567e453f953836190c8a9cb9fc92a9d580f443e49c3f927a0e5371174737de3ec8ae4da5b83d099b0d9f32ceb5b0c216231e81cd2895c4a589d99ca223e1ea
|
||||||
|
h: 200
|
||||||
|
m: e1ce1f690064c2a0f1ed049574e4fc
|
||||||
|
p: fb578b4776827c4d19d2f47bfa297980e31a8555e76356a60b621693f81d448ead27d48876f661eb1244d33b00c89b7cb79a77aea1314b04fa56eb6f878236fefc557d93688b83beae7ec313fd62628fca59080a6602280269cf94e979661f9899d165d90440d7ca607eb32ddf4a7728fd4f175839374d95c42d8fb9b1dcc01460681c2fceab65e08477897742e8e8ca4b6a18a6c31a517463891476865cd7640ae9b5220b7487277d36e572796e41b6f8d999bd1ca9faceaf1f929caad75cd090e23e1a6da9b6bdf22bd5433d4119a8eb196dd448cad32da3354d5cef388acb38d9443cc4982b3f3cde81d521dde1133e04fe2a0b3ba4bf8f7eed330963aca5
|
||||||
|
q: b0308cba4cb365d2fb37339da569367bd03ca3f23930f44099686eed
|
||||||
|
r: 30d68752d02635a13ebbd8f480fdc1b6b7c8597b3f63d6167c406d0b
|
||||||
|
s: 5993c4c6e4251f0b2799f53af455b72458e6243d3b204e7c29fef703
|
||||||
|
x: 6ae6c640986d73107c2ccdf9874f96e08b1774412bbe48eb17c6056e
|
||||||
|
y: abf3d753748c120d216d1e1640d7007966eb3cbf1d80830741cca52591c3092571e1526c052f5b25aff81fdbc9d63c16680d8df8320e284de0d27b01e81cbfa4f84ba4d25034c3ff97e44000dac72a0f12ce774a31ee3f21f0f6b3a2014c0062295253493dca53d0d4b4c94d49acc116d69d7f114ccaf537ff8d5a6e83f8acb7c911d062c6ebd73b87b9c65182d201555a9cf25622ae06933f81689bc5e3df3411a53182c0365d6457628d3988ae8966d048953c837fd8be6f91eb0f12498810eb277a531996f192bedacdc862c9b9fbdebd690c414eaa0640703738e655882a7f2f6d3c6fc1b099cdbd47da65162ce8cc4180656a7a3b00e9dca5c85a59291e
|
||||||
|
g: 3b5ea62331a5d0b21c4c455e020f128749bececfc4a919f5c877fcc919f1ca2bb5aac6fe81ef181d6331058cf33f4c6c9371768d126c9a60707ffc69510bc28ccf604d2ce1d596be3983039d88cd3400c9c2aa3b7e605950f748a46ac15e712b271a0356cac1d3baaa1b9e07b45dedd73baa8542af5f80c256633e893ddfd9b189def8624a3abed7294b592ed9d13724c998906a6fea0ee7c2d3b6ffa036781a77082609015273b9581ee557cb78af1c931308af842203cb9f7a7a5f26c3ec96f3955160a9009ba0dac6a6a652067a10867d06b95b0d8fff63d8cddd475d45cdc9278a2bc1203f83f59bec85d995fc9785e7d7c5a4f5452cb3ae3250e41af94e
|
||||||
|
h: 100
|
||||||
|
m: b0c7201effb15930174cabfcf428f6ad3ceb5ff85d3ddd84ab42a1e10fdf28d3dac7de9e6163a5bf631e662834cd54f96f2973c9441bdd40a471a3b27efb9ab4fbce0c53d05fcd4676058798da6a4128e9225c67f5848207da0f753d6cf8ab9372dcb938a565b5ee5799647fd91747de107a99757c08d49e5e9af205690cb371d7a043ede1b8c22501721886b9b3281c128badc8e76d91a5b709a5e0194079a15ca418eb535438f69de6069ccb7b21ffa10c3d0ce03aee4997a8efceab710cc0c0d8ae7ce29854129bcb629b4040f7fac3b8c968789ec8aa03d7c84e92c6218a3973962cb5c61999584d
|
||||||
|
p: fb263cf2b81f97b5e55ff5a8e84b65058d721f9b2bc0f96ef8ad3980c1ee80dd69af539c60ac86daa993d150a53b93f838266e6bee6bb234c32784e2018edf370fa30bf9535990deb0c43c376dc224c286aaad6423e01c2596720129b0badda8773804ab266221b156b4f880262d4ada4976de1954d5efbbbea4cbd89b8752df59059706843a904e38a1222a06b463cfb6008689b6d91dc398627ce6352e9110d170ae6a0e7ef09b3f76c65b57e90f789769d3e6305a9d87a1e76c570d7e2ba15cc90c6e2f69147352a6790077571eef983d941952b1ec6fa3da1bd018f20e0a6a50644ce00ec04f5ae55588885d231c005f165d99175061e1843a9a06e1892f
|
||||||
|
q: 8f6d2992082311367d0e3afb01a86e4b7395381d07760f18aa93a699
|
||||||
|
r: 1e90a73e89f237ca86bad8e060637432c625476f14dd372447c7604c
|
||||||
|
s: 142f95be07b2bd52d660b4a6d4ebb9a9d0fd60c2ec5003a0d0b502b
|
||||||
|
x: 154a292ff521c6919b3524829b5b21238fcb00fabaf38786066461dd
|
||||||
|
y: dec5227bf4795e73cb2bf1150a7a9fb189811b3c29f472da2af9520bf4771c5cf91946b051f805c9a7c5e2ca790a07b1752d1337b633d0c0a5bc4e7eebdd22d1e9b0e9c689d6b892437d0c17c0fc3007238ef672a53aabe49ef41d802d53b2eeced8c7635f733265c9bf104f573fbaf9614b4221aa2ee70a69f33ec1f6edc76487b62955dae27b735a7012d6d9f17805a82df1c28af63fe7cd0c0403d0b015d0870e2e8a385b587dd7b91e9dcfc437ad2d43f81cce08c3c372240d30853dead0e6c7b34060f1ff7eefddc196189425736d224ff0a2fc1cca76aa8c564deaa22654ffdf34ce87c5d23c2490bee8470c8fdc93d55bc120e653e3a19ce237e49813
|
||||||
|
g: 5dfb6a757c529e26d3900d19c260b686038d3cbc0a33c73b5b956780b0aeb4c2ee189439e23ec46f034338c2a6f7908c8c8dd7e9a5ded649c24a967188a35096e540ead6ba1ddf76a206b6fbdce8c7fbff0ef4d0c931cae2bffe29cb26cec6d069624d2c981584bd8b8c5de42d3f92886ab85a26c502b309f75e51733fcc478a51aa92a09bd7693166304d518f983984d2d4603fcb5d31f72708af879a700537c53a48cf40b89518be007a69b42e342c637f23e610c381a1d258ee841d9cd5ee8f713605fa2aa828861c838979fd5edd1c35b9651917698710dd96eee654c42a9fff208e4ab9674f11b10f423ffbcd24f70fd62e6e844169739d1007130f0a31
|
||||||
|
h: e0
|
||||||
|
m: fd0d1023cd82dc0a90b6a59139bd65e2e5b0188070abfc422459fc77f2c536536e7adeac20023df19254a51a69a81068ab4fb8e964e503486a856725ba7e09a8fecaca13ca372104477bae7db59aad99fc9706f41ed2e98d73c4a49478a2c98dc2d22fd2a6fbb24ab31c44030a98521ab2d84312ba21be24159b56778d32b9ffec50eda59273d116636d50f84ec68937485cc1590c
|
||||||
|
p: cc96df61b9406b260fae612f3919efeb302ec3f912b17ed5ddf13f0cc88943e6d6e440f3d48470de73c9c77a9e29eb8bb594a52f47a87b3ad15fbe31dd144a37bd590940e0d8629bc50814b5ac732d16f2031070b9776e5cd684038250cd371807e508349a43cb4d6794db47f5aa81983f0120208bdf249a3b505fea49bfce4f725ea47179f2344be81019080d4f3d58896b6d5819b809d36051f77fb9c6644d769956475e335d0e0ee92de7f1588f7017a6ac244441126599481dd1fafa0f9ba6c947d2824fb04bdf5dbbc3c02326038027eb6f8407ba8ed5ba7a4192ce0ccf16b64aaa227d675c36e61e1811ed47235233f6dec87130941305fe565ae1c489
|
||||||
|
q: d8864ddb2b889744268232c0faa7949bb1efde4d93e59904f4cf7765
|
||||||
|
r: adb1244036766ccde22c5012443f7dbc421d6bb2fa3d94d63ad8bc47
|
||||||
|
s: 60a9c1734f89ea29172806dad88588539243905b08e43d99c9bc0269
|
||||||
|
x: 88de7088e20689122fb5904005ca2b71091221805e96437912ca89ee
|
||||||
|
y: 4c421ad50bc635cccffd890473f94fd7e93869f7886360be84c5a356391acf60c561106e239f1cdad77a21e3fffaa27d7518c582907fa066447e85ec44a27fa3fade0b61ce9fcfb0a1624d3d7f7411e18312e2ec610bd874fe42c7c24491bf487dabf705f3931346b417602942be82498ee44f72d7758aa58ac2e4dc4e69bc6ea6df4835e71bec484c5a30b32b2323702d94a9de3d5b89c7ded480a4774b3003c3634e0a865fe8f8378833983a735f68389a5adde28765f4ec5d91eeeff86d324e66a238d6ebf019c4ada43c67b4d5bdda7fc35c6a9a9e0e56480233423ddda5cae1614826e306dd617cf78d1d357e2c5757800f6e0071ae8fe9c7c8e29469dd
|
||||||
|
g: a60b81650d52a438367b7219f9660d56edefb805eec8871125e9d6f229ae44411cb2b82a848fe235ec045a3af9ba4dfb17b09af61da95dc5a01d3217f716335ce6ba03b35d3d41e4f0db1a7bd8d8f1ebff3897fb124b0ac0a7442e1d2c884d181bc428165ddc89db585524b44ad9d9b29b1f30941a80514ca25002271bb66601450cbae746d70262497018f83114eebca18cdd65bda331e43947c66b13f12964b345cfe34b0d36b3fd4b504109366df6dc520ddbb1fd6d16c3391abcd5df32358e09c5e2d5d1187ef46eae51848a4d576fa37735667954f368f434fbb3895810bd029775eb25a6cea165d5073685e8ad9d14d57a4bf80afbd917f584b282a2ec
|
||||||
|
h: 180
|
||||||
|
m: d3951cc43ffc634919a5e5a2a51580b4bd8de2b413a7fcb13d05fed3b260e483c91b8d4bb62ab1a91a9a98d96f9e139add1c2c0fcdabc7dc8266426c10529ad0790bdff648572e98296e41113754b5db7c81c2e2fee535f1c6b5ec5edb733abbe9285d37ec7bfca4d5c77cb25a29c73dc8bd5c319784ac98593d1c69e751ea87c0746b704b3b38746e03f879116470b5
|
||||||
|
p: f6a4c18aeddc4cd03dfd41b0a6f66624828b79eaee52474d9957a48fad4903facad7f04977c83860a236d716a5331ef273205b987bc4813ea7f9e797434c3bb9de419e92f890a7a447e94ebf0ca7d6f0f58237bc2747d2a9e4c367de73f8b83f1e76760305c89f316cf31753f7affae77fb46bb4c199be93f3ffb13fb4b54d1786a3dbea5f24013a4ffe7880fee8efc925180726431b0b5a7badb382f0c053f9c7c3fc8f7773b14561ceb5f2bdda819bca34d7252d70e3bc3dd190dd161497a7d087115c40b087d7df81123fc4c917b75edd3e4e08a870f6fda8d92ca03860200ba6be41f3db6a22e05ea4df77dade736e70260950965b137b61d3ca130782fd
|
||||||
|
q: 9818eb04452248796eb475c76c717202ffa62da41c97bdbb2c731f17
|
||||||
|
r: 6fbf6d05b5489e1a5a1f0d44ec33ce9f1ee7a8ca4713af186624820
|
||||||
|
s: 2c1c4dc0d6de29c859bfcd01ae1c5d6956ce3f73025d186f0ae0c3ce
|
||||||
|
x: ff7be78b86f3e387b18f8d9c7e123c847fd30497658ac91a35267e2
|
||||||
|
y: 72ee2330e84aaa034898e53426042de0bf5dfb39b0e4dcb04c3ab986ea73dc3a1cbf592dbbb443e9cab7ce81e92ca5f4aa1156af9932e434c8975e041b69c4d42b8543200140fb02ee48de817f07f185c0cf23a446237b21d733464ebad78e318d48ea1f38066e2b5a61baaa110bc2e86b7c40cb3cf9c10a712e25cd611b30462efd00482c7a27645ee46afe33dd3800a14ae35fe0595187121c03831c2e60210d811b790a73233c410c4f33fece59d0985fe50580cf77af2330d6aacbf57303f9fa597578482a9a155b20710e7955033ce5c009d4e4eae30444066f03103b839a898d82f1b276224361baee7bc0e67199ff5735eca5545dd42846929118c8b6
|
||||||
|
g: 504ea8f552cf026b84744849a8596cd4a857c371438f44a3a59d28bf060cefa7afb6f15e4c94f03ddb1d1c92e7ecdc820ae2feed6c326643b8d161a3fa863cd0c7663ff2a9c786ec4c59c689314774f8f7d09380c0f5ccd77d3716cfb96684f1e57392e1446ddd1d0374a466c2f3d91842c83446a8d41281c58b35f9168a6aa8c17477956e8a382848f2a115cf2aa4650b86905b581476db9fa4eb4c2b645d73eb64104e8122cd0295f91b5ef4ef7c04a40a6ecca251440540d9d8b2827b519edfed921ffe40b79958246f9ad68edb769046878ccbb24fcd3617b46ffef038f0d4a6cd499182dbf16314037a0c5fd760da8c39d66a0f3c0df77802e5e903910
|
||||||
|
h: 200
|
||||||
|
m: 02611fcde38062882444a5b6a5c3d113d3133f63cea4ebda150aa8e6c036770998e4a80d7608216c15bc31ca5a4a9f5c6444e492159b203b0924f78d5d5ee0b636a0eba9db3a7fcef36d799ca9b7f91d0868bfce0bd8c85c255dca3119e0c852fd95d9f489a7867e34b6ae06be414aca5201b83cdbb20e193566a4e108673a3abbb82b215c4b9fa5305d3de8f3d42be100369b4656d5586ddbfc9a79cf91d03a8077f98ccbb7d0cda9e226258d571673279ed7f9bdb08e7671224193fb8b96c8e5aab187526e438066c3da9e
|
||||||
|
p: fdeb8ea9f5881856c3742d2174bdd9b0225c3ff89cebebd636d03bceb1501123523a20c6d0a243894605debe25bb1b28c88104a4301e4b957fb206c8ab7c9b85310089b86d671289af9b5bbac84928ad9786e1ac7b64c9d25d61169593faddf89585fef62bdabf66fe233ce3bf19f4b11ceca6f40231004295d54127e62ccfe983a8815b869d7723586fdad4fe2d9e47f1d31643ba9112353caa54caaa4f747c7254d568ce854fc7b9ff7563d24be6d9ca7d0a8cb38efc2332607fdf2c4c772926a26768226b6fc9c43acddf923dc6143a7d0edc99221d5887cd4bd478308f882eb6e607f817840db2fee8201cb69cfa121c5358915a97fee79630f4d2931053
|
||||||
|
q: bc5d91937bea6cce705c9e283bc6a5ffe0ddd52c345274165a9f7141
|
||||||
|
r: 58714c636e299bae30a22ee9e52d5760b0308d70848c9ae517b045a7
|
||||||
|
s: 40e600114fc32ae6d904fbe68b857b053c453b5338221f556e1d65fd
|
||||||
|
x: 88773e09cb596d940033af59011d1333cbbb071341bb0aaa11e55fc0
|
||||||
|
y: d208e6cf810984e92c3c6c68b8e9955a9248e2820cf3ef7e9dbd4ce3f57c2607690db105361965a62d191f8a14951125a68458ce2a6440e024406a9ad92d999784831f1d484b2ea206d539847afdcb9f6daab94dd9d6fc24b8f6a04ac6d58ff58c32bd8da89a5b7590c62fad986311fa05ffc88a2daad2f2d7a4cd943cb52ec057fdbba815551d25d35b878d0ad5d9178cf226ff8e197d700089d95ee6696595365ac6d22f12ceee99ad6479ec2d5dc2e91810858829a3ac741bc814d705478be8df07b28af8df9cb0af82e691316d11ac0b74dd2a97468076225b3627e13fbc9e9550c3c340566b9541bc7e1e4eca11160323e756298762800a3dc58486cab9
|
||||||
|
g: 339004a875eb778d79f9d5fb1980d1ee584bd30a34753562b876933028660e33d953b37d546e1994028e9a1c11cbac3b7be646525147bd2db394d039335f6cbe51da8b46455e5f500fd023f62f064538916f003da9a303a00923c0072daaf2e380eb8d210ad4f6299eeda76f76b216af03e85751a3b71d2fbb48c43ba893f53128301aa645a9bc8c73b34a50dd51d1f00bbc94cc3bf8f9744ab2d85d41839f1434d2317993175b2ec9dfd2eabace4730d3f092ef16c44472d6ec8313997c496e1d9bd7694af19d2c6ffcd1f002b3c258bc8097c58aa579e934c7122d036ec483b6e3ee834a2c3942f26a2689d22f39ee95dfd330f338628824d692bcad388115
|
||||||
|
h: 180
|
||||||
|
m: 55def5907ce32bb7f5cbc126da21ba22e6e06b2397158d896d77c2e8f85117fd0ed9992a90e697eef8982a0b99d788a02d89e2d488cd3c432deea59e822dc6ecbb0c16e9e5ba65f57a92329c01a6327a64d2398cdef36fd480cf5691727ccf903336f1ef53f80c54ccf4dcb9a26c2048318c44e4987907b8ebfdbaa686a6f3edcc62b9c66d693b41858c9f0b7415762bf72f4d1652b027facb042987ce1fbef45b8283d349b5c7f237bdf036c121f5cb2bcc6d326303426dfbadb32511b4bf902860223d2f3c086b3fda72c602c0
|
||||||
|
p: d53612a532088b1cbd5a45b28d266851df5cab53d93772bda8d56ed2a59c73ef721316741962f0cd646cdf26eb7e44178b23ffdfe124e1507d6ddafbfc9008aa6a9d5a18cd6884a7f8602039133abdcce7c9c52c5ee7943bd7cba3be993a752a3c25f1358efbca30aeaac008a3705487c01417ade90d5ffd41df2c594b1b8cf9e63f7caeff8ec570c530f59dc7b209abd33652be7a1afd941dfbf0e6754626e7590cdddb690f6dfd1864147f11ceb2c510c045ec4adeb0e99896d61cfc3dfb23f792ab690cf1aebf8adae1883a2b6f8c5bc90fa76a2893a380ae5f9c4591af6f195b8b41033d7996d90b1023cd0bbc0ebcbc935e1f4094a1870ce4ce87aa0b45
|
||||||
|
q: e38e9541655742ac02e7ff65b7782af8d961507db243965b23992bff
|
||||||
|
r: d463a099b015848d385976f7083ed444aef9c50fe9a474d0579da2e4
|
||||||
|
s: 473d9b0c3f15268d76aad9d6db04ab8704fde986a9abd435a19ff8c
|
||||||
|
x: 1f59104ed4f458de451fcf5c3c07f5bd943dc857a08d5b1ce560893c
|
||||||
|
y: 8ca19846b839b81928ec711726a170bc0bd9e75a174edbbb81cd9c910baf2eb74558f1459eb0f51f721fe33d3782512879d9b4e381b73d5a1379ef92ea5c65c98e9387c856c81def9f62a12e8f26d2ef9a34f5b949e27266186750be56181a280751ecee25c6d2f7e497586faf29237cdaa61ba2a298414873bb5df50408c5cfe868adec6d7b0dae2b6cea9d7665369ddb5e44cdc948063ae1b971b11a7853ba916caa363021fafa8b32ed90c76ee4eb3060fc7727007e9162bb25b069ce811cdf08f5d16f835312b620aedeca37063b83509bae3eac7846b6ffb9cba85b9b0b5e17aa59c8b34f2c3dddbaef168af40c3566c788abe49e86936cf3b4dfccf1b4
|
||||||
|
g: 15272e452097f1b5baf2c098a98622859734bc9a04fff302f31998e1cdc52e6110257571736c00cc73088e419591d07df22c400f4c47445c9c6f9f1dc75544be90f954b5f41f513fe0898e976de3ca979d65d498766f23b835ebf7187993167ac1b47917bb3407c89359a0b61ce6621d1b7294979ba0012fa33fbd1526cd27b7f93b5782d37dead4425c7e958000391f91db665165b1a957cf78131523ec60c2fbaed799ee15b049efac0a9d448dd60530b1056811c98acb812f330c6c85e7b91bf4c51dccb12e17e4758da081e581c2d75e783ebd6985e4138c331209c346496ca30d50ea461a0cc14e699fd6d904b11d88282f1913adb227faefd9421db832
|
||||||
|
h: e0
|
||||||
|
m: 987a1d94f908dd7b03b73079a19608ea47db2b708852b32d575753ae81597b9878bb20962abc387b603530c0ee38b813c751bdc34ab136e71b8cb41c6220e3eadfc99730507c4b0267558a0aeb03028c5ee1bb37c7dcf7bd202b43a245c469d771a933cbe710545b6ab5b7aa432873b8e3ff0748aaaddb22cd24ec5a213ebcf27da754911d7d5c2b6090911e9df0f15302a6e3896b6b3221a66daf384865bf5959c5c458a0f454c84fce81b0a676447d981591ca0d81d787a6396cb37db1e0c457d124c8dabc
|
||||||
|
p: 97f2b8c4e179de1e467917790cdf90be70e08d6713de630f9a7be512571f80c467a2e64052c5378b831ef0f4d84c0294d2d68efb910ec96f55eca47654fbc3344f0a610115b3848fd3e789e7f4c131ae81a1f62ec2675aff127475942512945cf162d9ac648622c1486a4100b51c764a4026f87c525e42fe11e5dc6df05d3089524000a875fc3d1f30a68a4342c6007c9325395689a6185c53459eb131436d711d2b96ab46173b88202b4558b426993840d4529052071dab93b6a5282d5da6b05b55b51e100e1aa132d3ea05806061324b5dbea4ef1c919055ac3215d01d5fafd1b23ef226d6981b7d196a9599a3f4768f2822af8c3c08da1b551f29eebd66cf
|
||||||
|
q: c40af4728fc890581bb8c20e81b9dee3ae73a87b2ac92d02f4712d3b
|
||||||
|
r: 55dd1fd5e8e5c875da6820cf5498e6baab510b165fea36377cf56492
|
||||||
|
s: 6e6e758d94dc01f54dff552c095fb0b920bca7fd90fb7b6e7bf28b62
|
||||||
|
x: b1bd22485d2ae1ca84e80b0595e77c34f6e1f8acbb70cf9d3f8a4d69
|
||||||
|
y: 29e308b81106cd2f6d5c45a7546dafbfd31e15abe0f42814407ce9e2b5dc5f3aba5560b4eb4aaa1f3c23e08e96bab9b5f81a069168ea1311c700b2296615fedba5a99b8904744d7a251748ca6b7548c88b11492136938ba7efd4941d1a6a0159874b58bdd0c6398b68d2e90280a5758ee0cf08ab79267d18e1075ed3c0f9ab17e0667f40a830381343416be81129576f0c4ee3e53882871f610bf03705b652144e75c08d01706834e423b79bde44570d02cdfa48a7a7ef19c0e41a2cac5a2fbb3cffaa183757dc60be6d1de60e7e83600ca956558e0cdd454076a714ee595801a17ce6493a99bcdfa8734a4a48a28c6ca1470bdbe3963e2844491d2dd96134cf
|
||||||
|
g: c4ba7aa3734b6ee990be72989b62100aeabbf487b4e8315880577b5d237d93e6ad24850516ddd4068978e3bea39a0b030b1cba360473d0526c30d6b506866b27d26788d25d7ce2163510d8e2072fdce73b3b4f96218cc048d8a82da7b6d18407c1d8a2ffe25ecc654266edc14b1b7fe56c72df87d43da6dbc0e0ff3b6a5383e8c849651fececbfebdaf2b89773eaa69ab746f888e1d0a9ffdc83a72a542d084813c302e6f1ab06108650bfd06466212c341f2f98e29ed82e0a7bc615d6611f508893b6e56e0f75f3ac8f5640a41fc7aa13bdeb25e205abba403cae13e9426d6771b2d85ee104d61090fd5151db8f91079a0c280e630857e385a953e61f5d05c
|
||||||
|
h: 180
|
||||||
|
m: b0679fc527deffa88d52a23c15fde67dee871d2c026fcc864f639f76eddbabc0ad7559c1c7fb53d806911d29becccc8b7772909884c30f10dd38e8e38bca03535b5834487fdc5025f61aac5bee1f3205d553a4ade6a239cd6bfffb22931f120e43cf665d6a16cea61dca1cb8bc5f392d231c2cae946e719fa69bbb77c1c22a73414dfb9fb8af1908cf65a782a610262ba2cc4cc3b22b65cff48eebb4666866a46542956d4627a635bf3b6dc87ce2ac2547b0681d9bd8b85c8427f7f5f9d6d9e794464b3f9d45dee80aab873b72fd38ac6b490110c6d53ac8232ab1deed5997d9370d6a
|
||||||
|
p: e5a15b5e6ab4a53ee0829cfa8e6349152d9f9e324939e626edeff925d145aa1894d5f7dc2795c58678095243379c8c77e77c9aaf7f0e9b969bcfef662abab0c09e63d2ad49ae3469a0ba577ae05ff87ac070cd77e3fa9d9fcbd9b32e2e69cac2373ef33a46f1f1df285bcafc904e5018836ba08b8fd05f116c6b7f6c6f8ce295928c57ce4d42112f12e6d7056008f73b68a96e0e7de03f7a39b2adc253c467e67937345e11e6c543271ccb2c66afce6dce148a4054299441fce615e7eb8418ca97433e3624da79129895ef2f4ec615041311858a0fe24ec5b5b2807f43008bc65385d7a81e2324bff45f9689e2d0a8fcd4f85c39fcef88c995e96f31fd3efa5d
|
||||||
|
q: a10ad23351175f14f9fd8a1d905cdea273a2ec9ed782d58eada644f9
|
||||||
|
r: 411b51e54e3852643cd5bd73a75e6aab91161843438d20513d234116
|
||||||
|
s: 4bd0e160c8532cb6c0826ad62c67865ea24859aa729cbc53f30885e1
|
||||||
|
x: 916bcb0daf1df5d428ae5d5ca92e1396ca9f41109d9f24eae76a460d
|
||||||
|
y: 941eee1b52814c58f793d216774553a42f0923f9f1ff9409feeab88102e9887a8b1b362ea7f1656d2f287ac4d23723217f6a7b94357eccd5bea305ac93a4dfcd61b34514105a5d1f8799d4f5e16f9bc9fdf78b6bd62925b3734a0a79233a1694012ff15ef64880fb911b8d0d29dc3c7a47b3be433ce8f26f90317746230c0264616a71685dc6e576ed983ab18160d690febc09de8ac0065bb86b78ad702cda1ec21802a7bfeb06aeb137a53063ec9b8b51806bf4c420917b783e5a6002d2685834df7c1dc022b14ac96f710ce9fde4505cb450191c5219d9f80dd5f02f5ab4ad2816aed508036017a28a7a44940258808f8c037e8174a4b62d7f43ea79d31d9b
|
||||||
|
g: 4a76e7c3c75efbcd99e1a0a92747180499e1b0f394c3a5cd36f60b264537a86d3b7500df7f058f80da985e88de0eb32ad879d7a434b77643332c5a82712b1bec9d9803110a8352df3470efe69d72b39cd86c6dc57a002b3b4f676307091da78528b2fe01bd3284fe6c039333492a1db50344c41b54d32f5ec513a5b2110f58a32c0213088fde3a61408b9d10e6e1c0ddc60746af1f2246b6bf97b789cce63b644fb7e085e38473a439f0f4c12b80d388fc739f79a405a1e44f459616fa9eeb97801642ae2ecd1de69ebaceb92d8689eee18493c245d2e85c848a050f507874a661c2a541b09bcd612cbe8362b3f06b2ef3c38d1837fc1a10d8b6fc2cf96fcb3d
|
||||||
|
h: e0
|
||||||
|
m: 4453a61a8ff6aa9287602e0582d1b86239b7930a2129776ca02c7faafb88b41de5bbffc346b245a71f06d1c3d074210d470a8dfacc6e3fda19c1983f56d626bc46051fb1
|
||||||
|
p: 87ca958345d017ac656162bfc65ea5f6489f1b3f4cbac525ad11c4c5deb637b3d92b6b32d7902e688449346c15a91671a8204b8a8124e0ab908ce816e3f9714328db13822bc3a222654c6ecfe61ea8e72ce4d5c20da1fa1f4341b8c01a9caaad6f38ad19b35cd4d2448f67b6f58a9bf897509b92e8ee3d4e0f987a333a3a086139e4c96b61a2423658dba02ba0bfe5f9ff2baa0e2a8e1dbc99eb770a22aea7f8a0b236e2f0b7c60dd898b92a8f6cb83d9e9acd752f7b28110a3ca94df68a98ce27fd2cb2871c86f08777a8c890a2eb1081250124e3c6bceed382a5f012d43f08fed3eb886a03cab66eaafc2ccd2574e51a2f712f89fe3fff760381255db073c5
|
||||||
|
q: a64d1cf2e88b9720c2d4d71e44063512c9b3d3e213c7c219222e90ff
|
||||||
|
r: 415d3fae30fb6e150eaede5c1c0328a76dc5c2076c1fde4fa36dd6ae
|
||||||
|
s: 461030c658e6741f3c0179a2e7f5355e8bdc7400506f5d1f94fdc97e
|
||||||
|
x: 72234df44a16480c7d83ae2414ec02a6213747cac26374eee402b81b
|
||||||
|
y: 4bc23e4393fa4cbaaaf283566b60bd6893a9b50035ea540783750ea7f88f56b3228fd936abc6a8e7814ac2084dd93fb98efa18cb38ba0f8c556622f897c9a41d610a4a31a2e1eb9e29ee09b4eb013b72dfb0d905ec750ff096faa7421c824dd6f25bfa5ea8fd404205dc0bc197f6d016816ed354e009f45c2381ce48b451da65397b1249d1d58a0533f1f58ddff558f06caff43c3405487508be650af71cb9247ab622b3726f473315ef7d52aefdbfc06e09d832452b0786332e644e7b48b8905549660fddef226d9fb2a4128508048ea120758eb3a935b2c29f76c35f8a7981a691a7bcd4319beb132a8734ef194062aa141b89f959ac81e9caac6e42a33c04
|
||||||
|
g: ae31ffa170408e74029e1830b447ab092549d61fcb641e134ab2899f2bab96a1dcee67589e4da87f186db5ec4a9cad99b8ad9694880db3b78bafd8c8d7e80bc4bcd4dadf4f041ba926c5c4fabba7d3cf507905e4d7491d78a3942e832eff0ceb78ed04c4ee7fdfc20267fbb702b2bd3a82e3701f678609c8346372e7924521c1fd04b844520eb83be247f07aad95dbdff5e1fc88d0e82db1837d5b5f2bb974e0220055ee4761f6fc1ba026fe8bc659f570f29d715c99d4f648cb43461598baf05052e2511b725682ce54d8970b91ffaf4733935a186bc4c935571ee256279e55752e5f8f8cb1e89978a416248401bacefb50ad45d3ced4e8665931596d24dc00
|
||||||
|
h: 100
|
||||||
|
m: 84f66f9b0e93041cb8294ec19df4d471843f7d3aa64753f5a521b7282447497cf89dbd63e56bd12da2596956572a2a8844b8775077862d77b10a1ae0db49efe7ff0897ae4be6edcc68
|
||||||
|
p: ed8b918621d0fcb3a69f649729dd48f3cd566e4ad4eeb9af1e45c50c3601089ee03c7c7808d931c0775022bee2e1b1d4492d029963fc46a0f17ff16c67d6247d09e9bb4ebecf9bd9afd9c2dc1a5a785f6aaac68cb424e17e0a203ab942341af71ee686f5283514ced5c307fc576d97d331a9b1beda20f2aa016dfaaac85df83756126b71e5ef435b86f43d24daebad922bac5c2ffa2b56e36248fe08677921583a3b417ad6e6005cefc0d60b1e52314e6b7f43c3b0b2c898b63379449068f808d6f6b89914ba05eeaafcb6a7b3cfd207bc9682313fe705bcaa3fb34b0b0024347ed031ecf37c3f1dafa3110fd280e533d53b9bcf8e58c1d2044d8037eabf2b05
|
||||||
|
q: f6538860b2ba6189ae8c78727ab7735880d6d6dbb38179bf7a42d417
|
||||||
|
r: 20c684bf8b14bf8abb70223da60a163548efe6b5991891b1008ba9f5
|
||||||
|
s: 931caa0ebfc47fafe271154236497c1df101ec07aa43ebcf43fb112d
|
||||||
|
x: 692b6f944ef30b7446793119ae6ce0087c74524972329f38a8d9c102
|
||||||
|
y: e2b80b32769ab8bcb6ae5bced1f348586da59ef016cb9f3d97c0f1ff00592f2a73918059bf9e8adddcf0ec8a1eebf5407359868f53466205898195776d8fc72e1e288abe14fcbad4d77be80dc07618e3db24f854dbb047a1927fe5e8c5d86f338a22901cc64b0be49e6a6873a680c88d1a61cb58e649c9ea5c17adb43db1a7ac323027dad2bc447f4af5bed702a36475a37b5ffb253c8337d5b2edaf94b8353bb94b2e060fbaf5ddfdda446b7a4f476417aeeb9791125e5c6a03d0b03783db37ca4ea13e15017c491bfccb0b8ad63e42056be910f7e956fb83de338ad1f52915c9b9d496b42551d8b25a73811e387fd8e75a69d5b4b88dbcc080652b1d836f7e
|
||||||
|
g: cbc65e112646efbe130803c5bce884cfc3357a6c9fcab87e2f9b23f7798a67624f72eb47802172887aeda0187ff158c20cffe79224cd7bb4532287dacfc23c4e2d211f246775806bc9d7f68b57c63f42ebb3e3502e3cac01ddaacba5aa266edb7e0e7ca5b4ab988e4098e553fd0039dec4e131f2baa350f4d00e86dd04479128b8b67c8fca668770dbbaa12cfd0600c2295debd3ae1c81fb22ab751c8ac67029fafb5a9036e4aff9125fce9bea0480dffc4529a4eb648533060105fac230e9820523dc3a9d63d4e04251efd3fd7baf635bf9878047392763321dc21886bdf98e37d8de36625587816744f5d0d1095e656d549fc4ab872b2b944d99165901b03
|
||||||
|
h: 100
|
||||||
|
m: 671bde36b2e4798b51a308dbbc4818443f93b33a4d9d7ef5624ac76da8265d876445f40be5971d769aa747b6c84a91d50a066866cf0d37d4d93bfea6b064e10dc4557d1a3e9f9c20036752b8e8ece4ed074c162f1bc261e3b1987417e7b9583b396346769f855a37217c5675d14dbcd1136a17ca772054dd4b750b65afa129f1cd1380e31ab9abb0c35f4171549d8b79b6e6bf02cb45a1131adf4563282f08fa9370d3f582166992d97127f4738e5b95c7fe1d6837c9b6e0324395a20b5e75afe9af2d2d8c1e6931acdd1f15c3d75074d80ad7c51db2f9875252bf8f93acb67310c1
|
||||||
|
p: b8f9c2c687cdf191cab9eefcb12fb2b62af2fe301b3d680d209f65940304df8e4f983847d6c6a3cff9d15d0bb272f0007441867e6cfa276eb3979d0cb5ac34ff4707657a2422fe6fdefec32220dd96d5844aac1a26d887bef213c6eb9e91071633084fa6729efd805fd6032e7cdf72848930cc024b7553d776bc7cb3f3dc40a5a52c9c7eaa0aa6b970086411a0b806abf8e6b70380a2f23e67f38933d850006b9f00b5b43f1052aa09ae254caf867300af17a55cbcf33165b8a4bf99a1664c1f28d7e6ddf4d7bbe49ab461e9f8bbb43a8f67f0b5a12b8c44e8d11bfce988c6d61d292eae8f4322efbd155fca0e6f2ff86c0d2057ea0bec74d1d662c7cc812cbf
|
||||||
|
q: c32a07738f02b5182756e499e92cbfbe60defb24dee0c3cf7f9957e5
|
||||||
|
r: 9111f2967744bbeae703cc72a0b55f510b6b0b6f55daecb9fdb842a7
|
||||||
|
s: 5f44a2c44731d74f071af8742066a8f939a2e66d71ad0d2dd69b286b
|
||||||
|
x: 1b83d4f87b4b8e9233160335d75fab21d94b17c68bc7d61e3f068d1b
|
||||||
|
y: 804e1b31320c3fbe85a4e05caf9a897fa4ef181eb34d39b539d0d60d9c0796afc294cac9ad0c0611efa23494203ce91c5f2dfd78051cfe8a7fe56fb308c87962e50edadc136c69e647772c392dd6879b5af0c264edd38f404e83fc4498bcbce8f2976cde07cbc17ec0424300d54e18f65b07c080152113d13f1d8d77f9e11296ed83db360cc98e4f594832fe917c00fb3c0b5c577278b78f0dc064a62f9b37ae2ff28f684329eeae1305973958f289498d709336c342c053d6c530090324ecece392c56bf2a36a2473664f8e04ea3a79e6981b07e1eb216eb668232ac4c63f9438ef1cc56e223da404c3ef455bf7d3abf49425c4271651ee04a77907c3821a6c
|
||||||
|
g: 580e939dcf92f407c347248a7a3bda3004e3c0369b879d421554497a3931108e4376c1dad48f765c916caedecd3ed3253a873feff693dca935d0b6b6d3d89b7a8a47d3796df47eb0d605ded12c53f091632af90abc0311d02695c2512c835326a4288033e7f154c529c1fefc8b8b3e6505cc5d5a5f869a4969b84f79b5d33e5ed8b19a2397e93029c68ecc88e3df749164ce9a58fc00cccabee339d59bc8c0397661a944e189b9e07841819ce17289527fa7b936879fbe1aca66567aab57795dd0dd5cbd6c79245697b6ed708f11c936aba54fde376561887055fa6c2d8fa63240d3952aee977b1c1eca498d8cf90721775d8f47d7f709c0d77c8b011f9663cf
|
||||||
|
h: e0
|
||||||
|
m: 3f0f120fe78ad61b138c1119e45b0ccf40ec67b1b943fd416411de4e390a1cbab1aafb8f6dac0cf526ae998452644c42280ddb1e6b0dd888a2c6e263fcfc589dd236930ac546c01d7cef15e1e0f56cf2e2f317fb488eeaddaa88ac1c43ac8c31a97b4882349ea1d3b2a74c4c3e6540d1752c717a2204ac2adddd4fe7964745756ed005ae79cbb3f19635b8eee4a02ab2ac6e19c55e8c70b023235454a706a088c25b
|
||||||
|
p: fc93d66c9faa51c0fef6d2d87d6a8bcfdf812dfe0daa991b9363cb08685c5117c5e6395e26eb667ff61e140234cb2c15be5d197d8fab9d222906635069c85c2d233572661de0c2a949b45b1af76c1a7d8015294f1d45ae304d9a83e3c995387012e9f4bc633767549f29eb0b01db6416cf446fb17b053ab780ec32a28843405261edb7237ddbff9d27980034a24ba6a1fd8c901267d10fdac5ae774a8dc6f742f11a89103c0f968950d420d0abfaaf870835d5034681317fb2391f4731b4b93d4a62c99ad50204892b383781ffe384e90e01ff397c9c281a35cab3c2e28961b81b82e881a97f0cac0d52ee03d705a85a1e69f239d4219382e69d4337889cfdbd
|
||||||
|
q: cd82a9dd219cfe4f2346007c8e946d812eb389096a4b6109b39c9edd
|
||||||
|
r: 6799da04e5af4a6858caeb02948a2b64139a3dacd05fa52424762e73
|
||||||
|
s: 12fe5ce14fee24f674557bf80cf5be3e67ce3f608cf8688bcba2b565
|
||||||
|
x: 68845ee5952857b002457ce33dd9e110ccc0cdb27fdd9b92d177f3fb
|
||||||
|
y: a023e46ae9c2f48841bc1fc291550eaf5106be36e71d32ccd2e9a79107afc37a6bb618414f1209cba4a4628d40cbd1f9acc343511dfc1d5c87f3ecb5846b52b2ccc258b6f17132d02d99bcf5f482a484816237af11c14bbef96309ebc2489a57d0605fe7c59a17c9199b4f7e4d1f4bd40f444ed6828ac430179c7a1b5223d60d0bf7e5fe4b2e5700c605d1c18210e141d905981afc99ac5e2666ae1f35f8e9cd4644f13022957cd51cbb034444fe7331198092c9f3823a9851c129204d4eb276dfcbec04f1f594148f99047410336ee2d0869a3b25d76f718ed7eac49a6867a5a61f6da53ea2e285224c175c7f79e2a05ca6f6d5510365fbf46fb02aaa5f915c
|
||||||
|
g: 80c3d369e4d92d39427d683779bb60c969e2d64ad25e36c584a770d00d8c51e44a544219756d27b8e2965bb382231d1345bf93dcfc517442027115983e67034a2bbde12a4c043305cdcf6d85157f30af655564f21322a8aa5e92b9afa05d0241dffbcc357bd2b1bd96307d973c27c2e4f097425eefdd699451d0dd73dbe793fb9396396973e4283d89a1ed34337a6d755cdcf470c42a6570fdb3f1ec495dd8bff14d4346df57b035ac02dfce79b8d8c0bb43adf679a324b64be938a6d44eb0d1cdc48aa2b829db5a82591acfae6412ff5d74b3ae44dd015a1196afcf0fc42f76307b72015bfcb1ddae1f2021a663bd6016b15518db5e1470a06001330a278590
|
||||||
|
h: e0
|
||||||
|
m: 41e82ec0969d77b4551a0fc983029d5c71d5baf115698d318c724e35f20670502589f5d082031cd28d452bd35b087f9828b0e00408f50ed72a530140ff522e0e6d154825eb3fd27987308c57d7d248462068b58ff70a2ae73fefc68b581892119b9007f01fcc84479e1a30066d4ad183cce683113e320a9bfd2372ebe625e33392f03c408a64f680efb3dc75a609a658d0f9794afea4d1844869a176af56fe7eafd6432b048c85778800fe18861402e29171d72914cc04ef4360b575fde8372203840e503fcddbdd2a0e11091ac0ce6d33c69ac7c4300cace45369edc10ea7c4e5bba832ec3f22dd7cc20331aa90ad7bf9797684ebef8424adb9
|
||||||
|
p: 8e99d53925eba8d0a9eed1863786bbd55c56a25622a0cc42db73357b2e4139d869c1706cd3276be64109bddb36ce4e4952340618a492e74d296c8a516b79bd526cd4f81a1fd6d58f13741ed80d1912ecf1ffda6f5fa674d4742ce2d11088a0e960e544c45c64c3f9253d985b0781b5536ffc9a7b1b8b1c97ba4d013074b016d39d5f958ea676faa8f2f3662f905677a17f3ab8ac85103217e843dcbc6c9d783f60765559ce806d9cd17eea7af87737d5a3f14e196408e109d7f25048ea3ea50ca03aba28049044ad056f2c1d4967cda53e755811fcb92df97259d1c3b02aca43df6ba6c475c8dc990df47f548be4d6f4c8eb5a20677b7731d37fdc65a1358305
|
||||||
|
q: d5aea02e6516c9dc4fa96787184fd0971142e2889c6a9fe11b9473ab
|
||||||
|
r: c9ee9f5c836adfc6995f8ae3070259ba6041b90a748fdfb7237d3b71
|
||||||
|
s: ae0131c9da6076318ed2ffa19775cf4fcaa351093af5c933cfba62e2
|
||||||
|
x: ccd9e373eae9ef4262bc4eec6f6c6be7086f3c62a524addb0051d760
|
||||||
|
y: 6d77b0297298c9e406ba4ed8656f3a62c2eef2a2880a430a23a80f03278f583a3114acafe263d63040d6dda8fb4ea99e258f3e6177aa3e059cb7ce2dce1a3cf6b96cc0eea09bbcf8a43e58739a4e6b69018d688c9427105a47d61b942cf3401442f43c3af60613f15ebb83078b17d6eb416e16ff80683340a269842fa4a289010a323868555026da7ec942e93a65dfccc02367fb9ff459e01b11a8b21816cfdfcad4e7b46a4a5e61dc8016703ed79672d897f8b1008aafde3fc4606ec6a0c4e232b2a358fd13ee08070fcdddcb3df4ce4b0c62789c5e211cb80a132665726304c06f76b009b08c9c9ef27ddfc314ddf7bf94497423df27fe852b0fc6bb49c671
|
||||||
|
g: 9c46da3373dc0e312399ebc0bec8ff437095b842cbb90cd5677613a98231aed6c0fcc66fc099cdcb42dbbc02962006ed02e2ae5e114373b0495c4446c2d51c337deee3a2c69121393be729958d5736ea0ace4aa37cb6fe8a4f8fe60368474d106a4245db7214ba82f4f3f5baefb7eac756ea6d20900d59499337d61d96d6de282e2b7e33b415da0e04317c42a9f27cca7f4d48b1584aa4cf6a3d69ecddb30ca4b0715e15cb69c83ccbcb1ad07b1f8be9c85b7638fe61c2b3ddeaa94ee59948abef693a49e45803439c9992b9c7be8f64f603b2ffc5d0c0680d217c49a5ce95e389ad4709ba921da9d20b1399a8a6880f2079bec9aa52450eef91455a35f5eae6
|
||||||
|
h: 200
|
||||||
|
m: beae243894a828b390e6679591b41879023f251ef94bc1be1f4b20220b90815dcf0f22add75f82e49c68056861aa054f81ac0e501389dcf0c0c721cd9906da87969b8c8efee1aa096df14b85934fb3
|
||||||
|
p: cfd184e5dd54345dd05b2da2defe6b70ce466dd82f7f8c6e0131d9d7cf08500dec0ecbaf76b542a6fda53ac2b35995ef1c15a07a568229ac459a99dce47df6f183103298458e5f771f5eacab8c7323847f38ec93dbf190ee3a871835558ec4da231fe8cbd919bd0314d131544bb015726cb436e9e231ce87df4aef465788a44fe09f579c012e17b4d9b828fa76e3ed9b125049c6d2d86da7d6b1c4683c2a6c7ccd377f57c1c7ba88d763973ed6f6cf67a1c23950e849318b461b10d2b3745f8f42030332703f3ad909ce772a35224bae4db506b87d79be37d69a27c8a2fd128c1291d0db9aec755aeabbe8e6c66046408ef576d5638a5dca8d7962a74825ee87
|
||||||
|
q: e99ac871cf8cef61c9e7597062183b67e4d76089c8e1f41d189b0ff1
|
||||||
|
r: 7d5511d9442b3f229b1b5d3febd517971b941ea3801f04b800b5a67a
|
||||||
|
s: cf7d37e2ef2f69012338bc79413662a7b3d274bc661aff9d15d15cd2
|
||||||
|
x: 2a98f662c3e1a928507aff57edcfe762310601b15e2e6d6ba98daac7
|
||||||
|
y: 2548dbcb4dc02af44133b7b6dfd32cf20ad4ccb8ef934299c1a44822a12704e61eb383eb69050738b4188bd0e9c14f2fc15a22510d7f8758b1a13357ca67c71a1bc983458a468dede04cf2ffb3981b5c94ff227ba75c94eec70ec657ad8c55bc37aa5b894996cc7f04d27f3b0d324e5da54c55a73b63f79550532cc7ac9fc77e2520999b8d8b78de0b373038aa6701e447d620142af2459a7b03a49babf1d39fe62c370d0191593d1d5ee56bfae700c2a31d7a353088d589971b8440ae6b41ba1d4a129fabefe745aae22892c5f1d01696b245a62082b81fac6228ffb0d96f8816c759c4f4dde3ef9317d22a3d0e75fad4d55caf57cb749d6809362f8a4eb5c4
|
||||||
|
g: 453e4da5f146e3b4a7ac12dcde333ce1dfcd28493979e654616e7acf1e41f3f36bba455a4a7ce014a036924f29b31de48597ec10529aed74487c9d797c0313e4ce6517800b8b2ed61ad9ed872c6b118d1a0fdf69c2176851a2476099360954dc781bddefbeebfcf78b84ef2b854a3d6a8ed94a873316798e142d2caaefdf1e713bce3520e0e58049bc9b9c13f3437cf91c3194b916944af697c6171ca10ac9d5a944f04e2a7eae3227217e87654b58cbffd403c9dca937693e657a0791989ef9631a4d9578388fcc34b4ee465ba21bf657203b49f66f72c556eec15bb2b339c3938f8f83aacdc62ce3f63623044bdd74589b2dc81d5f4e0d75e00edfcbf543a0
|
||||||
|
h: 100
|
||||||
|
m: 171ef5556865fed87dd6c0c2ebf8ab0499bb499bdd98ac7ef7e733c42ea01f25e3119cd4d0124384c0a1ab9ec4783582d63858b4b1048b2ba1a724089dbb68765ca030161c00f629dfc084ae8756a66a75ece0503e182ff00485f81a63952db86521b77a49101b016905b172d6c64e2677d8054e0ec232693fe0a2829420063690873034224eb44a0178ad5a3e4f21e3996d5141d1c28bfe4bdf5e90f64994f01e196cafd8eb79cd597eb1bd1c11ce53d6014710e983563952d93e448989955c0bf7ccaa9d57da6c7393a4843a0942a418c00725141b4d2d92e89dbba1ed426c3508fd775687b985bac540
|
||||||
|
p: b5ed35893934cd2fcf4828d13a23adafa3006a3e8f7cba9e9dd833729c4296e130ba3b96c10a98fd7c1208f626f836ee2efc3e01467d5932a26b7ef5912ab39ab956e48152254e827cfc30000753a9e4724bb62b8999b1c5c1a341a0d9227b8a091b7d65d9f07faab94a0b4b002109608b9c78550b33c06ddac21071c72a67b09a970d250f51b89452aa790cb76dc7a55147c8d6554d190f73020e964afeb44bef366c94c58fc9c62f0468ac06a059846b0038747153ba6cb5c93037ac4b18de245af1ea2f258df715638274dbee44bb040f7cb956f95ce3da0bf76d577af48296f778ebe086bc9909dc1b1658712c869100fd25bf3674c8697d07b6a32806a5
|
||||||
|
q: bdadeb9ed976bc0cce7ca75a318b5016a85e26e67c1aa2e4376de135
|
||||||
|
r: 9b9cab35494eae7156806bbe74462f8e61535f735198f74a078a4ba9
|
||||||
|
s: 2299f3fadec636bce903889db7afd928b5a1b5aaf95afc7cab2ba29a
|
||||||
|
x: 751a207b265d06858e2d63fd18ab370c0a7c4a546d94c90168e49519
|
||||||
|
y: 5d810eceaf1f9e1813141107e073936efbea24d50bc9b755f01d026f61b5e8cf8be23a62b48551343253420c1f59db42c5c129d2c64b4b1c39eaaba9f9d2cab6ac3e99ee3ea6398c012b8ee1c971bc2f0f264724cb7bef744302f24e42f9cdcc39ebf2d27dde742217c4e8ceccb91930be7bac5964939b42ee68ce9dfeaa548f3b24ff0381c0996745beafc49f08e9c04e2f9ae261d2505d6e1e29de05bd7390fe52c64c36b36b174ced54d9fc77e2f7ba122480c92d8295c4054116cbc7ba3d5e1439399dea5433f14d9d5bf6de275e4e6720bab7914bdef4f36996ee44fa5039e21691e843153e5430799ced0fa3ed65c857e33fe14d611a0b8792a5818f3e
|
||||||
|
g: a738ea71b71fb6598aa9dd1c5104be3f98a01ea15d0044d16042e2b7cf84816569a4c48fb01a5df6c62ae26e0705b98ce5f64745d4356bd27dc335f07c00304ca08804ed04294771296f3fbb55a8a09b6716e2908385bd0faf9c572107c2080cd59d7d49609412db47757072775b2434de14b516c14d5cd8a91b8f500f5d1287365e9fec0b92678cd43cd97f6eb3344a2600c1ec4710c4d320fd8a52811ebcd35495172c184627153dba8dee136775f945d68ec2e650940cdaf3dd58dd1bfd67e7079b7b5cf02f3df3e21943ce4828b03488f3a436e0d487c87ceaa2ebb08bdd9a15005c4b4953e88caa3a669731dd0df4f13dd243a6c1ce2c891790a5fc33f3
|
||||||
|
h: 180
|
||||||
|
m: db754c5e29cd56d09d53bb8686ee
|
||||||
|
p: ba2df3cf83588c1d78cde00c50968a4b296f234929c18b00c64ec69e5552cd97ff2af464d2af6279cc6d8904edcfe4966a77f0e2554e60772e841bc69d4bf974e87c99e7bed40f1ea7b428ff3b3e9b07f1166df60a43513233c20d1ee7e76ff277a9fc72a0ddddc667ecaf98e1c0d5c323dc8703e4fd35b872e42d87679979785958c30af350c09549d7b98771e78f7a76f26652f00234f88391b52d4ef6a82b53c660ef074609f7aec8f90f4b60a4e333f5b9112cec3304d0e7eb829e2f797e0c2b6ca71d5ad162d53a3ba43d9ffb88b29f9d2f4bd2a8b5ae4345f28fa6ff384183d104b08851870b4007b6afe62c277c01a1d3ac3af65c9ed9730c19346ef1
|
||||||
|
q: a5fc20c1300b2e62e3707225145a87da26b33de73ac86c3d77d797e9
|
||||||
|
r: 2e32cfbe4943be369917cc83912641992716b5b46708e6631b71a5a7
|
||||||
|
s: 6d920908ec2ad831e7a5d6981d27c09c2b6c67a4aed42387557a1cea
|
||||||
|
x: 6c33715a34bce82fb7fe7a0c00c121d606519b9897f97399dab7a253
|
||||||
|
y: 86a4bb45980a1b8a8da6bdbfcb0d7195827d1b2acb3dc6b5c3815895c81a124d17f1edbded256515e0c259db4e3fe10bd942ac15f5a6d186edcbcefc1718181781e0a9117367fa370b699fb0902799e9e79e8a57114f8839816aa976705562a407065fb2889d1f3c8a820e90fbe94f533b19c4f0be356e0baada311940d5504c42e8793af2aba43a14affe5d2fc5e745489ba8a48c1a720f70364d59eb969b4d3009320214b6f691d275d9ad33aec25dbdd6db4f4a0f8ad15e016f5b0809937ce1b0f4409708ccbed0461aa3a0fe7804e3fec9450a60423480af158e9f03a0f89d359c9649d9ebc65e405f670390188fa41fb1f2717627fae0cd4c0454fbe963
|
||||||
|
g: 86bce785ee3960759ba5a21517cd9f9a8d80ade9ca433927ed7bac05d9d93e6492cc7a9cdf8ffa539c9f3bed7be29b3b9ece6956682265a6c76e5df78486d510a804737b4285fb99fa16de20afba6a35d6605a1ea94dcedcb4230cf42c617e55d4746538745d4484a4dd41167cead25b91c9be6d6eb13e4e10cec30e4177f1fddb96fb62eedf3d66ecb2871a91242bd7c59b3137e1173399cb4fd5f42a5ebbca0bb0f595ed28f8ff4e125d3c1159ef4fbfdf6a3a7603860a28c499ad53b9073c4b30c8b671c7337cc77e3a982728949a9951edbe56162f9a1fd4c6504b64fb94b8f48440c47e8da5f61831bd1e8a3ca42cb4aacaa4b3395ccb5ae57b6d4071d4
|
||||||
|
h: 100
|
||||||
|
m: 05b6b23ab73d35c686c61684fa67ef8508ae441bc87ddb1a795a5047e0d4
|
||||||
|
p: c7733d50aeaf27ba860c4b3520a121337484a7af361d1d2575715c8e86168ceae5a445f82b98e4c6bb124795a2663a27d0b45ce3b3c3259cdc445b60c80b714ca5c548a0b3706c9a509ce8448e60c93b9789baf862ab826d892e74a3c07bfcfe5d24d0d55a2b08949e6e66560dfefaf18d4fcbb9fffba5435c46f2df719c7c9f5b0707eafa3c291cb06c7f8bec7a3eebe726a3e8e7b888ab27711be5202a179cd754e6e7baebba9b261ec95657762f9a3d68077be7bb448a4d2b98e80741273f107a7310fcdd5ac739098566e1c9bbd817f59948651234038a1b83743d95d52af1a1491b7d3003e5269370d26258cb656f5f195899e945aed684fceb03327a25
|
||||||
|
q: 98a603faa78c4298c2eebc636c4b98af2f842be6e6d34a10d3c7d24b
|
||||||
|
r: 6184147c3d5d60681e15cea03235af9561641afee5dfde0407225cfb
|
||||||
|
s: 7fe7d07aa35a9542f482f8c2c48aa5935ae13dbc21c967a47a8af792
|
||||||
|
x: 93f4d5234803ed56b01b8b37e0950edf81061990dae6b75a11f6906f
|
||||||
|
y: 81bb903f97b689b28fad927f5ec8a79cd6cbde1d7074cccf94d68b01cb153204cc23fac59a5eb639c7a4d690c78cebdd9948122ff108ac0645020a19f16388920906e00561f5a010a1a1a5bcdc2cb6697cd91fb14f3fec0249cefee1d07e1ef51fc0a54ebc552b5622cf031fca16acdf57fe0dbbd48d7324a8c852056f48bfbe7f9aec3ae49166314016ae01c28db6ea4ca8071c98cf74fc74c2418cffe9b0d644b4d4690dbc417c84cdb0fb6b6d9d48d2aa0ce3cf08efe7ea2508e9901af0bccd133a3e3ae793296e94d88c4270e32633a8326cdb5961bf6ae2cb7cabf202b649003ef48a172042c8bafa639fd3af79ff14ecf093a3351f2977b5ebb12cf735
|
||||||
|
g: 2e442eeb1cd2cf6e70de7b47378ea1ad08b4c59fb394a4df17147585198032839225757d981712cfa0c4711a6af7b0ac7146e0072d9d1e4828e64f1b0ce9222fc3cdb21847dbee96a0b2d033246f93ef02950d8b24d2f9a31ef9c097d9fd7cc889accfdaf962f690afb26abef329b22c5dc7dc44c3dd35a1d157bf17b19e4d4857deaa379bcb7b7b394b8bcc1a92b8e96cba5fe9fd54ac69e074e992926e22de28725f7d3508b582aaa73cf62a69a7b5db6e67aed4f60f81fee5ae4bc544319a6b8f2e027c73668b0ecb574a3dc12de1ea499116385d0fc9dc4feda09ffbf8e93aa34c4915e3b8d6eef0c49711d9729d1cb54e4f6bdf8a44d8183c9af027a7a9
|
||||||
|
h: 180
|
||||||
|
m: a3000550
|
||||||
|
p: b4be8c422fcf2f7738b8d7172ba21905b197dee42f8a2381e55409e93dbf091df3105ece90142e429598dfc8d73c485134c823ea2a665f53d36c5cd3791a7e9210a7eb1b768a78ea82e8d01185a75aaae32d1da61b6baf02969c8a43aa858fb67fc2f797dbd3e9f8b2d24b2f04c414b68c5cdd09e486b2f50fe8d4c93dd54ab8ab9bbf421e8b6aa139eb44fc807be228d2d7dde05bded318b80798b30dc97b1fc2ce68529ca9f8c4487bc0b47618899a59d4563c982de39a66c56b1340f49ad1adfec12199447e3e9e898e2f7c2f48c79d68cd59628b188e3b479a225ce6bc291eedd49efecd117a6830d951acd01b80dece07c056a7ea23ac687fba947e3bd9
|
||||||
|
q: a7299d55f43412914a78c2d8ffe7b299140a9f4417d9fb82d672b303
|
||||||
|
r: 7dd5fd7c2c4fab27936da13753844a46f7ce20e0923966712dbbca76
|
||||||
|
s: 8385958eed65f9613093c06fae1adba4dc9efb6e504baa371360a7b5
|
||||||
|
x: 4eedc9b1a84e2e7a562155d02fdc7b4f740b8e1cf7c7700256cdc2a4
|
||||||
|
y: 5958dc9f8ab723d4155c92ffa6a6d088d9b63d8e8837d57d808b9e1f8af350c941a29584c017e92758081fdaadd827e3bf203e325ff35e131ebc0aac492319c2583876b0a93693a012948c896c6d45dddc98a9b39f07b03b4e84c0408e1d5b497890017bf006dfd0d1fd7c0f186db30eb3f58079402c07402a89cc4acb15a2133bb11266a611b1cc3f8e29b02a67d31040da95d7d44b99e2605f471a96a82a721995567cd8337b4ccbd1b5ca688a6b1fa19da8dfa1e5d93d872ffa9c72048d663a17b8290119f1e3e270076f46ca05d55e4d2585f46b69cd6e7b96979bdf6e4f8776857f00c7adf4ab461ed062e4f7711f8c3c14133048c15e9aa15c8a9801c4
|
||||||
|
g: 3985beaabbc161d212d760d9c6a15a26755ac67b03671837937ecf649bdd61c181cde403f04d81e6e620b88709c767c6726aab332019c16a7d70b81efabd4b1fba145032fc4469aa77e41d3b3b983cdf1f4b05a1da0049102608daf29747270be366a6cde0061ecd978d554c2d77cc621bf5409eb965d48b745a1233afa046ea6b4cf4a0579ea1e9157c8248f3cacbf1ff09428476f9455f972c530b26515d2fa8fd62116467307bb304b83299e8c8606c1884f269fa54117f22097fd17aca12fde520751809bfa0fb5d7024025286c395a9f80230a5383fdbb0df2406f48b26de8837c6b51062ef0bc48e58a577a0982b0256f4ef1a4eb9d58eb5cd2065d7c0
|
||||||
|
h: 100
|
||||||
|
m: 71af351e12bfafaf688e721a5765530addf9f922e29e381a8ce2f6f6b607344c8203da7a5113827ec1a13ca683bd0987bf1c5167c5900b0c75a25efa2d345c41ac71feeac9
|
||||||
|
p: e9726b8fcbf273459e2b90864181d9ad1a2c9b3e11eb91c1bce070abb443d967dea05dc14ecc5963f8a51d9d58ced158ace32b64df2e5b37025efbee254097974ffc9ba806b88c1adcddd674f154489bc18338e76e65f351c1c6a515a26e3f1e35b2d5f0f4df0c6eb9855ca4816cdfec779fe4f4c4aeb313c70e5c480f38d9bf11bb742e90f07d86d89623798c4e39161e5350a9bc598125855bc707e1be3019bfc2fbee3ba6fcad5f934af34a996d3fc9201819f63ce521851d63b53daca4941801a6aaf7b07b25316b7e100e8e85fe13482b167bbb4022fd4cf625e2e586b70c51712159da85f4810c29ffc5f01a1206118d80bbb8ac14e21b8ec603e8d133
|
||||||
|
q: e3190e6a620e4d90764ee55ee395475ed0850ce40a35681df7c2d99f
|
||||||
|
r: 2d4f4f8d65e2309dec3d45a2958f161ef072ae323d9492d42c993ad2
|
||||||
|
s: ba64abe1beebf7bd3f97535a1df8479d5b0715d21f5674b2c41b8e03
|
||||||
|
x: ccd9bceee702432a7087d98249ebb29c6f4c6a8d560aa9e02ddc7f74
|
||||||
|
y: 61a73ae04dc5d6a97a60ee3077cb2f9ab1d1f3a89c575cdede58f555bb0b2a0e77a7b610fca07134c0ce79738d832bba5b0262932d6261fc9a2efa1db38f5c4300535a2d7fb05bd9cfedf3a101448881252b0098607d1165a1bbb935327ad31926205794d899d75492ea647cc1e6c8657242c06c71b1f22f027a9024e4da7ae4e8e9aa0a3cd52fd17a510494f4eda9efe1efb946d0744a89e23af552a1d554f15bfc1170f54f4a0ec28e5558c6e023d56a18fc9c8c5606d209034d1d6a5215acb2fbb42663b6c3520ef6ee7c19ca15185ec1edf793b73138c72cc46e712c90ac69931036f98c3fdeab7a3cd0103152023f66fdd26fd7ff2f9a5c9b5c82a3d6c6
|
||||||
|
g: 8e080f1ae44415033b353a103295ce461780b585ac73b4dd2c228e4ef394dbe8938cb4904e02ad6c80bf8b0df54a41173d64dee46869794757d0d5f537e93551add5116913e6ec75707557bacc6201735ca3e00d45fdf0557567eecd2c33b8ee0c16c9dd84b676c1f3dc30d0651971d9ded004ae6fa8bcb72928e28d04411d39c2553b9546bae92b9d2592baa7a809b061a3611e6ebe9491a09c8fc90817e6950741cad75e4ce359e6fa915059c9522b32e074a514cdeb565352aeb1c285a1cc43a703666410bc80cf76dc8099c8062892f0d9f91c90ad3efa296e4687fb0930be898cf9e62ac8227bcdfb08065571c7c71d301420554e5e357f6c5aaee371a
|
||||||
|
h: e0
|
||||||
|
m: 9fa8b6ad550f06912ec512cbf5fe6bf473e003aa3f91097feafbc89376a0b046d5a9a4da9e25fa193624197e97ed3124d3c454e4388853cf29011406e4b6d0a14cf334d0284c31111e0c5b4eb332237046a2cdc015e6a9671779c863ccee9040550847d7e7e67254fc2cdd8dade17bee877b137423131f4903abdc33f5a28c2e673f5100d4a9e75164d1c37fb9c99642
|
||||||
|
p: a9f1ebd3e3a97e9b365540ce652f0e1a7a04fbd67b59f30910dc868bb40aafdd6e670af8605be846e8135981d664449439b29408e825a9b92e35ca9280af46f40836b7ca4916c1dfecc599fc9fb99d9decf63b2e7fd19ef426702664a73c2bcdfc2a2ff02c5664aa9ebfc82f45f2dc2a0230051818c47eb1a36823686d824a94480d230369c8e9c65fc6a18d4956681af965f0f5ad86aca76b13aa83415753adf07da0fd147a49d444abd51e49d563ac40c94733aa02909c9a8de20aaa521e6be57c25766218b247b3a80379a3fdc4367514f437b56a490893b09082c36756953d718aa4ba7e35e72f89bdcce2726a30f31277f4d097527266ab5db08c1251fb
|
||||||
|
q: c48115bc09a3c4a8656517b942e2965b70ca315ae52397d8b631bb6f
|
||||||
|
r: 3fdb43f93dd63ab44e9e2d05a82f9230781aa20f21f5febf377a6151
|
||||||
|
s: 5b610f346fb2858f51386077fd9ad24dcc97efaac565b5a109bc54d6
|
||||||
|
x: 4ff49038bc04dcfd7ed381aa3905c6497f6161ad161c0dee57687790
|
||||||
|
y: 4af63ecd7d0956363d84acd2042a6bc348d4400bf9b8035618d27342a6807642151804d4ea382e192ba6182b41003642a5fee22ae6d00a7eb00a62f9e6c97b2da2df1bca7656a5812ab6e4f9fd172c626b7f8be565216f280441c0fc4daa25c4b30f7c8d8ac72ee7c4689d33298d06d4f1e61eef0b0c8599afdf813dd2e92abd846151509be395a767fd91f0e29364b9d3b1dc29e3dbd67b67e8e30837db7913ffc50a7aa8d9e786859d5c63afd1ddc744fffff558cde6bd98ad53212d40b13e1abaec215109abe68f77345338d0383aab9151567189b6ca08f6d5cfbf2e41016738081c9aa191b9fb482ed8eb405e8514beac41d5575af2260743f69860503
|
||||||
|
g: 23dc7e43338398db09937cf312f027a9e7739e2e743efb0fe327af438e23360ca00374222b530e9a9f1055606a2798e7801e0dfcf9ed6abda9b8bb9f59e22dc0f8b42d029a4867656bbf6c0dd506a49c732f55c34b1b115fbd56ba5ef57c21704a951efdf2d439d9570c1c63a192045e0fee974fa84763df07b662c26a9df5171b43283cbeaef0bbba4310c4f10dc1e7ab50933a2689823c10309239a86fbd8cc10da93feae18f511cb378dfea68ba9b18d9619081a5372433d9c02a6881c8e4af78294233c3351886cc9216cb46a9dfde0b5fe223f98f790beb09b8b4ea9df0cc6581c6bb674b52120b1d081c766c7d2337ecc40fd404759c527282cf32a51f
|
||||||
|
h: 180
|
||||||
|
m: 5c63c596f629d155b601501bead8919761081a3e1021b17e5e3f0d0414d2eb36f23f510f7ef4e9fca9ba90ed4b0eb35b26f58f9bc889119a7bb7b1bad834e404f5f0735a0bcee9a5ffd71212b729a67983363ec23c5154a4becf70bbbc6e0f8bb91c9c98df5472a7f4fa208753d6aa603eb51715d44744e177e0d65b0cea1e5cb29b2ee2b65903ff
|
||||||
|
p: c3c5ec55bdd1a0e940df1eb748b0129c628b57a6eb492f270ac8ca7531b7add68da08c5ac949de68c6093f376c4536ad38f5f84bbf09b066d327b9c0c8ed58ed9f8be9d80b8ad01650e09f2177cde2e5c76f300e017902b6d989a46b9759defa2f6f0468b0a31856049e32b1eb1f86c45d69587ff2c5b2fa1a0fe3c8d81cf9353817a74feb6c3752d0dde08e1689ee8e7870a9b7afa7826518017269021bfeaa48f9ee4a401d277f2a82dbf237f7f99a1e44d707b953ab56ea8b063e790e153cb69d2fb4c4f54922848d9e34fb5ea8e25434aac3ea037fa1ad1de17107f9f8ba9c059c86748907ba0a670def841df2ec4bbece9671933d8e2062dcfc67023c3b
|
||||||
|
q: f59d7b37fd04e2f3f0ed5fa43336dd951f2e3cf4b1287fc681c8aced
|
||||||
|
r: 7c1140bbf1b2aa6a9d8afcc8a0e7babb99e7f3b61c55c1ff9e634e2e
|
||||||
|
s: 4b68b54db6b0d6f912c0d5791177bb687bef89ac2c0c492301b87934
|
||||||
|
x: bf2526af70bc55f0cdd4c5c5617bdedb4f44fc56ca6f2604dd080537
|
||||||
|
y: b392c76b3ae14a2caa6af7553007a57ac21ef60c44797ac1c13ef68904df8b072cb32d0dbe10b2524243cdcabfb8e19ab31e82d693706f953bf29453325993b7278c7e99c09a666760b1ce5dbe36b56cc8c80a0e85a972f4c0076bcc0d349d3c17ee4b7d0e8257eb5aba5a4375929a0b4f4edc350f268c164e6eb204847bf24d23aa072c6596b2022fb48773f8538e3f85aa433e88330b302848a6ebf8f0afac665c98bb7b58ff11753babae22e0974f257bf4b6d00b87cff9e978a65a86cccd593f4c3d42b78142009ac8bf077f69b38a4eeef9c2d425406d06127135e6f5811e4f22f6da9dfd18e24cf8e589c7cc3591dd995e5eef7b07e38b3c99ae7bab9b
|
||||||
|
g: bbe02d890fd97e0b6b84d07e2e6a849378e01a3d2f78dd32b4cf0b80b51af9565048bf7c1e55512c46e41fb4f52623b95dae011567451235db9e216f6eae605951b19f932cbe98784e5a1b5c74b8efb554de8d155e07aecdecdb6e2a29c8a67700b70a941809e0e84053ee10464f947225040dc3e4294277af421e664ec90ee63779edba49f71ebb3aa40ddb1138bbf869c93bb135b5399b72b18f6c8127b114f80f1d331004718d53d3c959b927c5e8b50e54b48b78353ca2835032c10eab92930475d2b2cf7dc3b0f903935a6ae1dcce248df90ac993b7674b3847319deceb1e13edbeb32c4d126bc62c95d942a9227bb3b1c5fa7323c86d83499644908ec3
|
||||||
|
h: 180
|
||||||
|
m: c30aad0e2009b9dae759b38e15f48dbb960264b6d3836c7b28d1f31a84bc9416c9001e5e8f2dc6c5974141af76ed35c1e23bb852faaba5d4319c695d1beef19eb151279cd1d2b3ced4a9a6c921c044d4e4fcc31a168c557b13a8aeab47906da64e6dd3e80126690fc5633dd295c71e6208a096d8ffba2e0a5aa84078df1b0c639cf450aa02dde48fea0ba367d82764a248f4608bc8a2c9301ef3721d7f81b84b19cf11d4aa386254cc061ded39e180a7a3fbdd722b3c3d02ba1a5e682b68c34ae2c122477ca9d65b91530e94374538d824429bc1bce58f8bbf744403359abb96704d61cccb
|
||||||
|
p: fe8dee38db57a3da152612c5e8ada96f1a39ad0788a40cd2f72c338d37a04fd4698b4481e5040853d525c54810462deadcb9b9f11887124fe23de852aec93c36310e22b5ddc05bc0d713dd48f76e51bdc7606d764aa5e9d2413c894083452ddc395893ad576c018d17256c504251674231b045f818becbfa353ec82ebf7c88cc611e0c5998967ea2823eb3c14bcfc2eb642f40d390301ffc136fa30f79384064430ebbf437af76e8a1510f75b1e11490c5a4763a0bc10b73b61a21682266c2808c5d644a77ee9fe86dc450c41bb641eb3ec0f79ac9440d808b9abe69820fa7f4864b51d3c8b94041f37842abcc0cab94d24e84cc42a7f387c7dd9a2ac7e0ab11
|
||||||
|
q: afbcd117bc0e36ff2af98973b0d3b04ba4f9a3564bc7df9070c53b2b
|
||||||
|
r: 1aafdbdbfcd3e4264f01ff233fe2d5dc15b9ec922168e41eab6c6cf1
|
||||||
|
s: 9de80ab7cd1c95764ff830afbe573dce6768d82e67b76dae3229e1ae
|
||||||
|
x: 5beb69e84cafc3d551c6bde8fc4d41d535f486ff6ccbc16c0f33ff12
|
||||||
|
y: ae80b2d7788ef56f55fb81c67c1450a8d8d45ed8aa2b189efaaa6c7110f588f43710281bdd962ae523de629635f2bbc3bfad1f8a32e33380d001b181e2418de0b9909c8aa606428159be928fb7675e9b4eaeb3811de1f4e45fe431adb1241ce12d1430e5f880ee148604c6d88dc4886afd0bd710e523780101b6457158aeafdd1a0e9cdd4b4d29fbe7c2e883df5028ac19243e0a985df90648272ad8cdbfa87bbf1fd10846504459904ab46d977439af6c6154c10e93d15d9e68dac00da025740dcdc414cfb9aee9ab180b451c1a6f025a9d88535afd862ba10f2ef4eb69507cd1c5c80d4fbfb74823176a607e3753de48683bbe4c85d98f3da7fc9e492ad34a
|
||||||
|
g: b322f91f4bf16fad978a230d65f8dcc8a0e39c520dd81dc7bf25950a55b4410a413b1122bfbe0370876c511768695840f7427ef9a1c93312c554925aa4b50dd6fa66423c37d77fdece7e143bef37c0dba1e68f426744adcae0e9986e23caadf6a169d95adfaeba9ff69aa9710880ff429d7276fe0078ff2e1735edfdce49534a1fdbf624f973233948241d6139863860b10494ae957d8851dd200c64700d1dddeae72fbf14f5f6bfb0e885a0d9360671da190b22d315792232fc12e838fb0b4f901683e53c63ded5ab16198bb9f2671af9f9eab257baf9003de12681e900ff1182d80c69b37e9a9ab674dd48dc88f7020e0f083413ed8f6d35ab0e7cd86fcfb3
|
||||||
|
h: 200
|
||||||
|
m: eaa0c500986377044edb3f4afb03024b822f7646c2ef120b241afcb2f0aa8c1f673b9835f32c6f6f0f873b014fc3628b16c8df27775a4654d655b6f2f165eba548df892b0201e456e170aa3989b45c9dba81bc8851d00a19319414dbdcf776ac266cd3b3d07940c74ba7be7441c7227c15f7fbd8ee3fbbec97d5aef6ac640df79bec411acde25cca580d680573ac4d
|
||||||
|
p: da26211e21a3cd01bbd7fdb4d7a2c71712f1398050c6b2c3633f4f62b5bc88f7013140ddc4b8de7b86e4f85fc522efa9a0198d441610c4674f1b4e5cfda073307db97e917ca1274d588580d1a64eb31a50ba2c41846bb7f4d92b302bf312d206a5b7bab44375b09542647edf8d52b906442a21483ef2aff95357e8ecbb3b234b06f23b93a5e8a6aada365b366c24aadeb209a652c60989c3b35841a45aabba63de76dc482cc800f11539862611d375ae94f41431cd80432aa1cf066fea31ce4d313cb7023724b05f30e85089c105d9044a3d4eafbb9b0db2eb51d3d34b587063d98047972d9110f599a0a0cf636f1491b1e07bf937fc16e40e4143dae60deacb
|
||||||
|
q: f86719d2d44c3467f241aaffe1a77be6c2cec7cdf40852e724bd681b
|
||||||
|
r: 93d3607d57db2c3b09a6656903a3ecf92f763568b11db2db5a2e896f
|
||||||
|
s: 64158980a59418ede8146033cfa5cbf4381fc1f28cdc0bffc398f117
|
||||||
|
x: 4556f150c46a5156772f243ea7fdd1cfb40141facf27cd8cb8ebcf23
|
||||||
|
y: 7cc71c7a2b578283f858bfc158588811312600ca6224a86cc7d3911706aabf146044ac8243e42d2c1cc32b2b0771417e452eb4ca9f15aa4d6df1c45124097a9df3d9a3ce9f5e89c2b7e8caf02cb0a083e0b5332b75ad69ff097615fefe1b7aed604dd7b59b770779c6a3fcbd61b5598d122255d8ad67629dc44991fbb30e59727a3bbe6e53084b836dfe91a9dd03a447d0ecce13aabd6b498127a023a214b0a522911a353b853f77f202db7fcad1f212a1a9cfb3cc5be885d29740e19ae9d73f6e9873353080b3d35d05f994e592ff0024318b0b09f9798d45f20a815be52c7bbc75a88a348a7b93e19d68bcca5ae1f76171130fe7b09f4288d95b1ff3256912
|
||||||
|
g: b301a7e51a6fce40ed388a5a01285ab225dcda486a3fca99be4f1305b98529dad73dc3cdde986b5de3daf925668db5161c0f4f64737086d1db01e7ef6ac5007a553146025314ad69755b3ffb8763b90691519bd3ed85dfdc68b3e610e9db42c04fdec8f371f1f7173d59ef89d58ddb2c8d4c053cbd4e299dd2a973f5d849f3d0717385d3dd0675ebbb93a5ec2cedc3d916caebdff042903c51d4f6671bda8134363f52c8a901dd05551a9da8f4ea83628f9cbbd4d91d66d1f361bf8d8c447a3baf897e27f82e597b27c93ef118f0740601ffba40d4df5496663d55ce5eca53230f6db8bdedfe1a9211714e5faf607aec196be2272132d023f48a1c05695b2efc
|
||||||
|
h: 180
|
||||||
|
m: d1472adc75c626f4999ffaf2c295c51ce377f0b74b7d10177bf06c85390d6bb805b0d131c0c8c26d1b2a1c23cc77c7f67fceb7fac17ecfa94497e68c028058292ea8b25039df56fe51020888dd9b8cadb05d7e66b419a8a2fbd8d424021a1b5d8b80fee95d05d7c7a5af00e3e57af3bf52fd80a21c3aed699b4137388c88b390fde55fe9612f75ab0e25a8d7372c692bf519fb5786aa033b54d9f38c9705eb0db1dd5d0b5efb5b57524855a0b2b591f12456993a849859c74e1f6ef1d653e757825995ca014685c5c92ebbb7de686a685130853c09368281
|
||||||
|
p: bf786720318141a69f9196abf3fadc5cca630ff05b175d1f4e0a0784051129b25633b6de6c26547b2eaeae602eb15fe6ef5b5ad1e1d5a12aa65304b6af9f4d947bf56ef2d2e843ce3dae76d3b35abb7b1b6a7fc4618e719ca9cacb9a18e92ce4656ae404445668c299e5334992a49bd43a3a44ef2e312e486cecbed47c6439460937e485cfbc9e00e23c3d894af29ce2e114d1fd1ff567b1d716e879005fee7d6d4dc8f374a62b85c944a0f541bcbb8193ab76831e1b49218d22a52c777e89cccfa25b9da04c7d212ed2bc9bbc982d7dd1f099a6b5126be739c48ee6255d080a74ad8f30bac24d333bb767a4accc47f19e9f2b1e97792a749f92ef701c5452c9
|
||||||
|
q: e20001d8ded3f10e26f06163eec1e0fe1f59656874f9477c264bf8f9
|
||||||
|
r: 2d5582712a96dbda319d8c5c5c12927b891d66530d94563ca1c9cc69
|
||||||
|
s: ac197e0fce92a336c24313c6ee013d5d3c36a89716b783fb3218ccd4
|
||||||
|
x: 692bc821f47bc5a063f77c8323a7e41923749a924dcc454f9f086e5
|
||||||
|
y: 7c1c48a6db0c8f6eec09310c4c44d5816bb76d24cfb305f881b1ec637b1355155b7d40dda0f234b9ade1587be34127416b80a5de69b47580d42579fd0accb81f1b34449124d57ba4d6876a35916eb6d7e3470a3ee36b3b7018751c33b890edbec3f338956edca04bab21513890efc09e284644bc2b6dbfa70232f876b8768e00d58971fafc38a56d072fb633a9f74f3905d00d01d9185f6bafcebf5f40bbb7c9eaf1e941c72a265bd27191cb28e9364fdc76e50a9ab036f5975405f95f88a9ad70dc22514dca36fa3836feba2694712a9acdad031ef7e23d3d177b704ec02c196d9bef4cc7397a59c2e76a0e1a0520e66b89ecfcc93fe635bc357f9147b47eb
|
||||||
|
g: 3ed7b80b330ace5d9272c0b02e3bf48a3c836a2cd16178df6556dd8be938cbed1504087ea103bb32b789a4d807cf584921d387aede92294a05a8e6d76875852aa11867ce9a776f90c626db3c003c482ef1c1871832bd240f7824d6f1fbb51966e694e8cbd31f6b4d0ecd9adab5eabf1c51025fd5f8bdc51094b0325e54cf3ec4038622e394734e1c5ac57307ad1a4546d0ba043199ad9d2a1349bfcc8009102bdfa42d750473a229ebcdd83d5d165366f187f9ed7b134560edea5d414b2559dcb2d445c1e27792261eb45016987fd609b25221b30efff4020f60e7d39e546dfce4fdc56bae6c9b4b8d0c1ce684ac3ce70f951fa571e7a3b4700d6ec4bbf6e9ab
|
||||||
|
h: 100
|
||||||
|
m: ce6d8744756d63c0536cad533393cd50fdbd7c563849989f1bc1ddf42c04078558f906f17e934581a4609a501514e1c083ea4112c594a140759c7a7b09e77db62b3cbacae1f1554f245a59dc336a552eb7ad332a11a854f2dcc7375cb1f3e970049c28b30f8a9b7666386dad70be068633abf6168a4962c40ec6ae8e0b74ce472b4b45209e3a91eb7740a306ab352c8eefc23bd09712843c8e3ebf045b4413788352a7bc9bfa6c6155790eb7df94dc4e3f7933e70120fbfae2c6d9eca41074ca5e155f496ae2237b092bad5936dc3aa8e41c49151b11e14dfd89fc1a5cb8f5b1b9abc1e5d99780168a12a77b0af089b3bd69241b4e
|
||||||
|
p: d2b2da2141a925888d0a1f06a1deee7f912b362007a9a2f8b7c1af2b80a7223522dd2078f6a20ca962054272a33f10ecdf20d92e7756c2b41da66e3b82b7b04657835160dab105c299e51bb3863c37be75e4320ce6e3e73cc122fcf38beccc52bc0b59da29fe28125da6c6618d96998463edef232441cf19c089add3a376e2803c7ce000d88ee4e7c048fb95a3d0dbd41ff20064441505953e8dffecd9d9167829205603de5442d23880efc5322324d17d91a53ce0c2f3da567b852c4b00ff0042d67a78e3890177a717627d4a8cc2829bcb1fd6ff8a25b4029c00a47511fb58bac6deac28d3188e1032478e364b9f74df9e49c01b6780b7b06b1e074d153afd
|
||||||
|
q: d5f829f40008fcd9e3ef888dd1b47f0100ca2e68fa12002e5be92f27
|
||||||
|
r: 2e6f4720336fe39ae486e5813bbb7c66bd0bc27ce90f1e3bae64d0cd
|
||||||
|
s: 1b9d7e3b00f021ec8cdaa94303655d95a1bac1267d1f42653439862
|
||||||
|
x: 298ff401ff461420c3a43e2ea18e1271a77b58fb59e4340d2f532c08
|
||||||
|
y: c533ac2fb59e1d1827537c70833fc65625fd813c121e89ab2154d8965dcf07997fe6f86000bf26bdb5fed5df4c751a49397272bf140093decfc9935afc39f38c3a21fe59a8e6f918b606208116af3f996eada0c02babf8f3ab74fd7bc8d186432715ff8d8ac1591fc61c6ceee3452e77efc8befe1dc9abb5c77306889a45072d3efd63d4395d411785d1993275c90ce481abca8fd8b68b9b47ef37e58dc66d3acfbc214df4e21a8d42fb01d58aaefc40cb0bdbd102f00735f0dcd3b0b7c980d8fd91d59ddd9e42e0ad49afe275ea55c2a9180b747e6bd6ff6abca0dfe521d30058e310486ac9901e8c6c71c3b1be166380ee1534cd5e804e1b963c5c2fed59bc
|
||||||
|
g: 40c4edfcd24c5ab77ff763759835ae547b4bb1f6ef41b709a5de195bb1beab3488b5082d0b15f4a23adb8008f743ec585386ca97ffd16275332ba3f7150ca0ec2af66f1ba6deb1467c526d376dbf6f3e90d7517ce61de1299814b346e72f581cf89fd14d3a4240296efc3d403058f07586c2a4b9eed2861697bc58986e26206b7528b9a05c1a5f71ec3e52bab752fb439501ac1128f554026e48fd4d92c6007c214a373a94a0918d1a0ca5afe52006e762dccbcaf3890fc2d98d2f640eca079b222ca7f6caeeaf47265f068f83c73c9cbe4e7071d9d22c6b071c038fa727b1a26e3b34a4edb84353adb37645c1cba2dfeaf4077de8ebf2100e7222dbac9c0cc4
|
||||||
|
h: 100
|
||||||
|
m: 615978ae7e80086e3f99c5537e3604589a6d832243e6223148d286360090e517a8387060d93743a47ccecc5ab25ed9edf9fbc0e68c3e3a54b69a36bf4d7aaee138dd0f9ab45b2b0eadca4c78f826e86732aff3dc4d68d0f737c0bd6e246b503cf0ebe83f9637788de9d46e4932d1b1a21eda9d9bdb65d98ba7a1df04db2acfa57297ad229ab578fa865d93c93bb4de128be2e671fb7a6c062c29cb6a17281b4f7d1a2889646ff6113c0d896f2ab9c1
|
||||||
|
p: d205003f44c6c0f33b299b4eb8a05b3506f512778f4d837f8bdd3f408a783a55d674630761d0881ba5b61a6cac40ac55f3e73bc01196660880661b834c59f9614b20c872a9aafcf867078b7487d688335803cd581622b829d39fb9b807086dc30016abd7d612c815ada6a98a5dfcf3f09812edc578d6d36e2b34d83fb478a1afaa9b6a542ec519b3ff8efc85b43326f95b2da6c35b999ee1c7616ae85b4cc1bffef17bc44bcbe78f38a312247d8437f49ec001c8beea62f77eb512731e9a02835a99c207845497939f7169d8d61486c910f00410553a6ecfa11860d4a6d7b2c1d01390d5fb70bca57cc047caa3fc42fbd90149d87e0827903568030b398a2d4d
|
||||||
|
q: ccb1cd1fb6c4ede3d65f0a2cefca3d507a5f2ce43f1e9716421509d9
|
||||||
|
r: 88373ba66c99e37e053832396efc6d26f604fd835e859e8b8f1f4b53
|
||||||
|
s: aba32b5d785478ac6722dd52c0ef3ff945a4ea28a53553f8c3050bcc
|
||||||
|
x: 89d4394c0b9741544e300d51c0544f6d751f4b9914b9a5681330547e
|
||||||
|
y: 5a5cac7d833e331ef7e41f5017a869a24b8760e19a4e75a33ad593b2951258f784879c17bfc0071234f5014eab40b34ea195f60b2cd772d2acaa7796a5e4b30e33947b77e9616f6d016363c9c6d2e5019aabe854a7b29e837c6f5cf6af56f44fbc0ab08bc8b015f6291fd74a54f8691a8b2efdeb4a9756864d3376ce53431d6cb41082f569c2efb417674fa6ced28c21f34dac9e07f17858945834eaa4b98935c9583eb2e7354b978f18c414fdecdac6960c6c553bdaacbb97772709a1f3d61ca5841f367d570a7c59aa73cd26c891da647a4774589cabc211b6a75eef6494f63c83285b8ffd559806a6e2205498f54599eb055d9d62dbd8a4b71d777e3f0c61
|
||||||
|
g: 1a0913bfe15eb8cd01fcfece7bc6222835b11f5aa4fe9ea24e7fb15ab6836e15ed2c2b6d5920538579e08059df747626b019e5ca60440e73e1ce18a15b72d8a6698d479ad302113e79bfd8bd60d0b517db8aa1af230462a7fb5d14600d5aee7d4fb54028a1a21a51e0ab8859c6e6782445c0f0d8d9581579c81393c149c6a198709ffb83a0ac817bf883f6b2be6a349f7741f6c028b99f047a879fc9c16b03619f0af79e2150a6b9eb9873bb5ceea4ee9e5e6a0bae553f7f7df1b8706bba77761fcc60f575d3000610c46560a89c774678a2e66f2fed58f90509036124537277dce03c1c31b55dd72ca2992751f1f356c9a6430e8866459b41b2575d1b0e347f
|
||||||
|
h: e0
|
||||||
|
m: 821fc31ce0dae4e3
|
||||||
|
p: f75345e63e5ac46ba3d1cf9e7bcf1294cc811b3b1e92f6621165898f6e9592bc755de3fea50229a2fa619c813d5889d15579b04d85711128706bb730e60766e2e684d4b3da3f0849ae170954f27fe19caaf6772d5e7d5ed13abbd894f538b87d59c9a330ab617b70bbd56390cb5837f9fe2687a4f148f444e917c33d57285b91aaed34954ff2c66eeeaa77776e5fe40efd769f738a597f5b6199d536cbcd0f681b73ed378d3e3a79f37c58076cb0af67b0c361999d1e19a388904583f32110fc69df0f2595823391a07521e17bd2fadbfba400d366ed5553aa81f6da55b48d77d6737e192420dcc292bf62820507fe48a7df8f9918d6d974089741220d42a345
|
||||||
|
q: c409444821c410f31492725974f63e177891085b5d7865c5833a2cd3
|
||||||
|
r: b96498bf7944f31cd2a0c9b7a9b4bf1b0ede948c6b2606b2fbc06f74
|
||||||
|
s: 303b83241abedc19eaf0675f138d0379baa6c67e8429a4741f90a60a
|
||||||
|
x: 8c80c4b4a8ef2ebe319d16a1406845e9e88bd3c9c4b400d4b4bc130f
|
||||||
|
y: 1b156194a993ea73964f56d1a0f4b79266f3e3fb033dd074e18812ed29cf5d9f88b192a06a7aff2a135cf2c2ed3f14cd82813beb05771a69d62b0444938e6b7e0091ba8e992ee03ad0553616928ea5f7ec39f2952b6d75cebd0834d9ae22b30c491b1507378fc99b55488292a6deef73493641a8447789e123f12a4011a176814f24348acc96858714be6d6c461c02dfb45449ccb7096146d721b8f2ad341dae63f1c3fa3e9eb6a9e10c69a3cbc6c98bddb5bb4c5e1e005627c87ffc0685d30580276a81ea7e8fb745dc92f71574c5b50602ba73b4d1e6ea8969aaed52b76e2f875fc103fd54900caf319456336242247f233ae8eef3c7abd9356369a6c36d03
|
||||||
|
g: 84bb8c33660c6d36ce2fd5db0125f77599d1d1ed8a3c20be3e184182ce7e46744c6243239f897d9e41ca28ddeb3a94996871fb8fd3c20090349acf67eea6e94d40f645a255f05229ba32b67e496c327323b509c8f278e5efe79c1118e354b971678afe22121e0c4be8c6e40415215cb7f42703da5c34e0881b1521b3c8e53c3a23087b63887bf7cb5e0ece56728485e6afc771d83974505eb239e23161129ccc0a0b979cac98003070119dae49216cf216dcd08a7d1802642576b738165d2198d205a09eba54b05d8ec20a2e7ade599252bc3b315e8cdbbbe881b447ad5ee45934808b47ebe09e7a9febcb07b2520d573b1ec1a858ef2886079769d6b0d0e0d
|
||||||
|
h: 200
|
||||||
|
m: 6d8a6406ed2b5658742a0087802a31d51b54b4b453177d8b031ab226d5a1ea321db5775ab140870ffdfb54a1c72ad5e1a194c7f76a7a1379eba1ba6d587964099dfb463dc5342329f880b570f7578ad30040942c7ca507ffb6d1240c7caa3cf4489ac76cfb5e972d8fc94f60d14e55d9dc71f87d0d99f3bd7e3d1a423605637afe186e95cbe2eb6068d3df
|
||||||
|
p: 9c4e42fb45b8b66264a843691c88044e4eb65414fd174adad0c7e866d550195209438a54bda2260a0c86a619d2d02bd9cc09da948b9f8779106850151a16103389fa2649878bd1d615138e8aa7c215721e84ff2cc819f534bb8fa026904d2d84821bf0731ab2106de914d4a2d17438606aa10016cc5eb3597b75cc43fffdb6360d9df891d05354d5429ec84c87ff5d51976c6c9559fd0e21dae49a7f131d703e18c0369c6aa87a4585f5aee1726d4829d8433d2a1d9c745c47befadc1bdc7a12c3aba473becf22d460d38070eb9dc8d644575efd2066902dc9a516d688e113e595338f5104129910d99804ba882718f1cbff057833188a477c611c14eb0b10b7
|
||||||
|
q: 95ebe86036220d7015467eb80d34a5c59715693658290ef9ce880c31
|
||||||
|
r: 5224fa6e33f8c977a985680abe9fc6a1bfdc18f54013e9dd5dc56366
|
||||||
|
s: 733561a1612c23abcaeae3d986742fa8d38c1b74cbb2b15ce20047f8
|
||||||
|
x: 936969f28045210777ce40c6b0e06f3917d806498528fb972a1652b0
|
||||||
|
y: 2ae2fe2d77f70bb36f135f84cc1bd1b2b81bf1c18278d87190b0255fae2d342ff6cdda577ccc609d6c6ae1e3a8394525c562ba2fc303ff133fcf4e3c33a56c58d0553e3511a16e172235f99437b3e31f519e6b2d68a70985d2af462fe454f83e9cb5bdf639bf3b83532d731627dba60a5cea01ef45d4d7905930dc9a2b2e68599227d7156aa45ea9d1d28ffd88f0ab7c82acdb13dbebb02f83e6ede89c68843238bc77f7cd3598506df71426b5be6db4b86f6dada3c30dff841a3394e8b8a45cc349dcfb076d17347e9198732c0e066f670bb95f663a8d2a920dca2a067e7b4d84e8b805922767ba58af3187d674dc90c7615ce7c7185f7fcbfc13aab1f56e00
|
||||||
|
g: a516a43b28074552dccac76e1f9153ef5d979d400d51a16ddc41b659724aa0c577c3f44675792fdd0c0c85d42e808fd2403b4dccf3771224832ba8c4ff9ba5e60cdf5190260e1b7359fe940d711dfc6346fb273c645b6ede5872852bb9f0cee715ba3f2fcb77c1ce93a3c6a5d1b2a1ccf1007741fe13d8ca843c959f159382a1ece5b6784153dbd07853040964b6f7b6336636af10aba97e9f2bac124dec3be6dc8cf6d8e1382103bd4a16840750b87ec4f2bec8a3e9c9bb675f8fb7312a7ce2619f677324b27ec739601c9fe34f7d5f91c05840b9a35f79e7ba51ca93c2e226ca562f8d042d8fe12301cc2299bd9cd2cdac33990d3fda9a4e671071ac77a001
|
||||||
|
h: e0
|
||||||
|
m: e3aab0b8b862384bec053ccb80710e28ae003c7a32cc37eada858f9595d5362af48c64e444c6fca3c9a45e779cfdb3e28a248e4eedd38972347a586ab62e93ac61d6d9b847d84267dad39a1f694acdf85a2f372b4a024b72d446220f1d18beb5b01e6758ad6f1bd017cfa23b6703692576783ed4ca094ee1cd29bded021d793e256502be78f22ae35a58631629f578d6770d87d3963b7530dbda49f6ca6c2de3183d4359d0494e3778c84ffac9f9ca8e76d4a0045c68bc21c87aaa6463d9de4b43397f26116b6c5b1d8331fc2bb7c7dc
|
||||||
|
p: cd8cc07f21148cbf3cad498b37263bd63f8e6d446502fb6c84ced77f2007df2cb6451d6797718ee077234f7f02e5d0ee39c55d1cb4748ba501b35a1cbf468a40d782a6717b7bd627a8d5ede3ddedb16b29f29b45b88a3b92c879e97b26c085ea1409b857ae94269d859424d748575433015e8a86aa9621712667cb972570a090a687db7b24df02295ce432ee6d59fc3d6358a01d5322d52266b23d6e467b958f2bf0c5191d9669c024d9289f67803b07f169f8451c4ccd5910f0da3e781dafb679ab39d9ee914c61c38930f82c34eebef1fa38ab29fc5ea71bfa9423f0370ace21ba1d3fe045b1d5332ac5526935862876a100972cb3703bedccd68d772e3221
|
||||||
|
q: efb3a7833360b01d1b6c3cabe3bb2e9ac22912ea4a186f9f424a5b41
|
||||||
|
r: b01ea3ef5bd2ca0d14917c65457b8575f2f99a34396be7a5ad3f7bdf
|
||||||
|
s: 17ff9400f24a467e9759978f67236f9933e69ca3762801dcc55aa35c
|
||||||
|
x: 5c8033b048dc52b7129f12c003025b2e72a8625478457c279fc72b91
|
||||||
|
y: 76190c3ec95dab6fade064480e2d71795c4b9cee8628a003da18d823a4bb69c6b0506ba492f15096a84839190e4732b9cd667726a5fcf8e619d4766a4cfc2f42f5fbd5ea35170d75328b394d06ba6ec5085b88aa331932f9800ccd2cbb295f79492453285647df30861c750b02b7439044ac1c3e3a516a965fb8e516e60082ba7bf23121e52b2fc40967a2db888ba11e299ee2d4f1d4a3ffbd44818bbd19011e667e8c7d817f9e72dbf448eda75fca44581fae7c54c624f8fc169d8ad0a2458f15aeafaf8c54c5ee77a8e60839fe6ef03ce3f32cdb9f9f5e66645e470f78cfb8d28f8b23b7ba49c2f774f0dc4fdde6602b59dfb5a45087f6ef820d03cee2606d
|
||||||
|
g: 43ed94755abe2c8cfb5a7a2a0af3914721d9f9471023a6214c849a1c6f7bac2efff355edeae224cd974b6e79191f807e533e9347e8b5ccefb771cf40bb32b003fc23f4e41f8f1243dc481aeabf22acd96ee06a12224fc96474fb0f1f789e302d55b50943b69afd3d4d9687cc0143f8ba4c9265cc134752e3dcccd362278f130e8a43e05d5ba81827e46d5dd5d0a186111cad85d5869dc07c7f9f2d6a7ca38817d266716f8b5b31f7b3afdd20f2151ca66b9a4d8c66a0ccd8bfc8347545cb6f05a55d98e1608a36c2d6c45352920d0d769801583bdbb30bf227bf19547d56ecd1749436256b80680b831a0f7513c6a2d21191e3169219bcb8b1cfb7d587ce2383
|
||||||
|
h: 200
|
||||||
|
m: 0b3a2b159eb6b90a85487db0e86ef3e48c40221733a5c1e9a74c00b4ece451affdb56fa94bf3453d613c63e507009e4c93b4246fac
|
||||||
|
p: a39b9105d21606a6964fea76245e06e866e3924be90c95b7e848aab7f9f7f84241263f336cf31006c191d0a9e0712618fac04444bbb1dd090e0ad8ceafeb6c158094065d0bf0c838d33edc29d01adba3dfbd0cd86a465c6d9fab724b7587cbc133a0ebaa4bffe09cf7d872a77445694cc16ace3b1c56956ef765e48c327d79d3628410e46bb378be087ab8b5dc3897ada29826d0d334495f1eb9a504b835f4c98d66c1870998fe8d0a96194efc5b42057aa6f09fe024a92a237f10414f5942f5a84dab005531731fb67ae0e056e7ccb357c3b4b7b93876572d35d7e8c02d5952e500ad60cd5992eba41e75f10bfa56a2273397374d8c0704e567c4268c3b770b
|
||||||
|
q: b00dd8e0d21e3e4561797f7edfa87c111a06a6a6e94f249d108f99d9
|
||||||
|
r: 649654fd6d60871ae2ce2dcc75471c88aef5aca3e4d5910ff77aca19
|
||||||
|
s: a2f15deea9d7940080ee2ecfa65b62c42e953d37891a53c1cff171d3
|
||||||
|
x: a28fce73421fcc0ea92950e6a4c319d89e223e73a441f5d1afde8041
|
||||||
|
y: fed9a6a1c234c8fab3c8de87090be7ed462a34d1e97edf180f31ea264f9defc61e004cf5b5ed4a72e3cce449cb8993de1e26ce3bb9c849ad63f93a31a4ae2c7f49b137d44933fe1dbd26feaf5e3b3289dcb1885e2115950bdb2c6d7b0d05dbc6b77f7f1c8cde0f0e7bfa2135343cceda1013ecd93b4f774e5efd4085223a8871077f1ef1625079a08fa8e99d562c9bfa8dd60c8e689a84c071c2528e64608e6b9faab20ec327542d57ec66f093624a24a7a493715c62f1bde8a87b939fbab8c90eb42bb50ca6a652bd554d797ef54cb23b045af41d24ff1513514874d799a1da05fac75d6219b274e969c5d37ae5de5d6724025addcdceade19550ba751ba94
|
||||||
|
g: 51728bca97842ba96e2d8e4128ac60faa009adae876c0122f63165dee396adb692d1b7b65b95aabcf06bdc259c1a630a0ea9baf80ad3d4f7faa91e3aa1a30d00c762068efd4f5b75c4331121209d06a3eeede04c5ec5a28208fbdc309f86c85f11da215cb727cf88eee1cec488ae4e927724034f08b2d3cb942292072770bd2d26e160b12811181259ea160d55181e17a84a69d5bdb31b415dcd50b65f28831fde054f069402056af102dbd06fecbfc85413aac7a642ea3802eab302e1f5e86f294f2fab8735bf6ee434e2ccf7524a34c4d9f23ba323ecb5722a0fd334a4276c8482e8e0a5d773598f84f3b1359bfdefbf24f190edbfcec192843a4dd8957fac
|
||||||
|
h: 100
|
||||||
|
m: 850d1ff994cb6b6b3fad94bddfcc95a5fbc6e659a64b24d129af6bf80c3e13486a7a0d230542e4df16971eac2ac131de337143af186a2494fd91111b61a6dd467616d0b753d351956cae81a59e53fa8056eb7f5c899cdaf9ef5b57f340bd14be57fb801934aedec0460252f568edccf751bf1905e158c45772c5098905edacd761f9bed68389f25661f320020542caa70a08036b3e0bceee57d119be9fe96fa1b9a8315a730187f77e061a0f76a5fbb833284e4bce9ce0d81d68590c21025d7a5a7f205b43505743eb7634fb7c35105fac77974ac269f56962208ea34426714c24
|
||||||
|
p: cdbb297cb234931ac0686b17834760cf7525a46553f7c4553ee55e47ef35edabaf2cfd5133ded833cd86629cbda0d8d545d38baad4432469d977a9287cd1c9cbc2d17802ec65ddaf7042d0399efdf17804fad10fdd41fc82b3d73d5228fa47d296c37f78b3bd657618c3220530c62b02a19eab1d414b1a42bf0781627946094ffa8890d3b620abeecc762eefc30383be9602faab66fe53e542ec79c3e55f3c7f4771c2b0017040c44aeae537448cb59e7873e9336f295bf0a109a0bb21f021f140a35bb63fb04d193c148a05bca25a2676b137819b19c80b7d3b4ba41c5cdd81cf99ae7b4e623d49ca86ba7b3a899bac79a5467a613130eef2260cac02e6ff13
|
||||||
|
q: ceb64adbc91e079d692bca8aad942bd126191359d7fe7a91158033cd
|
||||||
|
r: 4ddcd99af2b5ebca3f13adcc9edba0ef541a14ec7bedb2faeaae1dd6
|
||||||
|
s: 317b3a61d6ec00a59319d9f1fa948d79143c857261f7a227b83f3eea
|
||||||
|
x: 6d76dcce94dc2c941040f3244fee951fef92cd3f7af31097a426bb3c
|
||||||
|
y: 9a4e23beab8376d1e41ceba731e11046f0dd77bea7b6ce5f21beb04153a7f0fa86c2cd1feea941e3afb0c326262ce24489022bb971ebdf8f12ca572ee0f1a9130be4fe8c57a89d621a19cb9723bf3789f0f909000148e87f673374752d40e60e595e1e4942dfadee7441234ea027ec98c6f67c6049f6818141f7ba68eb60e14b48b6adf15354e77bf8e0f8c9389492976889dcb228163fd57a65015574843074cbb8b205f3f49dba417fb736157ddaa2c56dd0e923a449bba48a5c8f1a6880c730ad51bed9a4b0651bf4199baa4c987d3fcf2c94bfe12a8bcb6fdf6f620ba03b3beee6b19eb96410602e66625348dc00664deb0586fac30fc48194b07944dc41
|
||||||
|
g: 31a2ab38476ccb2f6eb3b64c1b0e532d8c7c8062d718733291693d8c8768cd1b5f76ea56200172b8d841f2050a269b1bb6e833e888f01ff8fc097e1a123a8f8183243932ebedd7ef172cc9a9ba8b5581b06a543eed38da4ef16ec24ac3d0c12de6befa81a1940255f5a15d8a8615a9e7076d4fccc906ee92162922ee1230c6008a279ceabb2cbb28b1b167f46d9a4453715b9dfaa8e0beab255da1f52945f48d804b1edf8d06327c9b04b27772e296cfd18eab97f49ea2ad123cb0cce5f4765014bc334dfaef88782494cc6880d82e24d0825b7fbd600e1b2af44736563adb1168c304ad933f697d1466f7f3bfd8c4e63553c0c4e2310ef10f752b25a894e29e
|
||||||
|
h: e0
|
||||||
|
m: 0438a49c64636ea5d0a973b8887cde32f7354252397af4dd128543a60f81805f65b23374f0c4345be504d81d4ab442237fec6217ea5cbf809872fb1fab65fea6f72e270eabe7ab1ce52568762cf0a088a08120e5d9fab8f9a10bb5475fca1631af4082828c872d800e989ebc8107bf9c290fc8fddbe9deae4a6cbea6a943184c2664ead668d6266ac7962f774e171ebbc7dfb7
|
||||||
|
p: c11efc9e92d6f52c1223473d1ec2a024dae661bbf3671dee10229268824723f801598ff46da0fe8a67853d1ded0fd4bff692c111c0971f7128bab01872d18e4c1c69fe5d5c066d3fb91f3b75c8e3ac25fc1d5725eda726edb0080b464b557920faade45d226bc588d0d8048e4e643ce163147efad703129f9ecad4c843ca2f39a86db736ba3cfa7aae4d5a25482c8dab7479460c466565871c60d356f60e7992c761266009b15f1729df20cca35eb35a5505dfe6782429fec5a3138b02711053d9f36c99b00547e03e9aafa59f902e33a5dbcc96c1a74e5d7bf5fc41cf73bfa2b8887440bd487a969ba808d03483174862e2b91d0f1eb69b5ed38a5fd897dd0d
|
||||||
|
q: dcde01be27ac72bedbe45d5c8c5817d17bf41a3a612d622eaf88f4f7
|
||||||
|
r: 99fc764590fed1f37bc460cf7ab72f93dfe0ec3e439f21847d69b7b
|
||||||
|
s: b7158ad06fb21622f2b3957af17621f66ef9fc324891e61e230e46d
|
||||||
|
x: c38f89dbab151c633a3c9c71dddc3ecfb540aa47d2943a2cca779182
|
||||||
|
y: 2be5f3ca9c02f0e12abc0e35e82365490db715cd323f4e11f29f2f02b6a5ebdf67148bbec6ea6f18ef3356b57592e952de91851054aa03d9202c7680eb9594aec883cf1dd9a534a8d18eb428b9c9b9d95cd9433f990178d36914a36d266f67a7546cda5a66450edc1d3e4850e92ddc17438b051c0bbb39e42db129429c4ac78a721fe059203e67afec5092c032fe2d317154a9bfb01b08eb8754495a6462fe9944df64561cb21767255eb9fdc393d3cbd5122a2f534c1f921eea32f0b92925ac57080baa0228c31878d102db179a77a7571b491522ba7234484c3a232dd7ec7415c16a914cc4364276c412769e0a0acaf2c6f752821abcff332b09f3c79a5962
|
||||||
|
g: 6dea6eba7f8a25170379af7457c383fb149e35e47cf0b7ef00a185e02a4f07556aaf29a20cf5fe7fe6d60d37e24abf325ed0f99ebc7644e23f87f96a09a1b9b1aca3ddccf598ba99ea0ce793ba861eaf54058cc2606e49fe30d5f6d9c9ff7cd132f55077dcb7f7739e893dc290de96d2886f4bfe5ce546f61096e38555f9849c8048db57277893884d176446c14db61b7697a03aad87f60b69c8d4a7ca1e105301bd28a39b4364db169403c2fd3d6a159f08089e5e33bceb77de87a2e613bdf6808df07c7bc15b55ccc6646eb48edf075334df188b22744ebeaf0aa0a5194b4406f6086d5f17cbf7331fd88fe392f7648d9d87d0da60cc1d0f2b217ceb70aab0
|
||||||
|
h: 200
|
||||||
|
m: 1d67d5f4ddaa362edc4caec3a5c441dd123459232fd09fefde1c2d65e8eb5e00f0bcb407be753042ace8611370b9b7e1f921cabd75e63760f35e3f16852350477fe6ee6452383eff37a9be64231e0cdcf112b29d457546316139aa8d831d2663d52b7ee3b4
|
||||||
|
p: f2d27bf9ee65d7d4e54ed3cf58d38a655b28f16ef30eff178c1d63440dcb375d7530fb079482278fe1ba99f5a65190bf4bf373ca7b8468e3f89b55833ab75c6d17813daa7a5df5f1d24786312d53b17b44eef8f394b32f726bf7e620b96d84e9dff62b6452cbfcc7eb4f830dc03b9fc8949b2f586565dc4cf71f5822666dc9b9c66c18559fd908080b1be74738cb9a2ab619576d1329e8f863849fbc87156073419146f03babb6da725497aa1403fd20e83a137344c733cc7cf82af2e1dfc02ca649352682872475174cf79fe9eea2ffebc9cf91eedcb3cdc038f5552cce2532c2954998595bf6dead1a000935ea51f0514990c216e16e49ea8522e7ccd371a3
|
||||||
|
q: 8f3ec33c9b84d3452621cb9d7cfbc3df044df429299b23f23b8e59f9
|
||||||
|
r: 12e1a00a35642a20c0bec8af8f075fc5792a906e066ac436cbbdaad4
|
||||||
|
s: 602c1a579a9c24b5d1fc7c7522ceebbc36f2772f9f8beea13e1ad88f
|
||||||
|
x: 4d168bf47b3a18053a72f551d47a02b9629762f32e4ac6eca0bc4950
|
||||||
|
y: 83cf9fc4f3064f06984e1bec9c141e421b0777a1d146e47c3901d1564edbf41c985f7db9ec4d27de243caecb443f6d5f14e9fd6f39974677f19e2ff8572ce5e9898ae2f15f2e5c0e669d8b75d3bf677941e263d575074515b5acd60fbc3545f1f7f153b040793690423674cfc8b7d2e1e44e22aa2f7b48085f1877099d6fa0420a2bd3b73e7602a1bf68a54b4af09c2e13429b05ef5ff3e16792ff32b0ad820fd9d927a0abb4a131fdcd9b9c8ad4cca9b18fe659651dd0d3b31437332829ca6ff495671ec2f0b759254034e19c85321798dcd728792b268a069c0d88be42e6fef1fe5d00f0a7f07a8d0f5b841d1a5e78b8d093609d92d75d62a6476190379caa
|
||||||
|
g: 1a233a1311d4ed1894ac130e51947875b01750e8559ae352a1e2925df29775bb598e9e73e373c12d55bf60c69fc7e4cb72f085ec0f22dc954f79558fcd6e23cd3889d50c5858c776c336485ce23c064a693b15a92ef1c7e5631d3fa5bf0de572f23a0805efc634b143328d922effdba6b4ae76586083445d971c408090d22261f07e4a906b1ebd74fc02d5f875d2b09ec14cc4eedf675dd2f6cd70f8a8e5ca2bfb68a52d9cd8ba756242fe0fbd5a6ec19bd58f962abb12cc7c7b700b56890bfd96f6c798bca23d780ac5147278174ca4ea8dc61ba00909444d23c05ac2ffdabef9bc3ce6ac6990eb4c8d22d3426cdd8e8703a08939df7aaaeebcb127d2afba20
|
||||||
|
h: 100
|
||||||
|
m: bca5a759104c7bf1340667198ac430f56ff2fcf8e341c04881a950873bd22676e20f3523ffdfe05bb4f74fb28bf5b092f02a507f94fbe0414b7da2fe5add8ef4983253ea7350bca07737c6bed5ab9c0c085886c35825ff6a0d97149c50bade8f2bae5fff05c7e30d510da13de5d298f4c593a4d2a678231efeb8570ea56ede665b5cbf0ebd974bccea51002f42
|
||||||
|
p: a2a46c79a457d8822f5092ba2605ad9be9ced623db73758521a23a74121f92dc328029e3fbd0b8771060be15126ba048fc79c1d06fb02af9ecf99a359baac26c3fbc5019699c6c0d5a81e60f9b09ccd8351a088b74bac6a189f9f56e35cb143af878759545abc3e62d2aab675190b3292b72f17059330bf743e30c279d17fe0877fb787506ef0c3e77a83b1a067e1f7e82ebe5cd515de4bd6c31f727e8aae0b8b59c2182450ffb4d995872cf3402ea71ad8de3c08c79625f4aa72d23f9b3338abbf352466d7131acbb025ab6ebdb8c8b3a44d2f22f4e74f2a594d8b7d53e65a4b6388e3c1c6206baa19052ec82126f0e1e43e5dbea84f69e30648aa04a84354b
|
||||||
|
q: db78af52026a892f3c8813bb77f0251719d81995a00aefbdcfa25fd3
|
||||||
|
r: 63beb195b48d56a156b4a11d63043a2fdd0926285b81f51d842a450d
|
||||||
|
s: 3b3e0ebebbbd87f2406d7118fc45eacf88c8b295d59d481ea06afa31
|
||||||
|
x: 45323043e71ba5a1302242f9cbf31925c02ed4ff90413747b7a38976
|
||||||
|
y: 35a2185762ccda7995ec679bb15855268ee9778abd736b738edc832c4dc7e1026fcd13c8eab3de70e522dbbf6d5ecb5caefd4b06aa60975b116d034f7cced0b0dfaa2b42abf357a6278c5d6e9d40248ff5b76d5b74dbfe99346f1b1abeac9b1f2b19d493ac9445ffd7da5833b0bcd262b7789f48c5d663facd839be120e4af97cf4674b4aaac60e762aadeb748fe4a19bce4c2b5ffadfcdf8a3024e2ef0d05ff795c90c8f17d9b1e8047f5879dfaf7424fe6409c90e4df1103f540eebb5146b96bec7ff20053d3cf454a4a0cbc1b4b1d0cb1d42354b598dd81685f6b6ec5a134c98f055ff124cde48982ad409a752e0f2b3bab03a98c23ae1b12e14395799742
|
||||||
|
g: 27ae9217e20e348af00f9cd070a492a1022ab088bd0cf0e1c83e4319dc29ab14784ca175ac2ef81606a41a27226da6d6dbbaf3a15e49d4db564c18ceaada5674424a17e53c6822e722a841036e59e4009c1a1cf27412373bc25da89d7ed7738999b87f5b75367d2750e7fc5535dfdc3bd4d8c9be9448b74eada6a9f476e9fa3aa4ae77e9447c6551a0666760d3541c993ac046be4eb6e3082ab1ea85399c28ca102597a7fbf792f644948f2ea9555cf2aa0b9b08d33215e56b48d1a74e345f747e100731f3375ce9dfeff79a99e92f14dea2b59ada2006498b43e518f942a95920c688e19e59c302003a183b2eff41b9d6bab85ace9da3831fe8341c2609d0d8
|
||||||
|
h: 100
|
||||||
|
m: eac8000ff33efcc25b977821e86939591a4b76a487a45436432ff8d00bcf851ae54bbcb8659520daf3d7833cf5ebca309b5a4b44e46a4c57d55494c222f7561a5e7a6464ba6797e914961a16ede4298f3993ad7aa91809c956563191766481f1
|
||||||
|
p: a00de4c8a703320df711317f490b18c23c9ff09eb809b48df05ef444cbb9f44219e192d3112bef4e4e8be48ac14572cb7fb11c6b51279d25408b77610f05fd5673d9d13988ef65f5f74bdead7144457c5b07969a10576c626a3adb8eb6dce8c3cd244aa69860b40a1632b3d70387894c709a3c9bd93a337f7583da5703a092695f86002568ca29baa2c9c041c0b8f3751865cbc41e71797a3359d23205895a42767f4dd3045834da9192e3f15696c0df1482508bf15d110a8c9a658a73ab17af5dac32e80b92a4883d18126c010465e49167904300f79a4da147939bffb0d1b90b24d9b0a96b39897381d6d0cd0e2075fdf854578bc8f5f60471bb3bb6b77b97
|
||||||
|
q: 97c19e3be0291d58aebe99314055cb5f53e9e4f0b2230a517d2fbd3d
|
||||||
|
r: 3ac0f707bd12fed87237f1b75ce1cacb8d5fd1705e0e59b2ba187f63
|
||||||
|
s: 1af6733e5f495180ba0cf43e0211a8b03587760e352c9bb0bc6a9590
|
||||||
|
x: 30ea802a8787cdff6fbbc7f61f436feac394f1e19822e8401c9486cb
|
||||||
|
y: 7b3dff0ba27dfba956c88c5a4ba9d2df6f8e1dc30a5388703ebc572768fc2cf4e996f44b5dc48fdf8ea049dbefb003266d138b36f0a43ef04e98881f05665008c740f8bebad81ba71afc7186e367aaf24cb886e0672db2b5361c0e4ab7e56cea50fa1d2d35663defd6c8c54ef3edbc15c5a31ba2203e9c1de9e13068cef5b3d923004fc951b92cf34349b25a2d9e5ed8ccd25fadd87615a5c02a3807c210273c7be717d8a0a3fe4e5b58f8baaea7ab853b4a25e16fa7be9576a2715a2b7828644677bfdbc3b283c3f6bff23ee66becf993c650e1f704513f4e80f5d94df87fb732c32e90a97866df5cbd48bc893573a93c48e6bb409e074f99cb4bb4ca6cbc9
|
||||||
|
g: 9a495b8e471a87d5c9c5cce622092d70019ec20ab98a501f74953cdf467177b49ff166ee21eb21f77f50ea69f054fc4d1d2c4facfbfba602f73f52b4524afdf50787dbb658992a5f94d097280ba46ee91344416a300d3e78cef9b0adc33301805cd4b0d21c3367c5564e8d8f1abc07c182346f3f707a531d6b1e51bc9e510db78aa3214e8ffecc8c525f6ab3183e32139413710322c47deb5073156a5e4df31d7890632bc0b568252a141269a8098884d103f48444861aa360daa132e75ad3502ca376aae889cfeab3504d8946e17208d06bcc5e9538b84f7a494cba1fc6ef1a08358c922ebb9f4518b9cb3a816b35b7380e55b3c6af9bb1d51bdac695272de
|
||||||
|
h: 180
|
||||||
|
m: 2fc99b9bb9831b132e6910eca1353f81bea78bf9d307b2ffe84110439979a0bdc5f94cc79f4319589681bc9be4dea978ab29df7e62cd7f91d12f8e00759b5c2dee743f5dabb5f90f37bbc2ec01abdb05b3f18578063a1bd99d6388a763b8bb391d1c521b681505a39ebec02037250a6e6c467df21997dda5bfa5193c15cde28c329b4dce3a6962b3c2e9a0a0d92eb0901a2a87968c01360af00d72b4e47e3be4fa6ea9debf760af14508368e867e57ffd9405fda3a49ff88501b17cb48147868007d08a60d
|
||||||
|
p: d12a0b227544bb19140da6a17bd08bb92d2e716d87da2fb6d6468be922cb77a8d3269c2b10b7970be132c80c041e265a458881de5a007cd2af71197e10b13b20e93e818eaaae88dfa9726d702d1e98b309577065bbe46045f5a6ebcef6d08cd92ef2bda6c61512198bce02a565768c255020a863844a63bd67c8c5b58389089cd22e1fd5fbcb91736e3ddd3474906a7e9d79584aae5a2b01327ff5011fe2aeaf5e697343810304bce55d096c070ab99adc7d0113b6ac13743116ceed5f8edca162dcb3892aaa2ca833802805f781e1c50c88c2d96a1a304b8fe58c3153d9c46608e87e7f1d1e3c29419e4f11f5c5fc38432a3b60637522324efbb455f2d19c57
|
||||||
|
q: 9c89242ea3d46e0c33fff758fd61fc10e10dd7bbdc0389730b80446d
|
||||||
|
r: 661d9490fcaea9d7c8988c87309d8bbb482c0363859e10e89d0d3fc9
|
||||||
|
s: 44b19c3b1c2a2fb43c2a303b59969ea8bed829fa795d3c149c80fe6e
|
||||||
|
x: 90f68246c178956ef16e38b44cf3d14105d855c57fde0f3a19f64a15
|
||||||
|
y: af53e09f7a5913dc1bc168ee2c230cafd3641a72762b38ac02dde9c4f906b4306e9c062f71e4ae11af2bdfe3c32d0b823e621f2c0bd10b51a815f89f5e1b064dcb9b3a6c2746d5d68bf7ebb0eb17a9ecde0a628775d55e73aba50945c2cad156e71d828143cf618f4d6dea633fc7c14a1ff1dd5a52aeb44041f349adc4ae849213c2f58a9bd4b57eea576e58f6230968bd71455e30efe3efbcffedcca7f6ca9fab26442b8a26d512c3708735d0d3095ab0f3d5ad33d2ab74fe944c3943abcb39ef063737e7e5a6c55dee34cca7ab219712a842683bd87c6529d267393922e62884e1e8a2fe4009f19e962aab7716af368ba10013b0edae8e7e4a5f13f450d141
|
||||||
|
g: a45c4bd62a9ed678de9eca6be8ab3b3c55bd7294f74bbea33c11659178b8cdb8be8a7f24f18fc0478be253600f7121f1510ed060aa67ba191d00ed19374402820dda53306265c7b9f2f7932abe8abf63f1d52d13874c4cb2eea8dbcbac0ab463845456cb0b553bc5f999b0691a16815edc863996b651a0c75a63c96df64e4f99efcbfe24df877a9fbfd923cf9b22b0c57f1c43ce7cf751acf5902e65d34752b7514d699ff4e170a52535e9d8620e8016f9f4512e30ff78b4fe9c787452a4fdc362084b86a234b67d14261a17d4bd9e6103a251f1c73f9b7f6d7b2d2a8b29e75c891530ee9e7d8fb1cc0fc2e0ad7f858d991c57d77e7c6a3d03c11e7f6d32d7d3
|
||||||
|
h: 200
|
||||||
|
m: 4dcc7887a1d36698a64384347cf116edb639a4eb3e93fa379e683ae7bea1cfa58f3b5dd7072ea4906e11a23bb3b919900c756d3f3b533f889a2c2191d5f0f6a86306a76f4ee15fb88c71b55ee4a166e70fbba2a887e7cef2aedade7d9e973a0332d9369a1798e892479e019d02a4399b5de586d291325c17580b879d57e4bb98ce06e5a82bb7842ad79a0af99a97a3c343c9ff01a220db
|
||||||
|
p: bc98945b0c9089e7639657668eb67da6a87bf633d7aa6e98db90207475355e4973fd6a2910ac1a5746a086b666fc4dddbf575cee52c4ab3be46caf20ef5750704d2a50facd4bac27fe25d772e69245c375c8b423354d94be4d6c3bd658faefeaada7fb36539d2b7f76ad448ae764ee5e2a5a41452d8ad0dc20cd34ddea6600c5cf98db34136c56a3ed638037f202bf594b8d0bbe2f958a30d22aaaed618ca04ca30c905f6b3ad542b52e9731d389be9453f4c78731e1c09cef13146aedda9868f48fd4db40937e5436292762171dc43e19c031f614ff982b3c13fdda5dfeebb944f28318ae5b571ba60f62b8d465839829aa51c1c1c4e4ecca8d6808e6300593
|
||||||
|
q: 8f3d64a23495b4dda79528a3eba43f5b6cd78562a07daab664c46d3d
|
||||||
|
r: 1630955a8fe8d976dfa3db20375b3f118df68bab908dbe7e9366df2b
|
||||||
|
s: 568053e0bb668c3e1033d1a5304b4fded0ffa1f16d5d240d2788f8b0
|
||||||
|
x: 2a7cbabf1e09ea238183d5a286c904b4a65bd623de22de1b66db976b
|
||||||
|
y: 109e4953433dab109d4bac0862d2e0fa81ea2be91f64eade5c0bd8b30136e76d73696200110b21b31da0111a54cc497a1a4edb17a7b5b7ae54cf7fc62c980518d8d504976c395720117c70b202ff5f4c3ccf30ace2977337b1189851a480fe13dc01db4ab1aae74f913bd178a08a0f24baeaff9e7e0b3fdbad27b4ed87ed4ce3a7746df7f57dd8461d8e53bd413775804dbd7d469297b383f0eee418145904f4a03b952b81b2bb9888b6e5e804e10bc6617c4b654fe8c7dee3efb0798ef18f6637c880e62f3346500d45f4d4bd9b7145e6304064531327ffb962e884f1075f1bab9ac59a189b1e8993c749a32693898604c1c56a8c2a4e166da80b2233f2d2bd
|
||||||
|
g: 279e26642123f6a952227a2f6fcf0119e562d391411ec0acf8bf0346e28f188fe6809db177c7e21da02d2a3cd1d27579e8120126262429181bb1483a08b62aded0cd0d4766fa5cdd47fb229e594a91dc49478fbd60cd5bcde95ecb40b4483f7172e1142ff943b197858459a129e91cbe814cf78916ea819b5082aec058ebf32eb52180bb3afad2bf39dae3e51b02557257fd0b1cb3a4cfb8f6f052943b2c339008adb279fe5e5cfb7157038e099e296b605d42545b0e522ad00fd7324f1a81051996d7855be9231841e424635b550ddbbc24d6c6f381fbcb6d4ede291cf27f8eddf7ab46d828cee8d1f4561e8ca15d3ef643defce090496d27a77960ec55fc5c
|
||||||
|
h: 100
|
||||||
|
m: 1d228c3e82f29939fac978c77d7f986f289946e7d1eb00f546fee875f6b940148698
|
||||||
|
p: 8b11a4e9180e193d12bbbcf49346d5838410ef52e8b1a2889f5083d95696b9936d9be26aed6737fa6d9b6a204ce9b5b8d8c3baa9441e0c8eed50afb7679482ee6632cf346867f1b048138c80872f66c4d4f1b1634237842dcb8722c4d96ffbcf9ab5feb672035fad471bf325bcf97960ffe3deb5081d23298f998a1f7a026495b2b06685819e2aa6f1567ba37b7108c7e7a2e4d79e5a11e5ee595d3fa804d03e55b169f0926255a43d2c8063fb11c5f8d949d745d339c228d61e51d3c0fcd1b7ffd2c5e40e3fa087b5cd95d7c36507bd309ab6b9e38530cae56afee59706e351e3e5adf534bba368b58766ca28f74a5c7c8c86b0f5f249f49137c0e330f28749
|
||||||
|
q: 9075d45f3ac52f5995b6fafad1eb94f82961519c306c4e36cc4e5265
|
||||||
|
r: 442dc63fe77b2682e4f4f61ad4d152be01dddf27660e62664a4241a6
|
||||||
|
s: 1f4c08097a6f891151231f8131fba53089e9e3c5f1c450beb8b4c089
|
||||||
|
x: 13920f02359e20635a07f2793ebc4290c585cee32373526f75357346
|
||||||
|
y: 157ad5af5db70923175eb01bdbbdc6e861df85bb3a8f4db897aff2996ce267ef9dc1dbd6d4bea314dc4746f4bbf51e3178b80f0210e84461f45d7bba317b1161acc63ca59abbf0e6e5b3ed42addf67119deb1793c56b00f738f78c1cf0133705c84697eb6995d9d4cd246c8d5e21b8ef00f5e86ccf4743a54e1d8bb482d5f241b91020b837d7855f073fdfcb9099c18357a32ce32e32304c196ce011d1ebeb94fe2d890bafc97c4414694aaeeb776da2f2a66ee13c61e1aa35ffe27c4524c288d1c9fe33510a8233e45faba5edb399c40f20ae91f8e24c0a406c352db7d59ed86ebdb7376c1e45c3db1be8f63bc9db704365b7dccb15956047b39024a3afe916
|
||||||
|
g: 468cdbbcc35688fb2c1b84065c2d70ffcd392e865ab5440f30ce2bd5b1c1f92af8c7ff592f0283ac1c7a6d33aa4835a5556caf561bfdb4b4789fa07bfb84cf80f87c0c1477e3f5f079a27f545c8a2829950ec4a8584daca1c9bf2d9591e6b42c5ca740d1b82fe0e052573fe73cb0c2db962d41b4b879f7d1273b8d7cfc1e222bfbaa13160ca13aeeebe3b4a31790fefa348b7bc7e3d61ab7d60c1ce5a396630bb2a4dd7ee6ba8bd89197a572d741d3bf22d75bd227bc099b8a52c3292a2229887cdc7ff5f30eef2b993c84d48e86397e667e4630edd6ac09b47f00fcd9351f867584ac76aa081284b610395c8137d846bb19d3aa1b4764ccb7b0a730763bc196
|
||||||
|
h: 180
|
||||||
|
m: 2d104c6f91aca94e9da1db58abedca454fb3d2608a1e9fc47a643a1608614ea1ccfbd489225ed38c811845f0b5262ef7224dbac6050ceb4a5527a46c8f9cfc2d
|
||||||
|
p: c1fcb56e8fc3af466ca9fca45a99d680aa58f46e28247df1b0dac038d8df661b6d2a9e13caa60d2a8311d7fc684a9b18761d48fc52fb2bf98c2311f32f628dadbafcc1c4ad8019336908db7152a4c03ff3f0494936db5728dc8a58017365673e34c23675cc59975e8234210c8df4a4884e7fdc0e88a634e2ce956b6a956d5c38445b06bd4c813a697ddee6e3c4b552c584e5cae10ef1d0226ad778c79d8574bc0d9100ed4cc6177c58712e7256defed2bde2795fc09539e47fc03d54079afc8f32ea77ecabde6390df402bca7174b88fd3e47ecacb2a51acc359017cd6441c8e78d0a19a354233d9ce840137c7a134282c0728085c73a1c4620bda3ce3f93225
|
||||||
|
q: ae482d4a4a0f3fcdf0ca44736ee073d5d0952aff6557750cf199c863
|
||||||
|
r: c087c6f81d1d2cf2fec97807b75ab6eec4402f19808bb83596ff2f4
|
||||||
|
s: 36efb6709b99515c888916965be667413223759a3761c2a0fc81901
|
||||||
|
x: 70c6a82cd663f5293fa7eca96d682aced0b392f8fb6a5b29f182b0fb
|
||||||
|
y: 8c8d60611fbc01e1266928f7a537ad9557980575bcdc618f350985f7d5b648f72bfded937900627e4c5de7ec28d632b5af96a726c628162ccbffd6997d2e0d44cdc1f0ad868e9812de5c6931652c689604eb63bb73373e0c0b4627a4ac54a480204f5c7678150d1a7f22442023674b4327bc1d31fa7e4867d91ab9abb58d2b2ef3cabed3855892de6212fe717c8df5856f24f09cd76ee9aba097980808f36f7ec1589b2d471d10d2e87cb4ffee6314ca90b9aa71e5495e04d8965fbbcbdeba72c2f882d4181ea5cfd0d5d98da293cc03a223024924cfaf93597b429081c844ae933c10a3421563a5dd3c1ff7f910511ebbffedeadfcc34553d6e4f1449a5104e
|
||||||
|
g: 75a165b20da1883ffb3dde970f8b469132c0fdedba3b203ccc3a47c52a2e8f9f76d6e393d32f9d52486c01d136e118e9e43e69918e402898d1caefe9ba433f3a0348e74450e321cb95ff7b55d8cfa535d308fe588975411d7fa83b2497da0219e7b9a6f1fd1a3ade1c21eefe3baeca207ffc4b5d857c260a4d627ac432b94b3ddfe360162320e64ee6d86b5e1684b80edebc348b3ae62b7b5b66b0b6ef74470fde9650660a10a8c3bf15efe4f98186ec672b366b45d34513d58c7ddd0bda644c50cf2484d4ee75d7775cf2e3f9661628777aa7fd2b62e109dfa54ef1fad042fa8ab54fcc7e5956b6a49073ef5166066b171241a29792ef6302860011e2281cda
|
||||||
|
h: 180
|
||||||
|
m: 96916f7331921d7d15b53212d84cbbdfd33681a65c56dbcb8feef5cef8509b185f5900f30c432133e99addb38dfe4d2c5cac9c
|
||||||
|
p: acc8efbb28e8da47f9de7929366307b75b5938c38ad8ab1bcdb31090b45436576c298ab952329e868f37c29e7f192113c8abce875394c719a006a4088b34e71f301210e928c24e3822d7829dc5385e881ccb5bdf39b189c1d236da3c98ab7084dc24825dbafb7df43a69cee0e984356fe764671008eca8386a8db8966e0dbb742c83b8147113142d1fcd4c4241a7ace1328910cc4d3ac885db4b4604dfd40e0851c1481a82f4f9b56fe007b6f987cdffcdfa1fb32e6fe3315309e9ddde55db6bd840887a9480d6a2e32c3ee29a09856440639fee6ed9d44785a63d03537713b40b71d09f76cdcd4bc121308f40fa1fb2ea7dde717eab120a5211a527ba858e13
|
||||||
|
q: a3f7247817ad7d27cb798f1ceeae4d8d553be567944489e6b8c8752d
|
||||||
|
r: af66424e5b6fcb0d02736cba0e75ed378f99a1a95f3b3dabbf4421
|
||||||
|
s: 3ef17b32767ebd166c21d9c00e05fde6055a2105d42974e72b82750e
|
||||||
|
x: 6c51aaad103ae26d436008827c5637058dbc0f2ffdd564de20888445
|
||||||
|
y: 27efa706b08112bd843147886534106c8a81a2575db36e2820d872ae1c2f41c04e709ff4c877d39893ef54973ffcab1730b9150386fd26faf82e1f9a96d58dbba9a4b2d0057ad84c558ac19f6c41b53632688451388e34c093c8bfc44ae25be56328cf1663e3d7ec6e7bfe630426dafb9caa581859e84d25e39b892479f1d31f6de6cb7c07b44fe3c8adb4f4a382ea9e6b3c46b5b87202fa3075bfe3ef5fa2d1da81431befa336a84642edd631db356565201bdcf3202d7d63d71b5208b225a0bb3e6159a9afdd1a4bf2c562530eb9a20ebf4d5bda79cbe4e9d9f798ec8a334c1ec9e98da604b22f7ea6796e84c0f3ae4bb381015f229bf6e6bc0a3af8dec49a
|
||||||
|
g: 4359bd41e4292cf74c7253050deef639b08a68f65df5830ac57a0bbf29ae902ad82561e6791009076353fdc37ca277a4c5de2bb00bcfeee19b5b495f4ffa923d6fbf316e1d23e19f22696956effcc9a17cee537dc142390fd9fe0ba905c13060a047ecf39ad06ec60086d0b446b6f5c4352e1450633090229e56b2eb8b892294d06170a929bcdbbcbe917cd3394a3c5fc78481752dd18db89c578d0174c41ca79bb92a90bde56d325e34c1e89cc8d525da66664f7a33c56f97d2a8a784fe1c93d09912b47cda6f7b12f690a03c24956fc8f8b0f9f477221c265b667008eb2f76e61fe3a92ceeb527d6f3a9ea67b2ae133cd9f09560efe2a6f1d97f66973aeaf1
|
||||||
|
h: e0
|
||||||
|
m: 2fea6778d7dba18b06f4e928595bf059a3329c274dce0d7c6ac50bc6fc76821b8be30743aeee01f6c0aacf5b51ffcd942d5bc7de4943d3e7d3cc697ad076d49ab37a62b554ea1d0ce79e7fa23ce7f916e5657ca71d10768f37195cbfb6b103aa7134100cc84ac1ebb9547ef4738b2bd18b6b74f93773c8af5444d7dbc72c4389dcb15d21a9f5012e9f05aaf623a253f597c2ec7b31a4ba2051229485d64209834e64d4d717d9bb89103d4a253acee2c47d0e69a05685047d0fd5b65ba64cd76cbfd28a88ce0f049575673b43b22a826e4431e09cfc752b4fdb6bf0b8309cee7e8e
|
||||||
|
p: d59970c58c826ce041ebedc022b36759cadef19191b1e4b9e91b4cf268e8271262eccd89023cddbab79ec1eaa96c641f38735fe55b3edf6b586db873e6e1506be69e64b6c2d1130a9e5ef21acf787fee6dedceb1ce905f9fe797269fd995404f6af858a756039202a96b7e0e76a8ec3832be59a80ca274d8bb94cdc54b2a7c6937f40f826330bc6b7b2611c3bd5c14a0999e04568f3a4bc78158338339875ce076a293915562621fdde9eaee54563bd4abbefb4eab4f5bb79ec173dca0240151cc39f3ebde5e2c2c0798fdc75991ff471852104fc737cc5640b6e9e20b7cc0d0a209b84f420e441043f062cd9414004a59c331dc1cf8b343f1da02dd9c9dfb9f
|
||||||
|
q: 94e9c7903cf0ffbe3ba033d6de8877b7d47db8a6983c636819c8bba5
|
||||||
|
r: 561d79691648a72b27836ad8c1f49157e2b4c71a191370040d644f26
|
||||||
|
s: 4df8bb38ea60c7b410105dc53738e7503dea0cbfc23b5c5a4f96eb7c
|
||||||
|
x: 3c7bf4ca0d03cef2230eedc9795a26884217de929d21be27fb13caab
|
||||||
|
y: dbf452bef538267df67c47995e880c50f378023accbf0979118dfa7654e36b440f5010c17d0cd12329aa0411a7d05e3d9808bf369984fd39dfef4ddab6bb409c0d3ac175fd7eae084520a22365e68d86a44f96ea5f18c2ad8661078f8c2e382b5965349f8c667c24cee2f8f5a024bc27605e2f79b0fa8f11813ada77d16e13b31f51f69b66c0b9fea6883397def8daad8d144fcb8885c61bdc221cdfd41db877c71b37b0e56ce0a507c267fba57e487783319e4bc8d014d03cdea99f285dd9996110ac40cc7b36d13a6de6292315baa24b8a1af64fa678040b14f7a0b496fb97f0d4098c606ee9189abfc665c208f2c450424600f6d4a3b37b870b1ba60abb0
|
||||||
|
g: 10895d8026f54b864ae07953556fa245b7f19bbb88bceff9011a9a2b11ccec3057d2b52a2eac52b4401a63d964e1516b21c929fce9126fced58c2b8f7f9b759c78717e1c89e35dbb0998477470727f283718d7bd4389e8eef14828797e8569b13f1d7f0ee9185d49bdd4e3a027b750ecce01fce1a78e786fe728b7b793317cff15f76e7e5fcf424d6587fa3553f002c21ad48b1670ba6388b641d23de98a7a86794778c293f05bcf12982bae3d3d9949518f0f3ce1dd5192dc0847834d8ba605a477f861ddffc7aa9b1142d817b5aea351fc2d54c2430a70bdf6ef307aaf10a6898142d543113af3d215bafca11927c3cb07cff23f40545509db500979d30d81
|
||||||
|
h: e0
|
||||||
|
m: 3ace95ef5a0daac71d18c85f0b94f603a6477d3b91edefe371e5c06806d98e6eba0c4d43f6fa84feb13716912bfa8ae915b37e964216dd65c411e7784492fd0849a654d7139df78da4b8a212b5cfcd3bfd0bafe8723df2718202d90b3d0ec5c07393f0dae3c3eee54055a2f6dde877130a8df9b27c8feb0d937e5c97e8a67e219a129483f4c754011f0e029ead6fd0e98bf3ebbd6ce6253d4c808aea936db4bd6d
|
||||||
|
p: 948282365ddd8782118b1485121f77fa39412eb709b8369c4928d505823d10f01094ca3d647ea59c16b4575d6719bfe15f3979de569590ec76c68559ca759d8e9ce7885c538d610c5ad6c2614b9bd8406745114f62b0af236710aeb2fdd22d9184b44d04418b8a63f592e98a4027c32211e95c6e047a44b94a18a4529e683b48d459cb589db3ce85b2909abfe24f67e95c87dd2dde82d9415e76905a465f53182299d5b37097e4480d3699aa4ca70c3017c9a91edc3e70d48bf0a584112999380f31918312605acc109cbaaf557ada1a3a8b83133b1f33672f9060e40553f4aea6edf68204ca308c1cc8b0181f2d3342145278a7dd898ddb2c9046d59b41b485
|
||||||
|
q: 9ed971bff80e4b4adcee5f79a668b4f352d994b3d36b0114d2e441ed
|
||||||
|
r: 5a3127b5b3531883e084e7b62cb8755ce064e24151e8c13326f6df7b
|
||||||
|
s: 209b627f13c11a78513e79dadc859e98601b1d08917155fb5377e9c4
|
||||||
|
x: eec072298e13e1294698348b46ade14db17ee5b35611f1e761d9daf
|
||||||
|
y: 5771feedcaea12efba9a26896fe9bfb494049df1c45b537c7b71d476d96906a1b6b5bdb5e12fcc529ee6b4a284fd376fffc4a9a72a47c78f5c69c561c9e2a3926d239acb728887b67577b4f1c42d90270e588257f155a74ce3044386c89596a97d6579f2df2567c96ee4f74bd096f09c91eebeda1fec018a4b8e686897d4aabc8fe2e5aec887dd95287fa1fb446147278f99fb4368e685755f7a0cb3817fd356068cff3ed2ca74735434127543524c74d422f6540d8c3c4499b65268c48f99c20c0128784e7ed111b85c08a27c31175c8bb74793b1ec18ebcb38a4da36858e130f7570d7ee9b4ca76bf4dc3a9e2a7fbd6a233023d8fd575eb588957361788542
|
||||||
|
g: 52944a0dcf9e340dd2e4271b96b522ff35a42161e666566932eb0525dde9002c1ccff21f66fa7d2e59596aeb2387a16c7ca79ed7dff2b775e7bb1aaa83edd18fe3e46bd5a819dc62017661d070de533114cc1c05fafb4d46aebd1e1a25060a969aa471c1c9afd3c91cdeda55d62f427e95fe7f1277f9f0c6eb890d1462705d34265748672e94a468f2011355456d670d30fee0bfe2584bb938464001d6dac4e1b1f501d5b23791a381483aaeaca3fb48282a598c6e6060a6df64b05867c886c055f672b22d25a09fab4ff5195fa9f1df98fa52d2ba22dd033e7a1800ee15b248c422349fa55c7492e03f15325309b666d69036a8e671df85c28494d96d0ea715
|
||||||
|
h: 200
|
||||||
|
m: 37cdcc98484c6777d56d0bd5e5a4a70f7f5a7fbdb7926636b7e88d5cdec7f9c4ab439ccea5a06ecab597dd0cf345989e1e8f1b3d0271413329f3cbccc263fb481d48697c2b7c55bc45071eda47abace55dbc3fee3227dc570f936879e7d11d8e854d00d314f8adf1bc67dcd48362540594ad2fb339d51c8dfef221b3041fa4a78c766500b48deba3e8dc8f7766e55fa20e21b0a927beb28bad927beb0ee65097b2127afbdf841ab0f05f2fdd6bd2daa2927e6cfb0694a1f52e8a0a9ddebae9d8de29119c93b358d7f7beb85ef7b946792adfba4b55
|
||||||
|
p: b280aa377395c7f3168592bad72d37bea3b5c55bc3afd5372b0c70fc4d151998385638c48e1af154fdc8b70e6adb1539fb47fc4b29ceb5c2288083d8d0a18899023bf67ab479c084f9680a109be2225af34d21e7f10714a23ce44a87539acf2c9f16890e4582304ce79d5f34a7d836c14e3db53385f0d0774c752b290b6b4faebddf21faf85aaa7facb5830401cbadcd72231dad16bbaaedb178d247eb1676664a1a8af294e9f754b40bef500a00835d30f08491f5efc0744d3f8fffec35d422de6b92874470c95e8e0aba4aa0ed51b37a568ceb8ae4b16f62aafec195a545a5bc717580eff6956f6ccab797071c0b563ceab3db252be451ff62479a8e3bd007
|
||||||
|
q: cd2a24b2753302ae9a711371a1f69660cc419abec32b8949ea7490d9
|
||||||
|
r: 5741a5c49e13d3eb6a0069992c249b6b376a14aedf3119e8b91256ca
|
||||||
|
s: 25a958e1c3f0ec6ddfcf447833897eb6b4b6c21dcb0cc836276d38a1
|
||||||
|
x: 2c867afaab859531c2daaf8ca5ddabad8396584fb7f2bbddaca1e76b
|
||||||
|
y: 722734f30b8f39fd7fc121db75988eca86032a2cbf64f4f0cdbce9c46ec198547fa246b80197407864b18997fcbdb6562de25fa039399b1ae5556eb3c43023b0f717e1a4aebe5eb2e9aad8b53f7f05abf279d0c8c85f2a08c3c094af9bd2ac0819dcc71fa7bf709d6c5091b9fa98f1fb622b36d39dae3b89f3adb3f711e7f6e9abcfaa388a47eb761a105d737348e93e2a8c2f75f622bd216edd4f7088c1502f040109980d88d52cb8ca07c437f882d53995db24c8f71ed1c46ed2ad7744ef7d95c395d7f88c7a7916d4095bba70c4984e5eff14ec35eb7723f6971d2ec8d974160afba8d71b665b5bbf4ede74d95b1c0f678b939bcd7d30f793dff44ca6eba5
|
||||||
|
g: 24348254dab7d14747206fa395219750569e2b1eede9ad5efbd4e6df9a10a8574b62ab2c699079fe5df04b4b9c9429685ae4f65346a70992ab3f100a68a741fd0aa35469918e039e541e73df9ff846ae9eedf1c0f47de14ddd37d73799da478c1038c2322820fc2cff4ed5ee580098ce2887638f8f262794f3ba0efaab07a5a22e3a51d1bd1c777bc742f8950213562fe61853842c0973a30cbae0907e6abc086abbf8993afb023320d43a18a743bf412537e066b9c99a30686cc19d8bcfb4ac91766bab0bb7da0f95220bd881d6b674a2992b9b1f783ce9aca7340d946ed3113cfe012e93d39ad994df238f8b8ef767c4eadcb8365e33091f898b1ff52d3063
|
||||||
|
h: 180
|
||||||
|
m: fec23a4356343ef6d5c45d70b5c90e26730eea09aac93653a6256c6388986b723406
|
||||||
|
p: de28d34df473deebda4e9160dc3d986a9a18886db1d9b5ea5d2ae6215a8eebf148238f637237ad6077dcefa824570ddec5a96e508038c0278ca03fe4bc53cd149806f6e367be696c475f018f7b192a0fe05120105bc759f06dc3b017c34dbe1e2af421fb9d57f9a4c54b89e6235063912076d8cbbbd636d6491862323065ae64feab23e88bb915ad60d95d7dabd85b64cc87690613a9091cd690adf67344573a60cf80f07506542ac409656efb99b2b5633cdb851998e08c9002bd4013acada1e8663b70c48f4868f8c3ec27dce60cff758b328f41b1260a4ecac959e2560bb862bb7f8c8c7c83fd349d174a7487c6e54880c22d7b09fb223d06b2e8bb0e81b9
|
||||||
|
q: ea0c2779a444f11ad4dd8728ae6c5fec27519cd858de490cac4339f7
|
||||||
|
r: 5cef1e2bffe95bd6deca2ebc526c781dcdf4eabb0794b04eeede111a
|
||||||
|
s: 38973f016eafef11f3198eda55ccbdba1a002ba485d426ba01fb4e53
|
||||||
|
x: abbbecead270c903761f9e75b4a6406defeeb3ec363b7d91edd274fc
|
||||||
|
y: 3c1afc61f4f7bc72418144049844c2e152ae936ae6fe166fe24b1372e2b6093e8e07686e47e14920142121110004750a67af3c1fc47ad9b0621887a07f4480991ccf31fe512d7af0d3e9ef9e2f0d2ddee0722eecdb071ca3a8ed6d804871800674a8ccce5e8bcb038e81fb7edbd48b71d96cf913a65ee6f8ceea1e326254c6c9856c3088acb70efcba98ad25a62f764e44440f69c3ecfabd3ecd8906379aab5d86b07eedd9385671769bf6edcc088f2880555f2097de6ae1367b8c4fac2931fe97aada2e368aa71000bbe8beb876df0d73917d2601be1ff3abee887483b2746554c2b1ccaab1d7a7403cabce90835724ff550860406fb1db325225b04c19425
|
||||||
|
g: 5b229550fec5eeb79799312897c9d67a97cf4ace799cbb327ca884a14336a940f5ea72098021a3c5498167cafcf6ef5838c60843a0a90a4c8f120a8c2a9aaed08308e4e5e74beeb55dbc5b3afae0a45f5aeae400673e35966b8ca5956088cb0ec92e12e36ed7dedd10769ac1e2f0d1e198971d1e27a2429cb48a429a85b6e479b4bffcfe26ea94a01b9799b1bb0354447bd0da467bf6c8927b8988b5d9e73db50d01533c77153fba4744a797dd2ec09263d017c4966ffbd3fed208e5f10fb2196bbdfbcb3026f8664549eb5150add6f6453e9e476230b689f691f2fe2674f85406c64082c1281ac1340868f49d3ef70617cb3adb5ff139868da50b7b6571bffe
|
||||||
|
h: e0
|
||||||
|
m: 20f668f0a94383a7f8cfe7b5d44a892ea6e3a782120535415da9eba5824398efd1e603f9da14d00413987fec7865ba22c034592772a76617fe2a5d6a037fcc18e0720610702e39a982a079198698711fd1a6f60a9b15c374a259961832a95b99ebfd
|
||||||
|
p: a34c1e7bae0105d4cbc858a93ecab000effc5f2f3532e359241e0d11a1ecb889c3b7385722f946db89d21c6c09d7a47dccdfa2adb7749d3470e47bf18325559f45014ed3914b0b4a4cbb103a6ffb0ba25f67f33caa4443afe11242cbf7dd855a550796332ca3cb557d6cd5ae35b86cd0c092b7a1608aa0b7c1d72ef2df8678ce8b0c7355302b8269ed8e431cf623942476dd2a62823ccd9ae54255afd38be5d8742c8341e38fcc936b875ca645f97a7a0f3d253720dfab9edb5dcff3da12c14a8fc8b0e6a9d8bc80106ba9db5cb26d69d72a53451fc096d302db7232bddfd27a05c4ce01583c4d93a99a228ba4af839cddd63acd2a3896246780e979680e8c79
|
||||||
|
q: c7b19561c22b42a8a796a87bd4547fd31aca5a75b820a027c70f5eeb
|
||||||
|
r: 2671b4a2e397a9c62ca693db7ee272a70bfae8499fc40769f1fcc282
|
||||||
|
s: bb7434b0dcfe387f2cb023a62a2a660ac1494ec93b3e816ece16745a
|
||||||
|
x: 2a213ce1458288a3bfdf99dbd8f83cf1edbecdb0fd6a8308956fddba
|
||||||
|
y: a126c1e0403fbb64813e289b54c953f448cd397d98682ca7c182045a708d892872b70e397daf69efa4cac95d7e48a0ca5948ba0ec7facbe8a7b47a2c25cbf644a69d2ccc27bc8b86f40d7fdd393cb3add069eba49550a671866244948479b6c4619127f5a897d5f5609b42ab3ba22ff74a7f4bfb2883d5c8cbc6071ea87e9c557efcd6a84c90246b306aad6124eb93189a13f6669000f73e51066acba830d55ef1c1115fed5bd8ec196d7b26895a797ecaa4de70abde0ab6f6ad9836656e98cbeae16625516097014a5f7e0374f3d61f27377c922e1a576c12a7e39a859de9492d79cda74e75c0d9e65cde3695bc5bc933aa7174eececd3fda0c90581df71705
|
||||||
|
g: ad1cda5ceafc0f2b6e84bd184afcb52f90a5f7fb0c01d8c328106a88dca0d7e07603b88fa6d3b4fa7d188800c9f38a467441dd0573ee0c0539e7c604a3de7bcc0e45fd855c1cb5cc6f3408b475ae8e930cda83c751d2e2e2d5941ed9e7535476271e891bcc41c9cc7525818662f4d424098925f7ba5f944f940217ae20d9637dd3f656228f05aedb5dfba34400ea4440b85eb46fc171253e73eae0c4f04f4153cfe6c30a03da578608ed5575f860234cf7229f1dcf2812b13c4ed47fe53b739e1c704bf3470e8dde36c31daa1280c824ce573cf73559773164c251185e5d737338117c1636c3fe4e21e35fa7d33f6b0485cf3d445c6faaebd5dc7dd0ccb74a00
|
||||||
|
h: 200
|
||||||
|
m: bfa30f498a006f07fc8047ba4a506a1684f314012a723a527fa1c3df0020588db149af335a82ca28bb86670c54d196511be1a1c4e599c15ec988dd7e240fab25d478bd6ebe055854ade6a8ec280aa4ea517e711612bed2b1f8211426ddf3277bf99b994136e94aec9724cce31f69141e8b87c9d43f16c3fea3f3593b30c732eed46b202e559a35e807769ceafff631f84ff1828b21909b1f632a0452b374c650097c283f26186c5f43e2b2b87ad6a6c116076a91545ca8cd6e1a7ae28983aa26bae52337f790292f1cf89ac1a9ff4ae75b78fbfbf178fa740b7f45022949eaad50c7f63dbf7c
|
||||||
|
p: b2de996abd7858941ec76995cce8a695dd67d4eea4c5dd6b32da5d709fe347358dfe19bf67264b3ce82247bc933c8bb9d87c8d5cdcb13783305c52580da0fa48bc8fc3444e38fb2dba430de4dac541f7658ee59fa0f69756c287fa2b7ccd036c094a0178454d8e729f3a83a237982ad7365b6644d75bebb3339f77417cf742afda1dadaa582da89d0efb9864d822b29c05e25ae78e6f4f81f0450dfdf6966e7615cade8f94b9497f77cc17de70e426291f1e2b51166f2dde0e0fc9e9bd76a5413aba248505b0b82d4bdbcce4bb901d138effd67d491324e43586919ec5b098fbc2599bc186b3010d22e56f9c72b8fba5b68ecc39f85b8ece879719a0c2f812b5
|
||||||
|
q: bd762f7640b4ea7c39630176efc2072362b522e09fff305c9a23943b
|
||||||
|
r: 770a6ad47ac0908609c86272170c5d7673fe33551d2072cdadaea0a
|
||||||
|
s: 624c5d7ab0811768e7d2fb2fff8008d98f3e14c9885f095607e1ed27
|
||||||
|
x: 503f4e1f7a511c41290db2f0c8a99b3de8eff631ad8efcb0f693353c
|
||||||
|
y: 6f3e788ba66e87f5da758bde843d50aed13a993d95d27de0e016ee823dfcda0136f50a0b94e65b8b381f6090cdc4b26602719bc98f5d415612a95569b977bab73374bed374d832bc7af0ad3940e9848671925ce6f400715ec1e9091b901c95a8026de3db8347e9fe1c8c3aff7a0a943c980628b4fea4196737664fd57ce584e03574a10294950f243620a4b08705e6bf2d14cef5305a5691474e069d6bbda3691b456e7485482e9a4f5befb8c865a3ed2c4315ef9b60da922166af3b7a27bdf692f0bb7854928cb1205c90d4b3a468f48f76e9751d35980bb130e8f5d42a1ae9050dff1198d968f5c50dbae9abaebb492c41d1fb3dbca13e72a53acac0816d6f
|
||||||
|
g: 9f720f2ddddbfae7343032bf74328dd259862417f649cd36d3ab6e14fd686525c270125d67ded2af785c657792fa38403eba552cf6beefe2369353817eae539d70d2b3f1ee090f171cfe882ec70151df77ede0133507cef2c7f1bda2883f33589c1ae0cc20b261386cc665dcb3495517d211c91ae6a5f16e3ec95fa58dd5e30e3b956b7f3946334c8883a2bc76e97d65cc7e7d2fcab92bc2ef0ab3503be0beb8feb1503c408c7562c05e0e717b9c3b9e2f009881eea7ba3b8e84b24e822c430a2b5e64f902605a11adfa427dfd7a467863cb1316ba716f4a1231954ee5aab2590a9aa2e19fdbe6359e604d6db50040a83bee54f76b2404e1811ca48575dc60c8
|
||||||
|
h: 180
|
||||||
|
m: bef23942b2d53a674c7d1ef31fe5412e05d13aa91968d753e0651e45f258060f7abbab91b02515747bca4aaada151178c2eb763b288ee66e1c6a0b282cec44e258fb2509196e9f919c7fcd62266a441b5fa9f86e70d1a26959afe624730c319074a102b790abd7c2ec45d92f727447a98e65ee36d746dfe2548362be009c4dd8d479b87021edee43503ec32ba0813a9c9af2b8d196f1
|
||||||
|
p: aea4e8148c729129bea8c1bae82c792c90afb761713688220dd6cc31b09803df8ef4d6aa894af28f4b10da2504cda0a79785b3b01d8e517f196651f0870774c87a39835d6df61c10265db6a1625313e6342e8bcae50bae778998896fbebf02443e139425f2fa510762407feaae35b0c8438cf18811b69e15196505d82ddfb636cbbc699b6e8dbc468173c1c9eb75f7ce9360f80d98869fd8b6ad4381e67279cde4f73ce62feb91bb9ad7c6198f106dec6957921f5eda9b8bf3b003c2ee5091cd065ec6781ddf1a45702230fc0b7ef2efebc0ecd74b3bfb01c994ed3e303f7011dd56804b7d090cfcd27d358579ebe9b4b7a39e727f29fa09349e41c3f42d8719
|
||||||
|
q: c7667ec475c85e475f4055a2c77b5d44a42fdef88ab35341a552d4b1
|
||||||
|
r: b739e61d474f513228793dc4665e4d9522c93c0547f70d6612bc25c6
|
||||||
|
s: a736a8a51ef57d477e4bd7541187dbaf69a7284d08e292265573de21
|
||||||
|
x: 9e18bdad63f10c7926d99e043997eee297250044cf96b8b8cec3e0a7
|
||||||
|
y: 6dda29ee4fa436bb8c59e01a94209bd1b234e079a94dc696c04d13ce3b43e407829955deb1c49c102c8487d5e8ba4dbd2d6cdf56bd4b61c83595dda202e4e523eb1ae250fe9f6b76e5ccacde147a0d0f75cc841c15515ef83bb9eb5d516d647e5223a14765f8b9b2756c9ca2e113a746d93fda87478ffc924b829e9f5b2cb8dd1c63e0c60bd6819a8c5df4bb64036d35ae08f1e557cfcd9341b885519edcc859930a42cdf02db0aedce712b8125726e1ca96f22170c258a4533a31425b619bd63d38d9f121f4cea178e9410f6e16dff9a09632165de95ed3dd19bd4a120af1e0314a80e0a8f0aca48972c450c9eb65efb467e270fa2c09ec83f4c8c88cff95ae
|
||||||
|
g: 6ccc6a3a6e950cba7c4d01c0912d22cd8528270b2cf99d5d02d5431add6838d0bb13430a724e853c37bfb175eafcc8c23a9859ec55a07ab0eb37174c3fa4d628ea1d40a42b5f3d76351ecf8d687b4746780d733b52aa56d43ac32b3f5b9974741a0357414894085a67efd2b26409f41956bb0ff8a48768baacdf14c5bb5c199fad1db3589d07eaab84765cc32ad43e2d25c457e6e171c3e823eb7e540db0f9fb174b8c128552be562bba5056d2a3dd6ddd69532536d09c1239d0196a8945c95d56ac636c9b8cf622ec2be52df99c9b717de78937c2ce1311db9ec5a5f91e00e745e170704e38171299f851063972a64de76a69a1040dc56f4a6a43a981fdca89
|
||||||
|
h: e0
|
||||||
|
m: 547ec5b6b6bd4e
|
||||||
|
p: e49e05ae0d98d937fa79871a0124e8b8da5771b038765cd66e5df36b02dbd8fcdfa185fe54f93debb6f5b69678bbf647976ca2eda5e15100bbc8f144a27cc593e6079bbaf86d708e238eb8eb3a7f8a6408376657d390864c2c5d8306cbad4b6942a7c21c657bc5aed7fc2d8c8cd08f55dbda93f8ae4fe59d93dacd2f2cdc14b2e67140edbad64bbdb59d5bd8441f9b6af9d9019402dd9ad2457070701bcf51057d2a7a3f634e8789247c407704f59c83853ae6be3d3777a7eee021f42d940ca4a6e3f381c17342e626c45ce5d9c059c8b22380ef7473f94f6cd471ded0ab82a4b3e0a35a940b414a321d7fd09e878e324a40a90b55048b89c74342ae8c8bf193
|
||||||
|
q: 8d39c1fe21169a8ac53d32507478975228fe5dbb47ff02e08648b307
|
||||||
|
r: 44c0b43f1e82f68a4c153fea0a80c6491f831dc16f5a279b51a90391
|
||||||
|
s: 6b87473bbf573befd373d0f05739f1732a30d9fe1bf5399f091f8b3c
|
||||||
|
x: 11d912f44f94888e007bded07c0c0b1085b7a06995a7afcbd57abb4a
|
||||||
|
y: 8ba13000ef4fb7080d8eba8f652dcf82596b8d64463e7dca533af68f913e2dae697846362426ece2319e21bb1b13f7d5ae1fdf7f5acc81805eadbc3111f4ef810e25cc9c0e878ac739ee393a15cf047a4a0af95408bc298921358c1941c04869eeeda102c77dae198e0bc03f85455197b0c27f7923719d97294a066928744f9f82d446c71e6673be048c33434b13a42e5eb46a270b3f7fca0a4c8b31da562ca643d0364fda6d5bebf26a29a2664bc96df6a2346cb30b367d6489fb7d2d8992b957a1e16626c2898b8b2e457a5474f581f9003678a951a92d5e93a490348b11a201635793bff22fc829e7ba2af6a9d3c6f330c21a01283b5a5e0e8e1cdfb7a29e
|
||||||
|
g: 24d02260b32536be094a53205a113d8027026909d9bb8aec147cc74dcdadb3a883ebdbce8b33e78aee6c8729d32537118ccfddf76edc35323b87eef2548d1610ca2d47943e42f6eac7e48d56c27cc440460dcb3e58b23de3c3ad9bd110781b4dbe57349c70419fd24c495e3b924d1cc60b4aa814cced9b5c2a5d59640430ec13684b3534d447e1c60cf43cd461f72a07c79521003c0d24ce4dc5758957973c693ecd1074753e2a8620b4fb45cf182854fd889633c00d211eb985dcea8b59caaa02df8c9b0cfb213fbf19c536b444223bcf643aa76b183c84490fe65599815e9de4f2201baab1783eb707793a4213987c55b219b24f6c16ab0693b948f80e6b58
|
||||||
|
h: 180
|
||||||
|
m: b150c2118c1df086c44a89f5f46ac1e4abdeaf435ee2fcbb6c72d90047280782536aef0b6141600f9bcedf56ea09b60036bca9debed0e7b4b91873407b3eb9794e6668c99c8f997dfbf8eb34ad85ca199f804844e60a3419c710d2e29bc374f1b84b430770781909db4a5e15e74534ce0ff81a2b2f72793baa62e5e204fb846d1b46227bebd772e10370b3c78963e984808b589b7c5b9c3cd88a423c
|
||||||
|
p: 870c0792520dc2fd9bca856b2cc1122160010b67e74f122cedf31fa36a4ea29a38bbf025d62b1a6b6afe79bf31b824335387c5a2559d4cd2af13792987cda6d60951503fe7ce550f0a0f589b3f675074e6dc0db3dde2941927cfdcba0c9eb3997a35f13352441059cf14375357a8dc82c05eed2bda04f832302365ee52bfcbc5c8356671fb244906a490bc413c12aa0c2ae0719659b02a08735a89cc42e1b0da99c6aa14aad051f3b6a3a56d02d4501bb4bdfdc017b46bc79211519f0517cfec8cee0af4a437ad7862a074883b6040cfcc0b3d4b2d59e2e9dae299d3d8be0a2784a5cbdde1a3758f731b994afe1c6e5b5fc5f74720ba5141453cd0799fc8ae2b
|
||||||
|
q: bbe17a324adfe8ae7c52935477794d19b1900d59d3088fb540c58aa7
|
||||||
|
r: 29a7d9e218e6bf003339216927c05cd90d4d37d4ce58d26706ed96dd
|
||||||
|
s: 89fe2895db21e4733c5f637633f0c0d79d56ceeed749909ff6696fb3
|
||||||
|
x: 64fa4dfee78b6d8847f0161fd2d26c04314e7753b70c806b4e632555
|
||||||
|
y: 2e4a4b437ede304daad0efeab79feb1119111d87bd1dc0f98aa9fd8bacc37bd2043ec095e742238fa4479cc2887d75400704ccd8c967ba2780ff9d47c189b4fd2a3cbf00a68f88ea698dc355b69121a4d62c08c0c5ac1ca5ef5cb19e849fd00023549488683805bb6f63ce96ae5bcd723c5661668f3273a693680982f162174db275cc8a0a071653b565e53d071195ea39d6f94410931ede20419b337104878560efe1ba357cb5cfa0d87f311cf4829e1af228eab9d9fb891db708522af104cf610641804ffe6e0624c763d877666ae46caf5ef648e2e6deac505a9ae3837f0bfd9b8f5bd6a2a9729a5f01f84189dd8891359dccf4320fb2e5983ba1e9a8727b
|
||||||
|
g: 75d64323ea53c568b87322faefc3849d7ef7b8c6fb1aa47e71a0c3005e1c9383ae1790d7f68bb486128155f19577c971ea28b67695cfda51b39dc0f5f5535e4dde6f06eddae53489c8bcf4567d6307447846398f27aecd72cadde56370bacaf4283d95e6f361c1e2695b0fd8dfbc22e5f2a6e6fbdefa1ef3c75643146941faab401496e69d5a0d56d8875598279dc017f3efc4f640e11438f235cbb496372d246049d5e901e4404ed851714605e7f06468dfb739c328ed7d11a569eb1f3b383a0326f6fe0d043a812a96de00a13ceae3e3e9cbd118df2f5e9ec9a8443e36e641523f9b844dfaaa54e2d763aeeb4d53e27f15bc695214460eb4147b8e26947572
|
||||||
|
h: e0
|
||||||
|
m: bf384e
|
||||||
|
p: d80499caa0cef1cef769a2320f0c04136bab4940d4acbcefc898d1e776799be624bcb5ab57e677079ed3b25d425adb0e9e888eee1d7bf5f83c11b184cc80390353990777b042efed9a261672f5d26254815e77dd399a3b40f7c7444c191d187a3f307ebcafd2043070776d57e0ca71ce0f8856c3b629a26589e2b77daf30ae1a63ec68a3057c673638a4e08dd50170a465a4857635e2dc51b1dedf90c81bfa94720d1d0209d8063003e3991903a4b3fb87013affd1dcd9aba87e3d4c4c8cff62f52d3694d9d98996021ff22e2183d9518f001dcf5222b5d2d99fd2d1c6c44f1d424dae10933873c78cd2057fd820a462d54c02985bda6c02fa84d5915426dbf3
|
||||||
|
q: 882fda1bae239cb8c0dddbd407b81f8f97ccf844fa553f8fe4be956b
|
||||||
|
r: 4a989e11a3b887e41964b360339c3be052396e063125a96a1658275c
|
||||||
|
s: 6f0e5c344f4dd476a18dc46e60c09ab8be50143792ef05b0df43a514
|
||||||
|
x: 6e56d6b89fcbe580617fcad2950646f931e13d4ce0d8806d1f9a14a0
|
||||||
|
y: a3722cadcac122a472d23f0d3ea0c5a4992c2db13535b2929154012b12024c40d4016f22ff3343d57bdd8030411bb89dfa1774b88a2cf533aa8531cc92c05e93610f5b5479d4666ff1dcdc1dbf00601c5b2e441a2d8a6f054de54abbadb84875442d149d8ace871230bc67014727aff14e1c104257a6db58b3a066b69310778b7e2c41470c92f2e2f6e270474d9cd346e9c07105b55f15e9eb6a280132c5f608a95292ff20e6f176bcb4e3b454b34813cb9b614963f902ee3906b54510bee99acebaae5274c72818788bb22462d75cfdf1e0c085eef1a61113de867dda6c858cd8e50057477e7d9461ff91097133fdcbba04f12dfc7022e004a4a9e72791ef64
|
||||||
|
g: 87cfa3bb1cc15dbabf2b225167decee1480b8c89f9666b9e0cd39d37221e262190cdf82dded05ce000a1c2a11728385eefa779a56e9fc8aa9b81620495039f53cbf5ffc3f5080cfc301fe5e1be779aa8d71c06534259d6589ce7c201f9e517db5fa1800a5cc61f00abda46a9965761ea7969fde497b5e986419bbafdd2b53ff311a1be4093a749ade4ebb6409364a65e24c8305c57774b3ce464d2b37d76edb31894f361b2ca8914e4e738a1ee142f79e3f1401b7be42098b564bc5997408c298d3d60a5ecfc0a0f63cb5100e59750cd2310c9aefdbceaafdc7b2f0837f9dcb1c1cca5a0e160685f128fca4c281f163960df10c4b8d79bf21a8000f8b19a3f52
|
||||||
|
h: 100
|
||||||
|
m: 66017fa571ff11823f5dde2e72e48d55a67a4d25191bd8214c22ec25b167f17f16b913ee8bba7dab1c44782338667bcdc2b92c2e2ecea951a8e613665ebfd996a2efce1ee8a4ab9af26c154f112de2cd318324ffc4fef4bdaf997a69d6464f485be11864b950765d9e08b7cd6f05afcc0095d70c2af1dd023a9921c989ded4bfe4f7ea2972a2e3007471b6adac16529fa6e3
|
||||||
|
p: c9017cc101cc911f7f7969122cb35db8efd7ad372774bc84913d2d16614a22f8936c200711f493d87fdacb50b5a906d1fa6f1d96748f9c6bea278aca7e083a1ca655981279ed5d6cd61ab05bf66ede546f61ac25df55bb06810a2ca8bb29f8b9d67d8b347de1acdd2faab1698cf802cec24014804902fcbc8bc941d4e50682ae69959001b24a03e764aadacadac5b7a0d26184a8d464eb37b16e378ff5e3d0e65815994f1101b132f188da2351fadbb6a52bb01e7ee3bbc2b875bf0c3974b10cf3f5d335b8c91e294787addb02376b32c6dd1b4dee08b142145d66d34b89ec8e21510d3bdb4b1b29b94905af6a41f42a87fbe77d919050900d4791005e29869b
|
||||||
|
q: deeca54c111337f74a78d8149b05528b38a5f417101bf2cb6d692e49
|
||||||
|
r: a30aef48fad8d9b9514d69c0af32a0089c6e9fb629b63f000bd9c256
|
||||||
|
s: 2dffafafadf39d3b1b87cdb84a95f0d79f762ec4614767740bbe657b
|
||||||
|
x: a06be67433792c022d6c170621a6c89968a7afcb0dd513524ee7ca76
|
||||||
|
y: 60a5b1099c07b8067cd41d5e389fff4137fb1dbbe2dbf016213b3ad4ea1073b654cb7876d27386352a935598392f0723a3019d2284c7211538da25f419bce0fce48fcdee3828c3446e7634e9c1ed0928bd4dd5b07f927452e5584ff93d66ce5568d74eb51f0810fbfdb4313a4dfe5a91d296454e76613cf2be780797ad0c5a64f23ccc22d273be2bf39efb83a345218316db8eaf0f93ac0bd96e453d83bc8c7567377150db9a9327f823644e0400be8b76565a908044b1a30a03746d78790a6d50726d4df97e7e57024162df16fbc11efc29ef34972565b6e634f90061ee1d652faf0ee61ac2ec39da1b13804d645794c8faa1948279b995b977870ccc0561ae
|
||||||
|
g: 65c7fe976d82947960c4d1156c5bf92ac3c90283521846085da562b362a1ca1bd1d98a7a3dc4ade86ee9416c9be1d5268275796aa517f8af3effc432b429ace3c9f3b0c71b0c88ee062b2e27517972929d20c6501076508dc6908324d90086fa521e393c87bdb5c735ed5826e332683dee742c09b6302027d23544c597f86413da5a10f62e0d21987b683a9821d37a6c30d062346cab48af6b864617e1bd1917c3625029f4dcb9741b1e6e3d7bb2db592ad55e71ab1e51da891764d1aef7c9236e50d6c4407856bc12810383ad2a5989cdcf0d9a7c4d33cc8ce26e0ab8b12053202140d5a366bcc46f36a0e5182a6db043c81b7ad49ebd7630f0b2a55ba814c7
|
||||||
|
h: 200
|
||||||
|
m: 2a286289942acdd9044afafc7c8756844152f5edee25b172fd8bc5753d7615a3110b7a9226decad5b21ab5b901a35db84e51dda33f8cdd8360bc0ad264ef7ccf6eb426fc85bfc7adadaa6c3ba1f935364da34b3137f5722cf76aef99ea5268c87d1d3e524cf07c3cb1295b63ac43411df41d7ffd9c53bc9f
|
||||||
|
p: df91aef428570f4b57bedfb3eb6e8cc693bd836fe42714a97051a745ac8ccca3d34fe4fcb9c2a6b0a902158040a1b59091475215feec3f372c0ecb32535f3a27bfc6ee5fa0b82b6cfc2c4bbaa2f7b9bb2fa1bc50de2386768c4e38a1b16446a33168680dfba73dc505da5b3a0dc46f3d2de07eda7fed186fed3b5501e2dcbae365b79b0963e45dea6c8542c832b326696c6fae7ae9b0745eb7c1480e21f87627a1bf31bd4a41b26deef364732fe2949f1fdfbbf6cbf0b51729306ec3f13ef14475796b09d153a12ae213ae8322d53a813afc777031e8ec5bdc6c9a2ce2dbf3270966dbff61954b424a3e53153c5abccc8675ac71118930032ba2c8ae970ff8f5
|
||||||
|
q: cee328da11f516a35849de75fa51c0ae9dbdfe3ea5bfe2f55f7a6b03
|
||||||
|
r: 41bd0317c0048d46f200050f495797048c694e6433504d486ebd5843
|
||||||
|
s: 93e710dcd2e257ac8f6f166692213047a44fba8b24e27a3a7590668e
|
||||||
|
x: 984cf5a76065019b711ef6b5ae72d1bbffcd9cca79e37c4bcb00b0af
|
||||||
|
y: 7fd0d6268dd833af64148dc33ab4224f8058e547bcc3b268a2064f51afdddb037a5c01e0d9c2c1bc19df22de5b8767fb41654b108615d4a3e2a6e2170c7b971ff6c803ea858b588713f398f0ccdd99ac4407544febe42dc88a2712836d507844116f149a4c3c6d96e8d602d357c1322d7c7b9aadd866e397249536be9f4d0be95219d302e84e8396473313742768cceab366b5ab1a330f71e46ace15d27a2bdc240015aec976b24791f071df4fe17b0bc058106ae77d7cf8c97dc12bed26c549b0764855d50942daf43c2d57e86cb47b33012ed235d641d09387d07ab7ad9756e8ea2d328f325529a40253cb2138ce37a3edec54ad025b0c8bdb2c4d62559f9a
|
||||||
|
g: a9be072ce0597f655c690378793da14dcf1ce650e373de0f1af5e1aebda1ddef4500c42dc01a7ea69a89a90ef0bdc6e22e033932dea4f8ddd772db76f8fc06c9bea4b46f681d064673c54f50a8bb1264cd6ad1f0e7fd3076a3b218be4e09f3d177805c7e4baf11c0b3ceede646f474b61ed062819946332d4443e01c9b60236293f530f67a7201e01166c5b4ba9b142cde3205fd52356adefdef6927f3aa74bfad2b8d7b198fcd585a522a82b4422b7b8a9f1cdb5947b7b5742bff6810709b77887b3c03450b9691022f3223f323920af5e9c7b94e33dbcf7814160062326dd01de5c8659acee04ab27b37909303bc0f25c9b2375b8689ece7aab5e5ca8a3d2a
|
||||||
|
h: 200
|
||||||
|
m: 03e2e3fb98375867da816add8e6d4a82eb4ca778101fce0baf67b06c46c5f131f82772db149f95e354590d3a2c14d532c86f1702b42dbfd4d5060c094179ed49fc787707fa4cc2652541c8b3256af2aeca0256a60ce70c05baf343da1b0bccc77f7a15b4b018cd341e4f80641af7fa44b7db33ce23d112b0736b96c3366251feeec284fe743a7ffd55da0e481cd2acd971f7b3acc4757447d0fdac7c1ea5238eaee8cfb05f8a52ddb8725c6a8a55f17e27d0eaf50caaa8cf318c44a49b222c2c84a9f27189380096af3f21c0adbf92c543ce5cc06a1ab06ea6a51dfe1fce04a23792aa61
|
||||||
|
p: e3eb6aaeb1b25c3f3078ad1f9acf04a47675b1cedc136bfa87d7ef07639d7a84472b74c64d2462cdf94fb27abe102d3082bc9fd987fe5378a3458b159752e1de6f29df51b73e1163dda3e228a7350313d05e90e7cd5b918bed71ff70d2a9b6925a1eca4cf85090668a985ea38a43275bffccab4c4b8983461c9f855e0ff249a13e97b5e0a42b3752cb186e1024e06c33e69a5c17a196a57262e324cd976f6f71838a21914ddbe46d5dbf9439d11d27ac8afef0e24857416b43332b947dd7d46d8ba0bb15343d614a2108f582fb78fe32301189ec04d6368e4b13201bc762d8007716a86f8003f6c5cbe112f359ea0e848115dda6ca3ddbeb2a82b573817116df
|
||||||
|
q: fa0e632b3da513ae32f6945311381dc0b8b2f4602f69c45d2a613c79
|
||||||
|
r: 7dd67a091087c056f7e0c7fff9455c8717b8929491186ef22a084161
|
||||||
|
s: 3edcc935a52abefadaa6cb8ce862a019f3560f930449c6993481726f
|
||||||
|
x: a383e0868354b9474f3308274ec3cda9c00757c4eb56f602be31d6
|
||||||
|
y: b47df0d129b4cea76fc54829fc2b2f731794afb2342afcede8865ef1a2691e395fe1c4878f8243a16ed3438bb6dcc4f2f7a885a9e8343bb10dcada27ff68d6dd448793adba320eda2158ce647a20b0d01ffd8b563068cc515a0ca14eefed9d89127ae34bcd5c83d6bd7a94ae7dc2028db0125e536b3ff5bdfe984b1b25a16f2c90b33e0022d7f0ca7edc55361a308c2bf51656f622edb05d5b3bf40ca5ca50497ce05dc27a8d132644e100f8cd62736074f599732241fecd416566f85ab35730e7c0d17e5283c42808085979111235969a167ff719f07e50f3756e667b6e0d3c6709daf01c5fb7cc8daa0a935c9221c252fd1db33ad51979d2e332b9edfae6f8
|
||||||
|
g: 6ccddac671b83941e71f646b9c79d49557f321be8d3c12e6bb85ad192d1087f4ce2d1a0f50f3bc01fb25040fdb693e02bc2f4a433058179a1e55a53aad116b2d57df58b95001e883c6893b77f733bd61df324a861cff3eb730124839b1af3095eb2bf42324d4a731e2e1d496a520cb3fa5939d162c86deff3351a88149f0ac3072a37b2a088996cde1d0b01d8a9c0504d0d271d92c6e5c181359aa556da45cb3b41e92c972a411126507802211073c96617535af1126b65ead2fc04b1fd7a386908d60e7ea87f31e31e5a4389a6101252e3cafc98cabfd77d7b098adcefd5027bc6a3ccd4f12760e447628b36746ed78dc2c764d515e4655edb57fcab8256247
|
||||||
|
h: 200
|
||||||
|
m: ecf0ead39c463b473f5dc14f5bc0ba7d3fd49c0e0704e71e17279bf9a4f95a57d5fc318bef02c8c8c9cda539c1cbe39d15e03804326c1a7640292461405558a215c3ccc9f3d4137814180f31cb638993ba5b1f67842f4939bcaa59a893bc7263d3fb5f8c37de90bf57c93fa0f446f7c650770b62026cf23d4c3e2eddc4fbe2366c73a1e83bb5e7c4d10991d9f9975d56139e11025f5d1878f080a065ef74795e23689e6036482c92e0a06a873dac5618995b9d51d1a9b88f9b1fc28d2a13a1379eddf682198f9cc6d81281c88129f7532af7c3d775731ebaf3c328ff5c913241dde4156549fd1ec4a17cbb4c7d9c
|
||||||
|
p: aa4f0f1b4465a34d2c1b1e6a1f06744908745af870ee626d70a8b64a26682a7032063c8238dc2b49a6d46ba4c4f7935db689bbdeac9924c655eeba70fbadb59f6357921f48b2683c07cb7185d7333f38575b951fbeff8d7e26034eab1e833f400b3123233ba3c77dc6382668f094ae42d7b62e7dd74daf5976f8bcd0ffd2db75c49744f21c58f70822674064107ebbabc9da9b675ff649a2d5c26c98a106fbe3075a77bc68e9bb831218046bc7795a7ad07ab068a7c9f64e4690276a43f93a3423ff387a16935d4eb2367e9f94c268df6c2debcf59392d4b9d38d0c13f432771110e2478dacae7f1705563de33891e63c4fedca7b40cf261c57768b3f88d680d
|
||||||
|
q: d824d48630ba78ce49c0ab4d3c5ae2673f9d2e314f89e14d7d68d15d
|
||||||
|
r: 5a80062bda389b2a4416906fe797e7e410bb7f5451bf616cbc9c7f00
|
||||||
|
s: 856bd4e2e5bc0dfb9d2e524b1d9454c563dccdf7d1facfaa8e0f6420
|
||||||
|
x: acaa6a3a87bafc8b3b10bdd8c0ee9f81bfb72a8c21ae5dccff0c7574
|
||||||
|
y: 53b5865e147464c8f36b74c0f8616bfe8ca4e102de9541d630b849367c174535dc2a03e1a8576dc22ae3eb1826e0c0f52455ed670f7472e243643f0106d812d31480fac0821fe6801eedc6b8983e214448da514a049474ef848b9443dfa0ff8299ca6f4d5aa292deb830511882fcf12ab0a27b28eb893298de8463fed0ea2549c7428930fd949bf2d633d47f8d6392c4ad7cfe377ee31d87be9ecbdccb731d783409a1e5b42142df078e74981cd5cdc95e8a5cf3187160372e2b699350c67a9572e7452bad8fda89474c5355eed20b07223b44d0152fbe76f035878677b9807450e4db62d7d41375f493a926c3e76208b9c36fdac19aecb18ed83ecaf820f8d5
|
||||||
|
g: 870052d6f67b4807702c6169dd6c3353c5d5f46aab6b72f27c846c455b1bf634762653246be07912b5cbf5b9bf15af6e3208e8cdd305e318bcd729d024f29798c0aa250b0065a2b1d8b49ff8bc53843e83189ea261f7fc04212968c199b52312a4b946c0bfb72492c298cd5f1065627fc8b975824c4af69180dc33ac7f1f221ddd8de7ffade22b09190b195852680f1706abf49d13c5cf220a5a055d7d73ce9a24d8d0941c40ac92307e4f7fe458157539795192ae4c0bbd6ab6c6dae5240eefd08755ec48a2bc743eb103c02f0fc76983172d164ffbe0cd01c9d4c9c7c4002e7de59ea3a3f042b5b0349fc4ea483de5845b7deb42e9b353a01548822a2a9396
|
||||||
|
h: 180
|
||||||
|
m: 10f3e75820ea903122854d32e15052049840812b461220b60a7f0482f51c7cee03ff17d278f2d17e7dffa51c8f402f0fd418ada776d9c38b44b603a945397b63f508409122ba89131886fb7a75a33389cbe0ca129cd13273f96002b1a892b8cecd435c4c9bd7fc7de71183cb6af09e06046db11802c62d40136b47d3509bb509dbfb21676df2123c37cf6f2d71fa74d4ff4de0856a78c2504dc51b2dce6ee8456a43b49c7bd468cfa8d80aa886386970b0f0af419a7fb159cc46ede50f739d046727979de6bade33ca5ce45ef98dd6900d64f96d2d
|
||||||
|
p: a23a425464a2caa7d94357f27ffec09294e1fb44f638f22a7dc841a061ea05cea1e54ad1b5b806e08950575bbfa6c0fbdd18449ba73f566096e9733debce6b5a292227c4cd55ffcabbe57c0f381f3cddc93475ac22efe9ce61ef93adb92905579d0552e94786f297dc6f31e310c54acdf1a240c22b808866ecd89f1e78d72e82615ed5d34693a66ee2b05c9f1943929c66f4322b23d47c92c1869f76f4e911977e154fe8ec197cc95edbb3492d4c70b36fdc720ffbb0d9d35ba6b83e6eef91317ba1e989b63bb346f8fccdbb0d8e35ed6117525e91ccf635dcf000120f30e92e41b7bdb7719b3f0a9346fbdb0ce787848b2e4ab6ee9e84a087f7b703ce808575
|
||||||
|
q: d739719c439d4e5f60d8985b4b26a11f0dda24bfd36c50928eb61661
|
||||||
|
r: d5420263086476d3bd55339c3d8bf8be7f957bcb90be99d6a2d0baa9
|
||||||
|
s: 862918007c0eea2b009fe66e4693e3cd1b3e07baee85a0d842c310ae
|
||||||
|
x: 72f2abc751911ae780649680ad28cdffed45de61adb49c3d12351d54
|
||||||
|
y: 5ddcf7962244a259abcec9bbde726bec6318c6ea28a86831d5f5fcb671e7f884583249f179bd2ce947acf843bc871a848011ee0cc07158681573902de1fc8aafe7fce113b588205d9ed3ca20e645dc5f677cc90d058cc048607246aa6c0f3cafd9f7104b3f4951a122c8e7ef44963f911df7719b578fb119977cb6f7a0e6a2355e20c94da8fccf9df99af24c99f51840c2a4dc379a34838bd4972a2a71df51d5803f221075951fc791126ff54dbb85cb1ec2745b9542a369dbb30c91a68fb9a163883011a4d2cb11d74838af7f3b89ff75910672fbac9c0b483958bb720df2e4391298df4759c0d112e16ec85655398e4ae0352de55b99015d07265db5a63ccb
|
||||||
|
g: 26d622c515bbd2179944c8d9e28732454eed9d7c4774c41c0bc71780932ea1bcfe68fb629f6a3fb2ed9df294b97e5241e4c7a1bce749205ad116feb2c67d1c52a1f5236144d7b1733a5bb98aa3107f0e54b3bafb8825b2707ecd7dcb18be0ecebe6aa34e2ecaaa508dc5cceff9a136da1041c7bfed43b0e9781f97f3c9bf843df70c207db45d5bc234521d012bb9f8a18ad71a39018e1034b66ce75cd6325ea51af2cec370f3cb29682a68d70f9c62cda8f93b738ce8247d7c87fded0be6cd4d0d5d89fabe17fee92fabce76e8b31aadea9e05e1e63b2a96ebb7cf5a841f34e4ebc211c1b23c1a143e658a7337d5a8ea6de553e1e55ad2d8cb9171b41b2f6453
|
||||||
|
h: 180
|
||||||
|
m: 959c8778fd22ff7404169432a96b20cad155aae3ec8bec2467cea98550909ffddc1a33de9490352a1625003835b2e2a201db12fb285b216b5fa7ae308b45fc9ac97c72d4b478998a16dbe1670ca050790df68a6f8bc3f0d9b89ac03932c1a49fe6092fcf521a4070591e3c08137e935f68887cd368800ed56bf108b1214c0e5fa3637741586bbe35b99840dd9ebe9856128fa7eba2895e3eb910474f
|
||||||
|
p: 897fed6dca830b525e7197dcc462505366deb5c0ecee0b8dd86e41c99046acd058a09ca13c5d400f31a5d54562dd77034e73d24c55a9056db6e360d87b9e4b488e4bccb81cf4832823a004445e2fe18745a486d7971a97bb3aaa497510922ff65fd0679b221ba7bd0f1c8972bd19d68ad865e3de8056d963ed4ddc16089640aae8476a2dcbac5e2541d07d3ead334f4f82ad9c64a69c915b1608220e310bdf8351d8f54503c02666af38e40248d2525ac4676b3a694e95a447dfa9160bf14cbeeca3e817ba296b3874df43b3cfe888869e52077c0aaf4afa35e85614bf2da71812a83945fde37e3b9959f33b2813ce464fbbe4510940ecf4fe95a481fc0dff39
|
||||||
|
q: cc4d76b5dc27dca0f50fa9b0b85b67c26f97de6ebd9ca59542aa29fb
|
||||||
|
r: 6a20c2c5f5b5a3c44904b587498e774bae29e919407a18c8ac1df50c
|
||||||
|
s: 1a31e5c33580eeeeff765e8b70fc8193b4084c5e0aa004d94806e837
|
||||||
|
x: 4a9aa4be9fd3dec0d6f00738a5713053bf704093798fff301f4ee30e
|
||||||
|
y: 71b9dcd25aa3818606e7989dbb5e04516f411dd181d0a937c2dec0fe0081dfb7b9ce73d60d0a567bd42297e644efeb7fdca61df2956558fa9939b838b79320bd91209bec0cb277d1cbeabedfd239c41d2ed3b9b5f68c3bd32e71bb138759e19f667c461a16d522f1ac0984201305eeb58ffc05173a5a6017e2cc931804f78546eedbe69da0b7c2748cdf77636ef0473bca4beef2de8ce28153b9ca282a06514bb8ced0383b8665bffffef01e26478732e722b21cdc9b52558bed81f0c5c9b4fec5680e1fe090e72e740a6dd475365940a2c644faefb6cbecbd81c2a57c0b77f29c404fa53e05f7e181fdafeacc3d375897cf8e9f173519cf3adf5966216028f4
|
||||||
|
g: 10337c43b477e5510f230a78535ceee07135dbe749bb776810415514cfe8340a16a45d3b48a5f12158eca59065f1baeccf19816ff068ce00d609330cc29dca64f6ab3968808fa95056b3d576153b6febc23138925beaa651a584a04f55d0b7113e7aab8ded9622aa342eeac8f89b0efe03556970cd1150e40c44fae3fdc01d2866690b349ea9776045e4acf22982f18f7737f367b858c617c142f0d07de9231b59b156fd387acbddea610914b666593a76abb5049d3eed79a52c6b30dc5ac16d1cb7f37889c50d9a90ce89c77e2327b12be744ada98afcdb7d639b266f0f339c052dd994497846ddcc299d15a8757e3c1fcab33f65227dc7059bda459850ae57
|
||||||
|
h: 180
|
||||||
|
m: 499bbbbc79e51656368fff15e9876c31d1fbfff5eefc7df438ac553eed3821e53f4dd4db57414f72a65f71c406065d330d57b39e2a8fbb5f477c50557998e29de7134c3a30d95d5337d9e8f60599cdda2fbc95c6f240b97930682e8b092e05f1ecbcb8d0a9db308c514d58177b16c47a2c531861daa4fe9b176b595230f19a2106797a844c2b42438d217d793f
|
||||||
|
p: a299f58d3ab277dc8b7f426750e49a7954f0ef3201ad9e73c6a772f8d82fb391af4b4b12ecef240a4fbc664af4c77f443b6f449b937eeaad23ac1693726d88cf9a4d2597eff61cb884dab7c81c25ebccd2d4f77c5080c153aa2cbab4a063605fb71c677df5e719bd707c30a4c6d98e6814e8ebf4b65910f99aab6a19705310a5df460659689c4680ca89c04334cfb82e5bcb56379fcb28ccf87ef28ad9c946b77d309966004aaec1aa262819990a3e5207200758debd7625959e012e081ec2af78ab90908f962296d62faee66ea47168da2e6f786bd9dcdd7dbed963ec34e582a68c6c563dc74c54509a8ec3189d866d1841931b08212ca3087de19081a1ea7b
|
||||||
|
q: a156158c92e1087e2311411d59899b84602cfe24fe8147afe612b075
|
||||||
|
r: 19da8fd681dd05eaa164c76bfa898118a9a11798b636c9195886f4e6
|
||||||
|
s: 8a56ed8bd2acd2ce4c8957dd8030cd0a8405f755aaa968aaa136f6d5
|
||||||
|
x: 4930cdb1c058d93a3cbc0f48da2a90ed5a5fbafc1cfb19d6b53dc8f7
|
||||||
|
y: 9945530acc4579c9e2f8d24a2d1d108c62e7e88adab1c412713a571160057cc4f46b9856453b2e730e0cd3f94f350e70b5bafada6bf20073a01ecfa85b4937116fe09f36868be9f96ea8b9385dbfb5812550fbe5d0c7f00dbe12e5df66f7533079b4f55fa1ce2feeeaab3df86ad074caf682d7ae5f940838f2fb57ffa2700432e11e4c2a14d63ec6b7d718fd8993fb04957e12b046833f9dc0341b7e4acba9d92dc32346ef74879fc4b4a9e3c634630de3d7a32b5a14829db8c24f44442ec807945cf01f9e67af574a14597ca2f3e2602214d4494c1047e40b1a244f64a63e846746661186606508c89248836e48939c3832b03b032a2a0c8bef5e50356bd5a
|
||||||
|
g: 5d26063f4f8a1e60f6fb40ae830a733c01ecca3df07cb66561f364fdd227bd203d3b38075f0388ed2107feb8c95d86b6c976e6a8f38ed55167ea319bc14840c4521ff869e1aca2242cef6f97d920533b3c017b2910630fefd5470a3d982d8ceb48742356f045368da7743d4ad23436db91309331437bd8bdb77647dc28e6adcbe4b874aff4cb9f30ec0d92a205e0655c63d0be2c9c0b35d7a2e9f8936908ced6926ea5884f1f8534b0c5976fa2687bc4111007f1443b5c0aa67d99eb883cc50d12ba7f46d65de09cfacad981c4bc4036ce1fb32a84b4bab5cf9e0d04cbe0784d4b873ca11e4f6b2c5846e4c93d436d81eb6f171e855b76dd42a04791f4cc325a
|
||||||
|
h: 200
|
||||||
|
m: 1a4c514e6f77d885f495cff2975fb8d27364389463baa349bf9965016501279e043da73b019c3fc0b3763ed21df468a53de5a333c8e4b5795f52f2b852707f6774dad2ad6c7b861a849a3f36cad47e85d9a85b85af29be54f38ef2
|
||||||
|
p: 8651c980f2b9a6f61ff50b21da3ff07c7c3e37b7e3dd4b39edef8d84299bb6b1946a6cdb56fc81e0742dce8dcef0b7a7fbd8a63ec98c1deea6aa597d647b8165f54bd0874ab3985cac3aefe50315936451fee2979256729df379048fbdd702e66fea94e0b873744701ee20d45e10dbad24c78480f25b64b309b77dcf834feafbc72213ff9fc1eb1cb5b2a3594913a27b0de3d6d3b2a6c80df6cac24a16c2a19d42d6e3fa16036bfc367f31b4088d57d6eaacbe428601ff239f3b47504481989394692d8a3a3f172cd6ce9cc9be42977da1610e050aca4f9d89e87b2280c0c670ce58ee0ea7a78c2b068e9a496ff38b3a4f1c18a9df9faeafffc65a9bb873720d
|
||||||
|
q: f56b14311c589dd4c332753aedb70c3a50525c33e4264c70ce4ec443
|
||||||
|
r: be7ac9e696236a3c6f43a07d370337244db2631f1682fc517d904d04
|
||||||
|
s: e1808b7949dfcc5f8389ed4cabce3953f49edad6005d34381905c9a7
|
||||||
|
x: 82989b208424f015e5fb1ee768ad2decbf5d8e948a2c008a9bc06270
|
||||||
|
y: 77fc554a280753259d06cdc97926184c637848d0483ac4abd28eafddd26943120a39969a75fa58341dd8d956241862e98417f239c9a2eaae82870ecc179320c7a3bc546a6c88b0a70962655f15c007744dc106f87d2a4c952ac8b10c24004c11ee022bce91a4b31cb0bacb861232de4e0f85372a8d8d869757fdaca54718ac1596ca11640bdeb2fc42c9a735871c0d6a3d07d2a08bf80f51868f383a5b106132a59ca19c74dd24d1e6bd13cc00cd8eea871bec0ddaff15ad67478d11f30b2d72d22683514bd5205af8e438533c619a3425201ac1c3df40d058b0cd1b24390ccf321a25a186e8d24bda71cc735b76b0afb2d61ec50dbbc442c0765e9e3839482d
|
||||||
|
g: b55604bcdacbfb488912963ee4d2bbffaedcbc8d790eecd9f624f469fd978bd98d4650bc9612bce1f1f331ece2682d0881bd655972d6344049b58e2f6e370eccff71e37c062b329af65363a60dbcb86df5d8ed338e7efcc46e007b396cd5b55e38e38f523f3c5831f42a65f999e2b2c65f37f6fca68b27658b5a5b9067c95a655fcc2f38dab529c8bb6b65a19788e8c545c1483c54adb7e2d68b25aede56424767f7c9060ca05a602b71d70fe409ceb8153ffd2ee3cc42b5266ee3de79dbd9b8ec2e3823c7eeb6cea6d8a2e8e1402f604fda488f17ff24dbdc9d5b6621e96a1309b043f46f24f0dfef9b9eea64174b0eeee07378e9fef9f9b7355cce97860a6d
|
||||||
|
h: e0
|
||||||
|
m: d6b8f39bd05df380d28bcf646bdb703b6257b4233be8866843015ccd65c07bf8cf58a2838a34a81a5248bcc96cc01d45b08ea1ac96fda2316736440da765fb53318e720bff6afab7c9d2b97184541aa9f524b307b24783f2a5f51897cbeb14e14abe575d067ff5c5c5d44b729f9887692d1cf6d88d0ba2ae23787d1f126e6b7d751baf614ed5c77e01c220ff28e78d32c95b1106083a195a988e59cf626f210e5c577f44128f7f59540402cd76e8740eecb5f0a1d3d1bad353516f9bbbb2c69a31731ac6177649792704a4cfe945849f48e8bb03b96aa92e277c024df6b37b231d8d5549d286580d4eac00781341d2b91446
|
||||||
|
p: ba9ba55eac9e2d9d3c971ecfb3fa8c608ae90a9ebf580e67ee02e12f754c6eb912e5810f95ff1dd6e7f3258b339057ca28d9913e41210f3f50ed88d2f8c9079df53a12abd18833baa575b3650910c6cc9545474b53e61ad953d8690bc1d4d1850529ffd66851ec865e1e84033ef60afa2d1e2f3784b45f3297096458893476a68720163c723e9cf86005859caeb1f5f0622f93f1e501c7205292487f962f2aa14bd0f5c9d8f21ef3f70e2fbfc2b2901c87204cd430d1cc6e755e548729689ba1b099b84c06eac344dcd62552f73b33491130fabf5df5c3b7c8eaf472e0c151a65f0f7a2e5b80ad3bef2e3a83f1087a264a78437907017954445ba07c3b6242eb
|
||||||
|
q: d28c838fb1af5f837faec31f9fa7cbaeb413a05da20e0b865cfc0437
|
||||||
|
r: 5041b1dcf6e79b46e0c1863b4b556817a9b0f56dcf6db2c19313b1a
|
||||||
|
s: 6a004f442294b7e7a058692ad67e94f423b55d004f93b0a929000a00
|
||||||
|
x: a8150a7de89514a9010c7cfda8832705dea0badac2357dee732ad340
|
||||||
|
y: 4454acd4d4b9369324c9d8834919f1a284f9bbd63a364c56cb01a4a5e22882adad02ab816894e880565b695af1a253636b99edce3b2df155bc28422308fa70f5f20fbd09826bb3dff0bd2ed6100949ca346a111f97c51a1aeb46b6b4aebfe7df61868ff6c641738c51f926e607c5795ddc9a203e578e0138b523607f12f96bff805d1a8deb30ece68c97964ab06db07a38ca633e4b0dcd1f3feec754754eedca917d5ffd2ed503ff4cb92a2751f282d97cb0d4b3b05f9d243d5788a80c01df81d73dcac4721807559fbc4730ad85c321eb2ea464000d5d89d6f4174dc0015c38276773d0382f359364979c5612f965e33ec8a6bdef16cba505d5730d1e302e51
|
||||||
|
g: 7c3bc89ec219b37f14792421727b7a28a95fabf502dbf398450fb348c7f217f79faa26b95b92c2eb4f2ef91b043746e5e4d04e3cc32540a1c2ea4d1fec03ebd4bf3759169427e8ea8993c90ee1184d098d70eaf7233419260038d9efea3a386786f255ac59caced17ee7daf15b6b15bda4b2cefd5e0a43a691be2cf91238cd234fbaaa69c97cd4dd756f8a20616424d94f20baed3f9fe58b8abcf34b933ff2f0513fd27962cf12510909c611b8c02792dedf229ec1debd14f21be566cd902d21eb114b1cfcf1180d45143eda67cc0ce0f0251f9c2d8508e0101dd60e2da26ebae08c1bf759db806186a770c2372fb133efcb95872cef79fd9e9799078502d183
|
||||||
|
h: 100
|
||||||
|
m: 1c28ab2e2ec84b62617ac510db59c43d4815810122e9ea90ee9a84cd832e7f6fb191bf5deb8b2a57655fd6e5e7d03657406ab0f61a7f5cd5a676a54fe775ed9a563e7e2a94b9c62c64f1b0f6739fdf6cde738acaee9624d5f32a586e7b504b9ebadf55aa42827ffe227282240d49f0f046b68250b31941784d4c9a848f93b615d7a7ba0e68b4d7812ad678d4c476dc52f8ac9e8184f4d632178e0aaeed654f8f78a2b16e7a452959dd956fc201584767ad71dee5f40fec96403586a030ef2abd6e58a477cfd5d3adb0ad4bcf110b1f80648032fe96
|
||||||
|
p: d5fa68d13e297726da801b0d27987a75f7af53e82edae203248943973376db0529b555bcc7551da090dab460e756da16e6e9eed28b979b3745ce7bbb89bd673b4d287680f3615fe0528915a28ac3afacca400bce92792d42bc4d5a5dd49842bbb4a749c926b6efa38fdaef23957ea10bf6b7ed20deb2fbd01a12ae8ab3b5e22b7849d851bdbfde504db275d6c60bf94e9ed5eaeee45079fa7dd5359de561ea21983a3421c1afad491d6baae56c816e611ecc975b073078c464fe653934b9a9eec64c8c07715ac22ff5acb9b22cd762bc661ce73fccb91723e6ce168f91ae3f999fff7c7e34c0cd0323111f8064afb64db11d4537c23adec4071cf13ddc307277
|
||||||
|
q: 82d6654a6a5dfa810115facf190cafa0fbdaf7058ae1ec6058a24853
|
||||||
|
r: 2ecc267656e94a88114418f0715f6861f83885d5275a12bc136bc02
|
||||||
|
s: 69f24af8509e849beee2e38051cae4a1492237e124c282e181f20fdb
|
||||||
|
x: 105be11543080821326c26691132238f49cecab6bd09040570169076
|
||||||
|
y: b3c7c0f1a8fb683d786e87a8bf86a811f7b95dc8bf5b6bf1053e07c33850cf2aa963df0dcba35a8ba6879244f65abcc077b75c8dcf69d8143b889991282a210ec07d6b127aa3ee3442d6e32099c0c6e8ff4bcca2a598c8858f416e12834a7b6256b2794e11a05f77f3527ea876214a3a027783a509793afc5242f97ded6a25660e80c0f8349cee906da6f4509715b15260ba21d4ec194d5552ac81650b06e27bd8aeee22ff35afe55cba69da33ab2f252b39b62df2be59496383b60d9fba10510966bc6780af46e26c165e09ed31a8741cedcb08c3768f8142b84045af17e76a325781d446696dcfe869bc5529879f0e4910673ff637c9bdf7fe355ae2811d25
|
||||||
|
g: d24bfa14d1ec20666f72eb921e540bc6c6df53f8ea5fdacd1c1c2cdb75707847c1b2f9c2ceae7f82116499dfaf95a8f19d2851dfdbc084bdad6f4e77e2ac48540f49460fec12ea321f3f080a136c30306ef6c3271a941d44bba5957388d858330eddfd098056e45e12ad4f7f43b2cc98eb157c1a0b22035a17e92e6d9d7932766b1960e1734fe7f1b2f72914402c22e6733051240b958f65ba8ea649e51c85b791d2a3c51bd372d15010ea3b6c19ed805415adb75b80327eb952411fab2f133b5d36c9863f08afc01e3b57925ab1acd036c5717d96abff7d2501afcc0727d03df63a866a4e45422778e1ef4d6a716f1cdb1323d474840754cd507a9e5282edbd
|
||||||
|
h: e0
|
||||||
|
m: b87260c6592d0df5263b4dd4c2d6d4b219c8750830043f708b4498174eb78293775e6eaa20df7a8572ab8f3bbb
|
||||||
|
p: f60a8cc7a06f33e28b6accb53c1fb8578cf9c7c1195d00f802dc035c2b9bdfe8933b807012ef9feda2a53582c88a00b776d63a519714eb6694714349c9064c7664befea687b46ade42cdce4d28c85a2b659a478b40df460b0f275cea53553d5b0112d503fb14e43c52d8cecb78d84c67e41ea780cb87521ad417cd516d8e79f011e822cabcccd93d2917ca9ecd3c2befce50a0d01194d3d7320d8658f7cdc0b48299fda6ee3f94aaa4667be56a2243daaaebc15b33af79f4f57501649221148750e654a6ed773aef71ae3a5a7cdd1c77ee3e7cbbb8d37962549991f97b76af6bccb5d1a8d65ad4e1863a97a1c27d2a992635d38a63b805309fb10c73ed85dbf9
|
||||||
|
q: fb17afff01d84d71057e2f2b5411f2479764161ad4ced285c66703bd
|
||||||
|
r: d0b65e62664a2e035ce9e9dca72d87d492677c9afaf6aab0805193b9
|
||||||
|
s: 3d94ce41ececede3f3b1f00e6564c599430ef8db68ca0990b3c5dc5a
|
||||||
|
x: f62c07351a6745dd4fd5c1b526805cc9cf770c675c6d31f610d825d5
|
||||||
|
y: 53759bc7b20c37681c00ad1f1f0683a51aaba7349fca6dbbc7a6c5eea9807e100ac5c25924c008da4c8536a27169565a2bdbb2b81e839bfff7fd88d705158a287e1e129b46e30fad315c5cdcdf58834c58193be10742226473af027111b535399163a2bae02bbd5aa5c03060b3fe603f72c872976c789cdcb107013da6fa0fdfb610375dcba780e163512ba34b6a246f9c3df3d1520e947921f8e84c47db220af3f21ad622d2d89d5ea944210e0d49c02a494a957b3c610ada20dc61b6d4ef20c4271858eaa818809035c8029a833665835794543682f0a1415b6448b610d4bfafcfb3cddf666043d8b237c011b4d1c0ff88c0aff530a95d75dfc0026e2807da
|
||||||
|
g: 3db3021d30fcc265b6f4459b54f47bc586533c3b9e66705b1de75aa4c99bf9542af1d503f87c725fb60fb01c3b356e2accfd878d87df328e0532b0b5081c896bc654980a543f43d4630c6c7994736e9e791f64e844647c640bf0ad53a73ddc615746c4371eeb2a34d322ec36a6fc405c0b363208235295bbb268a1b4664c6e8eb98333f427e2778858e9cb5d63d9b4ab3f7872b275059301913590d8ded70a255c715eb5fa4c1e29daaf1ae31a41d98acd97a3fc8855b7a8313d69a7477aedf4d98345f191202a99b1be23c245529708daca00566761e6a181721e9f6ff4a2ba25f3f1ea16d482d738da36cb56b5a617f9b3b35c80c4180fd9fe5d12a7699313
|
||||||
|
h: 180
|
||||||
|
m: 2ba5969034deadaf4e4815f898d51fbcb957c44bf4cb5386a03a3a3e828eb8ad92e96d60d6fcccb1e6bf8b0acbe124237bb67b6789bdd03964b785ee1b2cc4529c8aab3880835ac16d2a
|
||||||
|
p: f1013f7fa39fa8d0afbe5322002d2577f7b081db014c5bbcfe9503b379dcb7227eda0032e56e23c5090cc814530ced2587efed95887de95fcd0f4e40a4d0b1bbbe154628d901d06e4a6c69072a3cfd40b751da88fd316cc1b6df712ccea51a981f9eb20c3150cae92c847ede6f837624f7354087628976ef77ba9efca534ba0539fca779e40773860b5e9a365a7a822707f2cfbeefe78753331598a1215647b57ebd7649e83492c533c5f85af81261647ac410cce4f3aa968383374844cf95b17d730d115ca12a9a78279cdfba785ce92566ccbfc22553eb18d738b9bbdc28a79a61653e77aedefc8177bcec4d5e2a5d3555a5ec6346b23f53b9bfbd9989251f
|
||||||
|
q: 8ee70200c95034a6d07e9f8f7fadcb5c54ddf8befc6731d4bc01797f
|
||||||
|
r: 7d07c010fcf91650bfd30e2ed92a515eb0816d43f87f9bfa54e3fbbf
|
||||||
|
s: 8978b89f966ce017b87d9a4a340aad284f12cc9e0d13b9e59f1afd83
|
||||||
|
x: 8465720b3e3f50818517634584239b80e2b8651a46e7acab84510d4f
|
||||||
|
y: 24f02fe60b5eeb43a5b82ef899828f3b4373f06e33f55ba1517b531eaf15947db4c99d3eeb363e45db40c7c152f6955859f3939c2eb7a9a9b00073c00e8455d6e20a89fb911a05c225d8b62bed7e049788f96824147904ba14b46d6077d0823bbe314e3abb1ecc9f926254bfa31650a9864db19664c31679ad9ab44fb028cd9b0a8c1330a340831bf326ad52bfc5c049459e2cb2834680e6c229f9c235d29066c5cd795bbbc234291c0488ce48f9e98f47b2f75e2ae671d4000da85782d9303583dd961807c0129f79bb1938c920c2e908c6071575ade4c5951759ababf8a1d11eb739227a95eb92c89737563004454bcd56b17841bfe7ce2951de6b61026d1a
|
||||||
459
testdata/dsa/signL2048N256.test
vendored
Normal file
459
testdata/dsa/signL2048N256.test
vendored
Normal file
@@ -0,0 +1,459 @@
|
|||||||
|
g: 3723294e8a68d2de71190ec5088b8c8660ece27710da126a0516988fe494da037a4592a3d674b3784c09e9f1c6874e86dfd99b16158a5a0f1f7d792b7f227e56ade3d515b6e7e7c8824202f9b4cda90b52b93b140101e2140d0217f1d99c01fdddd16e79551ff71a92d92b18df829bcee2967576063c6f204520bb66e26e6b6b039de8dbec0b18b6b8a075974398c6fc9e7e550029ec8da34c29f9a2667e4b837acb18845b5983dc8762f96cb6e6c4a90ce4b8e29a42a5e8b51262c66ef34d3b98a12736ee29e9543d493142fc1f1f97ba333c445826d9bcccf223aa09b8a3c648553feb93ef00045b4880fc4c75796e989955a3a4d84df1dc5817c55668d135
|
||||||
|
h: 200
|
||||||
|
m: 1be605ec89ea98c433af398370542efd82d9cd0ca3c9ee935eae055172
|
||||||
|
p: c15666a4eee2c16b2a9f986ce8dba494a3a62d62748c15183a1c9c162adfe081b42c55327f04753a80673d3d42e394247d235adccb8bc7913f0616b2a68a5f7189b531bec32a031dca71f432f5a14d36be825466b5d95ae15819f78c378f6a47e8c946893c3663789154d17a0857f158693f59fd1c188b638652dfc5e77dea49f107cc07e3be1db267b8194d1e1e72e7fbec4762b14017cee8413d8441d4e3bdabbc1775f1b4e55bb68bf30ddd80dce5aac25f23f7ad111543595f811f4c396621847f1e42037b8fb7499652bc167da4a230cc973f27077a66278f608aeaffc4ebd6e37b7c86ce518be4c7e375ad6da5bbeea0509d4b9d24767f00988b29c12f
|
||||||
|
q: e7b7b398d905b948ac0bee07a494fad5f7e7ad351ca8c7944ae41c4c7067b657
|
||||||
|
r: bb70ab67d4c9aa8198103010c855c2408206cd9b1f87a38a82da1fc4b81db02b
|
||||||
|
s: 4615b7fe007772d68023e3c350827ac10b59cfef328da0662a9939cd9a78ad2c
|
||||||
|
x: 271afc425c524a2022a8ae3455cd2d4b8b071239b770dc27b037dfefe821e990
|
||||||
|
y: 7c2b885e2d6b3ef2072550b9cbd5b62736e1fdced6798fb791e79782ce39119362d6ac850406148d917b1efbead9cae36896c463c8497c64b4f695d3583aa47bdd10f2862161610d30837d5e83ef1febd6677767bac51fbbc9393bd504b54a7b443802915179858077bfbd581771c959ef387fe22d1d7fa952364bc8e0e7c7167f28be470fdcf5c09a41be268029a2ebbb75afe96aef36b0628b92a7f91137823601251539cf06ad4738aead2e74c20a8a8a4f7f413f92113c89858b699583ae7e4f0af5b0ac648cf1d1801d6320c53480e653e02868590a86dbf7bbfc7618311da4a17e1ead2ddf9169ee86ce31186feb7a351d9fb8548a404b5b9737d639b7
|
||||||
|
g: 4a44b54b97efd7f767f0e824e38f75680e22fd0681d828a8cfee860d774ee274f58b4ace823caa487447412fd613ff0588dde6a0e6260e14544b59837a4b6e5e6f51a00b19a7dcda938b4de916edc788667ab38647dd674191eec19b7bff2bc4bb9b8d746deba9494aca7aa26eb85255d75b1a8ab16dbfceb624b99c43c30c333dd567239a99abe155c7af3d376b879963f7b04f146a10f7b2531e35a7a12fefb534ca41a957a3845ee8524e930a3c7f18278c8ec0bf519c9bf7c16ad030a0adab9741a336402f0b84e0e93efb84a41f3d485ee0a599251a986ee931d3e20baec79eccc09bb090154a817d243b58ad914c22f2a214cd4b0b15c058188ef3abdd
|
||||||
|
h: 200
|
||||||
|
m: 4a0f7282daf3727975260c582c04727db4a86d4562aa336de8d33276781da4d87f157febbbf8073ed1f3123feda9ca68eeb7676508e5a304f790ac0f29f65b972282f740b0754735487d1355a6f4cf6837834b24d0a198e9a7bb19bc6074f6edfaa7d260e1f0a9b79d7dde951bd4d25bb5eb06259457cd3d7384eecfa56c14bdc442aa0db053966e1768234d4920fb0d1f0707a5196495ac4b2186001ea8c3c71453ced898991ff248013183852e16aa9817e2de7c33
|
||||||
|
p: 9ceaec731f3c706a5cdf587f4aebd1862ac7ff15397afa3fdfc6c4c537cf04236cc44d1bad4ffdfb325248ff1e22dbed732f1c5e6291b0772eba18308cc20f3248ce62b8c0c5df0168aff913c75dc414c10a2c4521a2833731d7792d3acd528649be17d8d9a7b406d17852df6f308a9c916e6a3356b94d27db3fd05cf9baca2041d619a13c2363fae7cfe8ee32455a7d18516fa13a71d88db345df5fb7e8a97e1e692d57e1a640f07437962cfa7963c2b08a33c864ebb4f7f489dcc219887f526b7d55b7f4b0df7fd503d0bb6c0b4edd079df38b286566d18e7351fe5e34dc808fe9d55c53038b0dd31b53826d5b54ad82a1c464c470227ce86d457b2dc16da3
|
||||||
|
q: e74b4e501b0f6ea8c0d8a15d85f3b5741a8ae8893798650cfdef92705f730f9b
|
||||||
|
r: 70f062c9b247f93531f81678d9004c0aab1e7d96a2b607ad32c3cad060143119
|
||||||
|
s: b1402bf859da0a66e88d9af1600df1f68a2723993f47fa6563664f8ed95dd5c8
|
||||||
|
x: 13bca13e53fc79cd885b51d2c8a6c243ba85dc29826644c8f0b3bd2d012e72e7
|
||||||
|
y: 176220e3566743ab3b9bbe4549b955e5f57e58e99d876494f293439aa4f80041290c6de45d36d3916e04bbb7bdaf952ba4d3329dcb19074ef5809ece64a37686d50015e169b089df38b25a7b4875ae983cb8a3ade40fb0804f051891783593245b6ae9d26a6e70490bde95230b148e8e8efe2ebe7d3545782b40c7f54aa595f5ea591088ce89fddd0dbae4af62ea78b5954ec9320c5891bfc4879e78ea2bc599136a3adbb6be5a7ed372bf62b75f28034879f1d2451f32175664360f9598c580d099902ae21cf14c5dffd1a635ae44e17740ff39717016a3bb931e9e8ca57032a1a3fba61aceb7de9a6ad6ff1b385d6b10547ee901115fdd996e14f2ad303ed0
|
||||||
|
g: 5b132511ea4dd82c71fc64f6a7ccc6e611ed1fb5af214ce499b90a66c3774ed4e83ebae110b6f1e87f1259403a0edf05356e7e2bdc0a181eb28b98aff10ca01439f802387e2d40700cad758ec6ae44cf7798f81184828949f034dbd67118e5ae23c2b4a1a227183b43dd4a912abf283c68d7e0f033441eaa31ab60d8bdf27bb127586e38948f237d73075bd80344f7c386da5717f00f90b6e5be73ec95a19be8e27f9d6fdb14888b7a0beae71efc47d6a8c116e48c9ddb049ffb54e5c54317b24429d36a3ab3c78149eef997314a80450d48f3714995dec29fdd553cec1049be3ddf6874dfcf14db52d0942afd254dceb835b976b5cec0bdd7eb5e516a7bde23
|
||||||
|
h: e0
|
||||||
|
m: 50e97b87d28d30a9038d39917153fbaef05046d53d4d7e87eccf816d4d37b90c3364e17a99
|
||||||
|
p: 9101a8cfa105eb288bd3f16dbc89b262c89a6204aef37400d434b30320a35d4beecb2230e89a12951b6719ef7ff650dc28bb9bce7ee93db2decceae4932a5fa59ccb369cfc39ee054998f5d52c7294eb304cfbb6988d3b3bdda6ce432f9fb14ba22835fc53ecb7fbdf24332fc28001f549f2494ddbabc491e49ad1538825547aad6b263c867cc10495da172f334ed1a4ec1921fa04e6c357c674f9e91e2ed806916feb2e29b2937dc5d0bfdf389b91e4766c71af93f39159ee6c91c1dabf3785089732c6b09d40e7164bb8c991e8d930eb346eff2ecc98552ed9ac59263c18cb7e24f7c7ac38b666b117031e5e19e15eee91787754a4d781df81984f1c23bebb
|
||||||
|
q: de1ae692f0ecca7ebe72a0b96b8f6f827213f991412e83b9dfa044363806b377
|
||||||
|
r: 8e2d8ce7183a7daed0019778c980e8b895fb4e34cc201f4a435247a42d892cb4
|
||||||
|
s: bf32509a7563a6bf9d302f26b09500b2e3b8e6d6c4e1b9fad116b582fd032eb9
|
||||||
|
x: 9086a90f6cf02f95e89a514a183d7ca166d0f9dbe945fcf874f61e7a9b74fbf4
|
||||||
|
y: 2c50dbab1a4d301d92bd4e7e216b284f31c22cee1ffb67d38a9501d3de2da3fe024f0bc316f29b5876047d7f4882ac970589510022ab600936a58fbca8263c99b741fcb6dc769b1b016f69ab0b55a0cd84f799759819d31626d0d303126d3aed7b55bf87752abb9752394151363ebdbcfc15effe6dc6a25989df274440106316b08fc46fa020eccf0cd198a1f897c7a26e47d1b608a61ec0d3f1f247d9fc8abd11120349aafde3a830052226258a99049f2cb5e3776f0c7d08bd542ae20bbe114e3f1f16412b23e1e23f74c99e963fa5cc48d11a483852d7bbb53b68eef63a9d22b4146475bc588e3d4ce695eeba753459d14e10f4896c300a8604c17b123ba7
|
||||||
|
g: 20257c394ff38518fa4a14ca49d20d45694c6d392d6fdb2d2033ba46707249144b1c29206ce08fbc6b40683acc99a4acb204b14d44f4b61e0f04dd106d63571fd6df8fce235a9f290e17c922e07e455f620a958f2c436504ef0909e7c6cf579c457d1b3d7e6072db792e74bf49fe2f9da2d3acc3b970691f9ec64291d672e6f1712ed6f6aef2f5e6e3fc60f8215a9275a6311b85e5f707d0df3dacb42da4df99c7e3cf98b575a0526906bee226343a911c573d3e9880804e80abb88625bb407b89bf7d01d69cd89992a6656cc0060f1517cd8558ae6cdb8729d75482c4dca2a21ec4bc6cd03bf6d1c5cf250b7958190221e99d7db7d52d1f9ef3c62c6884dc37
|
||||||
|
h: 200
|
||||||
|
m: 64
|
||||||
|
p: c6c8355600809da95c969ba155492dcc4a2c51e557eee187d9cd9c5a9bb8e8a0da1aab73dc81257ce0e0d8bc17ae505a813c0625098f5d7197528e1f8ee9c5af8251a19e5b53dd8bbebd8d54d30ae34b90ae83f39636118102806b49a8194536d131e1b2232ba79ab9d1457d66d6ba108f765d1e80fa71e7f35826d579b5ad6d200d7a1729270216aa90310c519777f073d80beacad0821da043d4cd1a51e2b12269e688287e84f93d0899d399c83d72dbfb0c1c81662a1ff5f877c02c327369bbf9127247e7c3af1faafa28f3d38bb973dd7c6bcb4d47359dbcbf041db2fb2dd9e9cb610bcfbfa20d7ca463a14c6bbeb26e825a2c060000c6ec231a6081a691
|
||||||
|
q: c2c4fd73ae948ba5a72f5cd49e09f406955fb9395649034b4ceda56c519a14a9
|
||||||
|
r: 3319b4722aa1cc420ae7c3cf1caf936743574fe1ed8a35207e934eeecf27433
|
||||||
|
s: a3d548621a10e9dae0b9e8477c9a6e1d2acd192232068aafc22680b4632bc563
|
||||||
|
x: b45f87d480e81a633006621fcaa5c630ab8db6bbdd2a09a93064603355748996
|
||||||
|
y: b859d1fe410ef7b6252d58a5181faee5d7dea688fcc2866fe5ec6ebb21b2df4c688579f66f62ca4eec409a38bb1b334f65395b3f9826dd868d9a982eb15e6d1fba578128681d64c6b87d83b9df138b3956d48da1c13f6c82b10f8d63bf943f1089191b04cb0177840e61cee8f2d8feacba8c8e3283935f16071483d5c786bb80c6588917160cf0c676cd8401a1f2970b4f8b476c32e215e5cecebe28c0247cb5b028276ce134f136c8bd0f4d93bd856db664f3b199174a818c03f7cb32fe71d82763e7222a6b693b3f92f72d5b6bd31ad730d214478037bcda843bad9fbb8d1fb419e637327e58b5da9c7b76215cf7e3fccad03ccb35a2a17519b46b42afa9b0
|
||||||
|
g: 72a02738cc0633576e7727a364b6b1c85bf89e1b6e58527fa035dc4399daefadcf83da7a853ab66f2250479c459bfbc3bded589975143779063b3bf9f2bcf166d5f521c4d276b19bddf710eb4f21d0b032b5c74f6386d5a6ef7262f627bea61b18c0906ff56789cf70387768e5ac3a0dfb15f48c18ecf136d3fa5922a8d6789aad4d5454ca812c53c87e68c64d0e07f287ed508db81b434aa331ae8af6fab2d60adba6c448433b04e5012842eb817b64f2981b58297d72e22939498397648a18ecf97ea12670b6b92c37a0b3b5aa225a6064eb106ca820aa5b244408dff5460b0f4af825614022f501154cfcd2e222c7a7cba102c4975667d825fad9e58e352e
|
||||||
|
h: 180
|
||||||
|
m: bfebb28b42c0261d4c9b10db95c6507c4ff53b3b19507a34a5061c78ec859813a70badc8bd4da68ecb23fed46c2f22524da51d553508f8f71b3e204961e52abd6166e71404b41c4af2a21da130df61f903bbeeabb7753690276aed516b8f7fa4a246d2d0a2e5334373b911a2b2649e8f33f980aa4d81472c85627cfd6252494ab00b9a
|
||||||
|
p: e5796c9e9e57e0870389056a798a2865aba0155fdf0a6952aa267413f83f34dec8b4514448aa891ef66ebe38a042dd2d70be653c00d1398fd9307a931f9ea798e727ff21040fcd9286ca09b49670a9086d6e7c1689eea2922b57b5c456d4fb6e2edbbbac43d83ddfbc57d773582aa2f603878434e9e82ba1478afd519e71e6287521e51b90ce4c64d2e4673a25193d072160471b5c6312201cf0125e0da0b0635fb48fcd110e71a552a1ce4a0ffe4064143a525c6ad4fb4abfb51fb75b4d7c3e62974e4cd5d7e69bfa1ea23fb9445da8a2ef11e3280aac9a13ffc429b095083a37ebbd96c106473174442afa71d736a67754b8ecc336646155db15386690d94f
|
||||||
|
q: 913f4e6246eff6756fb3d48852669f91cc7c3e31c03dd42b1edbc3e5f7cd4bad
|
||||||
|
r: 40304e5d068cbaaf061a56f991a7829c59235fd59c0b2df0ecb2271b8d6af698
|
||||||
|
s: 80cabfc8bf1421619127ccc331d0830c1c7c243994436e36e9528df2502879fb
|
||||||
|
x: 61e555bcab1b482eddfe17800aab2410e1ed8663df197624d0da5bdf4d643993
|
||||||
|
y: e3f9a25239da793226eac79255f682b5481a4752f1eeceb88546b7a7e5ba76bd1bb06c5e28074c9d3c7e3c5b61616e6bfed3226d0d562183aa68e23247a8bb12257dc576920a56ca52c9af5f3ae90c178f54d3bb70724cd5095c2ca6e020cd8fc1f0234d1ca739600c72c76f9db94c2714be6b3755ab4aa5024f4bac50154c9bd8ff4ac4508df38d2240d35c232cfcdd00e6b60dc46e19d241ed5bc4d4713226273efb3e4c7be2ead6a835850a887110d367fe060e7b19ce9f0139d4421dea12cfd67f85461674b90ca675fa7bc383b62cb076af71e9cea06ff848403a9ba2f5ca3cd60df073fd236d23eec1e8790fad20cca5a69653976787a51e3c0edebb05
|
||||||
|
g: 3e10ef9a225b2ca3cf3e45832e9865d7460247ee62ad7027a7f2e265c09357215b9699e8b74a6c438a3d64d17b8be12852daf2111f77ec365fda9c45203486ab194b8f0858759477c02c2846c61d695ebb2ac95bf1addaec131a1c4ba3a4a1ac71d6afbbb0b90384ba03598b91954ff4a5393e77dd93d2cf6a2647b581f6d254e63794664a54d9ed34b4d483e39c2eacfdd4ef859555f5b859429d4580a2adfff377875b3c302e6f5185f982d0e1e3b54150af3e438ae5d520a31fecc19aa7ad89a060464ddf774aaf262ec233640378622fe9e0712641017344cbcc1a48bc6d9bff14aca5bc6d6dab2a1f2fc95c4c0b795792f7324f27fd080dfe2c71835c1a
|
||||||
|
h: 200
|
||||||
|
m: 9764db6e977846b864da3d97b70ad6a6fa7e630496a4decb09429d8a1fe6ed3d703832eb6518
|
||||||
|
p: a7b5b6c368ba6d8cb1d55e58b87fc2aecf8ef6d7df5e53753b7de3eb87c67c3aa499fdc53abf5e83b48bd7b395858345f89d1ddca5368130282f439e5a1ed2ad7c92f4c4507ec978182ea76a709d018827192d0673491f0444fbd25341a6bee82f8420ea344e114f4251fd8d6551f342ff3a1d8671c022a9ad24b86fa1405505fdc7dfb0de0c0fd3688b41fd6f5bb4760d4d0e1bc8620bcea7008b5d3f255ec13d556c67be263465ee241101536f4ecdaae230a2f5842b5eea43a1d474d4d990686938b7ced589f310fd90062fd6d8c6ae3c6cc402de2c3bc4ce74c5a65253dc8b94057b70314d145967e9d8d14067b837a02be51eb7b315c49d8d5936cfdae9
|
||||||
|
q: 8bd1b5f0475433678efa756bb234ef50a4cd98a5b540e519fc934bf8e3467f35
|
||||||
|
r: e7979153ddd7d8b21eed743d33af7e3425c50109495a92b220004005b461db8
|
||||||
|
s: 1d756e9a1c41a8465fa7f999cb09395a4a5b89a3b875181fd7f0247d78be724f
|
||||||
|
x: 3f0ceaad3661ee163823b68a1f921cc699a661d6ddc5d509a457352a6f62e414
|
||||||
|
y: 13ff0071a9549312efd58b8b3044575e6976527d681ae09c117c91351a58f55b88ef05c1d9242c95b374bdcd609ffad5604bc6bd01c8a2b86a8c3085e1b7319831530da7b0747354ee98c064956335316bb815d07befca8358353b2585a2b585700bd97c1209eecff7e056d819e7aaf75a83050292414bd83b2eadf4af60466c8bec7a9b1a560741cc030229b2129afbfafbddfdbeede1ca2c6568e7f0d7418a3638d07d3c68baf135b50df0aa0dcdc3546e3db8aa9bc9d285d9439e13d0f63f88ced0878bb3c54544ff3f9639207a58d3aab6df4f9097d22166f0f4a28eb00e9e8380a31adfb63c698fb501fe6c22ce8d6c1c8e3fe2f77f4cf8bdec0e5e4562
|
||||||
|
g: 5601dee6c5dc8fe8b01e1e2feefee8fbb3726c7d8506db67f06327cf0e6479dfde78183d9d135c4cee8f1a9e972fd281c7ce875b475880d8bca540dff2f413ba58d2fe773a4af2d3dbcb8a38a4be2b7d5da37e62d240ad771888abff146c971df34758642721002f5b7d5f14b3c32d61125943eddef41368a0c8e2fb21db16bff7c6f81f9b63f9906081cde0e33cfe92004d5a0fc7c19a69b25d292b22c651113ba6593096085f60cd674c6ba39623a71f6573f6229584d340f791d14fba9f07e6acdfe62ec134a51ac1e7a5665751b31fd37087b48f2967357d75a26b31b5417072ce153036a7c8b22dcf735ce3945a5a73ce7a67c5c5d0a627458931a5b683
|
||||||
|
h: e0
|
||||||
|
m: f6039f2c63c24d785ccaf2ce3e5b6177c7d350afb8e350655384595b972c5748f635b01be5139a4b8563584bcdc803c956d2199b12da9a01005fdb4d8e4731e912972273287771164c9d72a1160757651d68f508dc96a62665696f
|
||||||
|
p: b49275a04039eb172a5577990db00e2bf31d17b1f193f50f64a4d41c359f8dd97770df4023d54a42fc6e832113781c533af2aae2e488c73245be526cd8e7288faaff72c25ca39241d941c91a0ca03026ae7808dbd410031cf0c99b7c2a6516e83ad9c762fff2547cb6f862452a93761e75f449d52e7e30675ca7ede88bca32891940c9f92647e0b8ecbb4e9573a1356c08f4e34f2ae009c066d3c85f93c0115712a49ba8b6ac280d986ea64c95644b6cc4415287790d80a9af6109311af9683c3e72f893b62cde36c5ffca743bf2ba2ee3cb5aa4f996e15694fc9cf1bbe7bfea6111a2e7430230402b2104c3ed8e89246619884177e94e8b3ec3f2d24768ca91
|
||||||
|
q: d9ea638b88541d282ee5f200cde887c039d5f8fc215fc0f2248aec637b26492f
|
||||||
|
r: 95422b51110d9bcfd314fa5d566455943265d89138b799975bef4568119c3553
|
||||||
|
s: 48d5d6b36b852a7b7ba9fe0c288ecbaac4eaadf2aed6738658c24a1fbdc781de
|
||||||
|
x: 5e70fd65ac76b93162370790464eb3298d4b0e28aa71e8ef777be8f6bbea7a11
|
||||||
|
y: 19efd86788353c71ab7bfd4e80dd6e8fd4584ba05f539320c4616ad2bb955ebbf9876a34a0b9b5f29bff5fa99d9559d225e87c7d262bb202b917f1d1e4c68181798fd003d53d2bf94bf5822789ac29df2feb99d51afd8c2855832e2a47ccfb38fa23996796162ccc78d512188301747267fbbafac2d5eee7ac4466bf40867ea75162df7cc00e2deb2cb112e6deeed16c5a129ea80c85050afe692781b8977eb678f74dd076acd26c239148c331bc49294e00063be022fd7c191ccf5c4987e833f95c302d7c0bfc6c98a96ea89f92f7392f2724bd5c084089b15d669f6d301cb2a0d7a948fc397449420fca17d0856dd399d4e5777317a0bf3a8eb133512bb48f
|
||||||
|
g: 81f1930fe641d803233a995ab7b9c664fd2afeabaec9df04901d807e8e0e20eb3afe3e227b6014d53e06fd1e06d2cdf16b1b59fb09fc41f030e1a3490058493d5f31fc62c8a9fb6e2b9648b1b84d628a85ab2ffa59c3c499d4058c392a70c25dbfda2c3a3c6f243d6a9c97e647beb134b06ba129ffaf8b7204fa53f6729da151ed4f627cff93811b9cfa5052823c8d956e6d6dfa6189927143098eb89b0eef210fba4e36421647af5eda5e4a8160d730a035c181743373b2cfe8c8ad6d6a4ad3c729b90230109baaaef33fbdbb54fd84702e95674cb26bc38659b2197838cce4abf6c151ae27a13243772aa6a278ccca705f55826d4bccb641ea50c2aee842a7
|
||||||
|
h: e0
|
||||||
|
m: 7cef2a12cb9cee361338f3df15300fdde6bef6cd2a131c371cd61336e0d544fd090494f9e3740f699cbaea8f488309a6620567fa4200b8b5da544acd7e15ac0e78d762ceea977b12870f71f7077b2667624576618fd7009c8f635fae
|
||||||
|
p: bfc28df62da811722d7462f01d2261f034d87b6a9273e3deeec690a7016e3aac61bf766bc433aed81d559582ddd0b35fd14696aed66a7955ed624bcf8901627a8cc2136bf645b8ac60795f860c69ed91a566a34862d02b6ebafe6489660fdf28c27cea8bda84f048ffed7a195fa6f0a4c79d6fe5e034c61281e948bb19ec12ac330d4554441824f749947758e09ca008b221b0d24b4ab6c821a190f600b5181b46d8281480601f57ad05a799e237a00e602802ca095d71dab367f328522c863e8e88aa93f470606e184a83619f17441627807abb0b1ce2b6c82298213008304942fa3b50418e3885e57a4e5f66e2f66d3173ee4aab11a4cd29b29412accd5519
|
||||||
|
q: b98beb2e42bb15c89d937128545fcf5e3d4e6939fbc103b4a66e3862b7551e59
|
||||||
|
r: ac28d4f731b4430a16317cfc161f33af038dded46b7729f27ac6961675926fc5
|
||||||
|
s: 6fd2f08403af3d683c3f4e16e521d95ca68eb4ee1c30a1acca0eff1ab3b8ab4d
|
||||||
|
x: a5268197d4b07d7a2ce04966961e700b0fab0c5637a17c7b7a17352373708b66
|
||||||
|
y: 7fa870da04496f8437d16f198ec2eae0e62258c61b8cbe6188b7d47153c27fda2ed650ac54e67e7e51e62d0fc1b0ae3a390cab5669e5af88cec5940446f40f982db58505d575ba81d93d73be675ea145695cc6873428da6d93a5d669650ba9b92ed4b1a6e9f8815bec0ad32ac453cd209265743c34c861d62f5a08d159f5a750bdaa59f6678ba576021898c06edfd9b074024a997db600fddff367f5fd1d13eebd98947c300c00904f90faadb5a7f784702436d6b9450f28f210186266ccabc9e2e85c794e9f5e7ad941c57487c8106add7060523b8e14ca5dd28e70d662b2b7aedfff366de974c31082f014ff66b82ccdc688cd1f3b4af49f8e1aaf9eb6e883
|
||||||
|
g: 308e776f8192c010a3d7d86c4c072d034a10a22152cc80e68ec5bb718f433357ae15d95b78dbea777cdbc54bfdd57cfcebc151c173acbaa8250d1e4eb11f852492a12abcf175b4a4c4dbb9275053aba71113552157716fcfd596e65c79087dd5348d0a47b6a3b0c2512713e409f0bf0f1644ad95abb6a46da0d5612842f4acfa2acb0d8cbbf902ce205781c71e72ed3fa113513a608b8d9865f36f0e03f37d9ada20cedabd6e3e16e77ac1f24bf5454682bd46911137ff80d858e7aa9be9e093824420253e229a6b5cde1894b0c78b6b3525716c96236632b227615693eb0477d0ec4070700b2ec2e0e99cd2229715772255848bdf937a144f8880ac49285545
|
||||||
|
h: 200
|
||||||
|
m: e84158a7d082c01541e1c89974522b97391745d673b0b3cb9def4f121362aaa80bfc616fe8e40754edb96451c3466b6663cc01aedc34a45147f0d86d775944fbbb9b993551ab81b90472479b8878514d2b1b5cee81bbd0ba346e7070334d53eb87a8940b2c539aad5d31f0a654239e70c335628eafe3d8d8
|
||||||
|
p: ea62d3303656b3a2a06575f47b8295c4d8c7fee586362b1606a699409a0a4b6fbdcbb3b7050ce5379db1acbeeae53ee306f9571cc16172b6bc4263fab59f8e86cec982be72e1a26aed09194733ec19d8545ccd6e9ea0ba67d86bf4d22d5cd1f83af823d381b4aed6462a642db2e2d3616efe0035d1813823f291a95fb18823960aa0bc741a735ade737f77d3a708bbe555d294d016ff5f0ccf17b67743090d36d6749fccc22b56c850de70edf3967e00af5aa1ad7058c86d786332700ee741d0388e95e0ab038d4f2aa1ae999e250bec90c63b40fb7ece76b923e40f6322c2571f8407327d4cf354db8f1e3dff35aa5c400b0ee91d489ae8938ec1378f4a7421
|
||||||
|
q: 993c84ec2d07f444caa41ace0a6a63c548107afe0f422ad5fe68dd0558139f59
|
||||||
|
r: 671f81e8f320e48cb5ee78abf5d8d84513f9220e684534cde26935318f40de3d
|
||||||
|
s: 4199bde71701590794a75f6d0c25f12f9a297169a59f3ab2eabafc5d6aea9c24
|
||||||
|
x: 748a8ad45ab2b53748affb598a6f9fd23825790f9486cde9a26ef91b8b46c71b
|
||||||
|
y: 49a63e1b9b23b17de71b1814c045b9a3beb7be369b5cadcc4aa9b669274f94bc67917a0c958d0f96958e1b37abbffcce931be7a57bd74dd2b43d0d2a6002ce7527dda7d575d01612e46612b596acfb468452c7c5c884a062d3043afd4b0502187d1492e8eba1ef6d8328af4acf5aa501e4296ec7c7572909ae9abc52178ff7fa486b9b33e6f250d97408d552fdd4327404d675f8bc4be9ab4786f1161c1e3ff684fc821c3099871b964a1df9cb982bc53f378d6d4a3c40c36bd88fc19b185d56f67980806e83157704e0adaea1cdf5cccea1adbf5bb7f57f7fa845bdfa5fa037da4dd72e47c3063d39e6baf4c025bdb9f3b7b119b26c91ab5b1d6152a21796a1
|
||||||
|
g: 1bb4cc9a14981287198b2ba1b8256e854723a7583b26381ddbc405a4f8eab76df604fd5e9216e166a61771a08c384879c344ad3c20d496a56837b76a99efe0991bfbeb59450092d4cd1e1e30d73c9b4a8ad20d3321e93fbc5accf714e5f86494e9e9b9b655e57d9f163beefac04e192ed72163e3790538dffa6a755eaae941427717753d57837dc919a6ff182feaa17fc9f5261012a893f6c55821ac0e8a52c711d740d91f8357f760640393da75b6dc4ea613627a700d2d95050eacf71fdd3b91d5d1c4f605c84d15590ec265573e7e5468297e194789e6d687ca1f53c7ba261f02449e6f4b0854f563f2c7934703dd8770b7e65176db84f4acaaa9f779a36b
|
||||||
|
h: e0
|
||||||
|
m: aaac3d8361d0125e4f9bae9ba22933c41bdc4753ba389642c1d5e1751f36848fb68ab326528bbc98aabd6ea7e87dd9c3aef1f3f097063cf7da3dfc39b2ecfbaf28f6543db2719088af0baf3a61fa3adc2e8ff54d65a2e3218d3f565632a1f5c96c2ca20c17b3f0ab2ca4539cd755f35cccb4d59e0c009f33f11666c4a1e53cf88a353feffdda3b6e6391191217e0c2b5a3c9931a71a005a77b8b86f19d9395deb3c46ddd7eeea07b598bb2c8e6b4473afc389732f95c59c432e7
|
||||||
|
p: ad9a921b47488e9fc698e0b2405e302ddab742b66ced95bda0c3c5bdb8a89e6b2c764c4cc7be2181cc63d3aa592da1b7788753a6103a09b4619c8e1d32283fd4f6cfbe3dcb27aab16bd468ecf3d1fbba96e1d004bda871329db0fe852612a6f5980d7754ed78032cfe55559e2126a9af32c4987949a804d7981842d682a192678b6a90579b943320f23c3f69fe890ec7f415982fd5665bf0fefb47bb2451466cc7beee8067685589231f433656b718dad0054ac65fe248f932d7a8cf93aac54bd7cc648e46ec94a2de42ea224b675cf243f9cf65e08554ccb9ef49d9229f604d279e1e8d935f9be2392025f00f0e53c74d33821bc56aba7d84f3ac8799f0c6b5
|
||||||
|
q: b7cbf0fa23c7cc6e8e49e8487fda84f8191a32441e571fe7ffb5956bf18e7035
|
||||||
|
r: 9e08a8ad9a3b6def8ea63bcdb2f3afd4839b95c6d537daa2b3b78c89e091f0fb
|
||||||
|
s: 7cf83052047d53376de53fdd67913a52b7d686dfb8634c2b42798bec70103220
|
||||||
|
x: 7983a33de8a33c333fe853c717bd55f5a8ee4b67870f9e4d361ed3abc796d94a
|
||||||
|
y: 87b2f2d42c095fd0689a4e0cc6b998343534b72cb4465374b80e78d8d7ffc728cf6bfed68dbbe80ab72c2e5f445feb49dba2cd9e855ee9418ab0c3e0ab6da3fe8e9a694bd5155cf0284c13c7085aa7586dea9d37d51d3f013cef0846eb2da49e9805f616ddc5c99172ed0197e9c4c588a6446bcf769348a92b06701b2d656e43ec1b07eb1f2744e4663233ba5e717b25355a71c861467928114394654ffbb923eea378d05038340ed2c15a7c3d58f798f8dc42a27e3a3b19e9990416f0ccd6173fc8d08d5ecd7feeab972d5fbcc1280a10456b870e83270e008559e272b68a346d7bcdeefb56d82b063791e5883b63af2d7cc0c86f47735400312dab9971b75f
|
||||||
|
g: a8ee7d86355ff45010f5e0545b90791aa5bfba7417b3ef49427410733ba6cdf724529317a520073ff98554252e71da2ec105331d5c25f159c3c69752c4877a803b821d7e5ab1930cd0709864193b78edbe3107155a0de75ff16e2041ff6bea2ccbcd999617b0a04b61b5bb1326425212d89069cdf7b966088713521798d11a95652213cee3dfa3703e220deabfaac1154b1a01c61850f7d4b80c333dc6752445686c449fd0c97eabde0d573e4e5fb6b53ef982bd47f6da4e298f2c524d90e58339448fe0a9f4f743061eff1f9eaeea18736a21c84d8b279eebb8eeadd0a18dd9322d0acf488e4d46ff98e5e16aed18a73e299bc424c9bfa2a0921e24fe980d1f
|
||||||
|
h: 200
|
||||||
|
m: f84e9214f581991dfe10205f7a45ad8fcd77eb49d9e89efe2811622a701990baf9c20de6111623bc255cfacc52330b8976ee4cc36c348a15480dc4ab56f4506732ab08ed7690df2f0346069d0a3f129c8e13d9a9a31994e60d248b843e73de1702c4c8c578ac5d8ca95d12eac270a9526dd1c5
|
||||||
|
p: c5590e400e8af96dda10b398c0cb8e1e704d9b8284344c19ec97375f490aa1a50592fc3009ec0b006dfde3f0195488a807d17086fb69cb3f33413a759ed964c3442a88112abe74fb803dfbe89fa8f442294ed929e113f4f1fafa0ff62d8ebc456f96a5bc1f099063595e2fc35ad49d973214a7e04c3dcd28d7eb5337ed769a387ef543b51f6f763bfca4c308c0768b4fcbcee5d719c54f0bbf9ba51a8ecd711bb63a649187d108f69f9c9d5932ab5b8624ba611b964639d70076e023b40db6228943446477c174d832a2094d6cbe5ad57982d6b3e2fea012b81fb4cdbbf0307329d8f6b596b08332df64c9193239198579fa83c1a1083e656fb88b80736ed92d
|
||||||
|
q: a2b512968bcd4c30899a63f0c9484be9152b86f5e4746537c9da6cf6347df7ab
|
||||||
|
r: 65a04d3513cf1e452eeb0aa98f3c2c19d98f423ca7fdc71c056d4e22b9595ce9
|
||||||
|
s: 9a478002052c16c77f5cd0af2a01b5146272a048af45b1a4a716716fe20d4e54
|
||||||
|
x: bca5780883e13625bd340501c3ab6eb337a1cf5c9b5bb6c660de47e3aca1973
|
||||||
|
y: 6b3e7dec84cb76b263b3191b3545643e75296a362d90750c58a3701ee293a965068998fb4e77ab251b7c10b32a63b148ef52479a777c52567815b8332aa27987956d5e09da7c95a38b62f7772bed147d9430155eb864b437a7b30a63ea202af610d1f21ce00fca89f0ad1657422574dba5efbd21d98a85c1345abe02a3ca9e776e934f2fb452eb13bcefe9673535f6bf00d1a0e4a1d48f6e537caf335bd9b1275bd2357137c308a6c03c2fcad88bfc21a6e5cf1eed713e3a811e34814c090f9a1c89cf97586015d2189501129ac37e5ab6f943fa6124a3e0a973772166daabfa0b53cdbd216ae464fca1f4e04bb8bb08072ddfe232f2b0a752b3778eb7d6beb9
|
||||||
|
g: 955ea1e83cbacdd7d7dd58af1c1f2248189aad2d1d1ce85399e5ba5b9a7d9ca464e588a736507505d16c0f334316314700d91ab93a8832df95f7e9915f03cd38dbee5024bf9c18cebf19c141986aa345cd0d256d0d468ed8f8542616e6fafb0c8fdee74f8398acb6ea7158aead8b3e043dbb002276296b1b3ad80ad0ec499a475eb34fe66a4697bd16cb64adb754b87b82318da3570929ad89fcae1e40665c65b1c195a919a6c5cff87fa5fb198882926fc6766c1c1aca9a23ffbbe07d24a9b1b5e6d1f6e3b817af23c9c0bf75177ee318be80aac2f91a8c6b4a62b2cc1acb1471d4d53777e6cca2056daa5cb18b311113e87aed51565e9128b580ad41c00ec7
|
||||||
|
h: 200
|
||||||
|
m: b067eb82dae3f4156f6109d943cf5896d593c601172cf44f9db55a8a53a4a1e66bfb3b4aa5f9b046749e98bb4f62cfa2c6fe05d3779fbae6271cbc413d7933fd41d9dcea7204ebc3583a5535c01246d17c6674477cd917e7ff1dfc8d3fc3722836295e8fc0d84035a592b7a3ee3936a08571a5b71a6de477da4c1d7db88c0fc5f5131e474ec0a8fddf5aa5a8ad8d945cc75e940dd21e568f758f3a8a8629a243e77f30c00ed958ea18bce0a94956c950d5f51c593ff83e87dd6bce434ed33ab902f689d15e24b9f04505030ca5783cec74d253ae3862b2321da4f06044a5c3c4c0cb1772135ea8e873e964633cae07fc638b12932181c713208539ce461a4d
|
||||||
|
p: f395b07d434e6eef24a81e59d5b9e0fac0da9e778a8ead10e5613daeaf8a3174e8d2d50c6e8f1a85bb36fef5094ec0bc52cf12a35594ac237cdb22809a3c7a88b9547e4377c616cccd0d77f2c774f15e0e13917ce20aa26e789b07b45242fd0fa129b6db8c8f12e92b6c9add5a5e446482fa99b68a75009714e1fae7d7a7c3e72fad368506622815687c964150f36cbebf077ef110004bdff2064e50f66a4ab283d9123c25ca5e3cdac6589c31d45317ee53d3afd5ca6506411b1d24b00b639e25bec45c78b3e1f4cfcba763f277c6178213da178b1da81739c998072c1d7dde87eec1424530c7eff87045f3e9f1aa252d6559b0eefc667115103db677984561
|
||||||
|
q: d0550a0e3be4378ce54348e5a0ad58076262ac21a88387c4b661ae1da5c62299
|
||||||
|
r: 768241d35a5f83567f5e3083dc833b1fe0f43bf55a8a594b22f7dc0eebebfdb1
|
||||||
|
s: 938eb76774f7bcc8ee5ea9961fc79750a6c8067df66b8fa59fd12545fb42f794
|
||||||
|
x: a6ff50ce67e7afef046db6152455ba03a2b13d314ce32947dff192113ef7de46
|
||||||
|
y: 9061273d4d5c665f19a53c6624fb9edec986276eb4ea3973aaf1785464f32dc7c1e77e546088c5cc4574bca14d18f8eafdfa372a75ce775e345f7260977fc06436681ecdcafdac16a6d97e8df184163b29ae9627ed0077b9e3909598f88b31fcccd1ec7113cd2850afa351557877db9fa05b7e972fb96c0c244423221931e4d7dc9ffe9115e432ba4d73dddba6de23953318ed7facfa80f6b98f502eaaa838c45cc0da6038f1153094de71c618ed677c385fa0711b1a5f87fe33795b60d1b8fcc22b0e2cc1f90e8f2932b3de8c0449b7043c70a9f0ed453acc0045d3dc9492781339fd645a39378d9c4c4ad2541a7f99e52a920609d162db8549fdb4c56885f6
|
||||||
|
g: 4b8d16880d812d44eb2708e7f2112f86effd61d83a6eacd69b0f333d5bcc7d4ccf87706dc0b31b85272a6e678c78387fa37b1d48ce4f8175629dc641dca7963cd1bb62abba521f47a998341edb99eb715258997df8cf0af4c1bfadedf45d38bc66907104ec8dabb12ed31309e97f134304e13ff645357b68af1bb5c3b234c6748e2541b09071b92f5031f1606d095242baec9e5b5718edcffe9abe3f1c14708bb7f5e6226c6021bc2d91155dca2fe5886adddee0836f9d5db905fd41748f0700196296e51562b4a5419b1b97bc58bc41010ddd997d843492bd673570cb4df4453a0013c6d70bb8abaf0dafe6125ba05e2c2ada9eab2f52a087e7d72ff9d69bd4
|
||||||
|
h: e0
|
||||||
|
m: ff6dc39371606f56bf5988f1130657008f1575e3d58d9a44d44ab5fec9764999694b320c7f227253c0bc5c4bce6abc9daa7a9795b743795643a5d45404bf10b61e952e3c251d668f7b8228f605aa55cab81eb553934e47e8f751d5a7bd4ad815bd385b70995457737b1ddb72b5d2e1859c75ff59b691fd8e45240ac6f312dafb8f7cfb54216d16fe390dae9decb84768427ca1
|
||||||
|
p: d67996182cce04abb649a3dd90249f3aef162a74b19635689890628094141738e9ebe7f76e1a8f79a1e49e2c26c8eca952eb08ddc2ea9032ec3fa32a9ca2c865941b3df615cf6f0b2c48cd91b3077e9ea073156378a59e77b378b8e154e2a859317dc2c939853e491425dfcc503916e9ce8aed4c3dfdb2e895f03229ce6de6a95bd4b32eaeb42b5151a35ca18b42b6b25ce0679534ee2177664a355981afb6b3c6d2a9dcea8d07da444f670600d72e161c14560e5ce2dc58cbb3f053e08532f58494ac3871953e09cfd8aab398dd22b95f447c30cf2be164991f29a8f6ab2744dae784e3834cef6781a4fad4bb598854fcc2df45c857614cd743baeafc4ebf31
|
||||||
|
q: aea2961c67b6833f3ff1d484edbaf30f565fa3d2c96518a848c5a0eea288703d
|
||||||
|
r: 6c1ecc8e508dcd5882d85945c2ce16f10171eabf77626f47296c1141b691bec5
|
||||||
|
s: 184f7a4fe22bff5d5a7c1de8b690906384b1e3e13788ec9c4c1a944e5014d6d7
|
||||||
|
x: 18d3156c20c681d6ef0bf0ba5156ca6fafef278fb6c0a9f29633fe849d8e657c
|
||||||
|
y: a1a82876b28ef5ccb45863b6572ca7b4e5670e5efc97446ad6571de248ae9e482d6c5d61914a894df7b1fc8e49d6f3df9ec7e5a1000e61eb894e6e458cac4c7baa26b45a3afd10857ce0f0d689cbabab991bd7727942d9c3f3918aac076686ea769adc3015e138c16f9564d6828aac58045a0cec1a60fb1a58c7acf9971322253f306429ca6794c4e96e25ac5766a86f8087bc281f925e4432642b7e8604a1d0f1cb03eba5e7f7bb64dbddb2e5d2ddecfcee0adda175761460a1e8e363c995c1a9bbb5587d5b5c91947bf1f1b1c0094ec02e3c66810f39089b7d78b09baf5d9636ae5df8766627613b3bd0779e7997cb938fe9738c4e6c18db1a53532c386b91
|
||||||
|
g: 961c5f2a8db735b0ada170aa44a959b29382bc65b9be1983874ce4b975333f4ecd2fa2f3f070bed88e367ef13efc2b7bd6f9661d7c8530e43854f702aab72d04aff0eaa5725a7715b608292ad47280dc97d5c51a927b079eb8deed615cec48fd1f6d86813a3b603c78c98dcdb965539e0ace275ee2dda588d6fe2efc360a47319f70c9817f684260f6843e1a790dddaaf3fc9388b46f40ea6e4699d1a5a06ca1c5ef62d18bc044dd80b746b741042d15b86deeccc324bd6259662b8312a73761b83aa06e75d797f48015f45d04c6442ed08dc84918ddd036c1b1bb77c7eea25eb0722076026dea7b0b62f18287680855764e4ece0137f63ed0e51773dd7efcf9
|
||||||
|
h: e0
|
||||||
|
m: 19e4f67adc36872e8475a30433a643ec498c8f26d24564ac8945408903b55b3afdf486049806278c70aa3394f07a6809c6d37bed8a3fa078b88570291d0f7b07bdf3e87c6aa89963fa2d28dbe436c4d1467baa7b9e760ca44dd7225a991fbdcb1ad8555cb9a8e19811a7eeab5ea4c8e17ce47737fa7e41e5f125dd72d7e1f8302a829b316eae02a9f3e6822d391b8cbfd82d018326df0ef9d3ec27fb8fd75ed38c366a99354754f96547d781234ee8b6c2a7c41a4941508f8948e05c5fe188653358395ecd2a1cff7885b1bac810b15e5ba431925994da288c8a1548d69b626501532cde95
|
||||||
|
p: ec4d664b0fff7a282f453df4bd4f36acb3d69a9c48e32c7b7f62976aa79fdecfe9a5b8653a36565526e3f6cfb1932e1fc34817b2cda740c46576c1484758bd7f5a7c5728201544fb2324b42d7a5589e6d10f0bb9c9233b886fbbe699b8c6d364ce59f44cf62d7785fd392a05171c37850b93a9e5eab10dab8727382fbe795a16d989853a13c7ae691df9694ffa3c19933359c47b82a4d3848918e0e7cbaf596205532f202bca2106eb01c160ff8782ffb286cea259d10d7a3cea457c64fb8d5c4423abb9910544698ff60cd285d37c6a75c55c5686cf198103f081c9fcb536cee91b233bc9f15b8291949945d8a0b62aa0240426327de5073546ced39312f301
|
||||||
|
q: e0cfd88fe31977f93db91de0136a060d5fe3fddb7f6934d46bbec18db6e2eac5
|
||||||
|
r: 4e8e2668572416f06c45881916aaba41bf688df9236051425e38690142eb61cc
|
||||||
|
s: 303bfe00d19ef5b7c33279e010fd83bc78d8aa0ae00fa01c249d89e9c440bf9a
|
||||||
|
x: 9e5aeeae3d4d53cf906c6389cd48806dc6d78ba63910ce4bb9d33b9db6a7981
|
||||||
|
y: b7bb1375387da456fff61e8005b7a37ed47b752d29a74a424e004a1cdda85a47064f1cb28a763052cf142b76710b539fe8ca8e71fa4871b7ca833ca72a9f1915978cdc0c8ab2f12116ae52cde5f97274cd08f1b98ecc12a9ebc9b9d8fec5926cddc05553640841c7c22187f11eb452f62330e2bda98eec8a7e85c5b01c7e014136969da3efe1ae3e8bdd2686e7b5b0464c3968e15615ebb4a117ffdbbd930b8467ddc627a19bee0cf9078cbff694838455703bdd94567262ead49413426a4ffbf2a569a406a3fcdde5996efa75594b75d62029e10b532f7c0817b49aaf74690f3432eca8bf98c055ebbba7de03bfb8c81ce8c87839ee8ca3dc2b8a5724a13d1f
|
||||||
|
g: a930d5bb8a2d6b1a6ef95e6fcdeed2f0ada13015951a2942b80196c78ad0c2daf92cb1c80e5768ad746cfaf817b0aa7aedbb0070219e89a972d964fd8ae409d63ed0f296debbfc2926f0a865c7bf8ae7ff700d8c3f1893872c44261b7779c6b086ee8924cc7a9eda73effc0f694922a0ac2ec10999c91e1a47557b7d6bdfa267d2a38a435206fc0d5bb47d97176acbb9d1018b001a8288c9a3b63969c106c10d79dce9fa41ab4810d4c085ef7adff7be02a15d0080051fea7a18825dd97e82145149d5dbdce0b8af1cddf137a1d536729838c8ac9e88d946c029d3eefae9b3e2c0ca66f2f5d7ee249335f648008afb82a9d9b78f08cd08634dc17c5dd202d459
|
||||||
|
h: 200
|
||||||
|
m: 39cb6e5003b73ae6f1ecc551c6625154
|
||||||
|
p: c8062eee734d2dcfc62bdae9b864306906d77adfd71afe18166b04c84e7cb43959a231c7400d37999288820cbbc51d3ffd6f2521eb51e567fa02291456fdf61ed6a6806c4af412919b1c420fad1068901d7921dddc02a14243cc1399f2c931648717f3a55a28b213b94dfb45401b46d4fced9ee83e54e55b7c27535f8e7ae2a148715f54dea531159b9497019a322e9838cac19b8684edb15d4a2432f61ef241e5cd5f20d1ee0828c84db02329119457ff05bc5b15ba279f9233a1c9496ab64f743edb41e6a0bffdb4b3b52aac58eee659ef2aeadd2b1207debbbc47d606b3948b937b2590e35b7513b0837cc2e86c2aff06d0fcddc4e930202f19f9316b130f
|
||||||
|
q: ef454da53d9728decf112d714afb9242f6231632f86fd6373c30e9e49e10b11b
|
||||||
|
r: 3ff28bcceba7989a9832f8259b5ae1ceeb9eca73d0cbfa24ab4cb273e64ab25f
|
||||||
|
s: c87de7445127dcfdcb1194668df3d59cfeab327e3044027b099f2566b9735763
|
||||||
|
x: 88f1922ab190a7298c95f663e3cc9cc118e946a2baafe137ef8a21abbeaaad96
|
||||||
|
y: 398275d507d4ec7660fb3549ba0440a7f742227f42268dd07c01bdb67064d39522ebbc7164d274db4e79b6b6bdc35bc46eac51947e45376bfe8914ff5f014bcfcf219a2606dbabd59b8a25270d85812d8af35e4b63f7a19ca7566ad9cd23f931cabc712d80a06f89fad649f423ddf457fffdda4261559386bad2f350465090a626cbf5d6749b2473a2958888a7fecbdfd2a16d92ea54d67a75088be341877438eb4e92831898b4cc36118bc41c4235d31910c0aa4f731058d9d7fcd7741951c568c1342a2e92fa74b8e9c8c92786ec83e02f92e3216f489ec1f7f6c207458712841557eabc87d79b896a85b01c6b0e1dfbde4c8bc48f451f41aa38c17a7da8aa
|
||||||
|
g: 23d743706b16fa4684c9d3021b9ce528010f584f62c18a5532fb828b866bb17614c63c8a56c5a88cbbbaedcf9ebda81ee9fc676ee4a5d16be07421720365cd88efd6851ac97cf77c2e2afb014913779d7affe3f8999b01034128b958108fa74c0521230fc928f9bd274e30bcae3b173e971c527506e7587fc8a597fbaf92b630233b6c3ad5eea37098b5dbc67620c3fc1dfe5b709b26f6267057103b757cce3598edebfbbfacb6efc396507676af8ad8938d7f965fe2335e9d82a1229212bdb3eb9485af94787c68f9bae9a3e6f0cc8d46e31c432da59b1764577b911bb9b3a5f181954fa44c7e02c1d64a0d4abe9cdedcfbefc01c4bc8fe89861dac43259c2a
|
||||||
|
h: 180
|
||||||
|
m: 00c97c21e666cd643877
|
||||||
|
p: d2ea8cc1302fe090da3d5c98bb909313b8e1f0aa1452f17782e939412b980ccd9aa76aab8e35abddaff432da0b0543f52b88056f5165226ba6a5ea1b168a60ae69e5d617fa3c9c492d92fd736ab3c49504c987dbc7678512fbf3c6a64c55bc0fc76c0009ae95013eebd2698a48ca3570b7d9b9edc268e12d6214d4bb6033de2109ad8c4f636c129d03c43bf856b08af9ad82f1cb4d1f10c7f61f0add1a3fec2e85050015c6540895cbd03071db7bdeea333499438d73d22c32f00465055990d2a2d2c4050371306085854d2607c232a0401cb6580791e1fc8b6c28c659e2abf3977a9c686261b517e1687d93a659bb5d5fd9d9aa62aaad09a5c01c2191b148c3
|
||||||
|
q: ac2bbb7b01c286e50501047651860c4a9e783f4e326de6af7e0f87eb4c30fc07
|
||||||
|
r: 996e6473c06c9350f2d4270177391c7df361af2fdbbccd6f8f869263f91bcd3c
|
||||||
|
s: 2768364708a5f929ed32ca0ac734347ad4e8b773b44ea770ea60698cd061dad0
|
||||||
|
x: 429c4a24029957cc1b47fd219343f0732f254f9edbe80d69121e086df973e30
|
||||||
|
y: 2c5e043bee62305321a1bb6057b942a4c983c15499560d19c93e7e3707878b1ba0a6abeb090bc46b6255ceaaf9aef23603f606ae3886fe7d303297bbcd38abcba88827010b068825a6dc59b3a33575987429e44eb694deffca26c07f93dd038a38141fe0864be1808679d80c7ef709a6776b51e34b65884e43ef8884e2ef27327acf07ebfa34c6183e604fd849f0b15ddc4f33a56d33cb637bcd05213477fce4d451c217c5a27558dfd9517cf5322737969f7bc83f7dfef81d34223504f044013449f1259d8ee275d7cccd2753708a09d447db89ec42abd88fc204ee13bb1b6ccc9f535fef26c90a46357c922598876488c8d4e145e52bbc5b50f84f72b12f39
|
||||||
|
g: 577c75aed2fbd82c2dedafac1a45693147cfb45faecfdd077a10ed6ea0d40e39ddb62d568d73f5400c45ac42df1f2623ebbd8956f23a35d7d149c559b9d03282465bc47b645d7ba7bb4a5eb0dea01c1cc3637e7dff8f148e781450fc12625bf1a20cfb029e33785c4007a9888ddc7e35e50ea9d2a0a25920851bfbd37d959f3fff1dd7a236de07cfb6360fec44bed1c59af1db2fbbb9e6faa2475ed0e49ef7b9434e54f18e7401a1d80dc40b3a8a436006a4d5a9323247a85bdeb50d00de6a7050e61315eaa4d6e43adc067fd4bcfd3ee01d7af9da72095eb1d174772080ed9618ff34b988ba3fb6019462ffb9bc9f25cd2e142be39d8d47ad91bedce1e414a0
|
||||||
|
h: 100
|
||||||
|
m: 831f02072ee5daf47051957249aacafcd0b22f73ade72b33580e2a18083b5a329ffed5b9883127212756e63c7c9daa26e92411fdf6d06480bfa0d5a3acdf199e0e9db3ae7e4cd2b40dcd7db38f670ab32a4273d59dabb68055141674e92c784500606e04a63430d564a263d2914aa2d13c5df443bd77e785c83403cb4b14c3e1c68d8a0fd7c4fb1db07bbc7e43b1767c70632b216032823e2e0eee310122005430ddf028b695a6631a663d30653cb10c5c489fd96fcea3bae9834018d7baebe9cba0e4d5572b2ca8f075038e806a3aa2c44cc3279e82449bd23ae04112512733ca2f3fadb121
|
||||||
|
p: a8eda33605b64654d0b8d9bed1d6481e854d417f510ada5a08955ba0b212aa70317528bc204fa012f99fdb1deb8f41282c0fe425bb06bb9f5ded3963f75e6ff96802cd2e7aa666e9a01d6a7fec9c2b2031d8465e62296910372456b87c0340dd0d50c2bdfc8740ac4ee3958028d757768c90520303f55ffc57bc20a001a27540efee52e5d436c055f9bed0af613f0fd8714831c778270a2ba2601ac920eb9909cecdccfedcb670a6b218f358fdf5822efc15a65ec221021cdba76334511894fed6dd86571a97772fffabc3a7a19a54b9495a724aeccb91d7544c172ffd3713506f3b8fdba2a342817fcf5718d94699db3813ac2a684f4aee3a38fcde27012753
|
||||||
|
q: d305b00be079018cfdb72cfa7d594cce921dcfbc2d6651b8acbf0a7774c5d841
|
||||||
|
r: 9e50e9c4f9fc9f9c13ed982931b31a050d9bcbcbf697374ef86c85832dc0faee
|
||||||
|
s: c8181426d369dbf58f4fb0b3b2d01e05ce60d1cbda09ecf7be12bd921d901189
|
||||||
|
x: 7af19ba5541ca8ca9c449789341883528da2bf64ddf754439b8d30a527045dff
|
||||||
|
y: 605c836a8070ba4850008101451c38efbd30ea0eda6770a4b14ac9902fb85ae7731a1d5e52fccabda1d36b5ca3ee821a646d71ae075f80478ef7894239b6baed488474d31e2db2259ab5896616c0797a1254d5b2b0ddec63f408f263143b109ca421281adba13f3cfbe80bd571d52f621a15db04a18ec19981f5166c08e7f3fce94959a2a491662bcc3f0b8b7f6adee4338bc2ec2b4fde960af59c7a8d7218cfb087edfd853efea2ec2558ab797a69a1d4fa87728b54acbb438392debcdccfb549b2300c0e168118b9380a13b979b19c7b23dc9dbc775ab34cd262e917953a157489f539670b8b65241fadc8fc52f644c59988d466246ccfc2fa88b1a81d6abe
|
||||||
|
g: ace69194079c7ecf821fff3a0ca9455b6e2e105cfa090a82730279b0cd6099f178dec11ee836219168253cf5eaf689478e55f2901e31072b1326aee96e8f4d7cec0b2ff6017e8fdc6fe0572eb85753eaaf773c897dce049971454f8b4901a471586998b30358fabb622997b11e898d002287177e759ff393703b95677ca21266a06c2fc69fd50a7cdca8b32197b0b90a687f10edc1dc3031a34fb8ad88a4709b783b58465e6fa5d16d12b88aabe227dd2e8bc71baf829fe1d49a042e66bd3a27404417b686b6334bc53c76b6482ea8bc243bd17107dd4d535d570042d892ea91c662ce2bcc7ee1574e167e95b2071a3190564bc0d5bb7e934d60d4b7bbd66857
|
||||||
|
h: 100
|
||||||
|
m: 42e8ce93f11eae2fcd5dbfa4c3663d757ff9f8d4d507a25e3db258b990aff52fb7cf9f95bb7a9c195d6965fff3cf1d9905aa4499868f7ba6
|
||||||
|
p: e1bdd4669c50812f22e39a8a1b6afe353f33fc0106ef73d4cfd6eea8934125bc92f3e46054ba1e58d24913599e65859945cea7c919419fd70be25202b76d7ebf78d463ec5a1f2ecf22c83552b05de9e74c0b4930e4fcea347653ae06b88e660e16aa339a87599c1f187113e0e1717bed3d71e79c54b01bac7a76c6a1e680152f72d2c47b954f8213b83ca2ff24d0a5a5623289baac9d3ad9005a00b53ddcc19d92167ec3d590a24c8dc91f17111e1a94daf084581b65a4935af5ed8933a2ad2a323152100e26ad5a115f828f2ac43135d356076051c4ec37d81e0978437f8b9846231d091608711dc7bac4ca23da80e27d8be8844963465fa8e85c3f2c6db055
|
||||||
|
q: e2b7f96e822cbbaaacd2eb9e7670ffb526f469c861ee1ba8263132bdfd5f8bcf
|
||||||
|
r: 17fb40e8ffd6f2609d4733ac12104b9281a6618ed74ed31da6698dd7a31b9d5f
|
||||||
|
s: d1d68b2609328257e58da88d21d47e3da808a4901a4ad19fa6b767b2982bebf4
|
||||||
|
x: a5b2600d0440574b36425384f7737786e481fdfaa20bfcdef49f1af415a79984
|
||||||
|
y: cea577574fb5b78f74ae15c467a7731b2492a96390ab6f8e6ee9d321ee09f5fe014d37259f09889766063be6b4367efe9503e2bf0f9789ccd78c62ca5e34fb9dbba6a7d29a552904310ddae38960eca6862ddb8dbaa78a0e00e0eb56ee1c69f43c1f30d9a2a386f3d28986816f71d6ba8d5fc8e4f40aa9e7f826b1577807f99538793bcd4fd3b3099682476b422ed62660aa33ada1275ae50e3d47308fcf5f8c8c4c991aad6870d4f7e5a142e006c27fc646cc0e4352cfe4648208cc60a4e89e8905c862cb9e17586bb4ef2bfeaa39bcbd30b62a194983edd94de76e68c83984bda6561c06ff3f9a0855efeeb2a30a47c83cb62b68005976465dfcdb12874b5f
|
||||||
|
g: 3f2028351d454975a3f6d02b04cb625a742cc52fb6c7f49d1c5f83616316918655fa56e1dd7606571556422108fb5e5eb3950e7062f105e772f9d0840d1944184fcfa64c3e5cb590b4d226f1b66b63a423a01ed43778aaf64572fad67ff079905ea619271b77dc1a5a57e8751b07a180ae606287f1114ec4671177ab005f8367cd4664fa07a48ce054de88bd7a40fbdc10fb3b950fc9289ca8bb68ce16a4a2256dace7b4c5b430b7a6d17fe5983b1429c04629faa14d73ae3528b926c8d0144cedbc565bdd199aa397a977771308655819656cf6f8aa2d4ecdddf0a3167b984c3ee330a178b04b6dcd4eea17063944e80fe1d0a1e4b69db9442131d639e8722b
|
||||||
|
h: e0
|
||||||
|
m: a9ee8f4f857d
|
||||||
|
p: c275bbdde048f8a42470c43cf08cf098a413725f4fb3f1a4813b7639e702197e8d3eb1b1ed1714271718939dae8be9d1d35b8cdb255fe51f2f99dfe9dc6d03039f9bc5b805b64f943ff843bc0b9a913f5d197a5017f31a080510282db178c0d14138299e307b7e8a714e89ea8ef56ec04859c6b8d91e723e0318a4d60f0321c08481e7f3205e3e1938c4e0ffe0336f72d2d1caf309654639567b14658c96921d1e5811c09025e4964d09e62dcf929f7427ee19a98214bd976376bc2510e1b0ac904d25d5838b99cb7556e3521f02497445c2670f537e11c5e548c0847d332fa7a9451ff9aba0686618ee8e9e9a4d6c352eb73f10528ab691d68d5178b52cf7fb
|
||||||
|
q: d288fd8335a1a54378a9372beb69996ec7a608eb7c97207580291c0e403266c7
|
||||||
|
r: 17794e7d3b529db5132c4b752526fec1301deebc7fb47838c92ad571e95af99f
|
||||||
|
s: b4896fb23af45c31559b8ab9798978b89ff724430c09c21a66f58cabb6cbc5c8
|
||||||
|
x: 71a0bb903f406145f8204b69827ecef2e542b82cf08fd3e7c020403b4582fc57
|
||||||
|
y: 51c8313b2731fc50fd99d4780912a3ab86ec6c2fd4da2ca38ff994cfc7658e2bfeb9ad10609944d5a5a122d581994bbb0a523f58985cbbb8127b21dcddc26f26c239a3bd620f55bb6fd1dce2168e21861025afb4d0985d0399c3c7d8cc201790fdea160e00fd0b0bc362e0682b1982f875d7ac68ea4ce40a145fbe1f0748b13dcb67729bb95be99b64e6ecde41ad66537ce0a2d99db96222c528501e6a9e858c5626309931b5d0dd95a62e4ae16fd5eb7b5131994392d0fab16dd4d935e6dc55c7c85b9b6770d288b26842885dc45911086bf495df8d761f7a5755f9a145572ce0952b149f4ac7b9bda398c9416a65c89bc04412955315e08eef7b696662c19e
|
||||||
|
g: 7406836a7c0178035745400470e31c58180d0cd841c4b9a814581df145bf2bcb062e42faf7d3a3fb12fc282fe01154b8cd36dca6d4f6044fa6814bf660270ad2251e868b3051f4c35a2f03d506c5d4ed147268c72326896d48e249303e32d748c3e8b3787df76db62eb2a941b57c945b95fc563bb2b70a611df9055a2a6bc04a5383f7963708e4ad288573f3247051d2187c2ed3e033dc800bbd0cbae28aee5ae1bb0d65b2d38f4d053de952c63cf320c0964e25f83d69054e767517abef5d025b6535ee1d4a06eee4f72c0ac957e8caf667b6525f0e43a204a9e889301bfd6d2de594206764003a2a197fb48da1e75e16cdc3946f8c6438cba0db8bd3933986
|
||||||
|
h: 100
|
||||||
|
m: ccc5419f867ec3b2528bf7f77e16b53684003e91ceedf7f0a392b0d8a5b0cb69
|
||||||
|
p: ad9bdf1e57b3753873bc919cb3b9c5d6816495ac8c1668595fcdc5b760d1c5aa6eb6f0d6f865b759177bb25b17dccff6a18be59b3896e24db22ad9320388dda291d86931330cd76a06b4a50f73459edbbc553e6350b86515a79f8a17c2f92050db683f88d0c21e332ed04660ed91b976bb5ee47a5afe6be33bd1d4e97b7926ca76dcb7517367172f5f9e18a06b05769cd21100dcb320e88ddd45435b41fbe05be9ab2788a02ed46ccafdb95e133f4472b2c3d052495d15513bc3341783ec458e826685fbf9996334489fdf8d2e540d15fe861e6dec623ff2a2584c041a4182245ae4e100215c74e1b82ab40b0b77c1246681cc5c2888155c237a120e54dbc9cb
|
||||||
|
q: 91deec60a3b77dc0e867139eb8f39abd2a51a2b4ec143b9f58cbd17ffb499577
|
||||||
|
r: 229d2953cf39940206f51eb22de85a6de54191afae84aacee826d660e992a357
|
||||||
|
s: 55acaed98ba90aca72e05ccb95d37c913e7c03e32af416555b5338c24e37c7e6
|
||||||
|
x: 7bdbd64c954610f0ebf510be20087126162abb3ef375d6b6183b33e5903589a9
|
||||||
|
y: 13502f838272984bdf9914d8e02d510a596fcdd1809ff807ac847943936c5b258d326958ff03a451b2efd09bf09fbaae26400215601aa0cfde14649ae01c1b03818434b225a743e49cb51819c21b2b17ac4a342d514d98569c36022274d7c999b4a5d5ccc2db51f42c367a36cef98f23946ea507d02847566ffa1fa379218f52f5ccb76c3ab64208c6066510066cbff8346ebe6ccd3987ae6bf57539bfa1645e0584e69b0e9b09a3849a314421427935cbd9e4b063d906f3bffef74c0350a95247da2a49985928ee2f4cfbcf512a5f1d081020a0a7963cc8240ff0b5b5ea0d99a716d452df3518cecb092cb814bab07de668c4c5977b7ba6652952b9978bf1d3
|
||||||
|
g: 51f0f54e4a4e5ee6ed696573c8cc9166976d299f077f64fcace342832c02e699d42e26c9247167b0dabfc7123906d515335d76a272cc12faf41ac419edd6377916663bfff675e246f47038f3b0b3c80fbf5b20a56072acae5a868c8662b7b4bece9ac32d025eadbd4bf31119060537c6422df93e2c67b51f0a87deedbdd01199453527866349bc6f5665dd6994b9eac9b605465829676750affd57ac63e339825dfca541b72e27c6648b733f47fd7e0453dbf174e833ba5ee9d84af2bbb14fb3b6cbc333d267f26d2f25e84fa4ba3414afa41c8539896d73b7f47d8120b9bd08aca5ad323cde5673aa7da7e8b5d1ee9d45ed15695aa7967dd2886f52afe42ea1
|
||||||
|
h: 100
|
||||||
|
m: 0f95ff3b97683d1d7fd07ce417e49a9afb31e090b1a883d3051cea76ab8871ef555b8ef164ccfd71f0304275d5adcac2dbd647243250f4736f7f7e76e6203c5caf60bbbf28122adf71c0b1e9327a8478c57ac2d6e3974a14cef2e2720d1128c9d1da629479d999ec5fb61a1332ae4be25cb8bb99d9c3c73bb9b9e7635e80dbb23e
|
||||||
|
p: a742043496a622ffcfc1fb47939678867bdfca54e3cd68fcba161043d7faae8854708506b0904096ce6ba7d7042a76a5be9ac5fa316e8761d49effb83c08c6765cd1a6a50248ff804607319a31ee3da393eb4b6b80347891f255867f00f55af2b74b8391b05b6f74640cd56359616bece266dd7c1f1cf1eec0787f3b77fb40ac718fab735b0a0a1aba0a4d4d5669769afd10f77d77b756f2b7c841e13458bf89e7bfe0d9691c7b387961fda8f7c56119980fc4d92a9f6f74fbb33f20f9a1a91170af04b0526496e3a374bff44ac25814f0afe8f50de0c835703170695cf8d47a97d0848a3a0f00f4c613bae5795b45ac002d3f6dc266c1f64d51e4df2266caf7
|
||||||
|
q: cc8e1988d4d3acc4f5ff515e0d856acd69e55568952a23f41507c73daa33ad51
|
||||||
|
r: 226f796fc7fe4a13a2a681b34cd2923fe0651860a906d2261fdc0c7492848daa
|
||||||
|
s: accd4cf3bc38d358ce3fcb8217588cd35d1e44429f2b0d06277fc5c8d75398e2
|
||||||
|
x: 8d18a6fe96df9fb7e9e9e06d33e7fee9b6954a1034011bdc223a09e4727a52a8
|
||||||
|
y: 8ee4e1576c96575d9f50a3aa7cd6d8bd6f2a4df2d87d3b638c5b7e2c3031d54052d3d2a9baf808d72ee1d9ee5c5fb00361e3d3f7a9c0444835157f3e489c8394a3c4c90fb1b4f27451766c3702bcb3b0d546d84921188c1aeb6ff673a155b7da9078184204a77b81c46a53429ae83e9c1dc79fbcae4d0577213c5bd0bc7af1fc5228a51e2e2706919e70cee56aa214d244a560280d5595248d26fb88f262fb4b033a30ff5c2c1528e98b18f48d9efb457df983b61d247a4dd2e47a6c697f99945873e72b0c712df8a3f0cd30c6a04e61f722a75c03bdcbadc3565231ec28de8e30f4d1d026ca769e171f44ac08ef246e83aed26b71c0bceb0a6ff90059e4a4a5
|
||||||
|
g: 84f81c3b2171f1d24f757681705d73c089c6914012a1590c8163f7a40a5b7f04cca8db0fd573e7adc2514ec38cea5fc53e8e0185b738ffdf6e3ce2d5b699746010cba34897020dfaa766b7c00e6304c7eeb915204380d8e925fc3293d0fd0293093f6f8783a4cca045a87c090de79ccd671f978a5cd8fd0ba6f333bb27f0d0a8e2086680d0e0b328bc2367556367e042f35408cb48a5c2190d6f273e1a16f76d4d5fd5a151b6bac6f80cbc05c7d4a643494b0a378868f43e60924d3274da744987f909a820ebfa36a3b5ef03dbcfdb00406ac837a639bd949d3e47e2e3a81cfa6a90c22412505ffe0d0958a4190f29a2cda1bde50ceaf80201e998aacbfae8ae
|
||||||
|
h: e0
|
||||||
|
m: 478e7ce9de1bd541b46b472d99c9e3d326ac3bc97bebad93bcafb61df59498d26894d41c18562c57bb3b43a431baa5b9a64fa6a42189a9776757432346f59a9400ce2715cacddc7fd545b1607a7531baafa07226b4a6cf7ce2168989ddf633b471363740fdc80ef49d38
|
||||||
|
p: fa8b15ecdbed2cd36a4af57b4b9b31c36f34355ba081c40753bb7ba7c593c668332ee24d7412f4b762a578e1eb9006fa86b220cb00c355a3391f132f885bb1f38d67f3749623b0aff954a2862aff1e486eff5c4a0dd5932836b9be4dd6827abaa96f7c4c76f16051693677281d717debd456d063e28d5442acbf15b93439bbcaa51bc9acfee1c17fb3bfa72bbd107bbb2e116cbc7ceb3d6d56c59344c78c45e70cff3e7c66e994d2aa04cb62b1c0c93d0c07831bf2016146a0063d49fb0fe7a291d73aa144f73a52a705d71eb1090a3912d7d8dc14ffc5f8f69f2c501a9d002c297d034b148f315067c2ee404b1f8a39e0f06c8367127be81cbfc17392bdae27
|
||||||
|
q: 8811cdd48cda5150c19d7a7b81daba90acde023f885e74e2b6bfadfc7e219a77
|
||||||
|
r: 1652a0aebb5767af4b3609eecb12ff57a062124761e58f35214daa7159c55af0
|
||||||
|
s: 31853617c51d462ccf551b4d12a5c90ec5007449f518a82ee8dc58c1cd07aab8
|
||||||
|
x: 2e2a0376d26ca8bb6e96f443a0dab680f77eaee87baa0879e27a2a511093bef9
|
||||||
|
y: ed8275c783eacbecb164dc2946c082a72bc429aad3b087ff645d4ac265e2bde710f45a1c1e9a4184c1c8b2fb2315296fef6b87ab83f7687ff5f9f08c0dbadbf824c2232b1d50e5bd583848d280751c79973d1bbe7d943ab7425280f4b8ec948c1a67ff837696a3a6d470e03afb890bb44cc169a533e3ef1c64dbc60203a7a0196bd0aaf56cb78415ca3a99b9d98420a1bbb90e4080b42b41dfb55e057b35082e552f29d4e2a623d091798b471406bd5fbaad5ddf8733c36a18a7ad407e9debf53f534367411a952201a0276efd781355d52e522fa764d08af0cd152bf1ae13c90b37515ce09c0e0238c0b7de894cc2fbfc5dd0d5e2650502f77b3a256553d906
|
||||||
|
g: 2ea7db78543274de385e3c277e5f4e3cd0768f26ee5a4f479cf310d6c3d15539b2afd9308a0be8d0d69f015032438eaf327726217d75263f92a3b0d833cac7ce62ccfbe56159d282a73b22fdd1800e87c1b8acdbfd6ed1c40dc9c6a24c3aeec10001fc3456ffa966ecbb0794b9f890320fad12cc882dedd80739c741e24f337dca727b975126b1cb07f058788ffa57a2a54c948a7ec8f656c37df380bd05dbf766196001115eb3dac84d436be287e612e77c9fe1ce4cd932aadb8848d5fd209a2940a77315e7ed4f133daffc38dad224c83b4d3339834646c982fd032ac6a5a7b1a653f429751af6b3e33a7e3de6f8064d83a09115eebe7dbb4d67291812eac7
|
||||||
|
h: 180
|
||||||
|
m: d3
|
||||||
|
p: 82c3b47755ac0211f7cfa6aee8c184d97108a00016f46639ca1be9342455ff6da2287a0dc744d33f6ebe7e122bc57500742cf70c2025b963124f065b518b96265796df2cedfdd736337b9383a9aed90e53e1e2d020c58b5ff3665adcfaa2347bdc3d6606271865f033cb49e5a0e91d3011f22bc237e32026b9a6b4808ecbe937a7a39d073f808bca3d6644d8edb4b2419aee99372ddde94060ad4204491e719b8d8104cfae0e5b4fd1281a7b9b8e6d7238f965b5bff10728dca2c2a5c9fa24ad5bc1f82ebd25f243ca1cee64cdbac63c441ea275968c5bb5992d749bed0d47475e7353e38f24819a275fb5cce6f1997d99c9ff63b81cccdf464fe3bb056b0287
|
||||||
|
q: c482c7e3faf442f74e98561b0cc14b41cacf2e5005055fe14d6440d53a19c139
|
||||||
|
r: 2c9d6818013855ffc3a0e6c85e2a603e0c8e24738eef2ea18338136a48ea0593
|
||||||
|
s: 71e2c35d473986401a5a7ee068ddfba31a5a1d0c833841ef42dc37aaf5fce712
|
||||||
|
x: 797f4f061f4bbad13da298c9f10d6fcfad21e915e2a2129e73771e580d843815
|
||||||
|
y: 1ed11fd81ce77c4de03a2f31185ba794c499ccbd35141a611774945255fbe036ee4c317c7f0372543b175847ac75329373458fb8ed5864c5e2fef037b30e6679f27e57ed99926a7f4527daf0061dd69fc12b0824bb023893840568b879db23f98091bc4a3daf0b0b48c1c766eafb73692c71f6b31a8677fc43f07df9d5c4efa254f363c99e50ef0c7a0a68060b38394396467cf3c9eb178577a12f6ad4efa60bf7c5ea100e7c982dbe76a2e823d775369bcf2d45677fb66c20bd00cd6caafe407a9882829b2948724bf6a06512ecd1456973b3d6e03551658c04463a52e45cb6c3ce50c2d223fa26c97915ad206bd2c8a80d2100edcfec065bb594dc820ce0dc
|
||||||
|
g: 60190341f6a04ac03a9bac1310dffa2fe29e074eeb4825fe659f871b57424a5eb0a046c9b76f7a085ac7dc4752bf333b8ac54f35e650eee82591b846dc500c638bf88480bf177c6f1ce7144652497a393e7a9fb0554e67f1ce7410f862177026b7d993853e2edc83c7981ead33c728e73d86839d6ff4b10ee095b983020eb2b3507eea397fa4dcee94ca184b0ce79046d61794739784ff7006aa36b36ab6d00db7865f24dc41a94766dd53172c2ebbb23ed44dd80ade2384b17a8af12f088bdfbaf7dc8ef3f7b5b0be6f0c34d1cf260c88bb6afd66d7f45c7f2c7049639b5d1d320829916a46cbee2626dc15c4cc06fa302d4b1e0bcd398a4fda3bfe8ee4c66b
|
||||||
|
h: 200
|
||||||
|
m: aba2acce46d95feb5880b3d7e69952491d6d815c126b92dad051c6017e7960e98f3945ffd9cea849c9560e1c275f0f9f1fef0c73abb3f53f10c2e07bcc4a735637b7d92d0643ab4b205e444e911baf14c4a0e6c4f7353cba88fe6a2a418572c4cbc1ce99a9f8c9944f0ea51393d97d823f8a2db40ef04a78de342c3e5b166c2d070e4e4d1525358d5f14e5e5d7988ddcccb4700106764e827ed5795565d7a5bbd3632a2ed4283a9e6d1b035b18ce5293ecd2e7aca437111e16550932ee1d75be24b7610c4ecbb6989b95a5dd21e394697fd70658248188670fccaef73fd9e18312999fe760de
|
||||||
|
p: aa8f94f5a49c956c1e5973cf89ee16d485884aa6d99210714d384d204a009e0ef3793806ff81cdc5f4e581cbe6afe3e2c8919e7fdeceb921b2351dce7edbec4acf6101b8df7d80affc40c07fb4ad126c040e7f75a78446c5796b924917c1aaadcac132348aeba43619c1805896ae8e96523ed513088cbf1b15d67c5410165824beee1120232c755b6751bdf3b8f0f9e4d993ce27d37a7e507cd1474010079106729e589d6a0851679d24445ad43b91a5caaa8f4787bff4872807330893884d6490d4e5439ad6876540d8b2e61fbd543235d98b885332c4b54d858b356c9329b52607a91e1417b44789b9693789cab10cfadb0541b3d29c427319b6406fb5d38d
|
||||||
|
q: f4e120b4a58b6cce16abd1f7c238e7454d6bdc112db8df23da12a9336d374f5b
|
||||||
|
r: 2d0f4808d0f4491a2c7684c82a22351cdd138c0eca331b553f443f1e763fd300
|
||||||
|
s: 26a23dfc2881cd964b787b6f16c159f6c8e2db3477fa06d276eba3ebb6b4ca5a
|
||||||
|
x: 956fbd89de1f4c44fcb67784a1e3f54a8ecd607599611ed658a2e80b6fd3e05d
|
||||||
|
y: 62bcbad2614828379f3ca4a7114f41d0ae01cf1469b1e9e90d2629a601db12926ccc1d4dda88496f41bd113dbc69360b16e03ae3e97976924154ced4ed614e5e60f38ccc4613c918fe6fd8d6cb5cf7b9d9015604ee2fc4d597153089a1f25b540b9f30e2f9590196474c9d74d7295e654afb2b29dc6a5b16a0453d8342c3b92d11d665cb52c3078efe561d8b1f94d459007b51708e544ec11f0a7f9e845c105bc2656ffd96244ee8fc335916a1b191fb8518f99aac57770e653e7941fb86919d689a42a956d3000c9929b85e3b28f3fc44de418de74858d3627d22277552bfbd701d6b7e8e62645e4119d2f8737afb91d9887cfe16ff3f56044c2a3f9f29ea5f
|
||||||
|
g: ac8eb3f8039a814c713a28a8ff37ba5fb124a849378dfda98d8cf7914f98692c1fb12af205a092a7596ec1b8d7628b58c1453e6e17eb5e55ea8edc5d5bf3f7d9180e8329acba45ba8a1ba4de034523dfbc0bba623f9f8e9a8e057969678c785993d867b0d41b2c9b26c27a60650813bd63ba2ecfd2455754dc794aacfd1358b6627e556e2be0747739c35ea9e5615768e0324b659c7bb3dac376d0bd492d4c11b850dc1fdb568abfce80e8b46662fd17a79f76958766dcf90cbddc984fd46376b0854f2e444baa95e8b3d4f8ea638ad68b3a9fabf203c85fa9ad33b39ac1b14b7a29bcf988975208ccc039d5f6d9794932629629b69ca7f28eb31fa26f21dfad
|
||||||
|
h: 200
|
||||||
|
m: fa4f65c77419ec1bad74cad3c1a3ef4ef9ae4c8c6cbb826c9ee6eda60fe8c740f8f80f1a88329422b787fa3181be61d5bad5d025d73692baf5721f487b9079a989641372f1abb80ff754744c40f9aebdce4ad9892a1be802f75ff3bd75374a4e20594e5ac63e0eb0eba631c98cebd6474931dd426f636e1d4cf2a625a374f541bfd1efa5b28395a964d3bdf3c4d9a6925071d4d566b94d1e6b88f415e06b304c0b27304f62db7569061e4807
|
||||||
|
p: b7bcbbc1f5fb62623dca02d29d7563f8e7222869d65cc3837be8f5a101ccfe8e92bc1483de398b5c43a52ffb33bcde33671f96509f275e62566699d2e2390875f151edcbab34a8839ab4c7b9e2ccade227fe7e16681c2c69fbb9de237222b5c25edce53512cc8690eb88bd16717ce6c09dfc137f959494773b716b929b4304b72c09cb39fef5e9f8da250ec224880355b65affc1972fb95e69421a5515fca5d542e9f6ec337032eb49332c5aa2625f968e5957d69c91250e72c1f52b964066ce6520638cae33efe531214fb7dd0ea0573005879f3b79870807c6042a5b3291a6c810cbdd6baa76639c67923df21ae6794251366f67c17ac6626900748f64ca67
|
||||||
|
q: f0808df2f2e74b06955cba686138c4ead7fdbef624f0576da97ee9772dd1ba43
|
||||||
|
r: 5bd38c177236c8cf3813f6bf6c5b97db74d8f372c7547c2e27753e5674753ea0
|
||||||
|
s: d42f9e5e11a210145e1333379e481b25797d3cb7bf1007ac9b4995360cece830
|
||||||
|
x: 356822bd1b5aab798a1f13dfadd408be46a7ed5909be5e8aa67ca0dd0c4884e8
|
||||||
|
y: 3a2fa4d36611684a70fc4d0db09f2111793170882e190fb520dc0f3a0b7a2e0b76910a44d358150f57ac9e79e37582bb3d51a556711202bccfb50b9980ba2b848cfdb886c265389bfed32114c41dea3fab42b5577b205cb14d4f169b2d28a1dd6c20bebbf02fd3bfe911c4efb7851529ebdb9e6a27a09c26937d89d4968a63eb3798c1e833ba6485f54d640574db2d7d22da93a2fb4bef1ccec0b6b7c9b0f02e58a27d3f265f3a97a9131cb76ddf53e3d9d065f3ea51f2664ddf05c1c155941bb4e373333d50ffc32374b74a945b0ed4c342c738ea23ca5a4221625ab1eb72930c7f26cb2a04a24f879dd0ded40b27ff0fd50f416f81b0e6d8774c368bb2a991
|
||||||
|
g: 61734db989eaba2924c97121d1333bd7be6dd9b2c40772c4b202c869874fd0bd7720ff9cfb70d7701899c8efdf2ea06ad3c05e1f73525c5b6505bf1a251ede6e2f8b5ae38941c622490caad12aaeba139fc9f7b2c204e1540cc379a06921ab9dbc285be694c5b5d4a6de58ce30f0947ed862b3d5caaa5ccc83ceba55665f84a1515886bacd7c3480069fabceee5f0009a6a9f6f3d4f9778f822f3522ba3f1014769649accb61e3c5c03cbe4102a4f20df850e933404c194c9fdd329ce126ebef57c00f5654c301d5bc2222fbafc460a3349c8b7850759d5aec6f79d2545d0e7cf02ce84b0c16a032bebb64d81cbce76350a6a0ce60918e38125609f8c1012d76
|
||||||
|
h: 200
|
||||||
|
m: 344e88bfe00b72e89ff5c8be3558d3e0c1acdedf3b37d983db00ea59a4ddd28ab1d90e3f49072f9494fe625cf5424254ca5d7f3b6e86579c9f8789d90e6b750fb3bc24642c3d8890c2b8ebd065a5430b414eaa70d599f993c910cdc65377d4b071165d279b6787d7da327bb874861e5c1b00aee6464affee324a98127966f78b581ddc84f448ab80801a0576e192fa7abe1f63db6efe63ed5f3aabba675d5cc325a958b45010845ca008e5ba670cfd0ed8ad1cb0245b69285d83a9ff8bb763d47dae2877b9774c7dbd18f30011004fa2f621c9ad377a94d754dc108ce4264dac
|
||||||
|
p: b267238bba20604a2b652e85659e2a31dfa4e2074a6c566efba265eba5b080be1ae83da7b9b4a613e9779e67efb663c5e7b1f08c982031b872113094c06c994637326293911802beec6314ec3516597c2a3f3c8c2519163f4aea095283693bc8792025caa13df1f4be62fae9d9fff2aaf8e5f4fa8eeeda556a1bcde408adc472e6fe684c30b73508b096adf6a22d7524e3de825ba2712267a2bf51cd55b89544bd0f407cc8a2c98a81d5bc7e8a9c880e9eaed204b2d5873cd1e841438324f3730a32e51ad519983c4ec7297f7fa5a184c90e12bdbac4291df584a8704704a18b144f6deff0d023c60a44e9dd519b8446ab02f13751cd3b54b8154f9d513f6b61
|
||||||
|
q: 93e686de011b7b330c444bca07e59a1b489cad003447bdc8f0ee2070b0e06417
|
||||||
|
r: 5fd929e6aaea0ad965309bd748bb0f29ed73063174e5b56543fe12632062e621
|
||||||
|
s: 5951def11ee6bef6f20be51909f21b07c7f8c053859563d605ed4d2b11fd3e2e
|
||||||
|
x: 4e088b92640938673fd87c16f62d1e93635abb6b2c3f40c21f24fd40f2b6c7b4
|
||||||
|
y: 626aaaf30fa8182c99144cbf8300cb08673dbcbf6b92fdcb8368c64a612731dac87b53c26189d9adc509ab80b358bfd89c69393861b022d04026b97f52cc9c756fcec03dac564e636433b81e04422f5d713a48968079fb511082f8bcd3c3567ad55a1948c3adedaeea06fcc8a22b72c8ef10a70d692620d1c88192c0e3041e96ca91e7777935cb492d10f347114abcc6a204fd250ab20f0d7d014272c29051816ef22d40570c56109042950c198955e432f0153d4791bed13a9ec0fac379642c45ce9d937b78ab7f1daefcbb154796bd1171b5c9a31d18321afaf39e783bd572a3a8d960b4be609a06de126271ff06112912acd1f88373bdb78bf896da74625d
|
||||||
|
g: 388f8f779fc84acf4acb5d3d3406319f944baadca5a3c2de4fefc9e1a7b7fa643c628849261a9e405dab8ddcffbc6c93fbe70a9b5495b318e3a5d605629347d8b31688849847e6befebbbf2e79e43ec5a414af5d02f4a95616d05f9896e8d0e3dd90f55773bab4e59bfcb4e5d0f3e276e8e5fe384b6d18652e76022634c77508e43e7956191f4e74fd005930e9a4d909d9aefb25e60ab8120c7ec1707b76afd7b6bc38ae1275c71f00fc099aa2af1f4b6e90bb84fa7d691f3ea74920c5955d36cac9eeb0e8c6a07d9c966beece6bdc8e075334b0c587b3ba2cd030bda697f8f6945700fa4fa4b5258df9e50f4d73d9520654e46d8df6763af645f416ae61f3c2
|
||||||
|
h: 200
|
||||||
|
m: 5e4b1bc904fe606a35087cd6c79a9ebbdb253591e9c2fe8e899a136f3c57308a877597a0e1c345e592b5c1dab65a2c3000ed79e244192af67556b213f5b648f3e9fcfd53bba3850e0388f62844c19cd8c38466298718e84c0e2ffe08a16af43c0317c1f7eb8da8b1a5945d549be6f95c051a971bcddb49b5be7cb9a2ff3782b77b2a616637f90c29ccafd815429a46ab954cd19f49967abe3978135d700b9ec9e279351e78d740d460e1150d27d791f9b70ede0b340fb90604544df7b1569b1df63cb38d9a764987bc0556a588384c9d08f8db826d
|
||||||
|
p: f7d03ece1e31e9b7f6794aeddd406134e6a8bef74966df3f5a53227db6b607df88780953d0560b6b49c56f1efbe24d8192f1692a45fa50990e6367d31e2e65520d70280227eb02b423687f440c50543347b1289da7e424a11ddda443e70386f5065a44ddd485090b05a310476eb5ee839ff1d219fd7c579867875494c3e6e4fcb70f239e2a78426092f9547bfb048f79d95450895291dc73c4242f1f6ea24365ee8212dd4ea4204731f92d7d4f4c4e4c2d9e8f6ae300f37e6a0e192862bbcf57688b4e2417f4a18010d2dd00efe806c5aa123d5a97522feca3dd5c4c5101c006c89af6abace707c0eea0d86578836dc62f3cd1a666d62c47498d3d7d61282eb7
|
||||||
|
q: e9e563816813e87a6a244ee7d2974b4fb2f80515cdad284816854bf031f6604d
|
||||||
|
r: 5eb47f1f7e446b42b0a5fba98525fed8bcbd7eacffde2abbd786d935762514eb
|
||||||
|
s: df66611d2a93db9943f4bd83f23d5a09492bd10c6e008ec70b0267302a3ade4a
|
||||||
|
x: ce7e7d8b5557f96e1d1d336d3d33a9153ae44eb788201ffde8c7b545242cb0a7
|
||||||
|
y: 1b9542a2b6484c348e1395c1bfd3fa67ca32c1ce4adedb6d0d8e9b53e2279518aee859a2904b8968c70ac54a564ad8f8d55e210e66dc714bf7281e94d6e0bebc3218944457093cfaa3099d62da4d2cc017f1e913e32be85a60adabde406c3cdd6901e36cdff95de87184a76af4866fbfd2209c03440676126a0daf402ee5149edff07d148d30c4c757fe985d2dca66928c2970fbc2d177fd81821942d25485b0571b0c4f118bdbd7176172ae94d94088432a1b72a5780603f3987e1ba27ae8aac725d0d9b5ab3629b79095d4c401a5c7cd1f9d621b739f75a526084d784ed2498a4bc3ac61bfb2c8af428aa1d52016c91ae7233a007d4af927446cb9301fbb95
|
||||||
|
g: 19af3cb0ba993ac5f95ca9085690ecc0b133c36615b1ef0d2339b53739d22b4d4e2abf6556f8af9913bfd10b82c1bd0032628ce189795945c23cd3f3b244c77041eb60ff89fad2bb27c12a90a3e623ce547d554d3d3b358437103476924295c1b5dc33d669d16fbd9bf81bf347df9693d0593d1692f16519436e508a70af5175ff56eab93d05a3c50c92ab7a8727b5291815a790071a4fdc18f6bbb1e2759bc3c678175373d6ed7b8c0f2a2e1d5f56da3180a20f01c595766bf0c0b0b03a0503f1526e522c9df5964d435b540d1b241c09f1db57c205ec472edb3bfae8e6316c8d8b2dbd9b010ccce94ef2d00c5dece9d7e6b265f0d8169d0d61c3c9749ca076
|
||||||
|
h: 100
|
||||||
|
m: 63932df3ffb07f2797ab749e92af7d202b7642c812313acf729ae4b78d556867bca6ac3ee7718224e0dd2ea7ef25758857384fd903da201d6baca09b3207c7c95083db2db68c333249c57d11bea3f1679cd57bda8c1e37868e5552d77aa5305df56ae689a59f9095a894f62e23ee3ada08114f057b0d8bc876b4930cbe00e36787e54d8221f4977746c33b0a7a817f3e9cbff7c1eb456195f5b956eec5256ce3450baed681acddcc52abdaf54999cfeabdcfa6
|
||||||
|
p: ee4b77a8c79f3569eaff215714ffccea1554b96501bd33e55582e230850d0f9a66aa390c1ecb32f72b1ecf35497613c6035cf7059a802bb1bc16d0aafc6255fc7c0f11113a7e63d1cd0abb1616fadb48a156e7e8b3dcd3fe95a44c5e81955e2e9f17dd79a81e0d11622e0a4f18d8465c6d839acf443681d00b30d6ddb927fba5d922598aef47d1d87efe92b2f26fa6082f16f96392581b7857e5871e724c71ca6c36c967b2bb43aea87e739d15eb3c32b5e5ee61e36d3390e1259f7ad212ad9a3a22e54e3842ab5a28c650d704aff148cdd3e30c7964fe90e293f8c725589ecd75691f2e28c355c1e31b04320b4e0a79c2b4aa38463ff2562dec88b9aff35983
|
||||||
|
q: d2b63e06f16125d7ec32cf1a1aaf9071ce69310e5283e7bfa0888d756142b5eb
|
||||||
|
r: 59c7fddd72639d9a87ad8396bce88465344493b118f6b7e86afa31b2f192f173
|
||||||
|
s: a883a83e5a2a692b9973c8a24a3188ce12db4e3fbe08c25ebce350ed07f5e3e9
|
||||||
|
x: 946761321eda5234af454d161cfb9ba8527856fb853e6554e661f24141fe13eb
|
||||||
|
y: b23069fdb957d8b81b046ac261cac01546d42ef4e68abfbc7a4c144c9d449ae3ea00b4c13b078c800da7190ba610f4e362a2b239146f7503a03880f22ed3dc15cc6e01e384b875df6cbea8ada7f2e67be7c72c83dd7748a858e6603f28b9759786fbff43c722a6d57a839fd45a3c89960d464c2a962fdf4fc23307bd6ae32faa223267113a9bbbe74b5826bb9c7baf83ab0d2893c9ffceb904e7f2c23163a70cbc026da20eac66cb3a5cd0bc2df17e67add12a6b1820bd12e3957c5c924abf5a4112e8463d326f62ccb5c402c2cb53d90b3e717baa14380d136ca1a2ec7d419bbf30cf8f31f0e702b5f2b47d73d9682b196ce087ec754973924e01b389272ffa
|
||||||
|
g: 7c6c72f8dc74ebc46ac0b8e672c5c6e233989fa88f7a59872dcb848b2e7a0f514da136a51b74c2493d576d3c5f7c2f975a7f680767077810cbe722c37524ed21d39b2cf70e7e484ba7d9d3ceecaa5dac783e56be81bf4f76e09929d011581fd53a0a9b73dfafed3e8436187ca2203044f167cc319773ec5850e9e13dfa13ee5a95eb0be1639c71e851c4a74224be7072358c016841f96b58cb0ea2234424d4a7bca5b8603ac8834a6d166976fdaec86f97b174b5491fac3272dc167713996f74c9ed2b1b27ebf5596f2a422bc2763987b17498ce9c3d8bf9fec77b1485579809197f381ff8994a9e4e1ca9c8b958c1ade7838d5cf9ee45bc1f6774a64ae34b29
|
||||||
|
h: 100
|
||||||
|
m: 37f9dde44693ef29e7717fb2ff00e9103d1468213309c651544e4f9fb4fa2f94997a7a1bb75c4c372727fc457a0dd7929c2fdb263a6800e14cdf1ae1d7ffac1d773e30d878eff7f8e0d4037e3a6752ba8169bd089d2196e81526b0952ef7e298b12c43ed5a81b437b4a8e6dffb193faba8e5bd8da3f25cad4cd3577bb4ef37bc65ed64ad8cab3d9f79795c30ee969c5297ba5599d8f016d89201e2875d4b3ff885e6a8ae23cee0ec7d67b26e02652c5fa6f576381bf2874be55e7fc273f62705a0db56ab6452f9ea5143de85db10aec6ccc3
|
||||||
|
p: 9bb0886277e09edd5c1c1f54757a2f8940b6a539af0110f34d1c6cefa4ee8d21d0d58be5f235a3d171b68d1f01e4cdad81377db81dce2208dcff101160690ac18cda27c0b5af44aefd39e43ca92484b950ff0a5cba5db13827f9bbc4313a36b4950bfad768a10e0ed71252f5794d7baeeeb5f2a089759e62ac03fbed5f8ba58244aa517c9b9fe29fdfe7454e5259149a1654fdeef81138b4a5c7de650b7b74f4894412ec22b7b66eda9f877285932b208f7f362e18ed3fe78aa193afca16146aaddee1c2884891276b222c8cfdedbeeaff5409a34781f16eb2a83622fac07e767699b4b28ca6b0fa7f4ba12e8d32a3b1ed02e330ceeaea9108a59ed9aded5dcf
|
||||||
|
q: e7e0ae9c0978ee712309f37a28e8de237552d96fdddc3e83cc544403c8a59ad3
|
||||||
|
r: c62dbaad84de8ed15b28ca9c438ea7d1400009adb4ef982c29058ce9e84a9178
|
||||||
|
s: d737dee6e9b43b86b3b15d7329adb1a87417ddd2e62c0d2ea6c5410e1c0c0a5e
|
||||||
|
x: 4b7fc55176b49588be2fb62c85a36f6bbafc75d5b7b8d4089504e73287d394f7
|
||||||
|
y: 3b3c00e3ad57e45bb5385832f585363573f4cc1720cb5857e84a6e49c02eef3c70cf5b2f52e88db401913d5d4a4fa251f0a572d967fd2562b92dca8ad2a4f066d94bdeeeb9f2b8b1886b9c2ab46fce7d4c16001017febe10db1d0e1b7d03af8901dff5248cdf2704e9f5ea032dd12ca7a9e1af780eb8b47109bf7fb3fad706d4ad3b557652fc5901ae3af9858bced373d06c9ddafc8a9a018c88fa619b8e8920deb3e0a002c91037dd59cbe55a08d2e04a56ddb9a17d6ffb79dc10434d74a19816aea736e0ceb5e8eb1b03eaeef275ef96f639b84e0592c6ee450b104bb1703814bbec2b3cb1782cf08da2b8764a5ef1709edebf61eefe7765ddcb449c9cedfa
|
||||||
|
g: 8026ab6e5b7629490d7440a768c61a71fdcbf71a9d0f14246eb5038607a41eea962e55688398f4f6b677c66c094c33008ce8ce5f94a6fbb5dbd976d735077f759ee2770db6c423eb14dc53389782d2d1e5f38a9b525f4e266dcee4e3678df6fec436a92cc8a1a6ab86015acf42b7bcefeb95788a862f940022c205e9cc18cb2a9edb5b769eef3a4a23ab1735bf031a430c6e58b7908c96ad658b2936cdd4f7da23d2280bed47a7932085ea9f7e128e7abc6f43dca4f557bcc713d8a611db44f5ae96f496566da6badb53e0346335cbef34161a56c676a751d70378082833fe30c3a417f2c4f524fb40cead58346dc9eef4184a0ec69ed973be3b4fba33d2de30
|
||||||
|
h: 180
|
||||||
|
m: 99d6889a5570193b30ed19
|
||||||
|
p: cf173fc725a4ebd1885bccb5966ce3f5d537d76a1dea2e38732e3904f2607eef3eaf6cedd8473bfda382e0ba116515ddca45115bb8ef474199221adea40d93995bbed31ce144169d96066a01557a50f9261bd1bc492ec321bd13f0c690fa42ff408e1c7a155b202e4083d315c2330ca7570f0f51abb5dfc97e163c41ebfe0649deb0f29c9fa86dea061b4135d8c2feba16766cbc0d7a319e600c90cf851fb3e0c034317f44c53e94bf12f7d814536203000bd3b114a5797335b34408ac2f2b707063c5526045cb6426c4aa17a71dca3c1e722743551104908b8aeb84a6901c0c7f2407e93e790ad246a4dcb1f575f04726179ed49816fbda08db5f62e7f72f3b
|
||||||
|
q: efb1431558205946d5daafc2ffc70f68d36eee61ffe7bc29ab892844847f6fb3
|
||||||
|
r: ddce65c1cf83aa2d98e5dc57a6ca2d9da23be063cf1ed5874080d25ca46693f2
|
||||||
|
s: 66d87a54d9733708d3911099b820184fe1cdb1dc990740b2a8088254603ba6e2
|
||||||
|
x: d7d22e0576fc1db22da198e737eab989e0beae24661e0a07de0b3679b85aa8cb
|
||||||
|
y: 95a70c1bd373764a6644064946c18b04a4f1df99ab7805c8801db6ec6b58cb752f7e231c91d2a2183d49b7311669931d1a25ccb2199e0cd6ef934ed2580d5a2afc3dc8137abe0d18e4aabb3115a2b16a6905d27ca8644044a590c2d62cab3f7e88009c03b529d1bcd1ca5ba022deb9044adbf54984d2e4837da5aee8ae90856f3304b5a9f0a15c4222bb4254e0cd604b78805596b64b76486d7381a830c799b0719835ef9770ae9423821b2229ef51c38b208f8af6565719a26c3b1eebf6966f89b34eefaf4952a2c55f50f55302d7fc2f1971746edefc595c9ae00c6fcde57102efdd152d738becee526fd79abb128698033e4bcde6c09b1114ae23624a0116
|
||||||
|
g: b4e1d2028a6f389133d85e3b061f14e66b773dabe95c74479a6374bc669147f5518d9975eb153ba174f02c6607ad61a0527e77561e16b5502a23c328435d7f559dc22727f2eb7d9a1b094f5e72ed605d7430c9cc9be739c6ddea36d08846909d233a515781c13527e82c4a19b797a521f37f4b75ebe96ca7795ded21bcb3dc9dce2713b2c37eecfb9deb729243ded4f84462605446ed61fa906213dc35638b9a184055d31af876fee604463daaaf1b1aa9c0cde425a7cf7c5a6b0b4b70852e65df0b3d4021478b8a482f0dad940d666056237edee2e3ae23579c8b9cd05ac88b0db66190c3d296b257fc7cdb2f949ece9a4b28b96b0836e11649d67d94bdd403
|
||||||
|
h: e0
|
||||||
|
m: 1d212c77a95d98d6d8f9da18f426989401ceb5646856636643041e925339feecdc3ada9eb0afc5e8c6e87a6017ad1c984f13f9330520aa67c482dc5c25d4b8992cdbf95e08ea84f9ab1dd5fb688784b8cfac54e9face7569a8e93a5f19ca47d600e28224f017b28feb02595f06f303e877995415c15ad0d058d203e78c1714e302a2046160533a4307dc853e1d452058bbac2eabd15b695b480ae9e05a107d859e1ed1a787005edafc10f6cb8997dca91708473e66d8ff03f0fe543d0e7b
|
||||||
|
p: d42a6c750e0b41e0b6ace406f39d148adc383181e63bcb5106d9ad8a41ab5f7611e53de1fcc52e17b453c5bde071970e91bf504ef50d82ac24a7aa682f9a289f36fbaebbc4ff50a29a207b8c1769103345ef16f3dd51367e92aed23d4be71df5e69af483c72857b669d672c60b4367b10176fbca88deba8e8eee938b8ddcc7cb820a8cffb307ab9950458a871e91a5a112aed22bb180319e4869ef03737a9b9210d84b52aeb6f4f529c9c2eb8330033cbca7fbd122a98bc8fe511ffecc241c74c6fa2b0bd6aa7b143467edc383816a5ebee7e0c505a43c5463512f6026bdb4297ebd5540220bb783deeeac8548389c4f538a3a4ef34e6a308cb0f18b0f48207d
|
||||||
|
q: b2792bd300158895a0d0c4d0f88df3fe04a0c021cd1b705cd7e80190f6765e1f
|
||||||
|
r: 84b5f531f684862c14ddb6d51008992177fc57dae0d5b3673f6dd841638062f6
|
||||||
|
s: 35646f89d60b6bad191b7c01e84cfc3d16d9ffd39f4674a9a47ea08a8ba79d3b
|
||||||
|
x: 4e8e4f2681613b1941d3278323694d0167fe1e19c050b0089e505502fcc81acc
|
||||||
|
y: d13ddfbbde5b088bbb6e57c845812e310e7ec24cb5ebc4608071ff0e14e115ee5869eec0d4a066f09a80fd6eba955dbb845b28250bf021f6d397f22b33b82131e92a9b8c012ba8ff0aa0ad1d515748622bc7d1eb2458d63c39b885f460805bc3f44ab9d8d228c1da45e645eb253afc472122ea4660180d7d710a397fcf0be898f043cdc2d94191193799bd10b4dc5fb53e551574202149a8e9351d7a8fc2b235752533ce2c2fcfb83a1352be8291b8d82081227b96f9555f9565ff9da968076eca545d1bed3a76770ae729e881e17aefcd00a737176a49fa7e7dc806df1d1e7d1df77af6c9f2dabd2786915d93e0a6a8de9ba62ac331f6ebf1b6ea34f08df7d
|
||||||
|
g: cca5d135ec9d2bf01158cda42b6b1ddbb37dc317185ec54bd90890b58907039018ab65cf0b5f29599c6eb19a7aadc4268e94ea9f410f7d75b6c68cecdd303d4d4c6766693494d82e73fa58cb7543f865cb510133a370c4df2d269155323f5be3c6f2b19fe58bab0118c3ab99d3bd028d495aab29a9cc3bbc2b1889f5320bd4bb8a671301c98b2840c6e8478819afd5bf49543adea2d0bff84fd4e34cad9b8248d15ab4b28eae6f26e6f403c93c6f9da83fa142d41bc48896ed0cbe456a5d0ce690e3a383d67a73a38c3a59c065516f665137682d83932d463bf916a691cb3b45bf94f8bfcefd55fbc841ce3519803e6eaae82a3ebd770fffe96e12c58e37209e
|
||||||
|
h: 180
|
||||||
|
m: 1ad404625afba54046bf87e04c6e5edc7e4c53b42636596d01036897db078b24655d8e623441649bf70f21711b0bd14cfe35257e091e98fb01f8fe5f8d570378b895a996f88768a85831b2ad7e25e415faced740b69af0d64bafd115265a2540fb2654152dbe2c92aaebc948ed0656bf639d6a1cc1eb16efc1f9444b84fea8fe173f36b3
|
||||||
|
p: ece373c7afa118bf4071cac52f31570f9bb55457346e18fb9f0ed16506cc9d8eaabeb4fa62f584efced2cdb7d3f7f4e881f092d27d5fce09ecabf637b553988e7085c958cfe9fa24db5ec968a007e7555102bbba1085b6d910755e8c2ebfbb3889ef522e9ed13dc49136685774887c46cec3e6bd07a863c73ce0f0e6760cd02d73b73c4151c459465cdc64f4f535ac59ad2dbc5c68edda1e9419f11f4f4404624ab068673004739046c16e38b0e02ee80a57e5938f82bcfd844063d94300cca7affeed923f70a8ab7265c2166e5c0d76c0a1d929b590c0fb57d5983574d4a7c225dc5e0b698087a5090772163c2fe88a3210e13b95fb87d8cf8f45a9c8a1933b
|
||||||
|
q: fff877e432fcc89d58674e5ebb237acd268ab2a70adb731dacab12618cb20849
|
||||||
|
r: 9516009e31dae37fe78bd1fb03beff9c753f24f2520fbf07e13bda1649832afb
|
||||||
|
s: 971fd8a2e073eef11b4a55406f25d30c3501d4fb32531fd49ee017ba9688bea6
|
||||||
|
x: 8283f67a97d557a8a69eef0688560dc323fb7f6b11f44605604509a978b36d5f
|
||||||
|
y: c54e6f5017c72c8944bc6c9ba0573046d0aec2dedfbd03bd384a44234fe221877c0d03d6822b04f2c1b6855c138788d0de1da66df3fac91aca328c0e33ea51c595e518169e51783657cbd2981c8ce805b35bcf8af66a30533e0778b43011eb41c2aac42272c2868c55aa9685d610e59a76ad76957fafc7f167bd74494ea5d1ecc10e59aa244025fa364ec4ad213beab9607b308a0b6d8c33175825255ada2188777a692f5466f5559779ab0d1ffe5e5156b2eca8729141e223dfd81d32932c71bebd2b9c226dcfcd7f5ea6b70ccc288d11e9d23e0cb0a6390e74ace293ee172c537b552dcee3f500e2d92e7acbb3af6dc2a2294eab9b034638fb2fef7f51d80a
|
||||||
|
g: 56dc5c1ef24d9f2f8c73f3f8a7907ea962bf51fb4b0133dfc3c2fad7a4fc50c6dfe6906081b0f5509de0bb678420a8efc232edf92acacd2fb48eb806c86e384ae1fac2ec6b3338f7e7660805008b2e44d13777081f7b2c78674877cb0a891abb32ce86841be35e3fd3fb7aebc362dc1d47714a53c82fd7329216b83321bb968bc8f6d817e4fe71ceceb14cda332668610f66bc8f32088179af6dfd83e33554b58c40dacb725c23a968ab553068829c82c7484d6e34e3b6b5731fb7967fa0703dc532613efeadb4a9dea8d964955db299019e121b9391e846b576c713c89df5f0db930056affffc8ac224f7453d2c8b7647d6b1e7a7535c9df9b43a7e9d03ef36
|
||||||
|
h: 200
|
||||||
|
m: 9026ed558df31b65d3d8153b201bbcc887043d024ce6b2a30efcb9b1a694dd95383dcbdec6b1758a4665227346398cde3c2ae4cbc1de959bc42e757bd6e7ec6fd24e1e6a55e0df0224a627f6cf3d65fb904c7d515d707cc61953bc0b79aca78697bcbe952df768d2a3cbc037174e2b4b6c76ab842f826e2c35d68d07b91633617fd9c08e3386c23837ad7f8454f549b33e26f8989c42b4ef075b8598240f6e87d66b27078d6f31ec460ae6ff0ece7daba4e5ef
|
||||||
|
p: c352dfa974913a5d47cbbb09c839782e582a820662f3fa5ca4e5b69446c7a281bdf713ef9b4cdd1654ababde8648874bbc17d59cca8b21abf8526a829db7ea3ab4463fdac6dfc1ce58441529f20603489401b34e097738e33b792df1c0f2a8ce761814cdfa660e002e100340c512d7404bc8002ec1d5c14728a4a7caf5319df81ed5b8638f4f9bc3b1d17cc25201cf9d8038c994403d84cb482f58dc2211bf6fb876ea81a69b18302ffa432073b1a1093ce726b106cc93cbe3bb242bd32442723c497345f230948c6741a53d9d1cb5b98d80889337e5ea7ff749d1b951672601a04b52920e20ad93647e9345c7093687be7b71dcbce6165ddfc5ba589c0eea87
|
||||||
|
q: ba7dcb38564e75531d36d642b4d4693721c6a2a6997cf8542dcf206307581d87
|
||||||
|
r: b9b86c666042877360deb2d39d7fb9c66eda12ee241254353d21e6e0d6833a6a
|
||||||
|
s: 9b25124b4663190382da29fce5b9e4d43d302cfdd39b0b25be0e99c744027569
|
||||||
|
x: 9ae7729c62d274c335c00723dac4f60a6c063cd4837a0cb59fd8e08b03e6766b
|
||||||
|
y: 3e2fc195332100667b7ce4662e63f18129ced06dcaa5f3d06107514dfaff4b880b97a1f8162cf8d9e0e68960928c66d5ff00ae4fadc57a9731ce40deea0061b2d7d7218f2b4b82ede58ecf0f019f03ff20f00ce4db4389e475e29944b4cf09c85f36f1c8f352a10a9fb5cce9c00c98e57dcf8a5e092731888949a67e7d072347969afc54232ed8dbc3d861250b9f57789dfd3e3f2472c82d0edca2e7dbd22804cd7a13e81fd0463c12d89e389a522bb8bb6147888e2bf8b0409413ca9a55318f35c72a0f3f552b6ac6d48012475ef5a8e2c7d973b002abe5678b327f3e3daa206c33251b5e94cb0efc7666688801caf3e37b2bf0754cae1744d3102ae827f690
|
||||||
|
g: 3bb3d187dea54a6877d3e8b1a2eca5d2f7db982c105956b17e7a975f1c26cb58dd341c5023fcf9a72aeb4fb36b6f51e42cace96203a0bec2d1e368973101ab5c9b2c5c0ce56e6572641ae65450ee13d31273636d3a86c2d19074fac4782a80c5fd61d98184e4029209b4dff231dd21f2f6a6908b8941671cbf2a8be2c095531dad69710130ba72e300a5b379eb1b95215ef60109faaa246effd15d5d67bf7cc745189bc3cd6041e4b4ac5a5860b2f1789d6cc4e801b45ef5eb0bc82d6c9d7af97442f5cfdb9d14c6ec6a292c00684c78103c899612b02ab80e88d0512129b496301b1876a83fc684318cb780f1d1e385578d26510bcde49bc792a20b3ae5e7bc
|
||||||
|
h: 100
|
||||||
|
m: 890337b86fc7bdd10bce5cc562806b3c7bd9bc5f65657ff6d1e9caaf4a0517610f247f0707e18ffa3663e040c51ead6d4f7aec91ed8e8d808fc7ed635cfefeb260b01a940198b30f7c0602c932a57aa685e1f433d9692b4fe67b48d53c5ca67b0f235a1f0ae852c6f2f69c0fa64e3fcc5078003093a257dbcec25ccf8ee3dcd199d684f64de36bf17e7b36ee1db3b32a3cc153debf64ee5d52f8fefb
|
||||||
|
p: ddfd9565909d4a247a9bbf9a8f333c5eb5ea938cd507df896df79066fad8d199f6cba7527ac451ab852291e0a1d328766450fb9452a76542206a59dbb71a15bbd6caef6c68f6edef11d6b1999eadf7df5767d0b3a7d2a3d1e017bc4548d6403481e1979f60b1879240bb380cc2efcd405d4e4e9f7c6d2fe028df2f3cd55133ffe933b7aec7a1fa533f0d5348dfa65c1a6f6be64f41248e584aee93e813173b8378514b329c1184190bf2f34107a8f708f1467c6342470859367fe04be78bddfc4e119be10abf9bbe75ca2cb705ac1737a34a33bbcb1570e21a051e2d9f0eb427065ec757417e0ef894d1aa35e68b922311b39056d1e330d202607fd2a72bb433
|
||||||
|
q: 80083948949d6bc5f35aa19502e71f5da137102f9754b78fb235d10a6b0ab019
|
||||||
|
r: 67bd109f6d08acd46d9b62b4c9b0e47c0c53a7af8b12c82a88de323483710fba
|
||||||
|
s: a28faf9a28d27a393b4982722f87fa0ad9f03122498b60834573a3eec7e8f5
|
||||||
|
x: 759cb4b9c45b6705c0d0f044ce89d5f0a8ba95a54a97af53db2be52b496f6f5d
|
||||||
|
y: d088607f3accec36266202ced300e035549b46670fb1b704f379c636ff42e2d650f656be28c24d021f3f852fcc34d21d2979e6900ef96151ca554de550dd2fbf0d2ee555f6daf0eec67894d9899a5cde1d1394db4db4532a12935c81d1f6603286362e632063ceb86a886037e5c0e3a6e226f709baf4a2733e6477c79cf881837710ca93b07eec3eeff60ea96dd0dd57d6fe187688ff5ea3939c1233798a73994ced4b3edaafc4d29dfd801ce08ab626100bb8344d265e01319db4b29bd7abd541c0b634a6bc397c5bc460b4433280e3384d30d3d7cd4c2826ef48cebcca1280ebd50fc315aca00e6269b5458694fa8bf24b971727aa6d8b1b12b8a70fe3e549
|
||||||
|
g: 6ca2f175cd3b2b52bd2fd40f6faa36da603fca0345dc2c5ccb50e64e9c028b1726ef42196c5b2dd9ed9f5db4a3a987f62cea9e554427c4cc4280abbeca31afb684de63d132a9411d786614dc5faefd6d309a54da7f3396e352e1991fbb34b4f6356d38c43e6851bd3a97c44547e469585fc77ecb397fdb96a738a906193e05f70b4e96ca88e02d7ae619e732fa204889d3a111cd1ecf93b8bd215917bbc06e39321e730c4450b896f638c616cddf7e611bc79dbea607907b7ec2338a4fdbc39a5bf6f6ed41f8e062606df2d271960f28e482c0c02abf5b5e3965286a09331fb15b16e3c4e67fbb8067b867eb054d2474704c4e4ef471b7ff86e6e7fd7a7b98e4
|
||||||
|
h: 200
|
||||||
|
m: 6bef6712488c2bdd20324bdf5bcaa1c8c97f82c94ea3406e5bc0bea6b3d6d7c2ef984d4c8dfe6f077cbbce5f0e68486d4bfd1af62b8b05597e0acb3eb8385309287ca6
|
||||||
|
p: e8634f9616c0fb4354fd4c2dcaf438dbba1ed301dbb71ed1909b9f4844f3d18a7d02ef5ab9a907162678bf170d875140ce1962300c7175acf5f7d61efcbab980d0a509ed48c31180b36e38755c4bff35395180ea3090d6cf4c6f04746cb0494959e97cdb598b393180c1381b181b9d3918917f565a387949eeb0d87385d0a2397394574ebbd49c6cb100c7f29adec9ba8c71f9a8023b29b6fcf00f735ea6980f71f26692ff142fe4d895330611e20539783ecad67466a2c7e944e928d27c94eb183a1af17a0f221eac4de11ab5733bf23c5f3ef6f02d123185744facdb7e532187f60d1d89de294161f32b78b1594ae969722f0cc3b3038be9f80330e971f8eb
|
||||||
|
q: a8c8e31a4a95eae37996fb6f79de03ceea220724cf9a701663da1af728acb1f1
|
||||||
|
r: 796e71a88caf22eec9f81b2c0428fe6686153b32f14d20746cb7709a4ce19d5d
|
||||||
|
s: 308a2967f89a0319811ab4f1143caf651f2e409af7881bdd4bf43207be364168
|
||||||
|
x: 8186550249e5c62be784bd81cf70fc19e64e10e664d4650f6a4a34de7ecf038a
|
||||||
|
y: 82f8ff1b3a9ed7548adf3cd4402ccfbe6b4f32a1419ee74e8fc12486616a582c7863ed1678d6bb3bffdbbcdd883d2be2db89b337b54cd9ffa8b5a52025085faad16711be64fe99dd0c1a0ea17a22a9468e23af9e4b6d3fbfdb2b67e98abd912c956d7cbce7064b38d188492391a06b75d2c5f3c19fbf8252c7308c326c6bc63e78c6d5620a43649b60884b041ada3b5cf2b23a46a5ed7c7941dff60fc08a6a727bf7893b57ae0279cc11f876888d0b5dab932fb568c3ebf59d491f04e9ea3487832a29ee8461e1b36b51b3af763432f86f14f0b7cc69b755af9ea0cc9f81fce564a50b8842e1eff67174cad37e139b61edcd21f5bc7b929a3f05ccc06222f0c6
|
||||||
|
g: 20c7079f6d3348391b29461b6a89d16c0610485a66342408f6fecbe5fbbaa5608fa538026825726fa3b6d0be00dda8b5911f5c5fdbe7789bdedf39dec2aab45c52656fd62b7f4194b8aac0382a6782bb1431b55ec9ef797f96937d99561ef488640b1d7bfe1844105d7f7508b07952df6e8e0a1cbae97437dec4b838f5207a71135955afb862d1186a2b211bfc5e9585de84d64502b3e2075be1cc67ba61695b53522b3052e6f46e09940cec6dec4c147b417f594b2370caed7a1c2d8e34d1bbc02a0d82d10750c088c37d2467d56bc7c60eb2528594d556fe1ba7c5c3b868b14421b9755d05e7b5679b444c00b8db5f9c7188a2770ac04ec7627d5808961cdd
|
||||||
|
h: 100
|
||||||
|
m: 2899113a51c5c68765ededd2921ebcadbe27d683c65c6917bd411c3f93a243df0d09c21400a98d8637e185f6a4a06d5d1c6a18c0258b6cabdfbcd39471cfb0bc231f5973ad5eb4547177aa0cbdfa62d1b3
|
||||||
|
p: 9bbbbda9d29afc32dbdcbc1284a46ca2eda6ba2654337a41842ac0f65fa4896eb9d60ea35776ccf881035c2f6afba24ff46ea3e156cf24c21568416bfd1a2e2f6c6ffa1ca30472308fd33c056a016129e32209bdb0346ef0e1717741bebea31cdd24de90c18ee55c998cbe9fa4f9a8a98673edb6f57f8b4f7e277558e2d3bdd4e452d2c3509afda59cd5aface7a5e056a26213b5e725fb55e2a32f1513c926919c2412bff3b828170e0004d1dd430f677f3a1b954ccc6b30bafab98dd31d2d947acedb59900a5305463878ebca0ca3e62bb91c95b0bda6b51de80257b899491e7827f6805bd7d55809b9d0b241d8523bbd5a9831095afb0a6d3bab1d32206c0b
|
||||||
|
q: f6b7790c8e3c2804ae76907e7fa14dabb566ce5bda517c7504ccbfcaa740ad2f
|
||||||
|
r: 15415226a30af81c068778a39f9dd162e3d30e310b4e7eaeef6e3b98bf15c8b2
|
||||||
|
s: a158c8f1e5779187dc12ef94d7451d35cc9e3ac2a1c21edc09b1d738c153a898
|
||||||
|
x: 1a9cf01ed5e9eb3e01017561078dce7790e21e4ed9c39d3aaf3b43243fe57af
|
||||||
|
y: 4406d1f9940d80045d44397582a7a63d0e6efdcc844798f20e1fcc0c2c777d0a468a5f1a06b6fbd7cabf6a8ee20ffe93b3618f4ebf910341812697ce7dccbb92fc515001296140af195837d2fdc40404884bf654d108b5c2af333d472207882c328196a672604228023217b2f2b2067a4aaf066cc53d67c827131e9181f1478cd1badb3e4bd3036c001b5435a7051bf72ece6e3eae0e32228f453a9fa4485e6f5f47a349f08f0c65f24c31f0a434444660526f37d8cdc1337f9ec357b5a44c6a86c9f32b5869e832ab4b664bb482f16df354803ecdc094eb2b9c9d65cc305205d133d7724f1cdf02d2108c020c97b5805096c06e322fe9bca0661d683b1458f8
|
||||||
|
g: 6e6c230ee7a130a1c099969cbd22ecf583e9eab22eb00fcb0d43c513d4f0771d09b1d545aebdeb86718d1d60059197785c716abca74055d6719a84c03a0fd680affcbd74f5bfd11cf0adf4df98224c804b4002dc0c657d2e42f1ffb87a0245b33e4ae56dd975e165647e46f8d34fcfa3004a6e23f6239a2a5fb00a39d752d94b7dc31967f1fda48a8815057d5794bb1d682c9c64a9b63578090c0a1abc265b85391ceb1b82b49fb22abffae4ce4d8d0806eb5c9ae331f1666ae542ae68a4528abf1852d027131a1e17703c10a5f3bff4694e99f4de5defe110de314af739eb49f0162e0da00bce8a02e8dddb8b8e2c962d32523983672ef075104dddc9e4c6ae
|
||||||
|
h: 100
|
||||||
|
m: a343c7c0a91c44aca6b88eab1e3302dbd84adf4ebd20f6ebab85c3bbdd
|
||||||
|
p: e3908280488206662f49479c7aca2ea085863d80660d87bdc69ab54e40184b747e472a8c824615d66403149674860365556bb606071f67adcb9186e158154ea5f8e5909630788d9f54b6021018c105e2edbf3e6156fa30d753e4d7822088ef6eb431c5a0e603deb5f37d4ae2ee72794de594eb3d45eb84130616db3457a805abf6f80c7f34d4abbe39d257682f0251a6912b939a2ce45d1db664a85d5980aef20d97eb4ef5fb5acefaae4e3de900f2bb70d02cfec0d35ef71cc7982358e5244b16b5ea40e284feb422abb87dec47e2846c040ad4b016c47b5798408fe3986ccda2fae467ea84f0e0a8099e45b45c3c6a0daa36e56899821dd497f828736f63d9
|
||||||
|
q: f233c2395163266622e121b83ec29dc79ef7f83ce258fa4ce81cf82042127661
|
||||||
|
r: 3408db8c3e2dec012ca9ac5de29099f06f9c6530716fc796b4e192f7d4013d3d
|
||||||
|
s: c23a95ad647c780e0be2fbdfe2d42bc57da07b9918700d85cf9e49beeefa3ad7
|
||||||
|
x: 74a2d6fea2d8f041c10c3737d9747104f5c41f58f89e59d13edaf8591ebe6dac
|
||||||
|
y: ca3681ef51a692b55e70960ed80b605539a5d9bb625d44f7c9125aec664a88fd37d004575df98e4b0b52ce76116abd93bd64ccfede42113ea7e98bcb17281e14299d703eb8e484040657bdd539acbe4e7731630e2dea3ae3208fac92f180061f0f883493a3c7a37972054d6d4ae646afd60ffd76ac976a404c6758c0baa971356edde9c596d9db04109a2ae1844b33c340560dc75a2511bbb985539839335a57873efd29e30b95b1c17fceede808fd3d412339b1e91b954d0b3fd714dc51cab5270f1bb4e5a296d1bdbddee35cd486191b586ecf0b754f353744977dd9a03b7be100e44b7b7857fe80eabefdfbc4b86582cd912a5ac6330bd35b6f69c21f4a30
|
||||||
|
g: 3d7be4994c9b044b7de4f66ae796045213ba2df278fa55d4e357acb22f7a38874fbaead347b1a4e5928b6f1f0ca52981276f46406e7333d4830df201a74fd9988473a4b849df3b43a0f4ef03dafae34df95b0d7a22e445283a151785132dec8b30b2e64026704115be684d41b611bc874bd488fbd05f2f4bf983bdb997cd8485db147b1b5b93b25650feaa438248d123fc60f952a687cffd1c7679ad7339943bca6f782eb6f53a4fed98f0f3c7ef1f278d8b82af00e3844905d8dd0ece918aecae0b5e871be4fb6842877116112232a66a0da9920b6de753fbf28008aa9b8964b80464908be860c826d8f767711a70227645bf8329b053a6419433a77c29c11b
|
||||||
|
h: e0
|
||||||
|
m: 2e05c0d36fe4c1197df12e6e78764fc4d523064b007578bb0fdb710fb9880a4d34485889f5a938660ae13882f297ec59f8b2be68986b612c2d30f92ccd53b655aa12e830d064a46f6f1b00a6bd6072d03e16d227bbf7588e36f8f849eb3948c9336974ba3fbd99e7c919d8bb37fec8efd79c9d80c087fb1acb416d81732b30b32e141a5b52ccbac2843cd732409f3e729efc86a0a6c14d3e0412c558cc76963d1244d3819f6193d491e75eb7
|
||||||
|
p: dd4fdba7f8222d5f5c52b127a2f51bd70c45b4e5ced6cf47e2ecfc02cd09f2bba372486d1e301a4662601d27e1586f29d8241c5db63ec1eb69e78ef4b4ed36ac6823077fe0b03ce0b6c6ac5de859f8ce636e140588a5b672a8915e556d030e72463ede70f6a3940b2218d7b0d943490ff6bbc9a8f4f56f959efb11f0ece0f764403b95d97893ea6795f0d99a10291f5123837f227625a0275502599d895e18c98b6b2dac0cfdbe22291821f554b9874a85ea45dcbd601adafb3afbf74c47e075aad09c14567f51afa07bae5db340f1f7d37b89a68d566500ffdeeeb216ab0d8762412e6e73347c3d13b744676965d872749ad909577e6386abc06ee097251c61
|
||||||
|
q: cfeac6e0b5289d2696b763391afad0cddd6ac18df4bc15b2d1bb3c50af16a9af
|
||||||
|
r: 7529308e2753398381eb89214c4ebb45fa6c15141d5d427dfa4eb8f63d2fda67
|
||||||
|
s: c775c99af7c0217ffde06b5bbb2d2fea9a4743b636f72419c1c423f15f21df96
|
||||||
|
x: c6cdedbd3d6fb9e961ac2196de846a9aa619ca2eb69273ca7939466ff0bb1790
|
||||||
|
y: 4f6819faac96f054bdbcf6c9b042cfc87a1afdf1100a841c10e5607c90cf14fa172ca007f1df7342049ee27beec27bb80382902080bac15862ffe517e3e08f121d9c0e4366703d4be8822f9052331bddd265a4c45533982e45caff3a77b4aaa339f400648cbf5aabd46f9bc20f0c96d5f74ace61834da4fcda5ce3966324017a1064e6007726fdff6edfafd3e45c252b6852176e83252d89c8ef381fc1842d22884a52dec1a13029f9ed903c293fab5510a949acb39b51a5b80cdd45300000071936fb5c4988a6b9660314512e5aa96aea31699ad38a2a16a861c17ede3ac55edff5ae2c7a03005eab30340ed8d1a731005c268d74841c2d479eced6f17e5a15
|
||||||
|
g: 7c319f8ebfcead26f4731249bb341713d9ee052cdea7d3fc778b6775c529fbe3fc88ce0100fb5f1ac2e276f6042a0c316074888de69c0268d6f58567ca648b74e7bef708e526feaad05ab1cdf8a51570faf2acfd8a6b9b600002c586d906c353b609e2d71e0d2c99c35644f353292f0112e2fa70477a70a01a29ea04538426389bc70921f752a728f8ca3b26ff7f6b71f0473de8f0b235bf2b25ad795ebae5506a4ba9b954a507a9540d7b9df31bfba004f19884693cda6323daaf8f067e8f4bd119e63e84f61a6bc10842dbac9cbb8f947801b18d0c182ac59bf39f9cc1525f4a4a0479eb00a78686fd4f0865e130fb71dd8b28e2921ff79517a85902f3872d
|
||||||
|
h: 100
|
||||||
|
m: 392514fc513d86ce4bd78e8b1e02239bc7534632340c0275feeb302e889951687c530fbfaed16c0895656ae1e89d60c8c94d9a1d3f29fc1196d232202390c7d4853720716fc41f24db90d9a7d65b4680a1f99b475238c4163e4f1089aa534ed781f857f001ae84483611c5ad7768212d1d99082c3623acbb76aa14e5e76e0af14ecbd405619a561d6721c0a4d15ca1fcbd8d1a08386e5f50b41f4a581e0084b3b3f01e86
|
||||||
|
p: 96c488686f2d4bfb2ef950454506abab4af52fbcabebe24932f84464468cda68888357cd7729e4de1cbebaafadd44ce7031a4083140aa612b2c98f54925a8ae0f7810c775fe2793bd765072aaebab567a5df5f67e61d89c2c0903576c004f63f4d0839fb0eed60fcadea7cbb3fea4a1620d37fee91978da273c95c1751db58abc9b1c45dd35d42f06ae80f86de5a440dc3087bad45f4c20f43a042b6aeaabb59b9a1bcb71c4a12d1362f08068244837e55598e441210683b006bc442c07c3de55effb52679a1dbf43207dd0c8239044ff12927ba396f1faa04496801f1771dd847822a6b43ac5233051f24e7eab91a0c187dc9e9801c3d1278daac1af0d14201
|
||||||
|
q: dd7f66db32859ed42f75fe6ac4018d576ecbaadb167b7af4b54e183d9d5f5865
|
||||||
|
r: 40bacc07a1955eb9662072ae51e59651d51b9830246271a3493060c216134d85
|
||||||
|
s: 62321dd2cc990b7c988547e0b7424a21e9ee8fdf4b195934bceb683a39cf5446
|
||||||
|
x: 28d8835f9e193b58072ae3c1622bd01febdeaffe8642e72710b6d67711b82873
|
||||||
|
y: 92208ab5afc4d1954a14944b33b0fd56461ed957e29fa356fe81307c452105ca32381ef4bc3419b46ec14361e074e557ec0fdc7759e66798b0b3ec3ae51418ff27014cb67ac96444cc9266078b281136c0e5e144c0f3ce51fb5499590a02d785fe9b49782606c9b0defedc1d7f64085f105d36ee578cd1e6f8297512830af6025a48f1921a8702cc021786822cf661cded5abae9367478a854bcdd812a45acc42f357ff52c47c45f7626ce91eae66fb4f9efda53862fbc0d77c8ce468e56298f2c8660868151c3509e58a890b26a39b76cce20087a7252bb3c01ded879169af8c856d34aaa32b22fe45a2d2241c9b4fe5a0a8b29bd38f320c68a0081273b564b
|
||||||
|
g: 668b2d355703381c590ad322d1a950b4e242a946841b0cadf66f12d6396fd6b58be23829359acdc4c4bbf54a04ff4283f2788406df612eb9ad1ae02eececb23e4378756fdcece9ac7acd31802deda157ba69c8d649f13891b0ea9c6ef62e137298a872b3648f8f47850dca2120c916320935c27a0af2faf7ab526fd654833202cb7a7f2c0fb1fb9bda0a15823037770706a7632ba55a7c45160cbad8e6eee5fca7b873a63c3bcee038225592f59417c8cf5c71188bc430fad4eabdc13d64a67605468500816bc84e2f820ca915918bbd64c9d68df25f8ebe8bfdaf2938c02b632ca73e2ad9d2c518ac55c9f180e51a7eef84eedc99b76efdc42ba7fa405822e7
|
||||||
|
h: 200
|
||||||
|
m: 7bab985f87aa73cc43f2ef2283bbeae11be1ec8c2420a5d5b7a15ef8
|
||||||
|
p: d6dc85ac6bd5934ed1f18aae3efc2c4d83a03e76107b32a30b620449105eff0b7d23d147cf55bc57f7dc947a4524a5d8fa24c63f3bb630e9f83b4d221e2f56a9d7525f58ed8214f3ead6504a4514b1d82cfa3e7d7e44e78ab14f880a558909a9a3acb31b1813617e53c4a013c1a7a303193fff2b23beb3e52c0408d668c99fe5154f0d0f86028a34f4cdd5b1c3f00ac082031560a007cd0123847e139e3af4ac3103d51e76ce74fce22c6f69f9a271b253bfb074717ba617f63b03b7afc669fabce6a48947cb63bea9a9b890852d451cd92c1ddd603d4038ec29ae7ba875f013b6b58db60f26bb2954379732fc18798db49420ac985fff6f67312241979f5d3b
|
||||||
|
q: c5785bf9837bed46ab904237ade7ffbd072fff7d3808bb64740fbe5571702387
|
||||||
|
r: 637b532d438142623060c7cc96579cdf05de9c87bc1808fa3adf704e3939d0b7
|
||||||
|
s: 8eac4d64d71ba1884b380018d3f52592d874e71ec4c997de9a4d968c1e1e4f54
|
||||||
|
x: 923d23d22831679192dfdd0e3479381fe5ba2caa9d588024920ae7c4a65d8ecc
|
||||||
|
y: 3ac9e2a9614232f366fd62195d367d40ca1344a48971b538bbf4198c5b9f81024399fe6838189b8a3fb29e94a3fde501fbd0114cf8efac231c8101c59b770d1950371b16a69692b112a0f9358dbf9b1a7e5ac9bbf714218f495c74255b47ca4944c8daaaedfe1efc6b68a2dfbab94ce76d382a5f7139df50fa515f0cf83cdaf42f6ca30d5ab6768fe3c1fc60ffd2aa03b57e05cf20914da8a8596fb0efbef501579f36c25986de586c217350d01b14a062c40bbf42315b8c3f5e0ebfe162dd60c74ef51ff23e6b516aa2293c560b7795503d4bacf01c96cc119fa11f1f712bd725a73771e888bbe4af43dd545b99b23ca989ec190b587982c5bfffc3b7959d2a
|
||||||
|
g: a57923d048b0fc31cfc6cc9497b6a76886dc7f318ef363186dc17aa586011ad8c277b85b453e350d0709eab7e0b64e3fdcd84c0c53ea26a0a2a800a2faf57ec843e9536e0a0554e50d462c4097f4c0f2659cd8edbcb77928d78422dcc602c2c53b351f275f04e328b8775e36409e15be3fa7c067335d66de63b8d06e2329648b1c21bf22778a30baabacc333f75069f8e7a61939ec5007ed614581ff290ca2c7460c83805b6bd17ddb4e281233ca39baedb07b9c85bc72e0d262ef471d27000a0b73f24409af8a7fcc06b2dacb7053b1c6b2c7a6f123c191f3bab8ac9aa3b6e4615fb495744c90cb748e9610e7b734a397e825cdb8905d831d7358561701a545
|
||||||
|
h: 100
|
||||||
|
m: 1dc6d51b7c7212f67783cc38a6cbb6d38aea43ffab9950e0a93c
|
||||||
|
p: fd76fa23c6b7ef204570f852dffeb65d281f721758715e3c21b2874eb0931b85043923e5c8b218fab0d243494ded663438c3c43593c98f7b73cde71e717b6051ba3e621c7a980b99fd22603f785bffe6ce60a224a77dd824afc9840897204666fac84adaf72f097a44cc88c7e829571ddb8d4801cddd690f2ef1b7aecfcb68eed00bfc356a2cf2d77878d9ac1bc128a4aae976edd6ef3bf571c54a4703d64e9051e46a03d53854ac526adfad8e22085534c19f4b8799e901eb553f059ad293b58b3eee61016c3758b45864534eaa831f859d65e05604d6652a26337f4e9acae93f54d80309e81f511beda531b432bfa3a0e3c91978f49f38c9992647521fbd3f
|
||||||
|
q: dfd1e323f80e205c75cc95c9cd1238ad2550aa4cb799607ffd87a3730a9f6d5d
|
||||||
|
r: 539a84c54c5cb91f1c1dbf819e54eefe3b1c9717745e36a074f1d7ffd53d82b3
|
||||||
|
s: 45fa49c386227d1aa799f3b16006061691a8df0064fa5049b5eebf95e0fbbbd9
|
||||||
|
x: 169e8c6d70e28dd8f4af3c079fb247844abeab2e66c92e05bb03b02765591d6b
|
||||||
|
y: dbdf192cccb087d53a15840dd941bc8921a7b070a118ceb2232e21ab4318fe95a2be813ef961af62bf1fc7b3598b3f2be00aa246b66f195f049fe9df3005934b417d003f0090778ba7b20f0cc5bc18172af14f99d728b3e872717a1b68e96754d9f3138b3724a000629ec5036637baa4c36568ccb5d70bcd50b12516958d59e2cfa3dc67bb97dd959a1c73b8aa890f7caa72c4171c7d1c5ae130b11ec8d161441fe6f8cdd77c323501eacbe53d49d72435bf251c0cb73f83da40c2967d50bf6a610a370c1e7a7a442f47ad793f4d11acb0b5e7dcb6b5487d8e5a037987708de9c1501febf58d2df359469c06207efb573ecb9c44a57db6d227c5dadd32af720f
|
||||||
|
g: 43e3bef3a9363273d680b3e77003e3660065b494eae200eae97b547034e4cbc8bc257ee56b459f0981b6bd007894ef5c482af59647db2c2ac58a61dfd478f3a62d3d3b23ef021c5c4c778ba9ce276738e1e790463bbdac810445f7d9b2640a26a40d01504f007b7a63f5a004f3735f7018a3cd2d96c30b33afcb6ac904d81075b9e17f766e3c623247c92f67c8526ed933336a204ae8a4ff9fd9bcb4b4cf7851e8c13125561397b99f50694077663191be102ea36b0e1943b81e1757d96de9ce265995bc6e0d996e93e19437e9b70a927f4144c55aea4f297a102852f1ddfcc7a9d7ea0b6e30f970ad7cdfa1e5ad9f520a8600ff1ede1c6c50eec4764b51b273
|
||||||
|
h: 180
|
||||||
|
m: 5b303b1a4827fd149090ecd90bb430c81825f9b5caee42b6fbd4a8496084bb02d7e64cb60b261c52e23da6eb85f2460054683cc1d1477cf6d44876bbd45d1b0a516a9b2243db511175e7ec73cc8efd468ccddfbf639149580d69534e6ab9ef687ba9252955ebf7d4a94b99602f2690f617cb41da4f4e1b19ba20796d3129af7f89f03b905f5fd16247f2b8c9eba9ba0206ccda4e964d
|
||||||
|
p: e3e3fe78991ce2c2246e556bc8e7f3b2136e837a1f5380b6e922b27475d8afcd6cc06c3b0ce237aa648432fbc2793dd70d8e68c0f945b6da065f8b55e3ef0aa0d0d3c2e17aa25f4136b31eaaea797ef84074247362c803af9bf1523b3fcaccf0121eac658056bf258362d56df0bf4a1f6713e8b0d4000ba47aacba7001e534997d942a684c533f19e3d8c0389e46d429f24f5d2873fb8760d4f3e217a452cab119cf104eb60a9c0029a017d15e0187c1b4e3c7c9d7afd919f596a4f7fd4dcffd23d8f965790a64e5487708f82bc39ec6bc565bc46ebda44ced4ea83e5940e8564f1d730b6458e7f03406f12ea79544a87ce53a6568d0fc87ae715b079c1871e1
|
||||||
|
q: ea5381f73a0c9c51c816528cfb66ebeba5335de4c0b5f60855a4c9b8dda6ca85
|
||||||
|
r: 8d1ecf1cee0c9b84ae7e7245ce5b82d4ede8e64fe88b073f1ed46680965e3a05
|
||||||
|
s: d7aa619d74a0a7096d24c57df2f65efa982891c990c6cf2e562ae573482b645d
|
||||||
|
x: bf631840f56d3d5395e2ac67b3406cd78a974d9e18b47c423024063a54d60e83
|
||||||
|
y: 62f0d2f831aa5392e483c9408497c42fe0195cf7a86fe516e7cf3cc87db29728ff13841c4668a8de12e22b17cde7e33fbbcd686c731f2b638158760c10e4c65d1b16cfc57c51e8aafe55c049451fc2752396a1dc075df109c08edaf240228df2183bf2e44456e2409fff46442983babfabe6868cb41c221de6a85d06f21391ad35a22ac0f60acc8156f6ed80a45e966d43708916da91a2ed393625510054386e1fd89e7a63e7aa33c5b0dc891c3d71c16d7d8c0610d511545a771fdface741fae8600a8e23c1c47b71e7c9f19aa5e18634ce1f291e60cfedd201295b6d838cc3b984dde522eb17bd9cb5ba3259136c0f2decba2e3b00bb6be4da02f2207ebfc3
|
||||||
|
g: 81adf88e3e2c97638faf6d46a80f94d1253e61a57c663839bec900d524c1bdb72be47abbffb59e6483301f0aa86891da547709f2075eca6a93ba8850a5914884b40e2b9892dfb0114813b8c1f69d6fbf7e2964036d27f407bdf7f5c48591cbe50a807590458cdec17f0f203670493cd1d7657db94234bca7f4622fa27942b56e8231b11897412a621edcc6b0b918e357cef742755e1ad0e6ead957b83e8681a2647382cb00d8fa27d1b1d6c0fbfb4a1d1e75266b13fcc470a47f8bc482289a29eb414d8e0ff8c81a81fd289decef24e521ef38acceccd6648e9f81ffb9ed98f68817dfd3084340a263c5a6575f4511c29a6ef106844aaa66f1e5a00f2fbf01dc
|
||||||
|
h: e0
|
||||||
|
m: e4933f55b9b675fcb83c3d80fad5e135a8045913d207dcb6ce75765b6e61
|
||||||
|
p: 93ba1da95cd47488a18c35d86f50de5f7725a5376b67528610da830b98c382618029f80cd4ba90e1cef1e425c64165fbe70fe25ad8e89868f981ebe912d07c153df8566d09732d089f99cdd9ef36c49f76711c474d7b37902415fac96c3c252b05b26f9acc86997a1a537fa9594b943a8531fd285eddff606b7cb27f5a1591a0419d949b7dad706e7fe86d3b1a7714c05359bddb72c64de796ba787cbd9b5fc4ab93966adb1d7180ff19c7765a6dc33dde3c08c277d762803fbec9edfb3bf8a7e6d725056761237a6ccd2d6e24665d69580ed6ecef8a8f6ee78379916e18b6870421c58081ab88af06786f9a483369269b7c6b16448c5fbb24e2bc1db23fe871
|
||||||
|
q: c97351037de0c970da4fa95e7e00db17d4a9a7dfa14e8b3ba096ca4d8a9544fb
|
||||||
|
r: 38328f38beb6e1117400b949cd16c91fec581ed2ce1d0a7b145bd87f718e55c0
|
||||||
|
s: 87880542ed63c171ba390ec715d37e19c54a3adb24bcb3ae42b3c092b0db91f0
|
||||||
|
x: 38e85de3999b97019bbf7ebc38f37fc95031417a1b305dbe47d4fb74dbb421d2
|
||||||
|
y: 568b63f09f5e296797c7a36d498b4efd6eebca68a3238b6df74a82e857abd7070cf705e9bc63cafdf01f4bff56f55914b682931aed92453b56d2ee51a95f6c36fe90a22ad3716d5f6781176ef8db9e54a5cd62590c2fe0744199d2770b134135399af6454afe5633cee6c3a10304f7f2a89fbad708474c62d3e1fd019a0fe7c00a42fcc75fb1cb87c6e931223ecc105bf7a39bd97131b1b5172de62321757bf24717d52175e1842c795c8e82e83bc028f058ce69eab35a6c52f7b437dea8c2e5423355683c69281a302a3c7fe2c79e0baee4d900453a04b1789875dc3dfc6915b1a51ee9e27ad5fef5a9ba73668b3c8022d01226fcde29d3eff02b8dea63172
|
||||||
|
g: ccbf1c7ecec486a9b742fc89205f684063ad0402457cd3b2da6dff0107cb0bf65ae37f1ca3b701de1413a354658be80dfdc4f23a96a7d612f0560c028a870ae2e6a9169088c395e6fd6507ba60b91f1e7652bf1a1db4578c439f317477e4de00777206a6182d66e28a673218822e2ef2a31e2784f9d83dd4e1dfc745287b4dfe7e1e236001ea82d616f67dcd4bbffc12778b663e745a385d42ea3935d42e4d3fb23f3fc5dd82c2f72759c9f304e6b9c991c19a475e7b8403f27f9aab87d62e0038bfdcd4edd3ae5bbc8d2bdf53fe50f3704bfe37af89e6178cbd822e131bd400cca43af4296401de9c31eb448ad2d149e2cc2952ca8e2be01e05e6468b61b29c
|
||||||
|
h: e0
|
||||||
|
m: 1ee90766d5d4bb417e0d0da721f8b8244ab8d953af11d2e49dd5f6ff6b0fce24683624d8f02804d5418436d67d
|
||||||
|
p: f99b520623b031b47705f0e35a462253d991c7dddee70b481a78242a06e5ed9063a90d91e4da80eabdc649c080f50a318f4c64a52ec964aaf791cdc763ca9d399b504783490d335475ad8f93035b6dcf3f9c2dc61839cdceb96b4215ba70621506ab3df9e217a27a790eed5dc8a56e66662bed30f035482fde7f7a491e4832da173a82dc06d42cf669c0b56603c3b618423f058c6bb3af28ea096fdf1c2063bcd93c2221c163dce85d8d7e1fc07c7e4893213f5105e8c82432afe71202710991bfecb9d1a94f679d8298b8b0d72e0a5fafca9da0a319bc849a550fd94fd66cf097029ce945232946761f3193f55089974ee6c0f246706c7d33333f4e3e94ffe9
|
||||||
|
q: ec1ea4367e635f9bc7771b596e0915b14a4eb6fbe11f51925dedc33e1946abed
|
||||||
|
r: 44c3edb144027f081106feecd6aa221104289c1befa714720746e286fc5e0812
|
||||||
|
s: 2882edb4fd571c88d16011ad92117edda814779110a761eafa2227d0c7695bd4
|
||||||
|
x: d2ef5fe4abf800d6dd9ce2050c14651b9748e49ca5cb79361b936be9a181c27f
|
||||||
|
y: bd79d75c6b6e2f84a0c5fe021ab7f8914fa8e2e64c2018f622ddc44b47a4840673016830f6cf12a9c0fc81a76d1fca5b46f799f74ff950e17684331a88ada8e4d9d9a886112b4951b80575ac8ab63afdea28239e59f3560b2f981c0b9fdf8949452ecd9a2b5cddd7de51002a183609da4a1983e85a06df8d647e02edf0af114b1a5297de207ac7f603e6c087887c2154bf539f2961b21c9fcdf2e558367c2e5cd6ddf980cd96a6fd6383e793c57c6277fdc317a4166993e534c5e510d74bd6a9995fd59be63ab21ffaa31fa67b575a6d954123d549dca60bd84bf5866a3118060c9a4d16bc89c137d3392bde8afd49369e608e1cfc9524c1f8b07e467f466953
|
||||||
|
g: 48351df7fdf9f3978da9ecacf4daeb1c73ead457d9555e6f2ee402b53fdc4b3172e9721c31065f6860fc221301665c78800370c408be1a353fc89a91f72ceb466df8d289922b13e8a8ceff054d5e1e379406f3b10ffeb41906f10a61ec87efccbcdcc6ed2a725f3c15f9e6a9811311af65a30baab6999fa84eddc56c67c0d42145f17e27f867d4db2a7d90ddf15efe328aaf77fe3b8173a97653dc567ae5a773c2e7ed80d63c05d553d09b7d4e6f0b67c726744de469d72be0c92c2f782c55c3cba5e9538ba261cb4fa45c537ad17c10ad214723e4370b46b141bd2b8f617592274eb0208b7134ee6f46bfaaf077436e39d9c7d522fd1e2f68179c3362f0039a
|
||||||
|
h: 180
|
||||||
|
m: 432d42b307829d3ae768e91e63e0bb09ac801482df5185348ce7e846cc99787f20313629ec2a4ad242fcc1f2f147bd056a259e92b18edd48de9ce1a2bb703b29c921085306d580c8b1b5fdf22539eb5866ccaf4910d525f5de4b1f1bb87e0915235ba41e07870660aaa5cced774fb82f301ab503c1eeea130f
|
||||||
|
p: bb02edaaf53bab2a89ea97e20f971702fe4f2c8782ba67ae1d3809ab1f4a2df3b53104ac3740581cdb4abe32f6248274c3adfa6988d7cb51adac240d269a0f66189ab9922409233ab7b9c9fddc9b20476d59890e7f23cef3163d2f9745b4ba74e2b348b4cda62e35e16288870fb66c4261ada907096a89c9b66e949245797d2ebf302c3c4471563c28c8ee330f730c527d0ed148e88f4f210d0cc489ee4d84977c9c92b832e8fda76540a62b0ac611b5379e2e2ea446fe2295264f988e1f9ff0dfafa3825e4acfac3dc09983777e38e79ed579a0e0c22c83a6d884caab328d08873882d0ea1ba7157728000be7a5677fc7eba4fa174fb765f1da6e89b327a823
|
||||||
|
q: e0f83307910923c476232ea2f915a421f8cf798b48d5b39a95e47aa9d8888811
|
||||||
|
r: d95e68afe6dd506e9ecc3629476f75e05ee933310a4ae4c5933ed999d3978cf5
|
||||||
|
s: 6e213647f17b0a9eabb40116dd89926ef7fe7c4f3a724ccbcf9e365654d3a065
|
||||||
|
x: cd1afc9e55977be18a95504cbe42e4cce7166479a5aa1581686316b3c046bc3
|
||||||
|
y: 5595f77de86023675269a4f8c77b1d77d2452bc3a1dbff78b8867f5eac782b96c76376ac43691d7e01ee51e4bc181b4016bbee4d44a8a965ce09f2aa75e134ac93ea8ee3ef840aff42226274988b1e157b6c73adbec0fffa818ae9eb623ff453a4f78fb4d412fba4e4751d95cc3eced418c3c68c81b46e9185cb8b6e35a9f052840a18c7e858e35c260cb19b582c2e39075df1603cb773d685fba9c4e23fedc712e858975de18bafe80170abda2315f682f32733bfaa3b23df752117c84afa265a9f22cad5a18ec9a4ed426cc3813187664b3588183c0c0584f0593b17a3108746b88407ad6e29ae8cf75509e2719a61e235f203f7e1db0556b7ced873f40565
|
||||||
|
g: 5325145ccd3397a6ad5c7dc7d13716cd0fcf3647d6a8e2e6eea6f8ec3071d326f09d1dea10c3ec6deb392e293550850e1bd8061759a52f01d84675c61ccf847d9ebfcd740f9b15264c04db488c6d115995bedd96c647ecc8789a89dbfa51c44f23a2bafe7c61b6f97a8f35a5653900168d86d070ab2f7982d021c1f7623516d940f3948774fcac16682d3624ef353997b3c69d8763f3d142c4ff0e6d734402bcd6823daf54684834947d8b9258a5d7aed8f17004b1091d9910252ebb2dc10c95d00b5dfe57e861d409d0709138aed4b505aa5f6532d99f5d8b687ae229e0794066bef5b9e7f1548a9290e2e36190595ddfa2062ef9c70ca77d6705781244e6bd
|
||||||
|
h: 180
|
||||||
|
m: 57f0009f31b02b2f39dc808905f901ae4dd6cb966f1ec8020da03b4e038366ad1e924f6b95b693a032f2bfc694317c773ef3cc67a0ae1628a43132b2b98889ee2f60ab4984d3df13ac78235a054913ecd275a59530298f704a4d2d78cd819c241a5b715842f997f7
|
||||||
|
p: 9065cadabc0b92fc25d2539558a79e14c31478149b317756389c929ee4d4c0e286cb9b8670e26fd8be2e59a7aa5d4b99905225477c6fb689b10bf2414da2d15ca8284e9cb2330487f82dd3336b5e226464c0c4494a2b60c4940974959bb7103f2ada7eb1e1e6a01a44e3ddad1015d8729857439017e1071a09078f7c42ae6bc7883afec3e48cebc30a96c8ccfbaf945662d68eb3b371b7ae010b20ca5e89f8aba186dc530baa1f5d478d75cc26df6a728ec9d48d177978eec9878b3209ce85dbb61d51b6462c99c3072c70ddb25d4a7d8b54c32f9dd4a29efbcbeac4ad9f702371cd3fc397a487b6776d1716567eeeffe04622ebfd556e3b36aa49ce030fea0b
|
||||||
|
q: f7c79f3699bbcd143187f294e146c2f431221776c972005ba33c6aaa02685967
|
||||||
|
r: b5e11ed1ca2553fe8cd3919eb75c45a114f565dc5cbcc180aff64e5436de5f1d
|
||||||
|
s: bb73508ab4c42bd4f0b0a3dc2304da2812147290d18627cd2db46ccd3756473b
|
||||||
|
x: aee54b7b861818f42005590e0175c7725b4d27cc6b7c6cd2a16e6aa825e66d31
|
||||||
|
y: 13547903b97d2ee62dc8bb13f6cfe1a4e6903b2677580ae8130703100d3541867575b366338139b304f624cc7989e36a56bcd8d47af002f8f3f6cd79597918f8fb202ee6b8a54557a0cb609af53a52254efcae11c3c528292c0ab4dc983fd88243cbafe92411ec410d24cf1a2a1232f875772d609a3fb4a6bc4cb7ad0f26cacb90bbbe3c3da0560c21c9e2024adc63d1cd15415edfb997d25fc5239a1c84fdfd970e40aa590241fbc50a0d9f5fbbecf32cee79672c23d9d9ccd6d36a67297b694f6e90d9557c82a25f06496806571bcf97ee32870e97675cd7419c2600f227af423a0cf8c44600fc0d0839cbfb6e87abb6b168617af5e1ffae0e7141fcefa81a
|
||||||
|
g: 1c6ab6a5ea4120f9a1b50e5ce1e92c2cf564eb8b7210a8d3f61fa1946b152327a37a3a5af982911704972f0af2d04ec1efe4bb799e1fbcb1464d60a8cac6d4b634453c818adc464f4b1d0b076b7bfa2e99c6cdb80332e03325125610330693406d58fbcdf46c9f31f161814059e2a7fe3891b7f5f7792327ad4e64865db8a941f0f3a5feebc857151df72aa9eb8979c2aeb37af853640df5f50b0b1221f51a6662481e5c654e54450af451408d5cbf739b6b616ed0dcfbd08e7d2c472c3cad98a328ccad65773a6477b1169dd0bfc03d4a5f152f0c0bd99d2f262dfbde62028d5f340425be6327ca0c303b93b19a274223b9ec630a2788f95e01fb9de882ddf0
|
||||||
|
h: 100
|
||||||
|
m: 90040c27654dfabee4648fb0fda74ddf3e0c45e93f5ec80ee5322cabe34c9af4fafa64fc25cabee79ebc2f08c17deac7344ef2a555c095bf9dbcb4bd1906a61cbb1a8025cd905aa507811d1c6328d06518480af605995393f58cb40687a2b76508fd8f5f8f6b4f633b217cb541f7858d91ea15ecd3848c46259af811580c995d95520af50848f6f2af1fbcf1e9c7672a5754e3dfd82a719f4f64683d40ff
|
||||||
|
p: 8393ddcc5144683aeea20e34f385c91c2b4046bdf95436afe2db1938100bc0b5ecea54bf8299c76eb26bd3dc77c20b216f058ffb597ee88f97aaf439a7309e5df72a012fe3b47d6309bd409905fb2a8b21567252b6148f246857829e904fb7ff74ee466c5d860284aacd0d1350dd78d6eddd0ec23f5e90fb90b296dee94e9735e0ca3fe9b32124062e495ff6c6e9c2b3dbb3e770e3eb752e76d935d5c88a93b28caa9be40832ee9e126077fa1b416d9fae155bc80e85836825e280722c93b8b545a9506b35aae580b57370ddcc9f2dcd6de99098ca1c26ee066bcee8d9be06b2bd8ef89cd0e987ccc334311749cabeab4cf100e71f8e30f26b189cafcf4c2549
|
||||||
|
q: de3b45a2eaf3cf6f795be99afd0c5542889920dd4d9ba3077c6e4158a83c76cd
|
||||||
|
r: 8c9913b740725d9e9456c06dbbdf61952ee4bab60611d8f26df5020c503416e7
|
||||||
|
s: bd4a5b5c1fc798b02719fe7c60359392ea964252919ed7b41268581601d27b65
|
||||||
|
x: b55628105401645cd7b4f23e01404fa50bf21cae9ebf4d2229bfa0587a5c69f9
|
||||||
|
y: 5bbfddd0682d02a5dc85520ed73f5dab6d7309a7266f346e6c71b51b95c95e3e00bf76d54bda998a0a1ab27cf6d1452b0bb2cc150c1d5cf7ffe4b2f6ebc3b70b2923b2895a6df5334d2936c505b71d97229d8358a071cc3dc996eef4a3796da4e33835df333477f948454f97235eb27ca987eb6333f8a1ab6fabe4e0301c159d3158490609f97be276657361400e9cf0d8cf0bd7ba20a43dc9f361c4b8ad28d9701ad11f1adad49fee84b3483105bcd4e1291d2b63b43ea15e635efa60729aec4c75c48fb99303b5dd724de8bc58d705ea9aa74918aeb064830071ede20728ff6707c3f7712a128c7d1afb8f97a39c4dbec05bac437a56bf010497861c165ab1
|
||||||
|
g: 1848533eded65a9cb9c5412c676ed122a594214e629f988e395fe76bae037eb4833c682bfa5281cd43eea170759aa77c9f3314877e9fe9028458a7eacaf8819c75c80af6b7d4617b77f6cdaa552bfb72b1d2a787269a09af3bdf86139a5fbe134f4bee79a28b7cdcae9a6433f424c2bbac818b823b800f7d60984101f6cf3c9acbf10acf9ed3ef9b9144adade816b7f530e18ebf3ebc732238da202d2c67a45af0b43efc05ec56b6c329358dce754cea530956be1d8d3eef7332b0f5fc5c357392d0c6566cc7c9cd291031b4a39086206cae3dde9ecd688bebe64f4876ec166c8f9b416c674f778c742c2986deb73e2088642805c90dd875488d3b2076fd7a13
|
||||||
|
h: e0
|
||||||
|
m: 754ef844378a6eaf0012c21e56da93472016e18415a1b4f3be52d8f753acc761fa62ec9b55b1546b4a119a7a7d7832abee73b43e38849d6b4e80dddd0763e77517777d0ecc6738c4cc5642bd222a94f6d037cf6a1419b6f09219d0f60a2ff2058214eda706ee81acca9bfa35e4cd77b9e916e517527a76fb7b902a74d4c0269bf7f70495d18870aa0cfc5e8d852a2918391363993732344b1cf4d0019eed6105ce40f520e2b6241f7ed16ec41b26e1e4bade975d88af20842593faa1fe5bc43226cc596cd519589edcaf0ae09cbf75867e7ecdb393949fd07589cabc12e4aa412868a0808deea6f6fe822031c8b048c46586f90e1d40fb5baf9210
|
||||||
|
p: caab54f6aaed4284181218e37ecfc6281bc96b0536abe85fcb87d59fe64dbf0cc9a14ddc11662ea21333af005d5b18cd34390eb4120b1b768c13ebf0e74b1bdca75c98566a397a5ea0dad6aa70a04496ee96bff77b5230a6abb407bee8b5bb4c40624d7fce6bfe6d227a075d6915207a769be8c70da9d474552e1725201e96353d3b800716cc8723ba834b5edfc29b7df32f2e0f9cab49d40147b29ac2dc7ef398f300eaa1a81725fff9941b15dd6cc46e3888fdd6c8f2ce5076cf0cf7e93a1ad0390344df8fea5a2b985da2241dd2e915cffe90e16328217aaad55eaa254abe92684c5074ed349a4c8c3f834da27b69d3e5ba0211b9813e8999d9f8ab3e9ca5
|
||||||
|
q: 9ea50697e3c0165f7828a7fa5983183df26f6d30091bd2fbd344e2fca1348447
|
||||||
|
r: 803ee01a33ea6d32632bb9e4c73e4ee61e32fd041f4041d2f5002aea64906e48
|
||||||
|
s: 8b88c04717fcd93c02de19aa6ad993c95c56d9b11076b7834d578a266a45220
|
||||||
|
x: 356831231ee1b8e3e740e8d4666cd873d2123f8603135fc48c093a06491f6258
|
||||||
|
y: 41967640b7a72cc0bc2e0a51f09cf068afd9891f0bd7a62c5dec07b2a5f025ffbb09151a6f3ad86bf5f869aaee08f478085cada07870726992ce168720cb26207a204f9fd701258bf51081d0827b77e6e857c6a40a467bb9ed2f3bc83d8941ffdcd9b1996d0452383e10d181dd263edc3042cca53b39f1ce1a2ab2d9dcba5b9b0dcef9bb07f28559326d1b41b037e095aab087f89c2c6f693194ad3a8584b210ba3d6c42182e545bc58404cc3f9d9e211b97437a44db0acfbd741d3ea014b65e742c442dd5c7e43c139bcaa561a6d93ffacaa9818697430f3153191da6b0c93a94363aa92543222e735781686efd0f866677c71f2d2ef11d997ac80cd2945eaa
|
||||||
|
g: 456f174bf581eb5aa803bf41d7c2a4b4f73a73b990535a3c44729d541a993ed3d777d42769a2ddd0555de29e3f392c3486e2454aceddf7bda99b095d982c3b1f8c2851b8da98112e0f262870c07fbdad69b005a98a85172b51175f27c063998bf9899a65949478cec6baeb32e2b663044bf966be9f6e1fc5912867f20c89c97da296ac045c3c0ca5520c86181a881b31cbfdd4653af43feab8be1fabaa7165529c61b902ba15c900dbf9c77b21d3aa16786a95a9a060b80dd4c4c2ae9fbfc1c3dfd261c572322cf2d506e4d3192a82ca7c54304f41e0ee7e99ba5a6ef2c3a2aa236af65f9a2763aa14d1e92e55d84df3db8ae872d90647b248fc8c235734a157
|
||||||
|
h: 100
|
||||||
|
m: a795800548bdcccc9929189cf9f449f84c9fdc2d3e320b6556070d8d98b209b78a1cbd7401a9392c55ef01470d5477b17ae10ec6531dc88f739fc5e5cb37fc3586f895bc27845cd24323cc42d2fb3107
|
||||||
|
p: 8d4d239e83f4c07561a3384927c0e6a2a708d23b581567d8d2b238b48c8dab7d86e8ebbafffd1f383b20348c974574c89eaf2a16688b0321eb1fd44835375047b4e7d1c4303d1cfe12e260fb8e61153e5cad793faa7890d10fca1ad28da4daf76677888d1f4018921d46c4b63299a178229fb2c68a3ec42bb73f5ffcb826f502768de68c8b740da5a9cb63b4e7760073407b036eeb07e561d4035e4a87d467fd7560c969e1ad659d311c474edd6d526755c7147e45a2213d0d78fdfbf3be48e8aa2a7fcf326d24fe7293467005b9eb34c58a9891224b060126e7bf29b08694f895bf90fbccb2fe1015d2d8546c703355b28c080b2e41f0795a6e7f10030db24d
|
||||||
|
q: a136471f4322665e90d9b67a5c7f9c3d1c16789ea5472c245d8b22eabe645d77
|
||||||
|
r: 9a0791d875c6d524b7495b3db7a076018014967470a64c1c6d54cc247b05298f
|
||||||
|
s: 2a5a22e5e30cb81516ef1d3a849791e64753696e81556e2b3d9a0a2af5fe4064
|
||||||
|
x: 89b3ace84682a71bbdd0e8c2df57d4833db6ad87c239da2ec8c920e09dfed5c5
|
||||||
|
y: 262d31682157ba1977e7b40860943a03bd34e30c972b12c193adac02064c16584b4974de432196972b2e5437a5a9e29986fa4121bc92d60e2116fbfd855011dc2dfb66f9f3146b1f853b34f79384d9df378f5b79820c4965b92c45484538ae0b50c73d02cce5024318abc6c27540c2850d27c06326f0186bc1a46992b2813d27d82c5ee8745fe957efc6a6e4b84fe9f7013faae634327dccfc792ea03ba546e44f2634b4c0cda9c3603db0e84ccf7a191b05ba579bb662bd98f55635e12d3fb5b4a83f219be3bb6f989e165ef91c15d5fb563fb670f758028c136bddec6a8a12ab794909b8cb4313808947947c2a26c69413d3a90c40b7c746cfbcfe499a7e49
|
||||||
|
g: ac2defcb4fee2c630cd5a3f23ba39e4ffd8202e2f9ad64e62b6cbc1711ca442b9365480de72983da1843d450decb83f2c8c83bb105311cd6a905b46339fb2c6691038963741f1f18ffcd253bcaf35eacd52e27d16783fb7743ee2c7679cfe9134c666b24f0251050c0a0db0d78007893c40ab6afe58eb6b16b38b03abf7df38e8a3f948a4dfcf8c5fef8a98eb6b8421c8594b72c24934bb86851bc46d38f5b8ed98454327621569298675afd7f75c92b62e2cafa3ac93051cfcbfcb20691026f3a731bab4ed261d3f1a7a83b77556bc2e297cbcae6cbb1488167edca9221f50d62320c681ae7542aaf44bdbc4351aae09889efe4ae3aabe252090ed92b0d410b
|
||||||
|
h: 180
|
||||||
|
m: ffb4b22245b0
|
||||||
|
p: f0327019093c33acd37718c7acc74d8fda79aaef08c0d70368405f4b0ed468aff9d08b0cfa24c6d74090e54d243d89e56edaeb34728fe8ef61c4f58a935cc70b468d9fa6121272389dd7afab64d53b8a3c06c632576dde2da93cbd496dfa4aea0e21180df056a4a48f49498f2826cfe11b6db29a2ca8d6966235202aff8803a85f766827572b296c2d1f4d61a230278cad46315a63061a97f10387a8f04ed49f2f051d5f5fd5d2c5bf4ea175b13c699de0fceb0be22d99a28bae583cd56317c4a68ce5c174ece77e07f6c5d8ee9558e233bf93bf835341e66f0f7d9205dfad9bf6bd4f200a64aad7d2f74acece12f3c14de6ec2dab43e28dd3550f60ebb84105
|
||||||
|
q: 8e54333a23335bb7cbbfd4f135a6b5fba5e399f08ac5811c4880185e56346c71
|
||||||
|
r: 8415df996090bd19708e0e3d65cc47883c9eb326c4b811c05c9badf74e211c4
|
||||||
|
s: 2575fba4d2f599d01b9117e1ed78152363ea8a332384d26e9a76fd281d931fbd
|
||||||
|
x: 4000168545efd4efdfbbabf7f610b4876e3bacd9d30acc0ce6167617af61efa6
|
||||||
|
y: b33b29f2f73f3a76fa1d3e825dee0b1d19255a7461d03b6899fa274fda205aa69c4460a4f8a52e34b9a6c2897ea04320fa2dc522aa58f82a8f9f5304ddfbdf5c65939f477776e0724eda0fa57aaf6eb670d0cfe12afe88ffbbb6aaeba4642d9213fd34c383d1f19d85b0095216b0bb7a79b0111248bb2ac9ccf3a893ae4ab1761a765dd96f8196fcb287abfc21f4125206871781351f52ddabbdc6b59cb8cbf8060c9e0c3162158c17db1643095fb80954673848d5cdb86b9d8eb948ae8b374d754c2764de4c5b9f661c8e838749c1c5bf32cc9425492ca7ee2a7e8f5781090200be139919722cc560cf56606d9c768002ecbd7c0f4b201d25bca9fb4e548377
|
||||||
|
g: 9a598a0a3c4dee259bb6e8292a7c751dc20caf8dc4f5461b8565c7520f3aa9152f6515756be980fd4949f47ac33c1f4cef115d6a10234f660cab7d8ecd22be02cad3fce2f7eace400357d10500a75238231aa573e66dc28e0538896c22ea35c5c4ecbf75c8f73592ba9f0f5405f3ed3df9f5c9e66043d9ebc49aea812bba086217bf33844e164e0b3582db92f253d904c867805fc916a6da2bd2ef1d85d7d040a6e5d1572a4dc62e60b65d954cc27b97e546af67a747cd465de00f6160f7469f3aab386bf015b74483e14b34d25bc628718cfc03fb8a146a437486f0941f070f9ecadf3fdabb86a7071706066735ce73652bd029f2d767a267e2f03827ecd24a
|
||||||
|
h: 180
|
||||||
|
m: 6a347aaa125c9797ba875d6fbaa87497c636d6224ae0bf1db7c6ad21604cf4cbf6e7672baf59c5d75236a677495bf447c3a184c646e37c0956c2b4341bffef51a800db2f7316e02f9135787cbf76620855
|
||||||
|
p: b4240e6680c00aa99b3e93b40931c516aff1b8c10ff8abdf820652ffaaefb3c2098060c65372a5c08ded509e7405e1e762ce633ab0a372775627a22512514f1f617a665e266196a21d1e6fbfeb5cd13caea325b930251ee95bf072fad364a4c29d2adf06f7bfbdb70708559df40118ed6d671b16de353a067d34075c3672f97aa7aaaf9962a4186eacb28cb7400bc3a6edbb050ce0a7a545201fbc2ec8aebae31bbbad276eb7aeacf3fff8004d252cf3073922239a38703b9871d83d1761b2015219dcd3d1c1619c5dfaa7383912a15bf5eea43e16165fff68fd4214461cf01b2e032b6bfb81d383148cb4534237f12b3e200939dc7888a59fd7221a877f515f
|
||||||
|
q: fc194bb7eb92ac7c8ed3a037bd4235f3b84cbe467c891308dc334a46dc390a79
|
||||||
|
r: 3b9161c216640f29617cec2de99cda72821f799d3ef214cf97b02b90e3ec6cc9
|
||||||
|
s: 50a2a4a267baf151fa2786d5d5cc29ec9fa0e3ebc644743ee690f518f6a12361
|
||||||
|
x: 556f999b8e92c2237a944686ddfe40173c9000ba00bb5dd8ec11ad34c2462d45
|
||||||
|
y: 6af6d0239be012aa6478f4e9aac1b8162a112c3e67c81f11b94429a548651444485aa108400eb55079f39e75ea15d730306feb6c190e6ab2cd5d69f481ccbfad5038d1a5438c0e34ca8a426b72d582296535b8c5926e365fa2022a41d998d97e1e3b56ed97596fd5cfeed259367b7b61f8d26dae461bc40fc8bc9b58690d28eca2a3053d7c541dfaf3004370119c176e50e59e13d47ae19b4d9221f568449713c985cb66b5fd951246f76dc3f3b35c00543986ab3167090286c5a1e0f1e77b10de6f501d401c531e3422c265cda5633e6f912d6b6f70e7e48395921beea595ca656affdbab7e24c1ddfb37f6415e521a8795588ca7c72b17c6558ac9201c5179
|
||||||
234
testdata/dsa/signL3072N256.test
vendored
Normal file
234
testdata/dsa/signL3072N256.test
vendored
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
g: 49e6930d809a1bee01a02f9610d983d22fd44c0b1f6a2493d801c2bd1dbb604a0e962c4716e102f9acbe0ad7e23a051b9fdb60126574e62c287b35d4531500ca3b7e29797abcf2ab583f7fbf934f3f8fcf0e908910de4932cec237384629ce7f088d40128d55dbe83f25491d6cfbef103ac0e129f941d278db2998f7a7bf7f9aa21abff054dfb9af5602325957c5584c46c812638f3e71820e5f7eb88bae8207fdd62498408fe300e591156a38634d64eaf6d696dd52a44ef451af1593c65788ff8105e7665f6ae68c8f2c011ea964bd839dacddd5857fbb9209c2926b275a5bb7f3be960b28f842e78a600370e957ea1ec83bb5ac2d3e9fd58fae0275f794b76ff8715e67e70c63abb53e2939945ff35e23292226993210fa3f4aa1e512dd9a9ca245a7552149e1128e99b4f30bd4f48f181ccb33169f599787e27ff31cd04d5dbdd64e0187f89b821efbe11b3d330ab420f0fd7c44fded5837eebddbc818670d686f64f99321be8942dc6ce3b12bbffad3cf52f7205c4a99e65b5bac86c14a
|
||||||
|
h: 100
|
||||||
|
m: 72c62618547db4fdcc9325ffcc1a3ce1cec5fd9142053fa19f81d0fffdc2cd8ff21dbc41a44a6e36eaef7a7457ad268ab7d1f888b479310a526bba75a82461ba1734326d043e97b7d4b22340ab592b4546e02b2ae695fa74238859d855
|
||||||
|
p: c4c30de34f5303d4dd1e318d8a3be4298f176aa8108554fe1a1a0498def92fff2ceb40ec45c0d5d1397cf24ba1aa910cdac68072a2bae7f793bb991744b84a578c9bfad192ce2fa4db813c90ebe0ad1ac44023795876b4d8969097b9b0caa81a65e404e4b5636daf204fdf63be249066fdc4bf6af7883e17e3b33d6bbe3b9f62b520d9b357afa25022da9f4f3ea3fdd5278c915a0ed2b8947acb17e98ea83990c6886de1af20a42af1503604a2c7a8fc60167d3401a3935b3a5372a885f33002c3bf280fe558f46ad133111a12f706dffdf313547bce8f9834d091216e64620099acf82c97e42f67d65afd7d68ea36bc4680a3ef6cb5c08df10de7e6d2b75c011c3684a64f93fde539e3c11789342d7a7008e0a82102e1e6f625f4501ac253b4969c1cc3ee4929ef8756c58e512a2e8de70a21fdc8443e4ca29a7a05c2ee8cce39000e9a0a7f8d84a6ec48ae2088667d9c02b89304c3e2a51886f36d70b5b0cc495a12157cc6faadbb576dbf169ed793e57a40ea017b3a8d1a2baea86834fe3b
|
||||||
|
q: 93fd71f343eb63dfec7bd52546ebe25673cbbc94524d9caed3bed7d75cf98313
|
||||||
|
r: 413a490c44d018d26ba8a917c9566be316abc904fcf354c04de6715513db477d
|
||||||
|
s: 75d30b6411c4bf3482312b9c52a52aa838f1e6d5551f92363cdb3f69d2bc66b
|
||||||
|
x: 357c61bb275e61e191abed4ddaa37c6dc4f0afb9f00db99359d05d087a9de725
|
||||||
|
y: 3b5bb87c8f72459d71e3733ccb196f718b964a7dedc34791c29578a6d6a94941325b210e1dc8b071cddd428c2097a43c9d51cb10f4f2fa216cd4c695e2dbc1865bc143a6d3bbe747aec9f7738507a7d0851d482467723fc6f04d521b5e057e254aee4a4bf557a8d036695a945ec0197ba01d2080272a58a3c67bed7ab28cbeaae836b54e39156642e07b6d4c169798a8b1cd2fcf2e2121f1a835f7a55ff3c69c9d93c4091a8ddc25b6996f8b0247e574d65f42c954e62397d9df72ac3dc42240331c398fda9b6e685ad306aca2c8f18b280c58f9eeb70c38d89a476ae143d759b40f0c07cefed451d9e417c6a37fa5e0dfb7e549e5191cac63142de9a292cf753c7b400049fc8b0990b4d8b242bb6584966f1b34b543df6f2699354826a959d6a6e9cb02b7d402a71a17c178215175c2e426bb3c563848a6d35059cb077151c83d144886fe790c524fc95a670578712fb0a3d36b6d6310a7cc7d260b6cf520b15af3bd94222b0fa08fc8e1921cab8a2754e83dcc303578c187361eb1dc7588b8
|
||||||
|
g: 5aa403d7788597ea2bbe63a17d69c6ed0a9a9a571a4df72244abb9002c7a3f7bb0afe5a14f3281b639ed331cac11048d60a4d4117a015e21d2a3fcc5d2c0570499527fc3ef1bf9790639d55a17d31bfdebd6075b09154fe64e5928c68b3aba6ee10599dc45985016b77ce00c0a3248e0d57293dde97c03838de71c7971e8642c94913b16ff51096c24553b8da426d969d8c8fc2d99845b1952b406e46b19cf411fb558f8ac25d357d913c9e828e497a07e074f11f6a1860443edee7349c7a6417298b03b859e207367566ad49f40f0f0b4e4b5791061da9c28ad6765ca55454f2db058e0ce98ed5bb3e539b1bdea7a57c19d72e5e752770dce049483da079563b3aec0a75424e641bab2ba2deda8f86ceecb1ec26e962917c6e1461592af99707cea6c46395b2d110508acbd3d39f9e386e5f374d672670ab50815574ffe6d5c20c5f08c7f7955664d603b08165f58e817448945d1014a177d4058c33c368583f8c82c55197ce1f5e9e9c8640d86caa97c1de73fdabae3f9f9f1be2613f2c0d4
|
||||||
|
h: 100
|
||||||
|
m: 5e710084410ddd74c90d018900f7001dc3f103da35a239416fef6d607b10509bd623e58d86cc96e72d6279f817a839d888dbfe8fd012d6292f
|
||||||
|
p: c7bc869fd2c584ffd7c8c93e6072f4dd2e32ea2bbad9e99608c510f2a9956bcd61d418b9a37e9388af66d2f5780d328ee301fb4361856c7ac6aad1d1b8baef0c8c113ea7dfc0f52a079d874419b5226a55dc7509cb0e66f02efb503d6eb43cde8610783b564ba1ad1306c8c96d6c2f40fd8ed10298fbb5531920c3394921d8ac3f5576f0403e1f59ebdf074c3fbd4f3b730e246b55577e97ea705e5a39327688609694f35f0af79a2542462cd1ae4c02319c31b264b1d2f7b00271f4b246266a532adb513bcf18f21bea3a48365791fff11c9d50d00e2c1fc91a7e084a4e7725c0b2cecc01c2c56b9a438fd81629b6cea9d799072e5cdc6d76d69a5949f6495d6dd5d2d2ace98cba2b369f495a4005eb892890eb8e0a7883e031e7991fe9217a9364bd8a1e9563236e3f9e3acbc1683e9cc882ad9082893a1ab84ed618ca0caec00df0143e8aacf9b8a15ee1daff8b2861e4693fe24a996ed02260a229cd9f840b404f9b733bfcbf39d9d5eda6b853401d8b6d9f445766355a6a166fef281f5b
|
||||||
|
q: bff801fbd536e6a98417b4ddc95475b057c130ef429746e699314195a8149c4f
|
||||||
|
r: 17a1e5fa55e4cec816f26f373670dffb595ae3ec1aed98577a57adc141af68df
|
||||||
|
s: 7bef6a5af8cadeacdb1cadc04f5d14a385c842a4e68c42690da492ff90e72b8e
|
||||||
|
x: 797b3494b2ecaa3c50e73e6277c4d210161c8c412c33e10f3fd9e40bbca75d26
|
||||||
|
y: 9411c4322f0ef3ad8749137dbba75a2a61039a5505fd5dc6e48269a986ef5eb9bef783e2e1371ae047f69cef854e828bfef4065d80bd8d4059ee312d33538261131e9f2fd74efb4ebfd0039113b1464c45278708010f015a56debd171e39c0abfa0851b54e7ae3597d43efbd755a0ada48b5afe8b5a58077573bbd8c2ee534844f167df810d7111268bbe57d2fc8ce3b095e41a45893401f1388eba9601e444f503647ca2194335b6ce4db4fd49d5b09c89529ae46d793882934d22cd20704be20f725a87a3ef485fb8b07cfc8bd2c637353e71a6d1d76c69098bc0f1152c2bcb9e47466dba385e8c0ed4eaadd5fa2452897c172f3a9f5d4b298bfc1836ec2bf609dae39b8a60f4f143c1497575038b21674fe86ab1b253fbe689a180d7d78dc941a503af4d404f4dd6aca90854e9c801f848dfedddd480edbaf1c0436dafd1b54cff84f68e7667afcc24235d39e2cf27aea758d068a80ae95946e148f9fa2e4d5cfe32a6caa918bf102a2f87614194aba7d305bdbf5ed3bb8753b5e76cf37de
|
||||||
|
g: a04c7eaffe0785ea3d39a553a2f3b587a3621bab9d57e0851f80e6e1856861f0d52ce801a4fb74f0c70719914e74298c49ca782182c5e692b5b834b01f6f478acb9e82f9fb0d4e484a030516bde61b472f766be8e7ee3dd9116c151a5340714b0cec3a5ee97b35d291aca3e0dad582cb76921053205d318537360b12d4724f934ac150003d0868b5729604974dbed08cbb3353641211f36a6f4c060d304fc670180cd15e951516b117d7a2848da41650cd66e59086a2351c0ad91f3c815c240d212ad06beb57a36299781096fa8e39186aaa6402b35a380c14f2bf6cfc2ddd78be2ca2d1dd727c14252d58c7085c412dd3596859b8c57ad1788913c3371618c12bee8e2c7c4694bb930fcec749470ce260530d701c42ff662727709f16efd4571f998e05f587ed757784ac5e3a87d631d08d853a317d5fb5a095b1c71cb998ea5dee72de0776d17c34168b3e3771ef9b8d6314f8a5fcdf77d50dafb7293dbbcc5c9bd538b2d1052f2b6182232b245a21f0d4d36b476887621d8d2f95899c3988
|
||||||
|
h: 100
|
||||||
|
m: 8ace8c6ec04b9a1f02de5843fe58329584c841686e7909ed153ce78f3f9ba2ae60e7a5efa84d6c111c7c68bf12910e
|
||||||
|
p: cb8384ca68625ddfa6eb56f82c546e784a6b7e67138b99822205925b5e293df684ba9f8d81eb9e9fe6a08018a035408265824bb0c685fbe688c0a16ae8017e07245defb51652ee9e80ffdf847fde3b4b8cfaf6df253ab6dfec187ac616c459fcc3bd53f0b88f2a37acc8b32fe9f5efbd6de0a866d261315bec005431fc6d94c004c69c71317f4444136308d8a998d276694d7a6718aed4b345457ff92406f00359a96afc5a017c54564d0ca8a9d1d1396ea948c1af2cdf775d4cbb02ceb60379af5f90935ba3ae858d0a0ec382494fed50202b7e19350073e181874157e2df1c652c100232c5c509011a4f0aa3c1761113dad93fc051ee064573484385efb9c3011238e57907921c92201ff6588f7134beb5175fce89f7891f576a571fc4eaa244e418f858f25de8c99fb906ad6b8839d8c4beb5c3f4394fba1f35ada9c9babe6419809be6093fab0f42fb1d2d4cf82d563f7c128e90fe4bddccc6fbf94299d2ea6173badb6dd7f1ab786582b528dbd03633fc83fadfe3874b2ea597b67bfdb3
|
||||||
|
q: 8a17ccf94b115396dbdd6183a9b08e02c89415749da720c9c09319aef45e9521
|
||||||
|
r: 6301c9bdf8ee8ffb4c8e8c86064c2b0f45797f1a9f68b0715219112e9e4667e5
|
||||||
|
s: 8532948e6e54466883a59d7792d5a7937e9f3be961947df48e7c3ec1c3ea064e
|
||||||
|
x: 3ec4747e545c0fbf8711bec311f02ab9ff2c1037799550e93a64fde643f2ce1f
|
||||||
|
y: c2f690b036cba7d9a7e930bb92b4da8daa9aa7f8325c5870b5bdfe3d1a54a446edad969c3cca59a3a09b458ef857d676cdc09b0941958ec5ea3e3e2756b2fac5a33fc01d7c42d9151f8cbe30e54f43957f895cf55c4f7d1cece263af58e5a76e4f4b89c7f15133b8dde960ba5b45d5d049386041a8fd31d321655813d09dc389ea72248b99e273d0bdab3e83bc04a71883546b86a25fdd12ea5346d2ba7577a438a1d2cbce202382e2eda65a783a9fdf374714de202fbd66ec736147e481748c9512ed91642558574d503cc40c42fd5207f4f1f50d958f05bcecf92bba7698317749f95507ccce1d4d5558907dbcab2c03ee7330fb89e0083935d0a5ca2872f383ed211c6e9c12919580edd15ae1c5213995cf0cc53242f61632f023021106ac8e683b485950e2b4e8d3a5a4c20f7af6558db7404273659bbdcd17059cbb54ba8751f2fd6138698ae8f78f6b96ecf82a833dfa29ba2ca1110809bf9dd948b294e764da465d441773c9bbbf99bd37512df4b208608a25e97dda2ebe58139d93b7
|
||||||
|
g: 92000ea70ab4041fe58717a88d93ee93fecb90fef03740de69b2bf4b320f2ff405b79b1c0d588fff1669b616b728c55711dbe484f4403784b8f8a193af4db2befbbcba0818459e6fb7f022bc233a8ddbf1f885d030d385218a3a1d670b5f52cc7afda10d74b718b3a73d3d3de129bad7647daf2b72bad3f683e4ac57c75cc25f779d615a8562564705ff03cb188119c4779e4eb3a46c9a50543fe5170084a53a659b02c7ae65397353dc34e271d345ab3fff2d3ae8a018f95a51919b0510ead4cf28c55e8c629aadba454a5363ac5f82d49da2cb0a091c5c58d24ed86da571d1f815a83036b7510046f83bad20a49382b4ba016b4742146a284e173d07f8042f911bc2e5d910e5b15b09802856809b1e0908064e794acd0f66698b97e956fe8eb874af8bb96e70eaed6388e27b9c9897fece0bf4db80d6838bc4be2e3882ff45e66e9836fa647cafa1249b81bedef8fb94fb38d78bc8cce70b00ce087c8c5dee5d1d35ebe4ba56a933b548483b9d56e83e68f55f9ba3f7fb026a442547e15116
|
||||||
|
h: 100
|
||||||
|
m: a9354c66dce761985ca6ba3c7e161ea4c01b8edfd94950a7cd7f9360e05935446dc2cdfadb43659879f4fc05173abc895cbb0c24fc01f1bd659745fd37384b2fb75d76f9879d741e25d6e4cbf178c7c9ced99f4ce8e66702b2242a8de1d96de0d4fa5bab2a87cd901c910a59c706872288ae1988eaf21e7db14c6cf3cdcefe45b8fa2df167b50ca7baa7a1fe107d8518f7add1c5683eccb8ccdbddf5ff5ed99131f5ce68313d53
|
||||||
|
p: b5fad4366a5725718b918c6612afb4964f80eb3126e868c4f37a841295b2fa4c3f7726f87f6094f55a47155d7b1d6fdbc85a20bc8fa6fef9a2563a35d1bfd144138968b472efd48e072e3160626b66597f2e05688a4cfc04f44d0b594a528ba9f5791ffeb3adeb791189db358eef8b7b521f69a9f4497cd4cedceb1d45eeee308f8bb2ed3b8ca4a3e90d8ad62cbb4ee84e2e5b0f14c262f5bc93a559feacaf6e9106929acbbd86241d45438c556f5d607ff753eb8592c94e514ddd17a84ac9f40869c05cd0a2f1e6e3eb367f1c492ce9a5e4cd4ae55345640580ce0fc05bffb8e963168de905479412d6c1eda8ac81f71f6eb9511e2b90003144d5793af2137fda67d6e8487a797450a6c149c82d9a4830c176e264649d58fa7ca3b3605040d302c5db56d4bb58f452821934bd7ce689491c86bbd61088d7da967e07f13a657748998a67fc06845940498411b494babbfd9b6b6407520082666b92f876917c407ded2528db098bd98a8f4fe56bdd2bfda2d32f699d01933b90c16965d6b1e059
|
||||||
|
q: d2ce16aebd336e053f4a481b29fd561b965c393d9f8236d7ee9f984f73cb9a8d
|
||||||
|
r: c54cecac1a88615f90097266a876532209ec4d6080f256cb49d87a2a5ffbb8d2
|
||||||
|
s: 579e099e9277fb696ae585ff22b0885c4c866696eefaa7fe1866fae338e2a0a7
|
||||||
|
x: 63eaf858c516680439dc271cf65cbe7c931960704effe05a2e03d8d4996231e0
|
||||||
|
y: 95a5f0e09cc67d063e8786f2d9f79a5fc09072d5a29137327e6c33d1f256d3ca1a79d035b7fac3f410b234df0d44700fc723d03523747b6ba0c6a790ca880bc7caa921a8d4edcf4f2004cccf80311d75dd0f0cc701819d1636423969b4d2ccb3f4106cb2ad132c55ce4f2f230b060c955466621b414dcf0f7a6b0cb40dff6b9239b87781fe67c48d422d481f13f1f875e98702bc4e97a45e34caf4a4e24a1b51b97cc73b23d0f5e20ea6d25398c52cf513d0cca9f2cfd68c492f91e8bf9611e49aa48ff79f5f566e3698b46814af329944112dfc2a8fea3c51471d93184366e8a0a192bed3ad7d5e574524f1ddc3dd749458f98065bbf354fcf8912e81fd45ac2d791d17ab9e60ed2536039e2cc00edbec444ccd7bc94f7b2251784387d88e6ba6ee1c840129772385a4a12e540f58463b87507aa44d9aa1c6cf0439cc90c32f0aa0d10c493653de7d123bfd3e7a0aea7b47fd5f62838ebdf6e7a733971337da2dbb5a96c72ee3882c88eed74e2d613eb84d7aefb414f6b0d51ad70a1bdc614c
|
||||||
|
g: 94c5e4141aa62747576d8f77dfda28549b1d32b2385c3ef674aa0704fac7d7467bb66f0c1013782268993fec56c75ae1bcdb398f602dafce94bfc7a5a9b4ea6cb78e7a6bbfa7d9c735d709daa60389d4023ad5554863ae3c034071652a029b188c9ff605a0dcf00f82b63b90dc8af111bf92555415db91dce5752f03cb36f7926ba358c99c9a32612bec0712da6050eb7a27e7dd2d50f4ec9d0b12a64668525ad8214500cc88ec10d4a5d68a7440408edfc1732c0d6fa7c107d1f5bb259f3598f562b45b780e6a3389e9a173902994ad8c5b1641b2fa30d5a1a1c53f3b82ca2786ff21f63148093a8717ff879e580d963ebb5020b6a160c9731c3387108d3bbee2a3925dc3dd9ae0fa97c3e51bca20666c0e2dfd48901298bd46c11f9f9854cb599814a9ee5865653ebd29650d9aadc1469a222bea446aef443317e13681bffe506c023e474ab0910d6bf25a75d050878d6ba1f49814fe848619eae7583a54567c3f6ba0309783d48b4d653bb45b74e28389bfa36d563efaae36a67e18117bbe
|
||||||
|
h: 180
|
||||||
|
m: 4e7ae07569250b
|
||||||
|
p: c91120e215cf1263c2ca59975fcea94f1e118b6de0abc8c988f706b277900bb42cb2d96c9bb6a9519d25f5529e20d5b360a0acde1fdcc3b33ce2492d3661c3aab81cee079dd40bdbfa0dfcf867019cd1e03ef01f51850ea19de0f667c37ea7f9cba2f6c68598a11645eb3d34a7e6a52a36b6161a375ef3b21d3cc82ab44e45e9c76511b52a9c8f97ea435a9abb8e459799cb3371f3ca7b58faa1e1668f0cc1289d63d567faff48c569e252c200b978259e06d9b8b37f9d2b21cd606c8fe48778d11044c1831c80fa678e8f608e179b3456a78b678a047b74a03ffaa171c1c165d3e9436fdfde14e505b0967e5c18974354d9b86bd81e40f571c603801fb78bffa52a86a3fa5a09d80ad19d4d9c87be1d3348a8f6ddd1b1920cc84f2b46749d21693738a6e80abc6a5cd16eda93738ef3bf57c45612765b6392b12d78685e6b4a893ff0f27ed6528d8cecec92acae2a930e4ad04b5c48e1c70948aaedc1bdcc7c2afc58d0016d7515c746a0c502573958aa1812b3161d54e3db4fdd6960faa465
|
||||||
|
q: ae4783fe9115a7aa65f1533d8411425eae2898f9c970f6721f52bb59c2ef6827
|
||||||
|
r: 222f31f6086a4a81af34dc37a373c2b603493c76996a129d49502f64cac4bf25
|
||||||
|
s: 968de9546a45c6c633fb23db37ec2290755fb97a2bcce21bd19a9d7bff744488
|
||||||
|
x: 67749c7c078a2d33b5d62d9be1c4544e265a8a33097b5db480a4508fd0d5dbe1
|
||||||
|
y: 3359b5d22ede90ca85f596419f6e75cf4f3f1a0bd80d8f65cd7721c0e2866c9ca39067d737ffbdbe9c6cd827548710aa1807321aa6a65a600b23cb5ff25b86dd8550421ad20b2602ab036264f97be5ed88c9a0a1c7755bb41ed0e7472306392806e51d8b2ba50d335a01921c38ddecaca7af7c2f3f4e44a9a83dbca4eb81495026f2ac11322e07cab76ca67f880de83c2e9f5e628e275f7b40e114034e36efa6af3461f24227d0de0e2d9fdc709aea990f274fb8823ba3dfb18a3fd3d37892c65b1df9b85834391c35a484927a02bef25c483af48cacd6addb303957816772c764dc649b8202a81a8450c8ad50a68c748a01c9884fcb47fd51f497367ea7ab28eedfa171ff11b3c65a9292bfcd1d4904f3b25fef4ce75343f16eb764ce83b7fede384c3e4828bd71f905bcf4f45660bef76abdff80d649c2117728d098272fe9c965546563ae0089f5a1d49cd28adb2812049b44d521ce697294cf6a7a30d197e172d410110bda15bf5d204486c72d51ff97af4311ebe1f83af2370700ba7fb3
|
||||||
|
g: 40316306b4a213e51f1e2dde8724751c3fa1555ef68f900a0f3fdd4586a93b94652ff55023262aa204770ebac035cb9a10f22ea9d1f2fdaf8bf4149e17bb74b8c9861761b77c5e51519169d62a8cdea3adbc41df8b5fb18b7b46364cb85019d4996fac5325ad25d0a38859c88339dd4d23a3b992ee436ebc886670aba858e83c18e75264e77bdfdc8f10e8aa21e738cccf23984526e3de20ccbb2521a756e3ab94a9c795182df8daded27b060cfff738f6b356e9f7a7a297bc5a1d984b26451d3bf0e09469eac2bd8c8b37dc64c749b0bd26e1383c7ba5001f2abb2ecf0961b26cfc6191ef987adc6d3ae0812ebf255ae82b8872de45374f475d05c620f39575441b1d73071f0dacdbce5b9894d31f3561a6c0813c7994a2b98c61da75d3d946b23f47962cc79927cf47443a3ce61305437813c6749e8abd9e2a97d39a58b4b50cd9227dbeac3b11ca0764c0b8e34fe0cb2783d10106839930a13c05db4a7438d63be894ef6345f70ea1adbf46ee65c25f0ae858f7692b949183737034a45a30
|
||||||
|
h: 180
|
||||||
|
m: 0d013565871e6a07b5ea23dae74b7ef8af4835c080914022653911
|
||||||
|
p: 8a0b6e292cfe764c78a9449ff2b88778f41c09d777de23ddd13adf162d3d84e48b400c4487f1ca82e4e51e401a4d22fae911bd943bf216f59f00aaf8e94e87eeb5bc2a73333fd8bd49e0da0b3a19e0cc8bc5239c07f89168c8b8363c7cba2a8a090155682e788236009ada70d5d8285edd9a467df5bb014931dc6fa405c9b3332a666bcfebc395a082c113e75dcf5e28ad523d6b12709acfed7e62036a3f8d0fa6c433ee563745a900888f68631df2a362561b3140be33ad256c297162c1d6f28141a479e52bcc0fdaf0f53db9c7a1d013d6d0b7f0c6f02cbf977a2f2afbbf90ee3e65e199704e2d71498e0546346e77946d6bcdea28c5a3275069a18f1ec8d0785c3939831aa212503f9fa5d4d8f065c7b41b94bb13c6e2e1e75930148ce22b029b620c976e1f38b1ef6da08b3c1f2ab37f6f96f86494512f268c39bb33e68a049d19c9a0ba93b4dae8b270e13a99f5bdfa93321580074b422adcf95bfc648d14d7f55bfb341acd0d0f3f36ef5fdc7e5c3b499ef365a4ac6de80e43147b40b9
|
||||||
|
q: c55a6e8de86e0208693baa4cc38ae83c7d004a12a1a0b87e83ab430f4e29e2db
|
||||||
|
r: b949252f11cc02c38a3fc1218930db9ad7a24097fa8e9b42b44f1d09ea9f5220
|
||||||
|
s: 6d22c65f65ed864a1f232501100c99a331760c14566670784ebfc5bff3053955
|
||||||
|
x: e243660b0cbff5d84422bbbfabed9dcbd2e6970a999997890be51c01a4c128
|
||||||
|
y: 4f8096c18bc3ed8971b3514305200348a12d95c05e1487ebd7fca567adf70f0237fc19117363b051ee0e80f5e63f8fe0d90613c88750bb032e97c9487a00210b31106da93937807258411660a580eb2ff2c01ebf4c7ff36c5f70bdfecb2570e55ea6b8f6d9dd1c7ea752f1b492759a9eeabe8e3fe9385467f6820b5d0ac93dceb1e634dc1ab7621492c9b6f23a0258dcb44c0158de736b50a9e5034f3c984364da9a2abd451598ab5818de60aaed6fa7eb102e1f2c2623f8af70fa3559bf67933bf59137ba259af1ec00ed4b8d8f354a8b4fb048e7942db7a53f4830f456804cfc77caaf071ce727f4f61d540116f97cd06d1fc1d6cc222faa0310afce507fbcd963264efed234d70ed4198e7493e67ac2388fd0e969c0309131326b506fb75caa58584bb5533502a41c0516cb63a086124d5df1b530b5de36e1cc6f0f9386b9dc1597ea00601e2a3cc3457d1ac3b7d4e593d7575ae69cd0a664a8ae1c2f3ee128abe12ade38083917c77d6427fb3cf8fc2bf1d16e562f440f65d26a229f7ad2
|
||||||
|
g: 819ed31af9b43aade213a15f57f9c2a23693b6cdfedd17b1fbda475ebcc5666c8473645d62fb3a1d67b6966ca4a85588dc31c278e5898b76b27e48467161c9ef25615a1d5e1308af93af4fd4c9b6698adf65b587ee162ffe669f56d4fa511b896c2c91afe619259920ce02ab157599826723e259fcc1b158a053fac35bf2e8a899634e2d345aaa8dd268605ce8c9fa8de22355abb9d6c197999d67b31317d9f57fdce6e2ae77ffec26db0516ab2c5d8af752fa912b7c5e6631a8abdf0191871e5ef1035812c5ac3cf1e83c45ce9a57269eba8cff000cdd466ea95d50b0531eeb30684c7030b1d230fc3b53b1551095d305df5ddf65034a6052e4c7096b2f87968755c8da2a270901886139506c3165bc56cc070263d79becc30e27bd1f47250cd1463aa011af79309a8c007441f6292b6788f372510740c9da9631a0fefc393a2a1bc45f28b239eae4c82b97c1d785705bda235a2d95cdd28af794c411eee1f95d0fce855c00ec21139b45362fd69388267614458ee32ed0126dd427d42e23c5
|
||||||
|
h: e0
|
||||||
|
m: 5544165755e744ff748e3277d1017ce1f92996010a3e4c48b772041fcfe2ea5b70ef8c997df7a27c404babcf9c5bbdfe052caca08cbaa6f62d1a5fb7e1cf45faedc948ef620303daa8a534327851c6f6a17438fbbcd30fa22faaab7787d2fa4a3f2e7303ef96fb68c9fe685893d3ab32ab37eb9eee19a29e85cae582bbad1dfc50b98e4b2adfee9b3516062ecf9c2d07041370502486eeaaaccb7b50c0ef4420ba7b707a
|
||||||
|
p: e068fd7533926bf7df46106569173bb5a42aee40a5c996ad9b01ab529639b55c28e4dcf4fb9c0edb81335002a4e4111b1347f5fdb55def3077d459ac5317b60731eb56f97c035bd162af260910f37bec47437ecdaeb845dd185b91cb46b5c4022865ea31ebbe8b3272b762c1895881ac487e5c5d9ab90b6282059a1e981ea3f4097c4b8a8e8d17f26d73c1fcb779c9f67ad4aa75238b65d3d736a420e40a3309fd509a5fb47574ec667f663894cda29e9c50c5c4efc0d94e5f3a952ba874cc62da4a43223b54a3ccd253798e437340de9335b92741b73210d0dd3a2b41d15a41dc9b06c931340f7eae5b232832d9b7b4c67151ad8abe3869182784997c3f421cec561da7fe4de6e1debd0ccd12ad8ae1d03c580aea0e2b1b1a77f5f5572523a9c4afd99ff1b1ff6866677fe0187c5493c206c4d89fba7196bc68889cc71542940adf707fd91589cfbc207ea8a32e8e6caec2f761fd6712056a69aa2d454d2fc814844a85a3c6e43074a1ffd294c0fcfeae0ce48bdcf6794bb949fd0740ef7e63
|
||||||
|
q: 9613456933bbc547883efa93dc8c50b3528e31bee6ad0832f0aaf81393890203
|
||||||
|
r: 84084f214704c50fb35041dd1632546382496b1093d644544b781175e88c565
|
||||||
|
s: 7bde6c2d6f6d81946ffbc8d3121087683891fe829adb6743066ad236a633bbc2
|
||||||
|
x: 5f76f382983be91fa3cd87e20ea4f2a64ea5fd3a8b7e336321d3ab028c99a1dd
|
||||||
|
y: e72024d9babfdbb885f4c2e656c67a8c07749814476fe432db1c808576362b1fbc70bca3d3098f1c347c28882031a5b80a54096652e65f43eb9a9b1169c4af54a5671281c95572da0609d67648b752c9cb57cd7f10a40279b39af7480e596e4c425c12f5ecf8e33c0f7c1106dbc58f9bf8a3c8e81901c9ff97bffa5f6a3fc6940b0d468d160b973586bf1a107baf29adc132b9e7bf5c9f2bdc3d3cb5254bdcb09169bbc03d0a94f6bec6c9b2b6b881ad9354ca1cd6d235e11801396953e3fe21ce41a6c03ed4000484ed17e9f367df50bb65e31d03f77008e403ce27db5f3934abf69c9d8d34b74e473c81cfb50c881dc9762b0a87160885829b50694a87d398f0be11d1b44d75fdb7d2919a4f7f26cba7928ca5fd2607cf453ec7e2edae117dec51dc948045f992a899aaabfbf80d0b3dce08e63b16a136ba0928f087ec42b75cb57114b1970491071ce30c8119a6ea7855df1b23d005f98ff175b5d54b950d694df17878d8ee676d4acaea7b0869332c8790fca1cb9cf7766eb65c27dd0aa
|
||||||
|
g: 53d837de9316555dfa4f027dd2a56b4527ba164b94fce67689c554144dadc559b14c372356cbbc5f01d356a64a2da4138d04bed902d71220a131bdcd7c2c867ceca64c87e662f8f841f6a5040850dc4fcef2baca890728e762af6e81eb119e173a2a92bb7e2f467d669cf0522011bfd0afa25472c20241bc23bf0c7e9a7590e494aa7e1fe08dc616150b9f8202ce70b7b7c1e13bac8dbfca147f8d90765a21ecb9f141d9f70862f40af3c8edfc0afcfd3c3810c97e62ac4b4e99b0de795ee56f75749d4a4d1dc6afd23b1fbfd7528df5afd04155cc21c4b54a5386e3a98703601e1a9ed7c0c6fe8af8d54bb5cf9777e38af474266b179004d750344c8eaf0be6a1490290a26f4a9d1a144fd7841ed131d080b85446a35b3d93b4b0f092314818682a9f21ac15eaf65e7106620dd8038497a7e2f3df9b01c5b835e55ac4336a57adbef25251f95c487812b877a5453df587e58cf7f59e815e5e622b1e38fb808256547304b63e9548b5f03e8be4650203d64b68ae901a06c8d9c809147eaac90c
|
||||||
|
h: 100
|
||||||
|
m: 3a2c384980d3903dedfeb912cb73b0739652cf428805630143e3d5d8d093961ac6dde83a3ef46445fae7908028d3e16d0a4c0a449e016303511372e07a7451f0785e231fefbfd57797010f931a912425d13651cfc3da031705f61c4f11007ab2914c6eb30944e276801622c35d0570cb9162fbc65d12d6bf7257080192b04a54abe8412a3688c42a4cff79fff3e2532b12a6907b2b41521256918d05a8cfa28550cfce159ff8ded87be56204cfa39262db6c5aa6e30f13
|
||||||
|
p: a635c59a578456f0dc86a56b4bba959acc84476b72b5be1bb7814da6ef36396152078e6703db6af604fdb82468367838a26b2c9f9a8accfa8a8741b4166af0122382ac3bd474a8c62fce402af6898bc6c247559cbac578ff1e8caa1c96cb78804b182540f5973e4a6c6431dce82c7e6dd0390395b148ebbbe9b37dc1178c5eb8b4f10e17de4985714a23086dfee81c6424f88f24af94306f44561afa96c50e25505f942ad5ece4734d6b09cfdd4eec18e347800adaf839a87959a380e0b9b13f45ea598aa3684c813ce318729ccaa13257723b8c95565489d6f86af12c5153ab5272a98c42d6643b67a31ce64e1c358874f7793584ca059290a5d8af8aec5e480b730bb29e8750161edf88ad463baad3287327528cef517abe7e023a18a11d986aa0cd112a68fed6a4ca4ec3fb9b72461f101fa35132ac9300058bc136b7fcbf30831825e86977b81757da26b232ef4890ffd94297cef5f794e3129716226d804e23bdecdd0a9f878442c5bd38bdf97ac8b1e391845ec230732db657fd41f4f9
|
||||||
|
q: ae55f5cf13dceb13dd19cb6043b004e61d28cce9eb4b0d385ba5de3c3b18470f
|
||||||
|
r: 7191370e8a88cae5f03903829eb53867fb52dce11de751fde0d77e5f803230e7
|
||||||
|
s: 18e066762501f9e77d08b8ee6a182560f1e42202193739871a4680752f6da3b2
|
||||||
|
x: 914a809b0742631a6fc2f088abe6fe4d411e901f6c439dc3d174ffb6e71269dc
|
||||||
|
y: 4324dd5fc8ffb6087d4025b71d829548511598ba004fd0de676b322f7b612d1fbb1c48d5c392aeedfa54ea27d838d0d4ddc9a26ca48a5ad00c7fb21ecd5d61f7fa545c69b7224904929bedb71aa8adb13f05070a01f45b0d20bea9a425edace730aef05c51b6f3ffa029d44eec79d9e7fd30f15b9961fc7ad94355791a9c3c6bc0f31098f367b1eec256b094a567f2861c6a5049cf3bd6d7c9a8d81022f93273edfd660b53b5789410997327f5c1ceefb8e1cb8159c34026fbb38953b10e8ff9458cc79b2111e44d510b230b8251a6b3e0514b74815ee7fce3e24f6f1b28177f9e552b0b1a99e74ff936292021051cf441b23245493e0117f045d87dd697ff75adf1d75de3cc4853e1ae487d436062d533b157a6c1829c104e2f6ce6b045b6c1d1f4d83710b611da9411156934c896b55168c28d6ac80c943a397e5c2745ac32feaadce6b93fe1c3121146bd1dd7604897eaf41e8a2619816e37f2e22b520b00b6fd9a24420f47443fa5f14b0d620fd3920e6eb64a15b95d15851abc8b63b811
|
||||||
|
g: fcc8fc2cf59a7693585f1c39a01051ccca7d435842af80f0b0808142774473b8bee527a5ff3f858543deb2af4715388e319d9a36257d8496564fe749745b44f62939c358a6724d62b36bf0be8e5e264b0ed0c06e36a37a4af8908214c4983210b5421587601b04c7ef51291d4cdf4e939dc4b37b575712de8ded5be001bff2027bee49067c0e8247661130e34661c934d919709c6d7521c203a43fe4362ec0c479fa54279435206387450f655353b8139129ccd83da1b6b61279017b39e4c1b1a8db59f7facb682a4e6d642cff38a5477ff6be559aae9652523f12eb057f0519f958d501a62c3f8aefb7eb69cdf68cb217b5fbd5fe32e1e006240a2ad953ef454a234fb41ac75f7d7974620beeca05b3e51b901d2a6281f6a90c4ac4c60647bad3ac2152e813cd4b0f830ca36adbf65dca3483b95d7f05630838f99de52301649424b449ea05efcdf2aede13206f95a1290b2fd61907655d9025d0fa0b46d66d49e92aa09d8887abcda6d68a4c44e53b3fba72f81732a8fa7b3a589b3ee4790a
|
||||||
|
h: 100
|
||||||
|
m:
|
||||||
|
p: fee8d17b45d621340a534a162c58fcc0f397d4baa515ae56acc00c0d09211511e63e40c1e26fece6aa85dbe5ad57721c78801087668609dd3d2eb8de079d860eeb6d6064e0b536a609cc4d951374f1df5c1d98d934d2de51dc818ab1d8f19f8c97fcdb63cdee3878c25bed6f51a658458bf4024f8c26d234eecb3c3254328f1b5fb6419613ee530a4dade1e99f98f15028c837c1a19d30e367308145ccc71e54c35060d02f5c11605782ffcfaa0f210b7d1998defa6b448ba76401e827e50c7edd3433d5f95212b61ac75fc77461977b87368688bcfcc2889fe1c033fdd682858d8b34a64d04a138c30adb6dfe5387281eda06429604178d8d8c661342f35ea77e08716687503b2525c5ff390513d56093f5543be751e0d2de7ca9aaeb694adcfbff52d6a87f8d79bab579df3ec9b4dc51fd0312bf63ef4756c4b093214c5a64a4067a018685472cb37e81334ff9530dcd628a44ecde999f8f4e99408978d3b52839a04ce9110c6c3c11d5c2d79a38e00caea2a74aba044293cdae470c348f6b
|
||||||
|
q: db744f628d60ef586c449d07f004b05df98ed06774cac1ede88f8c9609b34c67
|
||||||
|
r: 27e44e643e960065b0f65c260987aaa22c91e92ac2c9f33db998d5f22bee7a2f
|
||||||
|
s: 56801987b9b68bb3ce55b3e0a62b4fda25589f2e69e609fcf6abd9c28355f79b
|
||||||
|
x: 3c38768ab71d691e0c26326ccab8b89cfdad211d0a7fde425b1993efaa64cb55
|
||||||
|
y: 3e3429567c42211b12193c53e926ada2b4521b4dd02992e5c4702065d5ae6b14f2a7c9b9554f96ba3e7001dad6a9e5aa2ceb90597a57d40cd67d09af9e482e9465bb614d0fb7d49d1e3095414caa7ad67101badf5bbecbbe20935ba242759919a4c5bd8fdae8c724a839019fb6acb58ee6ee6493cdd38690ead6f0a59c442bb387f08f62f7ddf70b64554f83541aa888dd78b5759a00b0380a2200cb6c95bbe4b43d44186f0beb6e98aef8db4a53164e83fa022ba1fbdd4ca6007c34a0b5ddf24d04e0d321b7be6731f8c4c28c18e56362b30f70a3a916e41b48be47005acdaa6d8d546f6bed9c554ad76bc9f1b517afa8d31ca4d2029aaafb795cf9e8dbe7322556e678e90c09b41e4a8c1533c1c4e568bb2478ec7b248beed68281179f9f0a60bf0f4868b63fc371ad666e6738bcb9dec5b82026171833d2d6842bce9e5214e436e2d8316e65a0ad24a30e38aafa1de7afcacbe0dec155cbe64d612218d22ce2a2633671714f7d1d7f0d715650e6a663d6595b0156ccdca935d93132b6bff
|
||||||
|
g: 212235e323636f061874040e52cf5c500b80e27c4dcf90784807114f7045cffbc83b425a5a31f11b30c56fa602109893e074af52f1236468aa0430e953009069ebbb48ede64365a8d4cae6b2857084a6e7fb59541e39bb39ecdb0bb1e9ad02ec4d89ff999e78eaa4f1bda133a730346c5e4676d7e16346ccb7b607c63ab3b9f320ad00e0b0f0faf6e6d75f1f441fcb038c546a329e13d1b68d5cae27c6359ac607112857c4ea367095b7de4ab39501c0900a9dd00e8cb64ab20d193465efa8cd5eb641128fe8daa83e29880c7cf504b07b14ad80aa9e044ed28a38d990bd2f18b4042da4c97528bf02a1fdd9086e44dfdb179651ab49bd0a6e68cafdb2be1af7f0de5de23e2049bcff30d9928ca70eb0896f5dc0b6192b9841f76029f1c56bbea86c0c213c7f7dbf7d42f795d2256715158e2c4054e5075ba908fcff6fd92ee5570765303e1931bdd878146bda1c34dacac43a2a357437947cdfcccdc2bbcce5337d5b4fa483b6c01ac9b389886b99efbeaf145979626fcfcbe5b4a6d9326d13
|
||||||
|
h: e0
|
||||||
|
m: cba4fd1d7a0d57561b27022803560168562f6997bcb1ae596496e79916ac13dcd044bb78e6f9e9f0f0b24c4fe30acd7ba3a78e29428d3baf5fe2ee569c9aea5e34e0169bbb2a274308ac78e06048bfede129497c1926edc90e55783d5fe4f0c11087ea64bb6225a5570fecb13acb75c47e0593e9c1e1cbe36ebe6b444791976349139b7f2c912c311748a742b6eca7edb400e5b3f8bef1ab31313303e9cf14
|
||||||
|
p: c0753b107ed449541d42eab7ae1e1550b4e87750ba7a45ee6e6a00764633dd34028c2619930a25e764be4a8dfc5f485ef52d9dee840a5e4767f4e3606e8437e310d08c76e28877fa9cc548097903d04a0b165b2d27bdc9b4cc9db0d179733ce45bee7b6497c9eaf6a56fb95431f4248570ed3d278eabc85c058193a39bf9800fa6a881aecdaea45b32070153062e4166c6bb34e44499f1054b72c928f2f91edde4a908fa75b501f3647d71df17b4aeb8668dc4bddb1cf25a52ed2611fc3b0f2cf0c96effe48e5de4dda75b62d5fd772ceeb52913d70af52a625c341169e2600472cc46f6c336e3c02885b96f46b4e77ee8b4f5c16df35109bf120531cb70157d820a36945c63028602ae5434dafac2e8374ff0832a65e185faeaa516705eaa0c93db88ec3712c627d7de880cf91a25776af02eefe1f331715ed66531186f14df58b58578af5e44a5b1065ba1e39d801afe4c373678b4bd7114f981c5159bb1e22474eb43386565d4014e155b310f3f09c3f8ce31557a2307af2c3917dbf8b457
|
||||||
|
q: eadeb843ff31d95daae4a01d376742120a1bd1c4f0c27639ba9d9de1ae9fb615
|
||||||
|
r: 148ebc9c6f1e88b32f11c207026d7cc2e84a838a75b0b906a816c332d55a574b
|
||||||
|
s: adbfbf68c9bfcd93813bc0452102ac6074b5c18a90d33bef438290d332b3c847
|
||||||
|
x: 65394f78cf7ef53ab7cef2277456d177f194b3468c61a2300fc92508369e1174
|
||||||
|
y: 3e440d6f5a06aa3eea13f9f27013f58b60a7d11cfede48c212f5f626ee33650556ac47946e6778d5b6c826c062ee48da167d08e835da58d085849b77ffe732bc91f0926a7fbe0fd02c76c6c539304b36019563e41a049b7165a43e73cba7b9e536755fd35bd85ce18a51206d72d75d485c2915aa7ad9c3aefe7892693e3e2ab2969f6cb31ba11b1726e8fa4f00b3b35254c2a2d4848f4b7ed1e52b0aa786016404346e4a764b9c56a261f5f9321a9e87d1a9b5221b44917002ed222f596ce56e9163598fa3baef48e7556f6c78a5c6f31979d90de4b12be3e23225c6478695768246dbcc12b9ad3dc7aea89878ed5938195d3c87179b0da01dc99786527ebee362c56d5622ec8c129d43878bfc226f3034dcfe5415ad1a01de156bd2fc1ace834e25ef7f4ae4a02bf4bb168eaa8ce8fd0fa555c5a93bfc17c038e2592359b4522ce15b03dc9bb0c460e714ef07db4e328ff82a2bc6bf52c0b7897eb1e1182452b008f459dcd8e3fffe716ff91653c33f5d7fc8e470ec6f079e94088d4186a612
|
||||||
|
g: 37937d8c7b7ff9b5e80b1bd910cf886325e697c029fac389d883d3559852d8c925a92b006b6e2e834847ef9b9b9f5e577e9731ca4b137cb51710fc52e1200fe24a2f25e9cb50f54bc1e7da264d44480b8064145c70f94e4e00958b3cb66e5ccf30e4fc10073a5e5bf19d43a39f911d78bbd43be6e854dac0fba93adb7e6f0e2fc65d938062fd0db42472e0fd013b361f6f3694c26c876f0e11e291299af026fc964336ce4e4e1708ae928f3312f8353f11df0c258ad605b1e084212ed7d58380f48a7595c490c722879661dcacd15439034382a158adbee93bafbc2584e2ffe9b8d55d92efbd3444e751e51a2cda5260d14141a2c5cfcc15e21739cf730dcd6b850fb523dc82a318b961a4f4e6d5c14f7e0a17417e5ab3e8c3b33fc1ff43d0695b4abeafd3d7f6bf03f7a9f4ba291464dcaa88e5e418c0102cdb17bcb03aa93aeb5d9ed231d12e99f27e5a6f0ad3fee43f2bb034aeeb4421ac22d2dbf3a5e93843cf9770d9a15e17c2b00fc2ef2891d2173b149137601efa0bc85a477fd2885c
|
||||||
|
h: 180
|
||||||
|
m: b4dda139569a44b5a179c2e5457bee1c65b0894c8bd3f3e336cfd61f22842a0b33228bc953ad110d9f471398802be2ad509993c6
|
||||||
|
p: d1975e9d4fea417fe2415982f42e9fc5827fdc851bca21f5fb890414e70fd082745433c713bc925548e8fae09f7d4c02330aa572ccac10bc60e7dfca034f3a1bb6a257de6d21ced88fb804fe2e6c98f62c407c893c56f7b87d2ee7e7438684b115f1d35f887249b0ab922b20a454e9410afe74fdb696b53a57eb038c341d5a1ea72e7a9e7b8d7ffa633981da6f86517c3a9498dc4d1e73df8a86c3647f7028a65a44230297465c563da84e5cb22ca990d1f52a0232eb948a9b9f98d27434e4e1559f377e0f2f33640eeeaf9f8276e729585f93fe749f7563b87e00a9725e75cfbda5c48651a09af950b2a67c0f481708baf71d1e2d61250df8b2e11a8b0d7892a93a91ac47022feeb641a0401256831a810d699f187ff2a9c564e28fff200b25d56e9d65bcca39a4957b67c1050b74c1c38a34800acab0007bd508aaec5496290cdf313b3b15e258ba0e852cf08e11bfa88f38d297c2b5001dd6807ef81d77a796af530fd9e8ecadd3b24d356bff4f20d81cdffc7f2e7b615416c3923ce1b85d
|
||||||
|
q: aac8b1f5a8f8f55410f312d6d2441b33c806e948be692f008ba7c21f4ff1e59b
|
||||||
|
r: 2b7e93a7e1123cb62bbede1c006d605ca4cb326482ed5610eefc3c09c018c799
|
||||||
|
s: 224237bfb5aa7a899c010bdc9bd3c995579785dd71dec357279b68ed9cf25fc7
|
||||||
|
x: 2367d7a1e5bb1090299898f1a93afbc7685fb9c9c6b6427c881b1f972be8e8a8
|
||||||
|
y: 5638ec10d489552fab7db5ab3e3632c1b474f2e34fe51e44de75c24320f7b88ea9f55a661a742005e2ccde5f274f4f5acfc68a45c1fdae90931ac7598b63fd3a222ba622f3e5d4143cfbcca3e764cdb3b52da099b66f414abef8516c3a7dfc440746c98102e1a31cbd8899e3aaa37b4b36ca42495468232d52441e0bf9d4f9531e985e116ea96bd1e0d05f80bb4604e8fea11544eb97e3f04f0c4b60cf0b7388310c1012a4db38e33045b7aff192ad25d2848ca7b787fc2e7059c6ae788095f2a186821de66ac1fe39827d6cfd4d2789198465570683f19099e3e1f3bf7096da9ac000a09ee739d299b418946b25f634d1ba6b53bc7761fe7587b02feff561ee481661d010b3d9e87998ca843a77c0459aec5d3768d462d5a499ffd98ebcfc7c112c417c7b64c22731467d56a5e7a7661b40fa5c954655121822b4b1fa3febc10e413e19c0599fd744a56254b7754d433555a49b8fffb5b80717c0b5049f0afb1c842e70a4e82bc8dae38017e3f456c5eb4b0820de0778468cbeaa782515abe6
|
||||||
|
g: 938a31e11b17fc5272ed65f5403b595e025137b510daec1038fd679f2e1c120244fb8007ca83f5d43af98cd88598e08e761e622febf417c452445da1ce0cf56442ac45ca500775b4f3c0cfbebacd9233f346c7477d86ee6f6ebe6fdc923b1e707a1b3a59e1c8e0c07dd36710012e79b93ddc219dc7f58aa4bd525e8853fca761a234e4badb5d8f001c119d5c5addb2cbdd4b0f89747faa6a5c1ea601eef695eb014ec7bbcc5ec71f8779ab5c31c1b7b0d381fac3699d7d38f7353f5e1188ab837cfdea4733242ec8fc86e372a2029818979caecd1f5d8d0798490ceb92199283a426d77e53e0c8ff4ce66d4a571b93186ea11a18f9d1db9143d057ce1d31effc82a84f706ed6b5563e8b55e41aba68f895fe743123f8e0b0fb7b2100957e25ad4974c4e03b6241dc2dc64166e507185cd01b7dade03d9452bbf9c58888fa3d3665f08f1e98538c6c2b648edeb1501e143eae11e2e0dfc164df0203eaab408cffa7b68c7f3dbd50716348afc688ade5673a1e30f7053484a1429b7349789a0336
|
||||||
|
h: 200
|
||||||
|
m: a6e57e358ee95fd5d1dd95650b1f20b6c0ac4b83ef07f213a7de4bb79aab5faebec0a609979a8d84f5c039ee08ce65f17b61ed5397fec71f440c2ee689b474425b94e695c90253e0810574a39991b664eb6390090882e372714842477de0d56fd333039a1a223549487c2c6e36662c2631ab0c80f2a79d0672
|
||||||
|
p: bbed6cc8f36354c59cbb3e073d68cb53304f7249326a3620012fd3bc32b416ae5d64f5e50e855df4de20536ab04175c30bc62ad07836365ac5c526c7945c9d52672cdca2750ba6d23173afaab5333f7d33120d836d843466ba0b529a43a010c4a3ebb10ff3d0d0e92635a7d94238689ab014aee50ecb8f5cc363da56f8f7d34a234cbec4ec7757245a982d2f2c09ec261bd45d511c500453579aad2efbef88aa0ba371aec852ae7cb766692416b25447beb97d8db8cca769bbe28d1adefe07be66b9b75d8aeba471cb6c32765f6e39425b273460fcbfe3f49f05dc64e9d7a69c28bc70525e8d5acf32096e693c41899b6234a333804551c278080185495a2372dee0995c583c762e131fb8f544a21846d04a260d0f2fcad9c85dbd30b48e32032bbbe11cb34c642163532c466953e4864d8768c2e8c2ee31144d0a9e69cba4b3d98ba5ef53682462786fe8a5bc43225a3342b87813c41e8a08dd65f896885f00928854bb0e068b805a71620c3d9c854dae4c8fb441760c628432e921b67dcb43
|
||||||
|
q: a39300e431619be4b8c2aaab03ae649a81c1bb8554f3c4c2c9200ba7194fd19d
|
||||||
|
r: 2cc389248e2c4bd59c57770a43f469c9eae30eb6c4744ec388de95712d58b5ca
|
||||||
|
s: 1bb7aac3abff58f138f9668f112c687d34f31c618992bceec68d022fdd9a3919
|
||||||
|
x: 7a9723c452867d5fe06947fa97f6850c74e991d4a8beaa6557700b459e298f4
|
||||||
|
y: 4ae5605095b89cfce482636d4e0fd2b07e2838fca7e2bbd5f496c4ca3c71ab1f06eca457bb8e7f4a9992451018aec6d0e24d007814b5a8bd8b5ee968285b55e287668793a8ff9a9eb9ba00eda018d29561c5b61fbe3278f91efafde86b81d402a6590f84cc6f0f90afe725e59fcb173e1eeaa5b24ca09ec0754bd438fb9fe1264d040a9e2582645807e9df4462bf069652778cd30db041399407dbd89e5dc0fb4359efd345daf8a1d1093ab137ba8d8fbce2badacd3bb3be438ddc3c45c4920e7e5a2703a40f284b7c2663be21faae3083a23ff4abd381ec93f16c82bc30cc9495c036679ab295eb7c7ff01b0020aad0c08569d4f94b8abaa70ae10097111e901e30c019f921bf2da5ad188c4659b57260b82f60fc7043242bfa9c5749e756bff41474126925652d84a4b18a50c28598b5d8c8efd0ed12c387ef9bbc0b580d5cfe3443267bddc1ddebeacd7b7a456d3b2a84f47bf528adbe825f5fbbda9cf06007f30aa5acd8027c47c76cca10dd9dde68104710559ad3324d6cf046d3416ecc
|
||||||
|
g: 564a9966353c55b57c6a42e5b17c35ea70ebe40baa9a71b1de5d72858d5154574d5b4959eec96dd8d3d1498fbf8857b7a31831db381943bde2b05b2d9ee565d9f388130da4d5e20e62c4ecde304b19672dd93bf8bc105d6e46bebb8a3d538709baa235e338ad47450f3a437cc89710a0e759694f65d74fa578fd9c6041ee5078d72dc5d40d868ced67ccf06f01f74faceda056c609a2112ce1e43b6181ce353db008fe783e8d3b4331640ba6c7a6769e917d3bfb3e97167e66bc9e4bcf576193970e93f83c817635810bdb98f544ed82114d8bfc52c85797306b799e40c1ab181d9c6c64dd1305e9a786bee62f83babdb4ea006d953f6b2a17edf8e455549b27ad05374c5ca5905a335d85ecb601701c529e0fd63f4e51ed6bcca4672e8effc886984975517ef28dda6ebe964170469cac61f83c3c8da31b9e867eedd0ba64106995027ae1b4365cec6f49239c0e522e88723a2e4d2ed13433beb155aa806c6793c16c12d232464fa954e1e72e241a17d460435c23be7d4f60e9345d008490ab
|
||||||
|
h: 100
|
||||||
|
m: a71b2929af46e7543e
|
||||||
|
p: ac858a709f5ee49f31263b09d9aabfbe89fa3ef7cda33afb3d8be3c53365d60a842d4ad3ebc6a8d0a2d02b51685df0249ba269e0f0f6655b5071417b282c9312d045d7362a9cbf34f308e939945db31b89c9365e704b1a3d9f14779a090e3746e6544f0b5ebc2d91b2d0f5e7e6c22a5cbdb8e92c13243891da666b7061f3a3a3c11ca48d698e8c8e00eafdb8e7ac98727429cffdebf73cc25ee6809c48578027ae2f9895b619650db9e043f83dfbe3bd2058673c9093c58ba5b4221f6bc3c52d6eb3c5a60179badd6d87516861bbf5c779969b639cf229a6386d73a22b39bc00d82b7038472d6985e2485137061dfaf574176ecbce66617b1a9fe9efeabaadd85212ba5429681ce7addfbbdeef49abdf510dfc949c4b75fe6744b1f40163a03ec45dc5a32027dd1ff1cae99eca4887284933119892aa469af527d212d0a54ea1f24f617b8b0760418b06f38f87a77ac70d450d7a7e67cd51aeeccafc8f807cba2b60a666d270486c236a27bdc5dc007b30ab4661ce37989245cb4e8fd2dfa545
|
||||||
|
q: 9a8c0039f364082e3828d98f62316ea3acff181bdab8b1d8ee8af6117d78d2f3
|
||||||
|
r: 41815e633fa50a45e2f5e67e72abb0ca5c850996b4d37fd126ae0270fe8986b2
|
||||||
|
s: 712e672d05e8bce407746bec1e26426de01c02801bcd508eecd0d58fda2f105e
|
||||||
|
x: 6b09b366c3b2aa81164208ec0e8ed5ebed585725befc895f37ae444fd42dfa04
|
||||||
|
y: 1d8573838adb591dcbea08d8105459914f575d72ce86a88dc1e443814eab46bab9cdb9ff0cf28b1b2a83b19a4d2805da15d77d101801fcfbb7dfc46c19f61fc4132e3f591006e6282ab5a609ae438b8f53984aa60bde6f127ddc727b999167852b53be146624d67eee9aab3c35e4e8ba112c78113cb1432265eddd51ddb7b66a701d7084c7cb99a1bfa8ae7743eb1b7258a0a5967fa31d5601e8933d96a81e5749a53f6356785cb962d2bcaae3b70a1bacc0348cdf8fd3347b689ea26cedbd8ce05a7c26175acdc66b13b8d3ed81d5baca94c0bf4a9b82e4e5caf07c23aef5d9d3fb3fee2d3e9dc7f31da6983e6a6ff61fd6f9212b2147389534ca768a21054b82e13cd3fb98735de482582a7028ad548808b635a3a7892be503dae2806090b825acca0f1d54df3669aff15e21337d3ccac8b989f3968c2b0763f5e89636e73b0625eb47962d3cfb35720d7df49cfac233b732d2e1075c20965682cf47c976dbec79574d3ed2b1f224fd72a672cdcdb1a55d88ae6e6d8aafa1415fae3d579e60
|
||||||
|
g: 6c211aab7f67be64dd75828e176eaf1dd9a5c12c464d8e86111bdcc8a9374c6e03a96a49a0afe383be7d5f56eb6f191013a17bb18f32dc2622d6fa5bcc967fe2c80a077344241c31f939e0f3c2134747e0edbda63e5b971ff1a2f084b7da8e45fdcc86b3ec8996fec01dd71b9beb87b622ba9587b3ea1baee8be528e5a6606846d2b0ede32385b8f59807ee09a3f523254fcdf6b3bc370b84b335875959c09bd2e5aef0dcd8bdee573b083553f658f1f766b5c7174b851addc8b8dcdd1f6c3266aadd97e6109c185b84ed2be6a641f40d722602a54781b2a663dce8746777706812478c6e1b996055d16a4e147a32bca50dc7c6e3cb065fb949bbaef072c50982f2afeeca1ad2e9338a80c150726fcefb05f96b8192590820bef40b8fd3ff8d0cd752864964e7e7274d974960d2469c24de432dc1d235350fef28b41dfe828bee7b7773428f48cc7acc5bad92104ede5d5c0c186e19296ec68fe9abd27b6d50e318cd7b65cf2b2617d77e38527a26aa13e52d3dab898a1b1814ba60b7402058b
|
||||||
|
h: e0
|
||||||
|
m: 41cff2f02d4ac663b0eda83f2efb939e2ba8c1376e5bcf5e22376a5d8209a6369563d99be3fa9c6634ce6ff0a1f988bf061bdf1b3b7e3fc8f61bebe04c7bb28f5c798ed4858ffa4b65a9297ac8a56ac47e5782fd231a1af7d96e073ae08588a73ebfdd7e8de8d58743f45e18386ca4b3cdd941c94dfb7adc30
|
||||||
|
p: d8e1faeb2fd188a8a7cde53b8b3b43ca37df1f085c0a31f675d6da92770eac126e02e5fc3837669362850cb89ab4f325c3ec336bb2f3addcbc03b6843ff4d0bd6a8db6acd91b0c6a73aee84ba5ca3b0b7ffcaf97f6748c103f54f32d0ab3fedbb56fc107c2df192510f19a636606dbe95652b4e40b2d9ef4a91d112160f168e4715112c8ff257aa1fd65a325242d1f6bb3d835a88dbc0965e542d8e32ae419029911c76de29cd85f80ed491de2ab24ec3f08fa80cc972179009874d48e3700041a2eef7c146f7f36b922f3e2b1a525dd0a5d5e0fb58d09e9d368740606e8b9cec3c59d69c57d68b084185a879bfa699e4e7ded1e0dd6d01f6e80e456e35e15c2e38809749bf4881d530e738c5b647c186883a2ac90c8d2dae4c9f79cc550dd1f9bca1b32c14fcd2c7805f5178ade716d6f3b7ef3bd12631116353e22ca5c298b485d2fbd5f43ef024668471facce5016fd1590aee5b74e4bcd4fdfe1acbeae7695a9dc92618e3a22d9112d636b4697977053caf5ed0864f8c7889a63f3f621a1
|
||||||
|
q: baf930264ecde018c65874e7fa04024256b22a84437cff82a2aa7ec4508cc397
|
||||||
|
r: 8f81fdf43c81e8f64d3b42401c5fd4d0034f3c7cb543690f6e187ff3fc1e3b7c
|
||||||
|
s: 498e069e14c41fd63647a0456e9950f99ed59f73516edf9cc02ab4c97d98de00
|
||||||
|
x: a91a1f6880a942d147802a32ca65fbb083835e159eafa577f8a958ad931de3cb
|
||||||
|
y: 7cdfe454be693a9c8b66e81058e73fcdeb74879fd13c3af7b1026da762d1b85e8997d6ea1d01b9f95896b883e9e9d1457729c953d64c9e55a1a8df4fb2195fadf55f59ae7b5e6f46a4ff35168caaa3076344a65e876c27b90d476bedf23db215282dedb8329d948d62f00004d45579c3017af70afdbae6b90f695d117115238cdafde16cf27f00f94a073d37d89377f7c72b812012ab1a467d981111d7b18d49cbeedfd71ffba34a556634776d879163bd10fdca99cec3bde95e97695432549ce662cb211917c5b129cf757004e2e009a73498ade0408c26ab6ceea31d3a42c1209176fb435729e0cb5e9b60a0a4129e935e9a28bdd296ef8f2366d0feddabec5fc6756c96f25b5c61267ff56b1fb1e76f9d899c0d46f1f4a89500b095752148bea3d7af414e326e4fa0591fdf4b455f489c6b6476c14ff5dc1ebbe6e4a22ff16ef8fe6bc0372c2dfced665942fdf9f1fe5374a5be6782bc7eed8439bc2163765062b97f6c331afc5b4cff28097712f5ea807c1d38dd9d157d583301c28add9a
|
||||||
|
g: 246aa59573c86300c83ee53d64bf1a7f4cace3ea40db0c309f653e4231c82104a26333c9ab3aa779ef84b607b273f71145cd3a0dbc379625382be8aa61f71c7d205297335e65ee9ced3ab29a00109b0893aa88e4bb1f3767f45cabde0715f4fa531aa952c65098da52b707daedc3c9626db68403c7b5d88d850ca144f4903872de6b6f622c64b144a7465967598b6d25d057e012ae011068a51d387b4f60faf13e79d96e9cd8d38b10ffd9ccd747cd7bd8a442941e3d422a164b6c43b8351a756daeb53522d3941bfcd4f91a397005acb6c84610e9bf13e6a3bf8bddbdfa69e172a635eb30c78e7d5f7c41b337394c449e411ce5d040f2d5dd03675269f66e9e17554e7bac006acad16c15ab34526290fe78ee8b4f221c86426c832f60697e59dd37625598b7ddd7d57efc7120967b39badadf111a7f74427dbff4cbb2cba83a285e370a8f2f0aa2d8b8de7eb94a4b4037e68e8ecba0b0830faf53c4037e9e217518d6787f00b61e882828941366e86fa1d40c5209935723b8b325dfd432bc91
|
||||||
|
h: 180
|
||||||
|
m: f8c04b2114f02fe4c8ad7a8f0f50ab2095e3d53fc03c688994e3eb42f70ef8218a9a41be21d7cd52d81ab557d3da2652785232dad130871b
|
||||||
|
p: 89c2fcb4f23d573ae016f733f5d675f7e04d6961040787f9879ac93e5d77219d9901484434a849445a87e23c6aac47929ebb3f68dfd3431880d92a8358ff428d555cd5194faf3011e0d8a6b4749f85fa0ec44f276ab957eeabee75e6d19fe960c54607a1356a7ebda002066a66e377c3e4b0758b94500c32f38386cdf8df332208e404e51565cac987de26fe7c2dcb2da7b760d91ee7f1136976aba2dff06999850d48148a4a95dd7c5a8f72674529f2f9cfb942e872ebe2deda1dc923c2325741fce62ffd279cae4bc2f82e8730796c7eb038ac17919f73b30ad2318878b08b7e8dd1fb3e7fafe73840b3a0b5848dbe8e4d714a4cddb48ef098c64f557dbd52dce8c47dbd3c3adbfd2b6d1c9a79914ddd9110b57b0add4fed67f5bd23139ef2fc4cc70ca867b007f174f2b3e5ed2ed9436b8720e516cd59afec575b58f6a8393826a9bd240b2f91eb1bc183ad6d3771922f4075cdd48816dbe52a15c1a49b88ca7a75a9db0e852259258445f3a8ebc668f18666182f6ade41d1c29315ed2325
|
||||||
|
q: f139ec4db606832bcd7225f9cfaebba8de23a2bf0bef7c6e7e6da3c0a67e340f
|
||||||
|
r: 94c027a53e44370294ac7aeb0026696a5a7594fa5981ebc8cfd4aa2beae182fd
|
||||||
|
s: a6f97f810c693b98fadaee961171491d478c496975d6a8d6a69e448aa6dc1a25
|
||||||
|
x: 70de3057cd3914c66ccf91b988a668ae71fcc8dd2cfd5f4ec234608eb8b2cbc
|
||||||
|
y: 45e6f1b509af74cb0ee5932fb3ed71af98dcd9bd6a6c37374462891d85b3935aacf2e4abf92911cfdb67d7d0aebaa6f03703d6426a3938df67749c4444724c34be608accf82f7839e20860954dd5c5d8417d148f4f3708fa43a8c7d9e63ca4c16c0d46fcc21d8aeee46f71a6f2674513a89c178bcbb7fa700b39f955f015198931cb90e9a3f51137d5f8888caf017a78ad94f3a874260afb5bd0ddd00e8a18ce5f67507c4623ee071685cdea9e84e8b602d96d637e2f3f3f230a6350f19ecedfc38bfa86d5ae1aa9964e8feb16b2828270c8fdd912c9c9b7acbced2f9f5191ebf507bb3b6ae52fc6b1682d26fbe674b05e47f1908abf0a1dc66b350124b6fe871797eafaef7adf7bd5e7a63c5d3df2c815492a94625ffbb9a0985142a8f2e3ab678310aaa5b031c5f2c71df41443d6d5037360381a71bd6d3e7dbc6b8bd2f2aad5ff6da9af039991b34d21e2e1b2eb0066b21ae8042ea6230da9803b34debae1fbff6e6aec96138a19e4f32ea7b55e3a1aed6356a2ad41852f45dc42f5adc232
|
||||||
|
g: 2439794053fbc1ad5dc947bd900d9055aaf605e4ed189bb186f9e7d287c8e7d4d811be0e7778e86408734edcc04c4250b67a6e525b9257336c0161db48fdaf031a2004115550c78437613a0ca4d6cbb0d23bd4d43e0667ae8f4e4e2bdd1ede22b830a289fe4b0d273919454f22681e12b66007a092549bed122baee5d507d2012bc9fc195a54689e33162f1c4e5de7e73a8cb45ca5f896aaae0db2117371813ae0ba966aa29705806897d0571e808f30f87c4de3d71d0452e120d4844bcf2d1c6a17771103ab3742a4d48a1054b3b1bc4ad607962f8ec818c20501bf17bfea56e8a4892b2825b53f7d60a82ace5c7bbc190724ca303f15896df50ce57d975c602d90a6378e710488942dcfdeb79806ee17211f77c51597719a076c7203270c0afa4aa4cd1f74452d74c74fd1d92577a85bea21c65528e2eff8c875c5e1380f511d47b0e30148bfb3a8ebe212dbfbb44e2081657d2d3e661ac8f63479e90441e0584df9256a7ae832b494d351df7a4254370254eaf0d7f316c6cbc2f4ad621993
|
||||||
|
h: 100
|
||||||
|
m: 59852f4236ba78cd9f2e6ddb4d5098e7d50073e550a92993a162546f439604a44b915b9133c8c2de2fa2def32118d7d51ae426f11f391088e082729825a0376e9c3ab24818864c298b7d304b3f6adc4258f19112a37625b23eec8f477f389cf6c89172fd1354fa9a57fc73b6368343829ac918bcffd47aece5507b61156150f22ecacdde4f8b16f8e83ac62c8842ce7a1e87d70b3cc3cd0d41dacf8618e751346605d234ac7989414e4d692b95c7f202bad0c0e332297151eddf7dc416bbd7c2ef841bd2bc3f8fcbf3af3fda107cf8cbc576eff5
|
||||||
|
p: e82433bbdf1b0342d22306244745c9d76dd07a6e8b291c4ef4b13575e7dc9beca812faa9296adf84c92709218ff59d4d9b03d6f353ffe10bf8bd744c687bbe1fcd50c15495b4007801be38b21b938a7ae7572b2d46d5eda936769dd1eb4e60a080d751a4b73c0cdbace113197916a33ce0a68f194276792eac1def1fe864aff03c54c0676adde24b1027c92ce1b9989fbada83272742e9a40ec035460f48080de3461e779cb8cb7598060d720bc400e8d712cdfada9a1170e7dfcc024d137145ecc84f378bc6a9dacf67fe636f85b758821d826c6ab326b388c99ec9eeed0abad77582f4cad6c68d6e01b5c2514468acba728066c98275efaf123a7fe33bd57211e4c9c6626a54a50c35499b88e6ed217a315541048b7a8d8c0780a8292f471b96ce7d482a7e79bea18cb33ae2acf2f00bd5c486dd61627ad574c7e1f90446537c2b2f60553fdcf570dc87f91d0a6d9ebb644ecac4309fb4b45ec9952b3742ace82a7ce0035163dbc3c378bc9b7b6c8b10affbc58e4de7beec584867e9f3c2d9
|
||||||
|
q: 9927f153e3357e818ab74f37fef9e8179088f98f3426f086488b960dae77a475
|
||||||
|
r: 3a8b87dd16bc200c83cc600848704bd5376a27dd3322e0f6d86707dfad1315c7
|
||||||
|
s: 11d2e1140a88837eea7c8a2ef7b064f1e25068a5911d7ebef19d9df03a54c0ae
|
||||||
|
x: 1e8e5f046a7dbe29d3e38766a676e48f78ae02c9bf20d3fb937efe9f5ecb7f54
|
||||||
|
y: bb70a52ae0547271bb4dae20efc3cbc92badca851ed1529fd126da0bdd579e9e06df7133d0f96b1f890e951534096fc59bbc5bb316c6977b776f2d82cc954d57397e14742b0c500960c7d942f116657ecbefe6ea54ec9a07dfdda77d605cdeee0f58b7bb7b3f9d0a681bf1c24b22520895a3a9a2991cf815641fe0c3b01634c7aae4af2668a4a07464fe430fcbbdbe56718e9af97ad6ac88e316ebb778ba4c58788280b0e5d982a9bd9c21f7209480527be2d5aac45a07c8e6080e0e84c804fc52f9eaca35edfea8ba285882141cb2333aa524b22edd9330fc8ff3e256264e1e2f755d85e873ef558c3ccd1cc0aed3ecfe534da328d3095011dffcafb70cc0bdb469a0b485e125f4b9225962ea007cb2b427846235c3cab9e09c600245ff43971a1aff04c6221c630753c3a87cf12d71edd5d33790d2d3a8757aab0254b438ad53db2c3318e62492e00ccbc8fbe6ff287e82d25dc34a50e454d2f04df088a326312e29686ddcf3d4e4396c73aa623a0b785f6d0ae49583d8c5c0c2c7c21b314
|
||||||
|
g: 90d56047fe0437deb0c3eedde6dd8b8c411cfd53139f5b7aa4c700b0e8c30a54572c039bf76eca66d7f80a9ba1033651611dbde3bbda18d54d8a8875dca65f71766c1b72148101b2d702ef9b5aa1a85c2368b4d3a4c9f90126a1ff47ec9a75efa4c0bfa3355973cc8708457196412151411d3fe12e09a72aa6fdad83f3b1a808289d99977eeac805908981e7c2a38d79b601a1222bb37ca0e9c14284eaa772153cf79ba3221814cc2d7e2f9c51540d7a3b23814fb40a943bb578a0b12ca5f7eb4d810cd7afc051410f630243c5c5b7cc672e778cc4b675bafa90b2de8fe1fd613caca26fc4371cd6153c964afc28f635bc751be35703fd587b36491a006a48824cddfddb9d8ecf329f832377336922b27225bdd7e994d6e2b93c36f889de40cbec8e23832d082c3e3ab2d556a3c18ce8944ea04001472d8673d98ec9c4d2ecad98f853288102c78cec5e28b587cd17c0266773fe826682e3096cde88aadc23b49cd422f9cb8f68fc9ede7a9887ceefc2c8554edd1bb5863d58448cc79ff6a0a4
|
||||||
|
h: 100
|
||||||
|
m: 76035b3bd6553ce5c469264452d82458c4526be46ce94416e5dbe4289ce836f6682e4b48f37dfcc4c5cf6086e82a29bf61a9ff8d21a1ed239a7cd9d17ee981e62ca6e3d6cb7ffcba4a47aaad0f884aa1fa8fd9dde2eecc734cfecbcd7b1bf73a72cb47a574485b55037c95f0fd61162526c7921199845133bcb7e25f5918c134e4b37e313780b2c16f5afc225fc1d9a058b5a82a002075778b3622aabc953573b4fd0fce2109c895d2d81d7a1d7f565a9b26bf74dcc6b8ad8624212081e70d4c894bded18da63163ff05cb7792e1cefa8206a4d146b2004dbf095cded6ac3ade513b8978d1e321baf49614688bc52b45d77f4d68b83ae21c7e92c8468f86b3
|
||||||
|
p: a402f26e8ac3f9a578f910de96aaf4cb6e06bf66121c45d3d365331f0bdaf099e90ca7c09373255204f19d3e747a0de6fdca44b0f7294a850b158bf1a77c5fb934f78c35f525199090bfdbc2e0190523eafd01d3e87595bdff792dee18a857f1103c9c70a3a01874edc124fb3e7adb22202edd48d950e5771cb722d3deb151ca8c37b0d028c26006003f4d2619baba2d92748d104023889d45c4e28a99ef537babc839d153168c2ddc1a98ce7d745c870192bd69f16561b90e5aa1ab3f3d853bb01bdd0c414c980873fc97c04602edb64cc2f97143ecfd98581e839557a1bd1114d5c0af803c274e7a55108c64daf601286b0d728ec9318025dafe80d915a9bb0aa74be28890d01fe835021974c3987b8bcf21e7852cefbbfb0b4f3af0585550ed5007a06d4dfc9b41abe01669810a8e3c1f85c69de39f0fc5111a51494c0377c75c8c9114b8ccfd03701c81f594dc0d5f85807f7ae7e89a536b7f03fa2ef3f3d92c03d32f821a293d1a044841e55d8b969a09905c6876756f3c93f0523b6e11
|
||||||
|
q: a128342cc13963a072d7e1f8fb48211c64d3fa9a88a196879f827fe2bf5a5e37
|
||||||
|
r: 7b9b903020b499eb52c02fa2c44a771507f7ee213e18739fe6c2b506257271cb
|
||||||
|
s: 7a75aa9cb7047b9be0b2bec8eac8b6d51e1c0c335380a526ee67d8f7c40c6336
|
||||||
|
x: 463d26dfacc068729cdbbd33fdb014ffcef9913f0cd3745125825d59a9e594f7
|
||||||
|
y: 165f2ee5c2f0a86bc3af3a97e9c83dbe6f8b046285316469736a502d8efa25c046a7ee2b541d18cb8ba68e29afa814180eac1a60f9da2d858167870699a5a648247aaf0d779e90a76d568b236a9df05fda494a68878c4f14fbe3ede875f9746b2f694208c8df9d93737b22589d1b440ed2d02e362465a3d7c573fc947842e7169c3924e586e2ce6cdb6b2496b1e0ca94be95ee98aac15422f141985e310484f71d6861623672c3ec448260b87572cf903202d73dec2c577d2eb5b7ade7f706d16350359cf6d07ff83fb82111050d1f36924299c10b810a0ec2b1f2647b96d28c719a8757ec816a7692e026455b66fc2a9cce27f19a5c69733d21713e38029ba5e6c45a72329a8299897f907626dd3324d3494e00155fbece2be23efdde7dc55b14e945c4758c38f9c00fe5631bc5b5f4ae2b74079b3e9268ad7b816ea5085c423b1cea436dc34800e970095dd888b383de553dc963b0d040093c6fe4c278b28d64ad722c55627a87b5472ec9b4996c9acc91c0a3aeea39a30702e366dd50c658
|
||||||
|
g: 5764707062116cc99172717ef717efa8005d28030727cd2fcc6688b9a834cb19a767f1628b9b63b3699b812dfc0dcb94c0ada4017922f536194aa6515a7d30982b083fb169e57393bf90b589936e4f187359d34f4f538017b4f4ac76c9fdb1fe2e9f390e4e1c21d6ca55d94e022e84482dbb9d4837dfac458e6be78ec2dbc3f4fdf4936e6c8d14a1100864bd8c57dc5989f77ff6b2912978126f962e58ebfa65a5de631b17474d8532d5d80f417e28e2de5a2b54d88ac0c198132e750a8f77d92933f977b53cd22ff4253692b0beb5d6b8bc8a00c93dfd4d5d770e2474b361bef7f452b2969b483e0753850e0cebe9e4bcd32748bca7e5935eff31736b8965c7403b14ef4f6e0b014466c24ffa48c25af65351f5f8c3094b4c4e52c4c6ce8eb85172c56c8d5ea30e9dd95deaedaba7fae22579958e4d1c1c156e5443b023864ab8685b3fcb1c98094dd36b9b05059b8aaa2304dcc65c2a5ab2e6c0b51978ae1d545b5e72359be8339014976ebde8548fc492002948908212960ca3e40a6ec6a0
|
||||||
|
h: 180
|
||||||
|
m: b711f04ac5fd89c910b1c0e582fabd78ca0f57ffcfa42c346a078588689fa371ad03fb4852915160f47d9af4446f720381c5571e8c5e
|
||||||
|
p: 9c0a94fcece70453cfee19ea72714e33761e57ae6747fdb63db3d76c462abb7928b61f9ae467d7d1d9796d8941b5aa47fbcba4ebdce760272fe644e90788591400ecc65c5e4beda021cf5bd761cf34e9ce0866e7c93dce6344e6c6aa3c50011de5040bd2d03e3af54b0f78fb534bc951d008a4e3accd54a4eb666fe479f6c837d8766b2693185629fff8c88f2c3c2bc7d35597b5ebe7920f3d932471e27f78899ca97f0c8bb25438deb9f3e313d1947dc52758b00c8985557617f411e96a536981054051d39e67b7a38f8f060281d4520efdfef4b832f8ac323bd5a18336e7fe17a648b106b3e5347dc2847d36df0cb63a1c33e2827abf624a925740873419f9440160936ac093eb5c5343d04ef8da6d0653b268a227a819e61deb230b94071057a58f818df4198d580dce76cc5511ef968d636e32892633a0ea4661e6c7d6766166ecb435059e07c102d8969dcda065265f08274326a53755d5d73956a16ff1cc7c6708a8eb2d5b8a15c8405c5cd43b350b036fc624912c446568b4fb435f3f
|
||||||
|
q: 864af34f127a0053b57efda497bc6716bfb8d994da1673b73e5fa76c5eb43d3f
|
||||||
|
r: 9d0125693a02f4db4f05fba2cd67a8cde6a09684102be94a433e57d8546a6dd
|
||||||
|
s: 20700ca03c9fa80b12a6ac38916348f47eb63c2bc2b23c7ce34918b2b2cf876e
|
||||||
|
x: 22412c573b55b3810506821515830084286ceefa19c7a1d64924e77bc02297a0
|
||||||
|
y: 49e202074ed99c408f3b1eb8f728be5198208c35816ba0980d062b55f0d3d6e6c88c70d3c3e3525c56e0596bd509f94bad73bc842e1876379facae5223bbd41686628b4472ed8b4f39e3a79263439d6736ce9346c9b94a6f72b18e86acfeb0138b2154f3f1ddc1e40ebcd4aa943d7e70240e778ba63d039258f54b85d7c402f132f069d9d84010454de8e6eef7e5ff9b08c68c8686904119bf2864e21ef7eb9b8587cb6040bed7bafcd7b71e6edec8ac2aed8f0c21718a0441f273e737c38aae2d769f22aab468ef82014c6419a8f9c717b40064c7badcdfb3dd873eddb0ffa29b540d3f27b7612e983ff841116a0c552bfa4db4a8225af7829779440f6224d1a5dc00cfd0ad533d8d10d4cc4e2d7db62f38eabd239a184c68f87072cde722f6999ce50b1b56b411c8068ff10ddbfa43fc64b96862f686ab437e6ca9e6dccce5cf19756b9905d553acc93a6b4693092f1ce1ac174543459a7caf0e8973495168f30e8e1564cd2072dbe250c09c8834e4dea3940c38a63db92334c126946bd648
|
||||||
|
g: b52366675b30cbc99d71aa6b47f774d84c1913ac563f5b5bbaa1e8eb604fe8b4626a128e90b2e1f47e3b0c6bdfa8ba1a49411c3fe9376101a70696d913487886efeae71b8f0bda37e9740089bc80ef8e77bfb3b9579abe7cce8463eb45cb2b7797a3c8454cc7fb45034e3dbd05a30af54ebb4ba5392eaf7f51ce1f6341b16890fc153a6b0d365dc1f931b5bdcf872b0b1b3223e2a2d8791ee84bef27b4032ede9f3ca89e62fe56d2676ef6a52cd518bd57b3084cafa629577c9bf3efef9f68d770a617c452f72d551cd1e723687b5e9d8e41e3630a6660d507545b82226c3210a6aec46b94bf14286bf078309f13340ba59bde46f6ee3254ac44a199416a12f4a8187524446643f9cf69a8e882d7ab77476b6cb137b653e5cf4f93b33ebf7bd516b87f7d39266d0088758c94d7eda81c9075dfdb8ce7a9bdc6bde60df2939a12fc1a455fac1893098133b209783c6fd1396c8bb2110e23ad7e3c24c42290136978493231de9c552d5b9ee9e53b286765f7240e2b2c16ade943af26f63598ef6c
|
||||||
|
h: e0
|
||||||
|
m: cdb6087be618f5cb6816b019752a6c9b1b2a34088844fa94c17ba5e12c87b5e01298e3a91871a207efce74e468e4d6968671a68d16538b9cfd13c150869fa128750a66e4d9adde677be2da3f1886afc15cdff6fca2494a112b1bda966e1c0d71955652c87813ae4314ff6af24a1d5eb4c5faa449e6dd4aeea7a4524017a7d42583891658256f15d29d058fcfb89a501f661c4eb4eb7cee8aae4cae8eadbe3a3ba24f117bfe377dfa1e2957a61e4d81
|
||||||
|
p: f4b0f3e4b4103c527c690c480004166ddf1bd21c6c8a76af29735525f8f79bd009e8a2116e38352964e440e2a4974a7f84a235d21c263d93766362387ba62f791a6fe230ab31668294f7b3f586196f2dcae2b7d45384cd15651525a27e6d4ff9634f7312a4feb0b3ee70febb01d7a36c676940ab0b6ffe5d8082bdc8ec5c0515e2085233808b834b3817ef5fbfcb95efd8c8f2c9db995f02c94c12a478f0976a8fed28a04f62f867ca5862a43392f9ccf143c3423503edd3f0170b1b2e3533a0cad8efbfd67026e8f53a2c16c6d838fb9c0a5bf182ce06304a1e97607f8d2fb52e02385389a24c9919d6d839f046127bc9b848715396f2d1d2c16592a9437d37ef39bd7d2cc02d5c141605fb187f51dc2c27546aa026334d82158b6c4683453dfea194cf41d909d1236c00b7d06be78827150d4a16602b4a5e47f43d83911e4fc52aefe080b0ec30ffad2b3e61fb25a7621dd3115be40c58c6ed5fb51ee55b14f7a14fa6124097c3f0b01dda122f8e6926cbf56d7aea8f634983fcb0325c5dfb
|
||||||
|
q: dc7dfe844fef142c9ba751bdcef77a0c0d406cfac2333d94ea57cd4d4f74c9b7
|
||||||
|
r: aa4bd24ce34f71d6bfe8c5962c418e99d6f001317c02af89d5eb85e150cc3efb
|
||||||
|
s: 6bdddfce0fb4b45820678f9fc96f671059771aceec106a4a4c040d6796dec18a
|
||||||
|
x: ad5beaea9d375ac3b2f051e4654eace6e69c274c30ef1e7703be7c24bf2637bd
|
||||||
|
y: 87e156b6ec44d4b2734e4d7cbaa421cc43bc30d475726ab3f2ac57ce87c7ff3e23b1a19eb3224ade9793bce23de15a4c5c6e7dd21115b9026bcf203438c8ac266137f92b758256f80c6f6f90a30fa8ede207c28f7a7d7206605ede85e3fb3ddc940af10360d2f12f6f134450afcddda5364f20fde312594a594c7e408e5f9497692063b75f29b4685911fa7b2e6dcf716c8c4db8702dd29589654b8751a2183cb7a8f59a079b725d10771d185a9888ef7f87ef8711e02f19cd268922169fdbccc3a35e5f84b8780e829ed1524a8102d90864f62c986552aa49af07fbfd5c003bb6bb27ad5f6af7805cbaa31094c7d8f40933a05b66ab94aa8633f4dcdd3ee6f17927e1d056441986550a909f401d81ba8164b8834aaff1143e6181fe781bed105a236409c9b148d5253dd13f1e944da61fc44b71a2baba102792e5b101fdd09a042e917f4a3d81ae60e6f462ea0f14f892f963443f7eab34ecc7c2214f65f4a4e03565f47a0f23cc7f4e68447db8c21301563ffa884e6b3adcea96a266c29f44
|
||||||
|
g: d713efad64b087c2cc9b5119f6297c70f61dc1dc532241f83000d04b1d6bca0997d762780fbd77313481bb90565a395aa79e09c7229f2b0d07fae2d08ad69565cdaed4f2fd50137ed6b0766388a7c738b4545f8562c342b09ac6644e3ccfc1995a3f5a214fedd5d6d5e631c728e87b65c9afa5ee20fde8c87962e9fdb30e0b3d974d90fb9418041493581fbadebcc17c4791e9fe928f41dbdc34cf0d30c51fc656d5e1c53732a3830822833aa96d0456f007c480fa747f9cb4f821d64b73314c3b47f333ddbc8b438d79979526e0fec835f33803c36c99586b87c63e91342594f785bb4a495e7af0277c09ed200c9346f825ca62db2063cad829ee1c5ce881310dfcfc6caa8ce70a31cc9fc325a7e2048b226a2fbef1c0088490841e89a2fc8e6686a27c60e4cabef23eb23b721c5d618426d4890038d6ab44ef55d935bbdc0376c4444ac0b85b872e64a3a58f55a44390c7cdc7431f5b53152533b25661fe5df3e634128836d5e6a76ee381445ab73b1096ec9a2b2ea3b02adab1a2df4924a
|
||||||
|
h: 100
|
||||||
|
m: 5f86e29f9ef35c4930273fa1b480f5485c8db0229d850549d48f4686df121b9ede620c411f80a355cd942273358321e021c6aa8b11a33d2f62dc506f74f20fc7200ab2ad07236b5dd3d77dac35598fa56169a48287603ad97103b00f8c32f5b455d0350e184a671a7e12d7e97b6de4d589642b9f3df880e0c8c473bc6142b73fe9d4be6c351b0ea024bef4f3dfdb6a6e47b2538f539c46f494846d18670dcddc0f2a9542
|
||||||
|
p: 9953d548a719f5b6e2d5c40c5402de5753dc86d1aee25f17fbab2658dac058434c0bbcc7fc60e6e436cb568f34af2be3526b388a32e07aca68bf24b0f955f4d92df4d9ff2909ffa251cbbfcb3366d1a912a6ee685eb29a35eba9853cbf509491a5c6377f205f69865a60cb9213a64d04b8dd6f399f5a0471d62077bf15a6d2eeb42f0585a97f7682783357f2822bd2c986b340f8974c53a2b1c18f0dcd6e2148acf58c2a636339fd461ce1d1aa85a14367bda77ede7125e846d93108a9fe4213acf6415165041b5cc0ad4994c812b4c74a079da16e021af1b8356712f32c4d3d1dc46fce33c5f568a8a046ab1b028f528636359616fcdedee98b16e7eebb6ba63e82e4402005c8f5340addb4e494f906730cafd22374f1ad0ab2aec4443b02a7493ed850481647b23b86f05428b1004085574252713682822c0406c86927329ca8294b6a8847724e2a3a6d274ead6608c96954ddd2c153747ebea52ed32ede3629aad22b5bb8258a205261c551f4db7e36169d3379c8a22f18fbb549fb006b95
|
||||||
|
q: d307be73371985389474519e828f990b87efa7c47e65162b7cd3f26eab91f471
|
||||||
|
r: 1c2b676da8c57ecdafab5988825e7c274380877bdaab4e5e3d949db999accc75
|
||||||
|
s: 2bf2af337e4701718c7a3531653b918cf4c11a82944e44f216f54a77295a0c25
|
||||||
|
x: 2fef5826efb21cf6fdad5e67a56d2c94086bd6556123133d922a9c2d7769db97
|
||||||
|
y: 799be060154973433a65df1484588e58909db6695768106373d0b7e5b04e191188ed9c199da9732eebe985b092d4f0ca804b305ea19de2b46b2d319e916e96767fb15fe76112d796dcb5aec065ea8ea3c2922b102265672455c1105f338ed4f55593deb39d7150efc230890e74d39f9a55e9138397ee4bee6322aac99d7c29073f16871c988ee0f00fdacaa9e730e72dcb7237e6856b6cfd2d61302481a996443dab8bf3040e29e3ee2e6ba33949289dded2167eb7be933042dbe5a0fa435f14ba703fd8b6b74f9f1e6e3d4fcf56da966c0c48314de97160a901b1f32b00605983e27875ca5d3cfefb5101fd582aa2a05d47f3cfc266eaee5a139842161cf3929d3d884912efc11db2c39f26e1a13bd69ca38d5fb9661cca518f15d3f7b2b710abdf57f9042bb4a8ded22d43d2b66ac9e6156f75f1b442bcfd2b1526bf95e959f8f846a4bc715f6503525406c2a93c287397b59ae820e1abd9771ea50f4e37c8796988a4ef7812232d991257630ccbe59910b4f52c001d6b48dd6836c220d26
|
||||||
|
g: 50e3684ae9af22039f636f7c47a7ec93aedeb3ae2199c0af0ea0ca0e6977595ea720e4b963d52c68506fa094e812af8b0a6f90b6accd87dcbfbdf857af73c21c680b5ebe349a141a78af969c5534afeb929718b09c1c0d25fc9107778620d8fb7fafa89626487aa36474766ad96bfe353c48c2421384dccc9e1b84ae71b18c1426354315e70ee02d6f2ee6ae33a065dde2d00240c626e6d9a53808af2b7a58e90ce6c5259b78a0c40fb53d6074afee5e29be15e70b2e3c33c753e37a2165e0eebd3c8fd3327186cf81eb9be1d19ef67519d12c1b40df715dcc1d822376180bf2c94b890d24bb80bb2302d5fbe1b175c206a785c9c733d01eb6540a43c3acec325a78f87bbab5c471945be6626c3e6c9f18b8c1bcf2aa771b59cc3130d3fe56b6a327597b724054bca2a9ec247b78aedf960df4dda66afff397f278de2c3ac4e9feed3e43a56d75d5f0a243f9cbc11aaa3b34d274f4e2e71d94f3e9c61957a041b1aa7e34a8c3556d8aa28d66cc590ffcf5b9868b8e58de8fbae3fbbd1218bd17
|
||||||
|
h: 200
|
||||||
|
m: 3bf1060d97176213b1879548b06188e007f3b1ce6ff47f262d51cd510d1e3eea893f706f29bb4f2aacf80fe973738a063560cb09528ad4da41c5ba92b72e4752bd983c75b056dfd1e2d5fe8fc712f27dc3fe15dae447be7cf85c82fc674dd087dfefb21c4dacfb33b84650cd74d27d991cd22e48a6f0cb0e521b503d1115eed48500efbc61ea2a8cdb9286a7a9a4f6c4a37d06eced08ba
|
||||||
|
p: 851533792e81443e6e477e8cf99647cbbcb8a028e871484e8eba49ba7bef8fcf248c126c644b4f0616e3f4ec822749623fe419ecad79af4dcbd16bb6bdbe7cb7694a6b991649edc5bca86c2eb2ef6855b8952326c70c3454b4dbc42429bd50ed9654a4901f1c007e4301170d78192f0e479b554f32b1d5708bfacee94a89c1ad8a522d08923393520412d4a1e47cd8679ae44a6bd5f531310b2898bed1d9490d4035ee4d9980b4b6f8bf23fd2bc4e5833844ac36768004cf977c6b8601a91a14fc782966777f72fa11edc8296d4f52ab4106eeaa00826dbcfe60d1c64863d77e7ed2a244d5ea7654d7c630af2ff367e244356afae88cfbc22d16ee54d7053d33b9f274cfea986270be668ae6c97ef19bc41d4f876a768e24fc9b0e45042868be36e950069f3e3044a1d41bbca352c6978e08ebfcfe3ef07bfc11c43feeb7e95b18692c2b1eea026b90be4c82e981ff8bef9737ed860c5476013c673dddd6c400e2cb68e35d7eb136676955f51598a48ca4971fc8cee90332b52d082cf738f65b
|
||||||
|
q: b7992e8e0e3bfbf9507b2d9d0882fb5375f5e0e9e753f669ce6344279fad1cdf
|
||||||
|
r: 18299fa7e2de9ed0b083d53b3d60fde8f53a74aed8a4e9916ef4c731cbfd5aad
|
||||||
|
s: a0f9fa736c98a106bd0014689bcd2685ec0e03d4952cecda22079070c568ee19
|
||||||
|
x: b186219e231b37ea1c7dfc17d3ccb9053eb90493fd7d24e7606a272c093ed48d
|
||||||
|
y: 1ea9ecd257062b07a62f835fe45dcb3713589307acf54c81239e33a8ca016f441047688c37f8839b291cc74ce19760087061153342716c00f61799cd79519ebe1da91c5094d111141a7586e35046f642c890d927eeadcd07c76a426f0c2b2c06946f97b8e7db018985ea13ef1bdde77f806886802c7e0e8b0eee6775c9e9cfe453a183012bc34eba355991c7d439f8b9a881379589ee968979b970264ab4629ff662b64a9d601567714bb27d82c46dda2b46bdf727f7b2f5130e650fb182d2b875bc0c39e726c763e998b5990ebcfa9dc3e60dc7dc1163b029dab939ee6bd89455f96da7fc94cd2c6f9ad187c31d6b6e97f17aaf2ec33b2a5e3d65ba170595d793c36a7d699633f752016d9f2881c73102b05576637dad84053fa750c427d13644883b4b99b412fc811f719aef5cf7766a5baa449c57495cfa3617ff7cb8473ab3e11ff03b5f545b33a831d7636a75512aec1092ed4deb77dd68c60177565ec3888384e97bfc7c65f9e856fee08782a0918c30195f64332f7b6fb5a46f883675
|
||||||
|
g: 38a1c6f59bac2e9ff7339597b2f6fcf6b7bc6272ca27479b99ef8a2a6ea6064105496edb6963287fdcc9a83d8e70ea1504abb2b505cc9ff6dac7d2e5579d72f7c3522d963b4fae9a5faed229530fa4a1f28ccfc0e1e811067ec91e65fff3a3353a831ab9af34965f5fb3979b43ef89c8d7aacba7c3a304dd6ed4b848c749f68749756ad8fd9fa23eb719f37a007ed9338fdd33e2601f184be60e6ba25fb0b58e9f041a25cb83aa5d86b622ff19e3077a9bff79e9c6063f1eea509e590eb60d779a8a00f3e49cb432c7dfc825bd0c93583f0e1c89e7d1acec0aec83003a928d16b4e18184c5ec0224779e543756f20951b73942e7ff89239136b134b08288e1669c36a676889ce4c2bb4a845f1bf44b6d9968ecea57f559c122aaa2892da42592761f65638da0c6c0ea2afbf78a05b8c42e0c6c40bc2150dc33a020d740ac0534ad50713d0829bdc4f7477c98b35773a958cde84d535b07e4108a5f848b25bd6d0caf383eaab4bbb49741a690bd745205bfb3150b5f6475a936df27ba5b0dc606
|
||||||
|
h: 100
|
||||||
|
m: 5bf1847e57ef2e2ca2e7bc0bda2439bb7371c0d638373d1618b0a4659c0fd6f2f525593b4ce336adefb8a8b465d7fa8e836a7142f9e53a4351856c268270a98cf824d1ccfcd1dd89dca9645040ddc989c52db0f6ca6a20e988912df86f28d2e57b53a0920be5bac2db84bf5525df6c2587e4c1ebcecbed27823df5c2635b9ffa635c0f68023df2ddbfac63e73d624c4d21c2a27905bd7248d8da2be324bd364ea8c1c4d3d1b1208dc5895beb52f57b73131ff0bc859d609d3e1cf4e3de15744f669325d18e6671e969d4ea70b7a3fe0b388a7720a722d65257b0c66167e716aeb292000c72925ed7cc801d63e75bd60b
|
||||||
|
p: bf1d45c2f14defaa83dedd0f963146938158c49880721cab543263454826bec0262a7be17dfb7a412728b1991784c228024b178fadd063a5329ab903823c2e22d4ab66ba73fc267288935c7b3c74b3606a97a010d635bb47ce2a5cf1f08fa0abb3dc97e8e0a2ca1adb0f7d4e408a6f70ca262aabd72a2e6ebc72dfc5a40bc42db54e8b3d258be97aff17cbe9255972adce24127e839d736af6b242b87a37d8dad93cfb70121a26126ccd40984b2c41605d9a6ba5d57be75125d553471110526539e59f938d4e9a58e439a8591626e9c189d16188fb28ec404377052a8251b43e0ea7ecf5c3b792fb02bd50739316d9d3b2234e7c4a914bcd59e09bdf7c67705472207019c384f6e6d3c536380beedde79e8e1b965630061975c54ef3a0228485261279d94e41877b00e31c5f85d8b0f5a185a211703b19b0aa45ed2b51f40f0996d9bf9d741291fdf943218200f8e3a74e6063d0d0cbf6185d752b6ce3b50ba6ed9806d3dcffe4cfd73a748b3443939672c8450683091f4da8938e78fd9fa4e7
|
||||||
|
q: bf203a4717e98b95fa06af9d41171e2737fb3b19f0b0be58f9ef46a583572c39
|
||||||
|
r: b8d5d2bde478e7369c6f431037405c6d96afe66c4417ebbe27dbb1074592716b
|
||||||
|
s: 250d8724c86de34350406a5d5fa0b881242a477066cc3884ea5261efc049f27d
|
||||||
|
x: 3a5415ab661fef04c90bf52ef2d46f01a89ccf571d936f3290fce5da0655cb8a
|
||||||
|
y: 3335ebc838937ba51207be4a5cc7ecdf6b7bbf9345ffe9e8dd992caa029635fe21c993b4a6c7f6ca6929f1ef9bef0da067437280071e7d1773e1ea591bc7658a0a88e4bf6ca0ade13ea5f6339ed0eb8f0e8319c0e4c05f40856da8e3c40de2dbff93afa7f50132e3105eddeb33ebef5eba416549b31afe1b4ff9ea9df891790462b94a860371d3c0be772826ca92968c9b7e6f38459d8b101310a9dce49a4ef65e767d0960bee4a9dcece1840260907d0d6e5c9fc6ec2c568a5e0bc13c502dd4847277b022a10ef564464a8f139d4534ef336fab8b7887e88392fa58fb1630e098aba05cd0a909606f14ef93e15279f818054e9090462b6a33ce20383b89c5cc4ba0e5b03d44a3a7df6e99cc555d4731a3ca406ee5b6bb3c4546ba620449bed3a4cd7982962e7cb8f7d552353732206d03e763391afff6421bf285f779d6bb01a6a164c8082503be965657f87a181c1f99d28ec4ced70aca4a89e475e5e9bfb8875a96509aea6ea8bad07cfc709ff37dbb08b5c47888f7604728a9eaaf62ca3d
|
||||||
|
g: cb1363519f3a5d78a8e24b3001c589c0a52b65ef4c52f67c4eca26eb9d82bd439b6772188f60c322709859ccaacc59c2a503813ea8476359fc7d75b619182ec41cccd3405799ae9f3e13e7b286a6725eb48b45c93c204968cf702912baf988e0259564483032de41b0dbfa662f8b295dd53094f075a37ea41e990eabdc64912d063dfc017abe7faa81303736b848fd9dab8f9abe353572c63a9b67327ae04f025ff6712adbb5a5fcb600309b32a35778d3e0a5834e75f5724a4f380f0153fcb7f8537c8f4bcaa559a5f2962878a73c9dc8f0b859765f6c14f72fa8ba33e1ea0c53da64916ffdb609f747559046f5b7bd2b6b46a6609dda375d4225debf2a6dddd9950bd2445b6f30674496543496eb4bf6df3e8c625a8d86f28a9f711e2195bb62be66c63455a85ae17804cbfcddcbedde633ba1d76d2f716d5fec58e897fc4caa7a67288fdd58c37f528cfc3a1590770342d1f01511d77c517b03c73e1ccd6f97332ff17c6cdada5fba582bb1cb38c09843f2bbe6b0211bd6d8fbdba39d1600
|
||||||
|
h: e0
|
||||||
|
m: cad2de0ce06aafa9772686be13718add0f2a7592626d4747942ac1e4794de1ebf19b6ee809fa3256ad420ff27bfec8f9d247949014ce52451844ee43881b877146a8a0527819f2268b4b7840
|
||||||
|
p: dc87f9966f346756a165953f8e5b69354a1e5796912c647bf0ffdede76181689354e053d09cfd49974ce6ed7b3bfe19601ef0b41b1e88656e31555dbfc7c99ce10dd61b7882349e59c0d23843421f0d4719050b933391b83b9506285536c272f289e74bb1d74e4419ce911286f4b62c70916645b8d12ff06e1af1519f4b627906651d90bd40fe6caf56098491b1eb45d1c5195d673416bedcb13b8f632e0f4e00da5147c4b8f48ae06738ef81d6ee63d5456f3e002ad5fc7968e86d0fbf0112ea34cf602d06691ac69a36d3262dddb5363cd6e493f329f4365a28a0dec7227008eb6a3752d8d5669028a9210933aef75125c516841e322f8acdf64796d2e345a641d5fb3a3e950d1bccfbcb5c7e784d125f728a9af3358c310ed05537e66aa3539b48bdfa9f597fb411e1c52e4e19320184b20477ccf95c0407f717dca500c7eeeedfecf29daf1833e85ed0f31b08b2784c8cf3bb87cd2fc3e19afd44d9bc35e9589e5d4c069502656bbd73bd07e76040fc8beac36a7ea36b9be10c5369180c5
|
||||||
|
q: b6ec58b0869cccd8c97973ee2e37010b9021abda0cf8c7cf7f3a60d98ec57627
|
||||||
|
r: 2e68a6610988dce53b6b90a8387221910f700f61039b7a1e7e4ea061bb60ede8
|
||||||
|
s: 1830e0b0665f20e98104f2aea6f8386aeee00c0eaff4b19b6135a4b0ed44bcad
|
||||||
|
x: 329f1b3c755a7cf792cccca87c92a72ce54a96fc4cedb19309e42efadff2ae8f
|
||||||
|
y: 5df5751fb98886f4c34e1bc51e75f5e04337b7cb0d7d4ba3d3a0abad5b9b205977955b0c7515024257ea833815a0afe6c2d01777b550444d3c54ff83d41cb889fd7a148500a29ddf874f4fef747da9ee1c84f2213643a200f81dcc57de3ed9697043261d9cf6ad01154dac9fc9c932c177cc810fa53564f3a157534baa5bd5ce343dcdfc53495826784c8a867feaa95f6c43dda4f8231f9c0c8c232f4966078d6cc65302f84cf85d9f99aa00158ce9fa789d8957b2e4e8cdd174b5310dfb3f560982f398b363d04c885c2a7ca8b80e8e974073217614d1b3fcc247cb78c55081c23067f55d457b85e6b5fe0de3c4f4e7a463022014a002cf517d09671aafef8dca7e3c16b74527b009bb9977be172e85994a3e7eb87a745c82127293ff9f9ee5c9bec5a38f0b3af5e8dcab229e3aeb10f88edee402b7a8fa8f2bed1b57a74d65292d70849a7228ba39affe2708084d432494b05ebbecd0c18599dec6ae1866bde89c59eff898e8c76894b1aced83e323c4926c9ffcfc1e57679da776c1d2bcde
|
||||||
|
g: 2654c54957d5f231ea51f06c3038414d27208d03178238c4113b92a2f28d0e74a82c4389d2fb4f5f15986a24a71f4fbadeb1158c244c7ecc7f68f252616dc209de7a459703c1cd085e99d48f0b9281d2bea916cc153acf6ef383426b0dc590e289046bcc74e8de8a7d9c050dfcad021ccfb9e00725027ad0c7ba202ac82aa36ab9f1be757aa843e5cf012c8e0fc143be56f0afc1ac109763a175fb9c4253879fd40ce26686dcdfe9c623bba02c4f7f4688cf3b82bfabbff2f9b3b8c4bc142d143a5c8cf634f55015c5c7a87a135c8c0c146c84c8ee721a2e4ade5fb84c935ace7be84dddfa744a6ad9412508325c7f965cd8c61fa48c42e29aff127f3e9cb3ddda3617bfc8f0433aa1cdc67df7b73d0d2154a1915e6eb177446678469e3afeb76b90c0fdbfeff7a1ae9c0f5f37f89d053cc394599f48d39ccda33d424776ad9f97e8369669f3396f0cebc496bbd563925d5838292ac5f1a7a4f2d943800c2ec44cf34139d4779dea375e90479aaab0934b574d5f0bfaa369cd47bda3b39b5e43
|
||||||
|
h: 200
|
||||||
|
m: c13052f7a9b02c725b91f804f703b7b7cd91265fa160b8a6a8d4b96b48d3c973c6f1781738bbc72734436327f08d34b04c523aa4d3daec93235ef68ca742
|
||||||
|
p: d64274f0b853957c3c4f76a4e228fcb99f3ba3bdb3b686f0323aaed4f6635319338feed69697c2c6bba0c853a2fbbe648bafd5e3f0f2fdf12d884b7d648d9c2ccb4d030ad3c9dd8388970bbfd832ffda49688c1f146c32c62a1c1f17ff24f5ff4d0eb553212163da141db6d9cf4e006875959b32c09d9f9111cf6782800fd47878f894fc62244bdaeea6dc27d15226554bd100e115a953c511455f5025937c16c9cc32c5a0038d1c250391e09613669a0e8ec94b6539cc6fd2e94c8c78cc5600e5a07f69012811f971943e84016ad5ece193b9d536de197f40fbfc1547328d59163479231015e8c4c4fa7748e9863d76825a0d26d85fdfc006d3134958da16f93dbc5fd01767abd812422039d3d4dbb0e2d7dba0de764b4a6b7345fe03d7c88d0def649532e7465339ed876dd6a06b4657f308f687237a3d102fa415cb2c3da3d3f545374ffc2db2aaa735a4bc2d377d21de36ea5583348a51c8691249ef2418b9e7bdcf765afce97f420d8156306df909d4783aaec74337e5102b261eddc69f
|
||||||
|
q: 85866b52ca7abb554cca8e2bd1c7a576360c741619c1c5828543af1854bb091b
|
||||||
|
r: 17681cfc288a9af204819850a801bdccdca7851c81f15ebd5e2fe8dda998ba26
|
||||||
|
s: 721971a5d0a5df0de7fc7bfa43a876ab9615472ea9d25a24da23ac3e7442b26a
|
||||||
|
x: 76313df7999a1daf6addcf77cb5035d85020b88c8b93d144c045d52f9d1723ab
|
||||||
|
y: c88d58b26f6f5d15d65b8e88e57b52bbb3f4605acd317dccddf0126d07da1728d8db9158ad6414bf05a21e431b5813e71a6136892ea51c31826c08127d0f03005420601ccf8bcf589eb57a4269b3c4c4b02f2b0c0c6c32bcf009138186045b7e4914c1b2e22d2444a2a0e13fcd6d83200ce27357c458082afdd42a969c5fa241da332252203b239f4be10fbc9bb71a2852717b88de58b52b8c3ad45c7095f258673a07438d320d5296574b76dadf014fed7122b32cc2f2cf9de43851f69da26411feb8d1df3c08ffc22a57d0096c712c59c34ecc5b6d6193d4e10fa14f8fffeba770c2528a2927fb5cf14a8ddecb4bf06084d07a08f67c474641748a33303edb7b6e58426d0cb2f1128b18cf62a5e4de47551034cb9fdee1eb6f43a82f47e2544acc0e7a1f4e33b3c87735bd135d04886f9d28ee1da564ea82e41e664b26da5d1099d2437a122c97e2e5f5d587f2934cdd1049cb0afe713d9c11cbca9dd4359a1f2dc45a8afc6587ba660d33a76655f283d9903cf96318ca2281b181a0410282
|
||||||
|
g: 54752997542fea6994ef20f0e6f4fa5480c9870da25b94a8503de5eb76f80a98c0273d626d92486a1337c2dae36678113cbcc243214a3820c8e89c98e3b2449b5c37947dd250967f0bb0c64c4501fb2668c3be02c2f1ab82689cf0ea023956d2fe2c38e99ab58ecd89dfac66cb92c7f30224bd86e42e1c9ea2c0ea79c5f7950225d802e70e62ea01e568a3f556bf8747dce52c762424b2b6aae25f89bc4c907a8534daca7f8858a8645a5319d22e7f6eec116b93c14ca8bc84d8effc25b3cba545249639ef1f53f10de54c9c91b51083b9f87fa6db438f17e846ee0ca140a3c083bf75f002711b1add956b5017131607d2df847b5ed0430038f32887206796fc8bb8428dfacf462644153d76215935f50010255471c771edd5b27e1db1e30a8212d7836061496df4603b54396da056b74173dad52edba35d8073d1f817b042e39f1fd1bdedb7beadd5cae6c115a3df14b780b15a6a840510f197a482486840ea097238c366382b08b5152678c6d4c853710e90895290e4a0641fd28eb7a91902
|
||||||
|
h: e0
|
||||||
|
m: 45f8963daab81ee0dbb33fd39d5c78531aca9254ad306e604df679159616a7b398d316d859b0edef37a440618217636e782cc9b6982f777cff0c1b9ee9c8886b6615fc1feb6e75b328eda66da5c9918889ad2fb1955da0ed1fbb724d8ee072782bcf1dc265c6eff7099eacd6aaf484b87e7439d78e6550eaec0c53fe69
|
||||||
|
p: 9be72f23b783501416b43f3261e247a91f35c6a29c2f7f06128235541888b955d6f0a85215e4af29f572863b9e0b6121a16f43c8a7e8993067c2ec6128c4cb05ddd271a15445e1a35ccddbb33feccd6b36699866681178a72174b918b85551dccdd708056d2d9494fecb401dd97dbe1b5785578902206487c931706475c27891938593a47b06a1b9ed930437ca26a6255be1a0e69df4390df1803f74049bb544a13756598083674db369f4c1c142f928382aaeb0e22687e79564bdec32db27ad33eaa18e93fb3c2ad27fcd9e191c305584406a985f068ce70c7137a10d2ceb644def0185e37d0357ab3b72af631c67d4695bae8e771a0e83833c32abfaad390218163e3a62e42a1180ddf57a43cef697bf7b53880de1f476337b836e4e1427e33985ad9e75748ffa67d9de615c258bf3bd48249ca57fb3a09df28a3ea087dbdc0d098661fd7d933007cb84618f1d42d4e3fe7b13c6498c882d4d24955ed68eca8dc90b785b3b2de4b217462442aec4a5551b1fcdc4c05f2410371f40206ce4b9
|
||||||
|
q: c61d00ea045811550ac15b93b7a4d917fee2e7940b2aa6eaae9113cbde6b7179
|
||||||
|
r: 4437040a80c38c48e0968937ad630a430c0b548008129012a03fce469cbf79c3
|
||||||
|
s: 1496011167df962f46f1030234387793f7380c4490ebc05004d8732536beb62e
|
||||||
|
x: f00d7ea6d38ab75ff0abae8ab5344d17283932981a6e840a21f152b2f9e4228
|
||||||
|
y: 2ff8c0a5fc1bf27e011d01b6710e03dfd86e5459782786db6c22b8862f12d600eae05b09f7294a27e10672897483649d0066fe0734df883153122e0b07b94162f6585f803d9ddc9c4911012e917d14d221259ca3ba10a71214a0b43f5bac72f7230de5e1e2dee30f52a3a6bf1359c6dc9d3747b7d5256479d5688435ca15ed4cacd07b886b9181604d00be4d7e5d60bc03d3cf16369beb611cb1bde5f75a06eadb3cbe56313e0bb56c829cdf1d1e7b9075cbcfd0ff49df4e3ff7345f8b21535823aa3cf639864a8fbbfa06571e56548ae9a2f3543d2e6a49c25accc8021f5d86903744681c70c859d749462f7d49f2b689fb8ee7b17e6c6dc2c765989d6b86489fbec179cf9d1a88f8f1b4a4078fa8576776cdf7eb77febcbe647e10e475eb18b65b310bc1bc0bd787134e21d1fd08549d47df7533e43f239f3f8337610703168b589a09e895c2b4c1c6122708469cdaff8e2fb094a7ed0283f9dc9245c0e178397238c457b00cb60bb59a313726d6c5f002ad4e110d55d20ab08ce0dc558130
|
||||||
|
g: f88b439c1d5a24d56b7da4dc0cd891d5f585a4eba8c04c9c21647feffb099cc4ae8c592aa07bcfaca724440b638696be6da9c63dea938bc57d217cb5601e2902d7058e3f92f228253cfe612abc2657bf78803b22bd7fe5247b2a7fc6fd63f30044794043fc7f09a4880f8b033234a482434ad118f307da0da05d10b7d09c76d80a7180891013b3ce94880ca0aef7dfb89e7ec7c38f5665bdf7a103aa5ea95d04a7ca851aa6c1bcc6d2d5c818ec43b7f1ea1ff3baae84f9253728705ce0b41e2b6490665f0d1718019a323a36fa647b0f60e54e292d457cfe3e53bbd09587adf566fcc602256023d7c4710c8ccd1076a7bfaf052b48774b3a447d3db1a3eabb3911d045202305c1c22b8a7180969c3b6a25bed606b05e010216243999a3550356e3964106be2d140a11616a3b0e93a030e65e38631def3d731df97d6c82744bd70e28d2790662ab8bd6066ba71cdf06375cbf24db30672c646f2404de8f83a6bac9bfda637d20127d690fdda530f843dc5fbc340a52a9e583381cc3733e1b5d8
|
||||||
|
h: e0
|
||||||
|
m: d8e89814a1c2bad79aff1dcb84cb4f47bfdb17a3f51e450aa6af09ec3cfbbf6c83a81c31b710c20cac01bd724a192492754b1d0527db6441c6b63f6ca174311a3b38a9c91af0a3210a85a15e6bd1f3bed8918efb4646f607dff24a02648aa8fc4d31075ffe0e290275c6b48338d33c55f99f5db6ce411721c7c555c3f05929426a
|
||||||
|
p: 9de469e959e408c0ed9e6a48b8966f8926415df7e6ece9c1ddf8dc5347c42f6aced941c4093db833a5192dd093ba5da0d2c3ecc9e6b86c4e8ee0512132277b82365e3c8648abeeaa4b0d833640b5c8639f41786cd237b5a67a43a6c4edee22527c0f35a84ce742fd48bb7028af4d638b0792de8ff89f41a5bedf02d05e5d604415387d48d26892e6fd64c760353e567ac899fbc70c4fc38006a253459ad1cb01f35fc4ed03201a66f24dd3da3a08eb68f69a320ae9f2a58a502cb2f27ced83e4fed0b820adcf1078055d344a9047c4dcf87b1cb6faf5b236db59b522aa954c1bcb5952f41f2393c898e72ceaf7745715b620a332cd0958cd6e5cb6853eebdf21a8957a69cb9bd90ed2fef1a4e14e23b074d20359b31faf2bf4c0b11aea73124ac73eef14901cea349452742f9fb6b9f5538c72d2c7c91908bfc50afd230630a87a76c392246fae232d664648af44565de85fede34fca9b20d50584ae6195b24e8ef554722cb28e782e6fd5d9dea5f3e072454a636099aaddd021a02ef6ad864b
|
||||||
|
q: bd64cb7286fb3ab2973b6d62271ae59a9f800784509cc6eeffabb9b5f4d5324b
|
||||||
|
r: b64e0bb2174fbec119f7fbf72cb4ef5a8c25c420e153fa3d299bb7886ab308c0
|
||||||
|
s: 3489553457d35b244afe5eb151ee27af3de2d3a665d608bb787a105370ef43d
|
||||||
|
x: 8073a3ae49cb8c9ed31c9e6e50ebd86d88ef9f3e91cdf3adb55a01d5cc6731b3
|
||||||
|
y: 70ad82a27171a57eb752fc53b4913e12dbd19d4c0dcc31ccf24b907e65c5f9515e89d8633396166cb44e83c6b4a94ef6a46bb7e4fe49a6c665947a7063c466c697ad598dea75f9ebe92136becc579c84ffce88a1c826574a987850352199f6b337964709ad5373870e158122b7ec919e84388ede9161a5ade3175161849300033c13880d6179a39040a44f6d3c25b0be4ce7c679c3c4cf4ab1b13444cb0ef2ed74fa427b7a0fc0f284180be14ddff22d0acef1cb480818f74cb398be50757ac8582ce70b71309fa355bd6d905c12c2a0a595886e334701d159dc6830d37689c4925a9bbc8d9f5404dc3b4d50919d2c3cee44598a261a9c71fcb8f866749230b381fe781af56412ba6173db3264adf1cd799e2e2bcef84a32f53786a81b099d37b7598564960f81b344cb9eac67794a643b6727b4c5b756fb14d306d8717d03e3f853dfb6146b611bb76252eeee1c31f7d305388077d85e23476f0fe221a52d26f861ed31ffce03fc4c1a4dd08e682cd7284c4e3c53161b1608c824ad47683056
|
||||||
6006
testdata/ecc/add/P192.test
vendored
Normal file
6006
testdata/ecc/add/P192.test
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6006
testdata/ecc/add/P224.test
vendored
Normal file
6006
testdata/ecc/add/P224.test
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6006
testdata/ecc/add/P256.test
vendored
Normal file
6006
testdata/ecc/add/P256.test
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user