2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
250
Task/MD4/C/md4-1.c
Normal file
250
Task/MD4/C/md4-1.c
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
*
|
||||
* Author: George Mossessian
|
||||
*
|
||||
* The MD4 hash algorithm, as described in https://tools.ietf.org/html/rfc1320
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
char *MD4(char *str, int len); //this is the prototype you want to call. Everything else is internal.
|
||||
|
||||
typedef struct string{
|
||||
char *c;
|
||||
int len;
|
||||
char sign;
|
||||
}string;
|
||||
|
||||
static uint32_t *MD4Digest(uint32_t *w, int len);
|
||||
static void setMD4Registers(uint32_t AA, uint32_t BB, uint32_t CC, uint32_t DD);
|
||||
static uint32_t changeEndianness(uint32_t x);
|
||||
static void resetMD4Registers(void);
|
||||
static string stringCat(string first, string second);
|
||||
static string uint32ToString(uint32_t l);
|
||||
static uint32_t stringToUint32(string s);
|
||||
|
||||
static const char *BASE16 = "0123456789abcdef=";
|
||||
|
||||
#define F(X,Y,Z) (((X)&(Y))|((~(X))&(Z)))
|
||||
#define G(X,Y,Z) (((X)&(Y))|((X)&(Z))|((Y)&(Z)))
|
||||
#define H(X,Y,Z) ((X)^(Y)^(Z))
|
||||
|
||||
#define LEFTROTATE(A,N) ((A)<<(N))|((A)>>(32-(N)))
|
||||
|
||||
#define MD4ROUND1(a,b,c,d,x,s) a += F(b,c,d) + x; a = LEFTROTATE(a, s);
|
||||
#define MD4ROUND2(a,b,c,d,x,s) a += G(b,c,d) + x + (uint32_t)0x5A827999; a = LEFTROTATE(a, s);
|
||||
#define MD4ROUND3(a,b,c,d,x,s) a += H(b,c,d) + x + (uint32_t)0x6ED9EBA1; a = LEFTROTATE(a, s);
|
||||
|
||||
static uint32_t A = 0x67452301;
|
||||
static uint32_t B = 0xefcdab89;
|
||||
static uint32_t C = 0x98badcfe;
|
||||
static uint32_t D = 0x10325476;
|
||||
|
||||
string newString(char * c, int t){
|
||||
string r;
|
||||
int i;
|
||||
if(c!=NULL){
|
||||
r.len = (t<=0)?strlen(c):t;
|
||||
r.c=(char *)malloc(sizeof(char)*(r.len+1));
|
||||
for(i=0; i<r.len; i++) r.c[i]=c[i];
|
||||
r.c[r.len]='\0';
|
||||
return r;
|
||||
}
|
||||
r.len=t;
|
||||
r.c=(char *)malloc(sizeof(char)*(r.len+1));
|
||||
memset(r.c,(char)0,sizeof(char)*(t+1));
|
||||
r.sign = 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
string stringCat(string first, string second){
|
||||
string str=newString(NULL, first.len+second.len);
|
||||
int i;
|
||||
|
||||
for(i=0; i<first.len; i++){
|
||||
str.c[i]=first.c[i];
|
||||
}
|
||||
for(i=first.len; i<str.len; i++){
|
||||
str.c[i]=second.c[i-first.len];
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
string base16Encode(string in){
|
||||
string out=newString(NULL, in.len*2);
|
||||
int i,j;
|
||||
|
||||
j=0;
|
||||
for(i=0; i<in.len; i++){
|
||||
out.c[j++]=BASE16[((in.c[i] & 0xF0)>>4)];
|
||||
out.c[j++]=BASE16[(in.c[i] & 0x0F)];
|
||||
}
|
||||
out.c[j]='\0';
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
string uint32ToString(uint32_t l){
|
||||
string s = newString(NULL,4);
|
||||
int i;
|
||||
for(i=0; i<4; i++){
|
||||
s.c[i] = (l >> (8*(3-i))) & 0xFF;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
uint32_t stringToUint32(string s){
|
||||
uint32_t l;
|
||||
int i;
|
||||
l=0;
|
||||
for(i=0; i<4; i++){
|
||||
l = l|(((uint32_t)((unsigned char)s.c[i]))<<(8*(3-i)));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
char *MD4(char *str, int len){
|
||||
string m=newString(str, len);
|
||||
string digest;
|
||||
uint32_t *w;
|
||||
uint32_t *hash;
|
||||
uint64_t mlen=m.len;
|
||||
unsigned char oneBit = 0x80;
|
||||
int i, wlen;
|
||||
|
||||
|
||||
m=stringCat(m, newString((char *)&oneBit,1));
|
||||
|
||||
//append 0 ≤ k < 512 bits '0', such that the resulting message length in bits
|
||||
// is congruent to −64 ≡ 448 (mod 512)4
|
||||
i=((56-m.len)%64);
|
||||
if(i<0) i+=64;
|
||||
m=stringCat(m,newString(NULL, i));
|
||||
|
||||
w = malloc(sizeof(uint32_t)*(m.len/4+2));
|
||||
|
||||
//append length, in bits (hence <<3), least significant word first
|
||||
for(i=0; i<m.len/4; i++){
|
||||
w[i]=stringToUint32(newString(&(m.c[4*i]), 4));
|
||||
}
|
||||
w[i++] = (mlen<<3) & 0xFFFFFFFF;
|
||||
w[i++] = (mlen>>29) & 0xFFFFFFFF;
|
||||
|
||||
wlen=i;
|
||||
|
||||
|
||||
//change endianness, but not for the appended message length, for some reason?
|
||||
for(i=0; i<wlen-2; i++){
|
||||
w[i]=changeEndianness(w[i]);
|
||||
}
|
||||
|
||||
hash = MD4Digest(w,wlen);
|
||||
|
||||
digest=newString(NULL,0);
|
||||
for(i=0; i<4; i++){
|
||||
hash[i]=changeEndianness(hash[i]);
|
||||
digest=stringCat(digest,uint32ToString(hash[i]));
|
||||
}
|
||||
|
||||
return base16Encode(digest).c;
|
||||
}
|
||||
|
||||
uint32_t *MD4Digest(uint32_t *w, int len){
|
||||
//assumes message.len is a multiple of 64 bytes.
|
||||
int i,j;
|
||||
uint32_t X[16];
|
||||
uint32_t *digest = malloc(sizeof(uint32_t)*4);
|
||||
uint32_t AA, BB, CC, DD;
|
||||
|
||||
for(i=0; i<len/16; i++){
|
||||
for(j=0; j<16; j++){
|
||||
X[j]=w[i*16+j];
|
||||
}
|
||||
|
||||
AA=A;
|
||||
BB=B;
|
||||
CC=C;
|
||||
DD=D;
|
||||
|
||||
MD4ROUND1(A,B,C,D,X[0],3);
|
||||
MD4ROUND1(D,A,B,C,X[1],7);
|
||||
MD4ROUND1(C,D,A,B,X[2],11);
|
||||
MD4ROUND1(B,C,D,A,X[3],19);
|
||||
MD4ROUND1(A,B,C,D,X[4],3);
|
||||
MD4ROUND1(D,A,B,C,X[5],7);
|
||||
MD4ROUND1(C,D,A,B,X[6],11);
|
||||
MD4ROUND1(B,C,D,A,X[7],19);
|
||||
MD4ROUND1(A,B,C,D,X[8],3);
|
||||
MD4ROUND1(D,A,B,C,X[9],7);
|
||||
MD4ROUND1(C,D,A,B,X[10],11);
|
||||
MD4ROUND1(B,C,D,A,X[11],19);
|
||||
MD4ROUND1(A,B,C,D,X[12],3);
|
||||
MD4ROUND1(D,A,B,C,X[13],7);
|
||||
MD4ROUND1(C,D,A,B,X[14],11);
|
||||
MD4ROUND1(B,C,D,A,X[15],19);
|
||||
|
||||
MD4ROUND2(A,B,C,D,X[0],3);
|
||||
MD4ROUND2(D,A,B,C,X[4],5);
|
||||
MD4ROUND2(C,D,A,B,X[8],9);
|
||||
MD4ROUND2(B,C,D,A,X[12],13);
|
||||
MD4ROUND2(A,B,C,D,X[1],3);
|
||||
MD4ROUND2(D,A,B,C,X[5],5);
|
||||
MD4ROUND2(C,D,A,B,X[9],9);
|
||||
MD4ROUND2(B,C,D,A,X[13],13);
|
||||
MD4ROUND2(A,B,C,D,X[2],3);
|
||||
MD4ROUND2(D,A,B,C,X[6],5);
|
||||
MD4ROUND2(C,D,A,B,X[10],9);
|
||||
MD4ROUND2(B,C,D,A,X[14],13);
|
||||
MD4ROUND2(A,B,C,D,X[3],3);
|
||||
MD4ROUND2(D,A,B,C,X[7],5);
|
||||
MD4ROUND2(C,D,A,B,X[11],9);
|
||||
MD4ROUND2(B,C,D,A,X[15],13);
|
||||
|
||||
MD4ROUND3(A,B,C,D,X[0],3);
|
||||
MD4ROUND3(D,A,B,C,X[8],9);
|
||||
MD4ROUND3(C,D,A,B,X[4],11);
|
||||
MD4ROUND3(B,C,D,A,X[12],15);
|
||||
MD4ROUND3(A,B,C,D,X[2],3);
|
||||
MD4ROUND3(D,A,B,C,X[10],9);
|
||||
MD4ROUND3(C,D,A,B,X[6],11);
|
||||
MD4ROUND3(B,C,D,A,X[14],15);
|
||||
MD4ROUND3(A,B,C,D,X[1],3);
|
||||
MD4ROUND3(D,A,B,C,X[9],9);
|
||||
MD4ROUND3(C,D,A,B,X[5],11);
|
||||
MD4ROUND3(B,C,D,A,X[13],15);
|
||||
MD4ROUND3(A,B,C,D,X[3],3);
|
||||
MD4ROUND3(D,A,B,C,X[11],9);
|
||||
MD4ROUND3(C,D,A,B,X[7],11);
|
||||
MD4ROUND3(B,C,D,A,X[15],15);
|
||||
|
||||
A+=AA;
|
||||
B+=BB;
|
||||
C+=CC;
|
||||
D+=DD;
|
||||
}
|
||||
|
||||
digest[0]=A;
|
||||
digest[1]=B;
|
||||
digest[2]=C;
|
||||
digest[3]=D;
|
||||
resetMD4Registers();
|
||||
return digest;
|
||||
}
|
||||
|
||||
uint32_t changeEndianness(uint32_t x){
|
||||
return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24);
|
||||
}
|
||||
|
||||
void setMD4Registers(uint32_t AA, uint32_t BB, uint32_t CC, uint32_t DD){
|
||||
A=AA;
|
||||
B=BB;
|
||||
C=CC;
|
||||
D=DD;
|
||||
}
|
||||
|
||||
void resetMD4Registers(void){
|
||||
setMD4Registers(0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476);
|
||||
}
|
||||
1
Task/MD4/C/md4-2.c
Normal file
1
Task/MD4/C/md4-2.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
printf("%s\n", MD4("Rosetta Code", 12));
|
||||
27
Task/MD4/PARI-GP/md4-1.pari
Normal file
27
Task/MD4/PARI-GP/md4-1.pari
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#include <pari/pari.h>
|
||||
#include <openssl/md4.h>
|
||||
|
||||
#define HEX(x) (((x) < 10)? (x)+'0': (x)-10+'a')
|
||||
|
||||
/*
|
||||
* PARI/GP func: MD4 hash
|
||||
*
|
||||
* gp code: install("plug_md4", "s", "MD4", "<library path>");
|
||||
*/
|
||||
GEN plug_md4(char *text)
|
||||
{
|
||||
char md[MD4_DIGEST_LENGTH];
|
||||
char hash[sizeof(md) * 2 + 1];
|
||||
int i;
|
||||
|
||||
MD4((unsigned char*)text, strlen(text), (unsigned char*)md);
|
||||
|
||||
for (i = 0; i < sizeof(md); i++) {
|
||||
hash[i+i] = HEX((md[i] >> 4) & 0x0f);
|
||||
hash[i+i+1] = HEX(md[i] & 0x0f);
|
||||
}
|
||||
|
||||
hash[sizeof(md) * 2] = 0;
|
||||
|
||||
return strtoGENstr(hash);
|
||||
}
|
||||
3
Task/MD4/PARI-GP/md4-2.pari
Normal file
3
Task/MD4/PARI-GP/md4-2.pari
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
install("plug_md4", "s", "MD4", "~/libmd4.so");
|
||||
|
||||
MD4("Rosetta Code")
|
||||
|
|
@ -28,12 +28,12 @@ sub md4($str) {
|
|||
when 56..63 {
|
||||
$term = True;
|
||||
@block.push(0x80);
|
||||
@block.push(0 xx 63 - $_);
|
||||
@block.push(slip 0 xx 63 - $_);
|
||||
@x = pack-le @block;
|
||||
}
|
||||
when 0..55 {
|
||||
@block.push($term ?? 0 !! 0x80);
|
||||
@block.push(0 xx 55 - $_);
|
||||
@block.push(slip 0 xx 55 - $_);
|
||||
@x = pack-le @block;
|
||||
|
||||
my $bit_len = $buflen +< 3;
|
||||
|
|
|
|||
200
Task/MD4/Rust/md4.rust
Normal file
200
Task/MD4/Rust/md4.rust
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
// MD4, based on RFC 1186 and RFC 1320.
|
||||
//
|
||||
// https://www.ietf.org/rfc/rfc1186.txt
|
||||
// https://tools.ietf.org/html/rfc1320
|
||||
//
|
||||
|
||||
use std::fmt::Write;
|
||||
use std::mem;
|
||||
|
||||
// Let not(X) denote the bit-wise complement of X.
|
||||
// Let X v Y denote the bit-wise OR of X and Y.
|
||||
// Let X xor Y denote the bit-wise XOR of X and Y.
|
||||
// Let XY denote the bit-wise AND of X and Y.
|
||||
|
||||
// f(X,Y,Z) = XY v not(X)Z
|
||||
fn f(x: u32, y: u32, z: u32) -> u32 {
|
||||
(x & y) | (!x & z)
|
||||
}
|
||||
|
||||
// g(X,Y,Z) = XY v XZ v YZ
|
||||
fn g(x: u32, y: u32, z: u32) -> u32 {
|
||||
(x & y) | (x & z) | (y & z)
|
||||
}
|
||||
|
||||
// h(X,Y,Z) = X xor Y xor Z
|
||||
fn h(x: u32, y: u32, z: u32) -> u32 {
|
||||
x ^ y ^ z
|
||||
}
|
||||
|
||||
// Round 1 macro
|
||||
// Let [A B C D i s] denote the operation
|
||||
// A = (A + f(B,C,D) + X[i]) <<< s
|
||||
macro_rules! md4round1 {
|
||||
( $a:expr, $b:expr, $c:expr, $d:expr, $i:expr, $s:expr, $x:expr) => {
|
||||
{
|
||||
// Rust defaults to non-overflowing arithmetic, so we need to specify wrapping add.
|
||||
$a = ($a.wrapping_add( f($b, $c, $d) ).wrapping_add( $x[$i] ) ).rotate_left($s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Round 2 macro
|
||||
// Let [A B C D i s] denote the operation
|
||||
// A = (A + g(B,C,D) + X[i] + 5A827999) <<< s .
|
||||
macro_rules! md4round2 {
|
||||
( $a:expr, $b:expr, $c:expr, $d:expr, $i:expr, $s:expr, $x:expr) => {
|
||||
{
|
||||
$a = ($a.wrapping_add( g($b, $c, $d)).wrapping_add($x[$i]).wrapping_add(0x5a827999_u32)).rotate_left($s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Round 3 macro
|
||||
// Let [A B C D i s] denote the operation
|
||||
// A = (A + h(B,C,D) + X[i] + 6ED9EBA1) <<< s .
|
||||
macro_rules! md4round3 {
|
||||
( $a:expr, $b:expr, $c:expr, $d:expr, $i:expr, $s:expr, $x:expr) => {
|
||||
{
|
||||
$a = ($a.wrapping_add(h($b, $c, $d)).wrapping_add($x[$i]).wrapping_add(0x6ed9eba1_u32)).rotate_left($s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn convert_byte_vec_to_u32(mut bytes: Vec<u8>) -> Vec<u32> {
|
||||
|
||||
bytes.shrink_to_fit();
|
||||
let num_bytes = bytes.len();
|
||||
let num_words = num_bytes / 4;
|
||||
unsafe {
|
||||
let words = Vec::from_raw_parts(bytes.as_mut_ptr() as *mut u32, num_words, num_words);
|
||||
mem::forget(bytes);
|
||||
words
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a 128-bit MD4 hash as an array of four 32-bit words.
|
||||
// Based on RFC 1186 from https://www.ietf.org/rfc/rfc1186.txt
|
||||
fn md4<T: Into<Vec<u8>>>(input: T) -> [u32; 4] {
|
||||
|
||||
let mut bytes = input.into().to_vec();
|
||||
let initial_bit_len = (bytes.len() << 3) as u64;
|
||||
|
||||
// Step 1. Append padding bits
|
||||
// Append one '1' bit, then append 0 ≤ k < 512 bits '0', such that the resulting message
|
||||
// length in bis is congruent to 448 (mod 512).
|
||||
// Since our message is in bytes, we use one byte with a set high-order bit (0x80) plus
|
||||
// a variable number of zero bytes.
|
||||
|
||||
// Append zeros
|
||||
// Number of padding bytes needed is 448 bits (56 bytes) modulo 512 bits (64 bytes)
|
||||
bytes.push(0x80_u8);
|
||||
while (bytes.len() % 64) != 56 {
|
||||
bytes.push(0_u8);
|
||||
}
|
||||
|
||||
// Everything after this operates on 32-bit words, so reinterpret the buffer.
|
||||
let mut w = convert_byte_vec_to_u32(bytes);
|
||||
|
||||
// Step 2. Append length
|
||||
// A 64-bit representation of b (the length of the message before the padding bits were added)
|
||||
// is appended to the result of the previous step, low-order bytes first.
|
||||
w.push(initial_bit_len as u32); // Push low-order bytes first
|
||||
w.push((initial_bit_len >> 32) as u32);
|
||||
|
||||
// Step 3. Initialize MD buffer
|
||||
let mut a = 0x67452301_u32;
|
||||
let mut b = 0xefcdab89_u32;
|
||||
let mut c = 0x98badcfe_u32;
|
||||
let mut d = 0x10325476_u32;
|
||||
|
||||
// Step 4. Process message in 16-word blocks
|
||||
let n = w.len();
|
||||
for i in 0..n / 16 {
|
||||
|
||||
// Select the next 512-bit (16-word) block to process.
|
||||
let x = &w[i * 16..i * 16 + 16];
|
||||
|
||||
let aa = a;
|
||||
let bb = b;
|
||||
let cc = c;
|
||||
let dd = d;
|
||||
|
||||
// [Round 1]
|
||||
md4round1!(a, b, c, d, 0, 3, x); // [A B C D 0 3]
|
||||
md4round1!(d, a, b, c, 1, 7, x); // [D A B C 1 7]
|
||||
md4round1!(c, d, a, b, 2, 11, x); // [C D A B 2 11]
|
||||
md4round1!(b, c, d, a, 3, 19, x); // [B C D A 3 19]
|
||||
md4round1!(a, b, c, d, 4, 3, x); // [A B C D 4 3]
|
||||
md4round1!(d, a, b, c, 5, 7, x); // [D A B C 5 7]
|
||||
md4round1!(c, d, a, b, 6, 11, x); // [C D A B 6 11]
|
||||
md4round1!(b, c, d, a, 7, 19, x); // [B C D A 7 19]
|
||||
md4round1!(a, b, c, d, 8, 3, x); // [A B C D 8 3]
|
||||
md4round1!(d, a, b, c, 9, 7, x); // [D A B C 9 7]
|
||||
md4round1!(c, d, a, b, 10, 11, x);// [C D A B 10 11]
|
||||
md4round1!(b, c, d, a, 11, 19, x);// [B C D A 11 19]
|
||||
md4round1!(a, b, c, d, 12, 3, x); // [A B C D 12 3]
|
||||
md4round1!(d, a, b, c, 13, 7, x); // [D A B C 13 7]
|
||||
md4round1!(c, d, a, b, 14, 11, x);// [C D A B 14 11]
|
||||
md4round1!(b, c, d, a, 15, 19, x);// [B C D A 15 19]
|
||||
|
||||
// [Round 2]
|
||||
md4round2!(a, b, c, d, 0, 3, x); //[A B C D 0 3]
|
||||
md4round2!(d, a, b, c, 4, 5, x); //[D A B C 4 5]
|
||||
md4round2!(c, d, a, b, 8, 9, x); //[C D A B 8 9]
|
||||
md4round2!(b, c, d, a, 12, 13, x);//[B C D A 12 13]
|
||||
md4round2!(a, b, c, d, 1, 3, x); //[A B C D 1 3]
|
||||
md4round2!(d, a, b, c, 5, 5, x); //[D A B C 5 5]
|
||||
md4round2!(c, d, a, b, 9, 9, x); //[C D A B 9 9]
|
||||
md4round2!(b, c, d, a, 13, 13, x);//[B C D A 13 13]
|
||||
md4round2!(a, b, c, d, 2, 3, x); //[A B C D 2 3]
|
||||
md4round2!(d, a, b, c, 6, 5, x); //[D A B C 6 5]
|
||||
md4round2!(c, d, a, b, 10, 9, x); //[C D A B 10 9]
|
||||
md4round2!(b, c, d, a, 14, 13, x);//[B C D A 14 13]
|
||||
md4round2!(a, b, c, d, 3, 3, x); //[A B C D 3 3]
|
||||
md4round2!(d, a, b, c, 7, 5, x); //[D A B C 7 5]
|
||||
md4round2!(c, d, a, b, 11, 9, x); //[C D A B 11 9]
|
||||
md4round2!(b, c, d, a, 15, 13, x);//[B C D A 15 13]
|
||||
|
||||
// [Round 3]
|
||||
md4round3!(a, b, c, d, 0, 3, x); //[A B C D 0 3]
|
||||
md4round3!(d, a, b, c, 8, 9, x); //[D A B C 8 9]
|
||||
md4round3!(c, d, a, b, 4, 11, x); //[C D A B 4 11]
|
||||
md4round3!(b, c, d, a, 12, 15, x);//[B C D A 12 15]
|
||||
md4round3!(a, b, c, d, 2, 3, x); //[A B C D 2 3]
|
||||
md4round3!(d, a, b, c, 10, 9, x); //[D A B C 10 9]
|
||||
md4round3!(c, d, a, b, 6, 11, x); //[C D A B 6 11]
|
||||
md4round3!(b, c, d, a, 14, 15, x);//[B C D A 14 15]
|
||||
md4round3!(a, b, c, d, 1, 3, x); //[A B C D 1 3]
|
||||
md4round3!(d, a, b, c, 9, 9, x); //[D A B C 9 9]
|
||||
md4round3!(c, d, a, b, 5, 11, x); //[C D A B 5 11]
|
||||
md4round3!(b, c, d, a, 13, 15, x);//[B C D A 13 15]
|
||||
md4round3!(a, b, c, d, 3, 3, x); //[A B C D 3 3]
|
||||
md4round3!(d, a, b, c, 11, 9, x); //[D A B C 11 9]
|
||||
md4round3!(c, d, a, b, 7, 11, x); //[C D A B 7 11]
|
||||
md4round3!(b, c, d, a, 15, 15, x);//[B C D A 15 15]
|
||||
|
||||
a = a.wrapping_add(aa);
|
||||
b = b.wrapping_add(bb);
|
||||
c = c.wrapping_add(cc);
|
||||
d = d.wrapping_add(dd);
|
||||
}
|
||||
|
||||
// Step 5. Output
|
||||
// The message digest produced as output is A, B, C, D. That is, we begin with the low-order
|
||||
// byte of A, and end with the high-order byte of D.
|
||||
[u32::from_be(a), u32::from_be(b), u32::from_be(c), u32::from_be(d)]
|
||||
}
|
||||
|
||||
fn digest_to_str(digest: &[u32]) -> String {
|
||||
let mut s = String::new();
|
||||
for &word in digest {
|
||||
write!(&mut s, "{:08x}", word).unwrap();
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let val = "Rosetta Code";
|
||||
println!("md4(\"{}\") = {}", val, digest_to_str(&md4(val)));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue