mirror of
https://github.com/RustCrypto/hashes.git
synced 2026-01-24 20:08:40 +00:00
Added GOST94
This commit is contained in:
@@ -16,6 +16,7 @@ as the Rust compiler.
|
||||
|
||||
## Supported algorithms
|
||||
* [BLAKE2](https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE2)
|
||||
* [GOST94](https://en.wikipedia.org/wiki/GOST_(hash_function)) (GOST R 34.11-94)
|
||||
* [MD4](https://en.wikipedia.org/wiki/MD4)
|
||||
* [MD5](https://en.wikipedia.org/wiki/MD5)
|
||||
* [SHA-1](https://en.wikipedia.org/wiki/SHA-1)
|
||||
|
||||
18
gost94/Cargo.toml
Normal file
18
gost94/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "gost94"
|
||||
version = "0.1.0"
|
||||
authors = ["The Rust-Crypto Project Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "GOST R 34.11-94 hash function"
|
||||
documentation = "https://docs.rs/gost94"
|
||||
repository = "https://github.com/RustCrypto/hashes"
|
||||
keywords = ["crypto", "gost94", "gost", "hash", "digest"]
|
||||
|
||||
[dependencies]
|
||||
digest-buffer = "0.1"
|
||||
byte-tools = "0.1"
|
||||
generic-array = "0.5"
|
||||
digest = "0.3"
|
||||
|
||||
[dev-dependencies]
|
||||
crypto-tests = "0.2"
|
||||
201
gost94/LICENSE-APACHE
Normal file
201
gost94/LICENSE-APACHE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
25
gost94/LICENSE-MIT
Normal file
25
gost94/LICENSE-MIT
Normal file
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2016 Artyom Pavlov
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
7
gost94/benches/lib.rs
Normal file
7
gost94/benches/lib.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
#![no_std]
|
||||
#![feature(test)]
|
||||
#[macro_use]
|
||||
extern crate crypto_tests;
|
||||
extern crate gost94;
|
||||
|
||||
bench_digest!(gost94::Gost94Test);
|
||||
49
gost94/examples/gost94_cryptopro_sum.rs
Normal file
49
gost94/examples/gost94_cryptopro_sum.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
extern crate gost94;
|
||||
|
||||
use gost94::{Gost94CryptoPro, Digest};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::{self, Read};
|
||||
|
||||
const BUFFER_SIZE: usize = 1024;
|
||||
|
||||
/// Print digest result as hex string and name pair
|
||||
fn print_result(sum: &[u8], name: &str) {
|
||||
for byte in sum {
|
||||
print!("{:02x}", byte);
|
||||
}
|
||||
println!("\t{}", name);
|
||||
}
|
||||
|
||||
/// Compute digest value for given `Reader` and print it
|
||||
/// On any error simply return without doing anything
|
||||
fn process<D: Digest + Default, R: Read>(reader: &mut R, name: &str) {
|
||||
let mut sh = D::default();
|
||||
let mut buffer = [0u8; BUFFER_SIZE];
|
||||
loop {
|
||||
let n = match reader.read(&mut buffer) {
|
||||
Ok(n) => n,
|
||||
Err(_) => return,
|
||||
};
|
||||
sh.input(&buffer[..n]);
|
||||
if n == 0 || n < BUFFER_SIZE {
|
||||
break;
|
||||
}
|
||||
}
|
||||
print_result(&sh.result(), name);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = env::args();
|
||||
// Process files listed in command line arguments one by one
|
||||
// If no files provided process input from stdin
|
||||
if args.len() > 1 {
|
||||
for path in args.skip(1) {
|
||||
if let Ok(mut file) = fs::File::open(&path) {
|
||||
process::<Gost94CryptoPro, _>(&mut file, &path);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
process::<Gost94CryptoPro, _>(&mut io::stdin(), "-");
|
||||
}
|
||||
}
|
||||
49
gost94/examples/gost94_test_sum.rs
Normal file
49
gost94/examples/gost94_test_sum.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
extern crate gost94;
|
||||
|
||||
use gost94::{Gost94Test, Digest};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::{self, Read};
|
||||
|
||||
const BUFFER_SIZE: usize = 1024;
|
||||
|
||||
/// Print digest result as hex string and name pair
|
||||
fn print_result(sum: &[u8], name: &str) {
|
||||
for byte in sum {
|
||||
print!("{:02x}", byte);
|
||||
}
|
||||
println!("\t{}", name);
|
||||
}
|
||||
|
||||
/// Compute digest value for given `Reader` and print it
|
||||
/// On any error simply return without doing anything
|
||||
fn process<D: Digest + Default, R: Read>(reader: &mut R, name: &str) {
|
||||
let mut sh = D::default();
|
||||
let mut buffer = [0u8; BUFFER_SIZE];
|
||||
loop {
|
||||
let n = match reader.read(&mut buffer) {
|
||||
Ok(n) => n,
|
||||
Err(_) => return,
|
||||
};
|
||||
sh.input(&buffer[..n]);
|
||||
if n == 0 || n < BUFFER_SIZE {
|
||||
break;
|
||||
}
|
||||
}
|
||||
print_result(&sh.result(), name);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = env::args();
|
||||
// Process files listed in command line arguments one by one
|
||||
// If no files provided process input from stdin
|
||||
if args.len() > 1 {
|
||||
for path in args.skip(1) {
|
||||
if let Ok(mut file) = fs::File::open(&path) {
|
||||
process::<Gost94Test, _>(&mut file, &path);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
process::<Gost94Test, _>(&mut io::stdin(), "-");
|
||||
}
|
||||
}
|
||||
44
gost94/src/cryptopro.rs
Normal file
44
gost94/src/cryptopro.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
use gost94::{Gost94, SBox, BLOCK_SIZE};
|
||||
use generic_array::typenum::U32;
|
||||
use digest::Digest;
|
||||
use generic_array::GenericArray;
|
||||
|
||||
const S_CRYPTO_PRO: SBox = [
|
||||
[10, 4, 5, 6, 8, 1, 3, 7, 13, 12, 14, 0, 9, 2, 11, 15],
|
||||
[5, 15, 4, 0, 2, 13, 11, 9, 1, 7, 6, 3, 12, 14, 10, 8],
|
||||
[7, 15, 12, 14, 9, 4, 1, 0, 3, 11, 5, 2, 6, 10, 8, 13],
|
||||
[4, 10, 7, 12, 0, 15, 2, 8, 14, 1, 6, 5, 13, 11, 9, 3],
|
||||
[7, 6, 4, 11, 9, 12, 2, 10, 1, 8, 0, 14, 15, 13, 3, 5],
|
||||
[7, 6, 2, 4, 13, 9, 15, 0, 10, 1, 5, 11, 8, 14, 12, 3],
|
||||
[13, 14, 4, 1, 7, 0, 5, 10, 3, 12, 8, 15, 6, 2, 9, 11],
|
||||
[1, 3, 10, 9, 5, 11, 4, 15, 8, 6, 7, 14, 13, 0, 2, 12],
|
||||
];
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Gost94CryptoPro {
|
||||
sh: Gost94
|
||||
}
|
||||
|
||||
impl Gost94CryptoPro {
|
||||
pub fn new() -> Self {
|
||||
Self{sh: Gost94::new(S_CRYPTO_PRO, [0; BLOCK_SIZE])}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Gost94CryptoPro {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Digest for Gost94CryptoPro {
|
||||
type OutputSize = U32;
|
||||
type BlockSize = U32;
|
||||
|
||||
fn input(&mut self, input: &[u8]) {
|
||||
self.sh.input(input);
|
||||
}
|
||||
|
||||
fn result(self) -> GenericArray<u8, Self::OutputSize> {
|
||||
self.sh.result()
|
||||
}
|
||||
}
|
||||
231
gost94/src/gost94.rs
Normal file
231
gost94/src/gost94.rs
Normal file
@@ -0,0 +1,231 @@
|
||||
use digest::Digest;
|
||||
use digest_buffer::DigestBuffer;
|
||||
use generic_array::GenericArray;
|
||||
use generic_array::typenum::U32;
|
||||
use byte_tools::{read_u32v_le, read_u32_le, write_u32v_le, copy_memory};
|
||||
|
||||
|
||||
pub const BLOCK_SIZE: usize = 32;
|
||||
|
||||
const C:Block = [0, 255, 0, 255, 0, 255, 0, 255, 255, 0, 255, 0, 255, 0,
|
||||
255, 0, 0, 255, 255, 0, 255, 0, 0, 255, 255, 0, 0, 0, 255, 255, 0, 255];
|
||||
|
||||
pub type SBox = [[u8; 16]; 8];
|
||||
type Block = [u8; 32];
|
||||
|
||||
|
||||
fn sbox(a: u32, s: &SBox) -> u32 {
|
||||
let mut v = 0;
|
||||
for i in 0..8 {
|
||||
let shft = 4*i;
|
||||
let k = ((a & (0b1111u32 << shft) ) >> shft) as usize;
|
||||
v += (s[i][k] as u32) << shft;
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
fn g(a: u32, k: u32, s: &SBox) -> u32 {
|
||||
sbox(a.wrapping_add(k), s).rotate_left(11)
|
||||
}
|
||||
|
||||
fn encrypt(msg: &mut [u8], key: Block, sbox: &SBox) {
|
||||
let mut k = [0u32; 8];
|
||||
let mut a = read_u32_le(&msg[0..4]);
|
||||
let mut b = read_u32_le(&msg[4..8]);
|
||||
read_u32v_le(&mut k, &key);
|
||||
|
||||
for _ in 0..3 {
|
||||
for i in 0..8 {
|
||||
let t = b ^ g(a, k[i], sbox);
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
}
|
||||
for i in (0..8).rev() {
|
||||
let t = b ^ g(a, k[i], sbox);
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
write_u32v_le(msg, &[b, a]);
|
||||
}
|
||||
|
||||
fn x(a: &Block, b: &Block) -> Block {
|
||||
let mut out = [0; 32];
|
||||
for i in 0..32 {
|
||||
out[i] = a[i]^b[i];
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn x_mut(a: &mut Block, b: &Block) {
|
||||
for i in 0..32 {
|
||||
a[i] ^= b[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn a(x: Block) -> Block {
|
||||
let mut out = [0; 32];
|
||||
for i in 0..24 {
|
||||
out[i] = x[i+8];
|
||||
}
|
||||
for i in 0..8 {
|
||||
out[24+i] = x[i]^x[i+8];
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn p(y: Block) -> Block {
|
||||
let mut out = [0; 32];
|
||||
for i in 0..4 {
|
||||
for k in 0..8 {
|
||||
out[i+4*k] = y[8*i+k];
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
|
||||
fn psi(block: &mut Block) {
|
||||
let mut out = [0u8; 32];
|
||||
copy_memory(&block[2..], &mut out[..30]);
|
||||
copy_memory(&block[..2], &mut out[30..]);
|
||||
|
||||
for i in [1usize, 2, 3, 12, 15].iter() {
|
||||
out[30] ^= block[2*i];
|
||||
out[31] ^= block[2*i+1];
|
||||
}
|
||||
copy_memory(&out, block);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Gost94State {
|
||||
s: SBox,
|
||||
h: Block,
|
||||
n: Block,
|
||||
sigma: Block,
|
||||
}
|
||||
|
||||
impl Gost94State {
|
||||
fn shuffle(&mut self, m: &Block, s: &Block) {
|
||||
let mut res = [0u8; 32];
|
||||
copy_memory(s, &mut res);
|
||||
for _ in 0..12 {
|
||||
psi(&mut res);
|
||||
}
|
||||
x_mut(&mut res, m);
|
||||
psi(&mut res);
|
||||
x_mut(&mut self.h, &res);
|
||||
for _ in 0..61 {
|
||||
psi(&mut self.h);
|
||||
}
|
||||
}
|
||||
|
||||
fn f(&mut self, m: &Block) {
|
||||
let mut s = [0u8; 32];
|
||||
copy_memory(&self.h, &mut s);
|
||||
let k = p(x(&self.h, m));
|
||||
encrypt(&mut s[0..8], k, &self.s);
|
||||
|
||||
let u = a(self.h);
|
||||
let v = a(a(*m));
|
||||
let k = p(x(&u, &v));
|
||||
encrypt(&mut s[8..16], k, &self.s);
|
||||
|
||||
let mut u = a(u);
|
||||
x_mut(&mut u, &C);
|
||||
let v = a(a(v));
|
||||
let k = p(x(&u, &v));
|
||||
encrypt(&mut s[16..24], k, &self.s);
|
||||
|
||||
let u = a(u);
|
||||
let v = a(a(v));
|
||||
let k = p(x(&u, &v));
|
||||
encrypt(&mut s[24..32], k, &self.s);
|
||||
|
||||
self.shuffle(m, &s);
|
||||
}
|
||||
|
||||
fn update_sigma(&mut self, m: &[u8]) {
|
||||
let mut over = 0u16;
|
||||
for (a, b) in self.sigma.iter_mut().zip(m.iter()) {
|
||||
let res = (*a as u16) + (*b as u16) + over;
|
||||
*a = (res & 0xff) as u8;
|
||||
over = res >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
fn update_n(&mut self, m_len: u8) {
|
||||
let res = (self.n[0] as u16) + ((m_len as u16) << 3);
|
||||
self.n[0] = (res & 0xff) as u8;
|
||||
let mut over = res >> 8;
|
||||
|
||||
for a in self.n.iter_mut().skip(1) {
|
||||
let res = (*a as u16) + over;
|
||||
*a = (res & 0xff) as u8;
|
||||
over = res >> 8;
|
||||
if over == 0 { return; }
|
||||
}
|
||||
}
|
||||
|
||||
fn process_block(&mut self, block: &[u8], msg_len: u8) {
|
||||
let mut buf = [0u8; 32];
|
||||
copy_memory(block, &mut buf);
|
||||
self.f(&buf);
|
||||
self.update_n(msg_len);
|
||||
self.update_sigma(block);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Gost94 {
|
||||
buffer: DigestBuffer<U32>,
|
||||
state: Gost94State,
|
||||
}
|
||||
|
||||
impl Gost94 {
|
||||
pub fn new(s: SBox, h: Block) -> Self {
|
||||
Gost94{
|
||||
buffer: Default::default(),
|
||||
state: Gost94State{
|
||||
s: s,
|
||||
h: h,
|
||||
n: [0; BLOCK_SIZE],
|
||||
sigma: [0; BLOCK_SIZE],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Digest for Gost94 {
|
||||
type OutputSize = U32;
|
||||
type BlockSize = U32;
|
||||
|
||||
fn input(&mut self, input: &[u8]) {
|
||||
let self_state = &mut self.state;
|
||||
self.buffer.input(input, |d: &[u8]| {
|
||||
self_state.process_block(d, 32);
|
||||
});
|
||||
}
|
||||
|
||||
fn result(mut self) -> GenericArray<u8, Self::OutputSize> {
|
||||
let self_state = &mut self.state;
|
||||
let buf = self.buffer.current_buffer();
|
||||
|
||||
if buf.len() != 0 {
|
||||
let mut block = [0u8; BLOCK_SIZE];
|
||||
copy_memory(&buf, &mut block[..buf.len()]);
|
||||
self_state.process_block(&block, buf.len() as u8);
|
||||
}
|
||||
|
||||
let n = self_state.n;
|
||||
self_state.f(&n);
|
||||
|
||||
let sigma = self_state.sigma;
|
||||
self_state.f(&sigma);
|
||||
|
||||
let mut out = GenericArray::new();
|
||||
copy_memory(&self_state.h, &mut out);
|
||||
out
|
||||
}
|
||||
}
|
||||
17
gost94/src/lib.rs
Normal file
17
gost94/src/lib.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
#![no_std]
|
||||
extern crate byte_tools;
|
||||
extern crate digest_buffer;
|
||||
extern crate generic_array;
|
||||
extern crate digest;
|
||||
|
||||
mod gost94;
|
||||
mod s2015;
|
||||
mod cryptopro;
|
||||
mod test_param;
|
||||
|
||||
pub use digest::Digest;
|
||||
|
||||
pub use gost94::Gost94;
|
||||
pub use s2015::Gost94s2015;
|
||||
pub use cryptopro::Gost94CryptoPro;
|
||||
pub use test_param::Gost94Test;
|
||||
45
gost94/src/s2015.rs
Normal file
45
gost94/src/s2015.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use gost94::{Gost94, SBox, BLOCK_SIZE};
|
||||
use generic_array::typenum::U32;
|
||||
use digest::Digest;
|
||||
use generic_array::GenericArray;
|
||||
|
||||
const S2015: SBox = [
|
||||
[12, 4, 6, 2, 10, 5, 11, 9, 14, 8, 13, 7, 0, 3, 15, 1],
|
||||
[6, 8, 2, 3, 9, 10, 5, 12, 1, 14, 4, 7, 11, 13, 0, 15],
|
||||
[11, 3, 5, 8, 2, 15, 10, 13, 14, 1, 7, 4, 12, 9, 6, 0],
|
||||
[12, 8, 2, 1, 13, 4, 15, 6, 7, 0, 10, 5, 3, 14, 9, 11],
|
||||
[7, 15, 5, 10, 8, 1, 6, 13, 0, 9, 3, 14, 11, 4, 2, 12],
|
||||
[5, 13, 15, 6, 9, 2, 12, 10, 11, 7, 8, 1, 4, 3, 14, 0],
|
||||
[8, 14, 2, 5, 6, 9, 1, 12, 15, 4, 11, 0, 13, 10, 3, 7],
|
||||
[1, 7, 14, 13, 0, 5, 8, 3, 4, 15, 10, 6, 9, 12, 11, 2],
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Gost94s2015 {
|
||||
sh: Gost94
|
||||
}
|
||||
|
||||
impl Gost94s2015 {
|
||||
pub fn new() -> Self {
|
||||
Self{sh: Gost94::new(S2015, [0; BLOCK_SIZE])}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Gost94s2015 {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Digest for Gost94s2015 {
|
||||
type OutputSize = U32;
|
||||
type BlockSize = U32;
|
||||
|
||||
fn input(&mut self, input: &[u8]) {
|
||||
self.sh.input(input);
|
||||
}
|
||||
|
||||
fn result(self) -> GenericArray<u8, Self::OutputSize> {
|
||||
self.sh.result()
|
||||
}
|
||||
}
|
||||
45
gost94/src/test_param.rs
Normal file
45
gost94/src/test_param.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use gost94::{Gost94, SBox, BLOCK_SIZE};
|
||||
use generic_array::typenum::U32;
|
||||
use digest::Digest;
|
||||
use generic_array::GenericArray;
|
||||
|
||||
const S_TEST: SBox = [
|
||||
[4,10,9,2,13,8,0,14,6,11,1,12,7,15,5,3],
|
||||
[14,11,4,12,6,13,15,10,2,3,8,1,0,7,5,9],
|
||||
[5,8,1,13,10,3,4,2,14,15,12,7,6,0,9,11],
|
||||
[7,13,10,1,0,8,9,15,14,4,6,12,11,2,5,3],
|
||||
[6,12,7,1,5,15,13,8,4,10,9,14,0,3,11,2],
|
||||
[4,11,10,0,7,2,1,13,3,6,8,5,9,12,15,14],
|
||||
[13,11,4,1,3,15,5,9,0,10,14,7,6,8,2,12],
|
||||
[1,15,13,0,5,7,10,4,9,2,3,14,6,11,8,12],
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Gost94Test {
|
||||
sh: Gost94
|
||||
}
|
||||
|
||||
impl Gost94Test {
|
||||
pub fn new() -> Self {
|
||||
Self{sh: Gost94::new(S_TEST, [0; BLOCK_SIZE])}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Gost94Test {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Digest for Gost94Test {
|
||||
type OutputSize = U32;
|
||||
type BlockSize = U32;
|
||||
|
||||
fn input(&mut self, input: &[u8]) {
|
||||
self.sh.input(input);
|
||||
}
|
||||
|
||||
fn result(self) -> GenericArray<u8, Self::OutputSize> {
|
||||
self.sh.result()
|
||||
}
|
||||
}
|
||||
0
gost94/tests/data/cryptopro/1.input.bin
Normal file
0
gost94/tests/data/cryptopro/1.input.bin
Normal file
1
gost94/tests/data/cryptopro/1.output.bin
Normal file
1
gost94/tests/data/cryptopro/1.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
<EFBFBD>_<Ł„‡<>„űC>¬V›śXJÄ<4A>#LÖVŔ
|
||||
1
gost94/tests/data/cryptopro/2.input.bin
Normal file
1
gost94/tests/data/cryptopro/2.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
a
|
||||
BIN
gost94/tests/data/cryptopro/2.output.bin
Normal file
BIN
gost94/tests/data/cryptopro/2.output.bin
Normal file
Binary file not shown.
1
gost94/tests/data/cryptopro/3.input.bin
Normal file
1
gost94/tests/data/cryptopro/3.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
abc
|
||||
1
gost94/tests/data/cryptopro/3.output.bin
Normal file
1
gost94/tests/data/cryptopro/3.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
╡┘m©в9-vw6∙$щttYМ│C≥~;)├Ы/т,
|
||||
1
gost94/tests/data/cryptopro/4.input.bin
Normal file
1
gost94/tests/data/cryptopro/4.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
message digest
|
||||
1
gost94/tests/data/cryptopro/4.output.bin
Normal file
1
gost94/tests/data/cryptopro/4.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
¼`AÝ*¤ëún˜†sAtþ½´rš©rÖTšÃ›)r
|
||||
1
gost94/tests/data/cryptopro/5.input.bin
Normal file
1
gost94/tests/data/cryptopro/5.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
|
||||
1
gost94/tests/data/cryptopro/5.output.bin
Normal file
1
gost94/tests/data/cryptopro/5.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
JÇaF‘»ô'ú#!kèñ
|
||||
1
gost94/tests/data/cryptopro/6.input.bin
Normal file
1
gost94/tests/data/cryptopro/6.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
The quick brown fox jumps over the lazy dog
|
||||
2
gost94/tests/data/cryptopro/6.output.bin
Normal file
2
gost94/tests/data/cryptopro/6.output.bin
Normal file
@@ -0,0 +1,2 @@
|
||||
<EFBFBD>)J6PŚXoĺ=tgeçvTrxnGpŐe<C590>
|
||||
v
|
||||
1
gost94/tests/data/cryptopro/7.input.bin
Normal file
1
gost94/tests/data/cryptopro/7.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
The quick brown fox jumps over the lazy cog
|
||||
1
gost94/tests/data/cryptopro/7.output.bin
Normal file
1
gost94/tests/data/cryptopro/7.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
╘1$У©,m┐ц╩В"╪UV⌠$\╔∙uAТшвъ╞│7ФР
|
||||
1
gost94/tests/data/cryptopro/8.input.bin
Normal file
1
gost94/tests/data/cryptopro/8.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
This is message, length=32 bytes
|
||||
1
gost94/tests/data/cryptopro/8.output.bin
Normal file
1
gost94/tests/data/cryptopro/8.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
,ïÂ÷·½ÅᎥ§OóWçúÖRÇ_iËç‰>ÞHë
|
||||
1
gost94/tests/data/cryptopro/9.input.bin
Normal file
1
gost94/tests/data/cryptopro/9.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
Suppose the original message has length = 50 bytes
|
||||
1
gost94/tests/data/cryptopro/9.output.bin
Normal file
1
gost94/tests/data/cryptopro/9.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
Ãs\¼ÊÏ‘ZÂ’go!è½N÷S1Ù@^_aÜ10¦P
|
||||
1
gost94/tests/data/cryptopro/one_million_a.output.bin
Normal file
1
gost94/tests/data/cryptopro/one_million_a.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
†“(z¦/”x÷Ë1.À†klNJAèôÿÍ'ÝUO
|
||||
0
gost94/tests/data/test/1.input.bin
Normal file
0
gost94/tests/data/test/1.input.bin
Normal file
1
gost94/tests/data/test/1.output.bin
Normal file
1
gost94/tests/data/test/1.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
Î…ąśÄgR˙ţă\«š{x«´ÂŇ\˙hZô‘,IIŤ
|
||||
1
gost94/tests/data/test/2.input.bin
Normal file
1
gost94/tests/data/test/2.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
a
|
||||
1
gost94/tests/data/test/2.output.bin
Normal file
1
gost94/tests/data/test/2.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
Ô,Sž6|féÈŠ€fI4œ!‡CDÆ¥søIýÎbóÝ
|
||||
1
gost94/tests/data/test/3.input.bin
Normal file
1
gost94/tests/data/test/3.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
abc
|
||||
1
gost94/tests/data/test/3.output.bin
Normal file
1
gost94/tests/data/test/3.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
óCHÄO±²¢wrž"…ëµË^)Éu¼u;pI|¤Õ
|
||||
1
gost94/tests/data/test/4.input.bin
Normal file
1
gost94/tests/data/test/4.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
message digest
|
||||
1
gost94/tests/data/test/4.output.bin
Normal file
1
gost94/tests/data/test/4.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
D4ì±<EFBFBD>,™¶¾Yì=$iX+e'?HÞrÛ/Þ¤ˆšM
|
||||
1
gost94/tests/data/test/5.input.bin
Normal file
1
gost94/tests/data/test/5.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
|
||||
2
gost94/tests/data/test/5.output.bin
Normal file
2
gost94/tests/data/test/5.output.bin
Normal file
@@ -0,0 +1,2 @@
|
||||
S££ν%ο… t'>U%f
|
||||
‡*RΩ&©θώW3¤
|
||||
1
gost94/tests/data/test/6.input.bin
Normal file
1
gost94/tests/data/test/6.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
The quick brown fox jumps over the lazy dog
|
||||
1
gost94/tests/data/test/6.output.bin
Normal file
1
gost94/tests/data/test/6.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
w·úAšÅŠ%ô›Ê}hÉ)e)1^¬§kÑ¡7mB”
|
||||
1
gost94/tests/data/test/7.input.bin
Normal file
1
gost94/tests/data/test/7.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
The quick brown fox jumps over the lazy cog
|
||||
1
gost94/tests/data/test/7.output.bin
Normal file
1
gost94/tests/data/test/7.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD>ڪ<EFBFBD><EFBFBD><0B>1ڵszg<7F>g
|
||||
1
gost94/tests/data/test/8.input.bin
Normal file
1
gost94/tests/data/test/8.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
This is message, length=32 bytes
|
||||
1
gost94/tests/data/test/8.output.bin
Normal file
1
gost94/tests/data/test/8.output.bin
Normal file
@@ -0,0 +1 @@
|
||||
±ÄfÓu¸.ƒ<19>Ÿó%•àG¢Œ¶ø>ÿi¨¦7ÿú
|
||||
1
gost94/tests/data/test/9.input.bin
Normal file
1
gost94/tests/data/test/9.input.bin
Normal file
@@ -0,0 +1 @@
|
||||
Suppose the original message has length = 50 bytes
|
||||
2
gost94/tests/data/test/9.output.bin
Normal file
2
gost94/tests/data/test/9.output.bin
Normal file
@@ -0,0 +1,2 @@
|
||||
GşW¦
|
||||
w
|
||||
BIN
gost94/tests/data/test/one_million_a.output.bin
Normal file
BIN
gost94/tests/data/test/one_million_a.output.bin
Normal file
Binary file not shown.
33
gost94/tests/lib.rs
Normal file
33
gost94/tests/lib.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
#![no_std]
|
||||
#[macro_use]
|
||||
extern crate crypto_tests;
|
||||
extern crate gost94;
|
||||
|
||||
use crypto_tests::hash::{Test, main_test, one_million_a};
|
||||
|
||||
#[test]
|
||||
fn gost94_test_main() {
|
||||
let tests = new_tests!("test/1", "test/2", "test/3", "test/4", "test/5",
|
||||
"test/6", "test/7", "test/8", "test/9");
|
||||
main_test::<gost94::Gost94Test>(&tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gost94_cryptopro_main() {
|
||||
let tests = new_tests!("cryptopro/1", "cryptopro/2", "cryptopro/3",
|
||||
"cryptopro/4", "cryptopro/5", "cryptopro/6",
|
||||
"cryptopro/7", "cryptopro/8", "cryptopro/9");
|
||||
main_test::<gost94::Gost94CryptoPro>(&tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gost94_test_1million_a() {
|
||||
let output = include_bytes!("data/test/one_million_a.output.bin");
|
||||
one_million_a::<gost94::Gost94Test>(output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gost94_cryptopro_1million_a() {
|
||||
let output = include_bytes!("data/cryptopro/one_million_a.output.bin");
|
||||
one_million_a::<gost94::Gost94CryptoPro>(output);
|
||||
}
|
||||
Reference in New Issue
Block a user