MD4: Difference between revisions
m →{{header|Go}}: update sub-repo url |
→{{header|Python}}: Clarify availability |
||
(48 intermediate revisions by 26 users not shown) | |||
Line 1: | Line 1: | ||
{{task}} [[Category:Checksums]] |
{{task}} [[Category:Checksums]] |
||
Find the MD4 message digest of a string of [[octet]]s. |
Find the MD4 message digest of a string of [[octet]]s. |
||
Use the ASCII encoded string “<tt>Rosetta Code</tt>” (without quotes). |
|||
You may either call an MD4 library, or implement MD4 in your language. |
|||
'''MD4''' is an obsolete hash function that computes a 128-bit message digest that sometimes appears in obsolete protocols. |
'''MD4''' is an obsolete hash function that computes a 128-bit message digest that sometimes appears in obsolete protocols. |
||
RFC 1320 specifies the MD4 algorithm. RFC 6150 declares that MD4 is obsolete. |
RFC 1320 specifies the MD4 algorithm. RFC 6150 declares that MD4 is obsolete. |
||
=={{header|Ada}}== |
|||
{{libheader|CryptAda}} |
|||
<syntaxhighlight lang="ada">with Ada.Text_IO; |
|||
with CryptAda.Digests.Message_Digests.MD4; |
|||
with CryptAda.Digests.Hashes; |
|||
with CryptAda.Pragmatics; |
|||
with CryptAda.Utils.Format; |
|||
procedure RC_MD4 is |
|||
use CryptAda.Digests.Message_Digests; |
|||
use CryptAda.Digests; |
|||
use CryptAda.Pragmatics; |
|||
function To_Byte_Array (Item : String) return Byte_Array is |
|||
Result : Byte_Array (Item'Range); |
|||
begin |
|||
for I in Result'Range loop |
|||
Result (I) := Byte (Character'Pos (Item (I))); |
|||
end loop; |
|||
return Result; |
|||
end To_Byte_Array; |
|||
Text : constant String := "Rosetta Code"; |
|||
Bytes : constant Byte_Array := To_Byte_Array (Text); |
|||
Handle : constant Message_Digest_Handle := MD4.Get_Message_Digest_Handle; |
|||
Pointer : constant Message_Digest_Ptr := Get_Message_Digest_Ptr (Handle); |
|||
Hash : Hashes.Hash; |
|||
begin |
|||
Digest_Start (Pointer); |
|||
Digest_Update (Pointer, Bytes); |
|||
Digest_End (Pointer, Hash); |
|||
Ada.Text_IO.Put_Line |
|||
("""" & Text & """: " & CryptAda.Utils.Format.To_Hex_String (Hashes.Get_Bytes (Hash))); |
|||
end RC_MD4;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>"Rosetta Code": A52BCFC6A0D0D300CDC5DDBFBEFE478B</pre> |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
Source: [https://github.com/jNizM/AutoHotkey_Scripts/tree/master/Functions/Checksums MD4 @github] by jNizM |
Source: [https://github.com/jNizM/AutoHotkey_Scripts/tree/master/Functions/Checksums MD4 @github] by jNizM |
||
< |
<syntaxhighlight lang="autohotkey">str := "Rosetta Code" |
||
MsgBox, % "String:`n" (str) "`n`nMD4:`n" MD4(str) |
MsgBox, % "String:`n" (str) "`n`nMD4:`n" MD4(str) |
||
Line 60: | Line 101: | ||
StrPut(string, &data, floor(length / chrlength), encoding) |
StrPut(string, &data, floor(length / chrlength), encoding) |
||
return CalcAddrHash(&data, length, algid, hash, hashlength) |
return CalcAddrHash(&data, length, algid, hash, hashlength) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>String: Rosetta Code |
<pre>String: Rosetta Code |
||
MD4: A52BCFC6A0D0D300CDC5DDBFBEFE478B</pre> |
MD4: A52BCFC6A0D0D300CDC5DDBFBEFE478B</pre> |
||
=={{header|BASIC}}== |
|||
==={{header|FreeBASIC}}=== |
|||
<syntaxhighlight lang="freebasic">' version 19-10-2016 |
|||
' translation of the (pseudo) code in RFC 1320 |
|||
' compile with: fbc -s console |
|||
Function MD4(test_str As String) As String |
|||
Dim As String message = test_str ' string are passed as ByRef |
|||
' some macro's |
|||
#Macro F(X, Y, Z) |
|||
(((X) And (Y)) Or ((Not(X)) And (Z))) |
|||
#EndMacro |
|||
#Macro G(X, Y, Z) |
|||
(((X) And (Y)) Or (((X) And (Z)) Or ((Y) And (Z)))) |
|||
#EndMacro |
|||
#Macro H(X, Y, Z) |
|||
((X) Xor (Y) Xor (Z)) |
|||
#EndMacro |
|||
' a little piece of inline asm to do a rotate left on a 32bit variable |
|||
#Macro ROtate_Left(x, n) ' rotate left |
|||
Asm |
|||
rol dword Ptr [x], n |
|||
End Asm |
|||
#EndMacro |
|||
' #Macro ROtate_left(x, n) |
|||
' x = x Shl n + x Shr (32 - n) |
|||
' #EndMacro |
|||
Dim As Long i |
|||
Dim As String answer, s1 |
|||
Dim As ULongInt l = Len(message) |
|||
' set the first bit after the message to 1 |
|||
message = message + Chr(1 Shl 7) |
|||
' add one char to the length |
|||
Dim As ULong padding = 64 - ((l +1) Mod (512 \ 8)) ' 512 \ 8 = 64 char. |
|||
' check if we have enough room for inserting the length |
|||
If padding < 8 Then padding = padding + 64 |
|||
message = message + String(padding, Chr(0)) ' adjust length |
|||
Dim As ULong l1 = Len(message) ' new length |
|||
l = l * 8 ' orignal length in bits |
|||
' create ubyte ptr to point to l ( = length in bits) |
|||
Dim As UByte Ptr ub_ptr = Cast(UByte Ptr, @l) |
|||
For i = 0 To 7 'copy length of message to the last 8 bytes |
|||
message[l1 -8 + i] = ub_ptr[i] |
|||
Next |
|||
' unsigned 32bit integers only |
|||
Dim As UInteger<32> AA, A = &H67452301 |
|||
Dim As UInteger<32> BB, B = &Hefcdab89 |
|||
Dim As UInteger<32> CC, C = &H98badcfe |
|||
Dim As UInteger<32> DD, D = &H10325476 |
|||
For i = 0 To (l1 -1) \ 64 ' split into 64 byte block |
|||
AA = A : BB = B : CC = C : DD = D |
|||
' x point to 64 byte block inside the string message |
|||
Dim As UInteger<32> Ptr x = Cast(UInteger<32> Ptr, @message[i*64]) |
|||
' round 1 |
|||
A = A + F(B, C, D) + x[ 0] : ROtate_Left(A, 3) |
|||
D = D + F(A, B, C) + x[ 1] : ROtate_Left(D, 7) |
|||
C = C + F(D, A, B) + x[ 2] : ROtate_Left(C, 11) |
|||
B = B + F(C, D, A) + x[ 3] : ROtate_Left(B, 19) |
|||
A = A + F(B, C, D) + x[ 4] : ROtate_Left(A, 3) |
|||
D = D + F(A, B, C) + x[ 5] : ROtate_Left(D, 7) |
|||
C = C + F(D, A, B) + x[ 6] : ROtate_Left(C, 11) |
|||
B = B + F(C, D, A) + x[ 7] : ROtate_Left(B, 19) |
|||
A = A + F(B, C, D) + x[ 8] : ROtate_Left(A, 3) |
|||
D = D + F(A, B, C) + x[ 9] : ROtate_Left(D, 7) |
|||
C = C + F(D, A, B) + x[10] : ROtate_Left(C, 11) |
|||
B = B + F(C, D, A) + x[11] : ROtate_Left(B, 19) |
|||
A = A + F(B, C, D) + x[12] : ROtate_Left(A, 3) |
|||
D = D + F(A, B, C) + x[13] : ROtate_Left(D, 7) |
|||
C = C + F(D, A, B) + x[14] : ROtate_Left(C, 11) |
|||
B = B + F(C, D, A) + x[15] : ROtate_Left(B, 19) |
|||
' round 2 |
|||
A = A + G(B, C, D) + x[ 0] + &H5A827999 : ROtate_Left(A, 3) |
|||
D = D + G(A, B, C) + x[ 4] + &H5A827999 : ROtate_Left(D, 5) |
|||
C = C + G(D, A, B) + x[ 8] + &H5A827999 : ROtate_Left(C, 9) |
|||
B = B + G(C, D, A) + x[12] + &H5A827999 : ROtate_Left(B, 13) |
|||
A = A + G(B, C, D) + x[ 1] + &H5A827999 : ROtate_Left(A, 3) |
|||
D = D + G(A, B, C) + x[ 5] + &H5A827999 : ROtate_Left(D, 5) |
|||
C = C + G(D, A, B) + x[ 9] + &H5A827999 : ROtate_Left(C, 9) |
|||
B = B + G(C, D, A) + x[13] + &H5A827999 : ROtate_Left(B, 13) |
|||
A = A + G(B, C, D) + x[ 2] + &H5A827999 : ROtate_Left(A, 3) |
|||
D = D + G(A, B, C) + x[ 6] + &H5A827999 : ROtate_Left(D, 5) |
|||
C = C + G(D, A, B) + x[10] + &H5A827999 : ROtate_Left(C, 9) |
|||
B = B + G(C, D, A) + x[14] + &H5A827999 : ROtate_Left(B, 13) |
|||
A = A + G(B, C, D) + x[ 3] + &H5A827999 : ROtate_Left(A, 3) |
|||
D = D + G(A, B, C) + x[ 7] + &H5A827999 : ROtate_Left(D, 5) |
|||
C = C + G(D, A, B) + x[11] + &H5A827999 : ROtate_Left(C, 9) |
|||
B = B + G(C, D, A) + x[15] + &H5A827999 : ROtate_Left(B, 13) |
|||
' round 3 |
|||
A = A + H(B, C, D) + x[ 0] + &H6ED9EBA1 : ROtate_Left(A, 3) |
|||
D = D + H(A, B, C) + x[ 8] + &H6ED9EBA1 : ROtate_Left(D, 9) |
|||
C = C + H(D, A, B) + x[ 4] + &H6ED9EBA1 : ROtate_Left(C, 11) |
|||
B = B + H(C, D, A) + x[12] + &H6ED9EBA1 : ROtate_Left(B, 15) |
|||
A = A + H(B, C, D) + x[ 2] + &H6ED9EBA1 : ROtate_Left(A, 3) |
|||
D = D + H(A, B, C) + x[10] + &H6ED9EBA1 : ROtate_Left(D, 9) |
|||
C = C + H(D, A, B) + x[ 6] + &H6ED9EBA1 : ROtate_Left(C, 11) |
|||
B = B + H(C, D, A) + x[14] + &H6ED9EBA1 : ROtate_Left(B, 15) |
|||
A = A + H(B, C, D) + x[ 1] + &H6ED9EBA1 : ROtate_Left(A, 3) |
|||
D = D + H(A, B, C) + x[ 9] + &H6ED9EBA1 : ROtate_Left(D, 9) |
|||
C = C + H(D, A, B) + x[ 5] + &H6ED9EBA1 : ROtate_Left(C, 11) |
|||
B = B + H(C, D, A) + x[13] + &H6ED9EBA1 : ROtate_Left(B, 15) |
|||
A = A + H(B, C, D) + x[ 3] + &H6ED9EBA1 : ROtate_Left(A, 3) |
|||
D = D + H(A, B, C) + x[11] + &H6ED9EBA1 : ROtate_Left(D, 9) |
|||
C = C + H(D, A, B) + x[ 7] + &H6ED9EBA1 : ROtate_Left(C, 11) |
|||
B = B + H(C, D, A) + x[15] + &H6ED9EBA1 : ROtate_Left(B, 15) |
|||
A += AA : B += BB : C += CC : D += DD |
|||
Next |
|||
' convert A, B, C and D in hex, then add low order first |
|||
s1 = Hex(A, 8) |
|||
For i = 7 To 1 Step -2 : answer +=Mid(s1, i, 2) : Next |
|||
s1 = Hex(B, 8) |
|||
For i = 7 To 1 Step -2 : answer +=Mid(s1, i, 2) : Next |
|||
s1 = Hex(C, 8) |
|||
For i = 7 To 1 Step -2 : answer +=Mid(s1, i, 2) : Next |
|||
s1 = Hex(D, 8) |
|||
For i = 7 To 1 Step -2 : answer +=Mid(s1, i, 2) : Next |
|||
Return LCase(answer) |
|||
End Function |
|||
' ------=< MAIN >=------ |
|||
Dim As String test = "Rosetta Code" |
|||
Print |
|||
Print test; " => "; MD4(test) |
|||
' empty keyboard buffer |
|||
While Inkey <> "" : Wend |
|||
Print : Print "hit any key to end program" |
|||
Sleep |
|||
End</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Rosetta Code => a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
|||
=={{header|C}}== |
|||
<syntaxhighlight lang="c"> |
|||
/* |
|||
* |
|||
* 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); |
|||
} |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<syntaxhighlight lang="c">printf("%s\n", MD4("Rosetta Code", 12));</syntaxhighlight> |
|||
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
|||
=={{header|C sharp|C#}}== |
|||
<syntaxhighlight lang="csharp">using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
static class Md4 |
|||
{ |
|||
public static string Md4Hash(this string input) |
|||
{ |
|||
// get padded uints from bytes |
|||
List<byte> bytes = Encoding.ASCII.GetBytes(input).ToList(); |
|||
uint bitCount = (uint)(bytes.Count) * 8; |
|||
bytes.Add(128); |
|||
while (bytes.Count % 64 != 56) bytes.Add(0); |
|||
var uints = new List<uint>(); |
|||
for (int i = 0; i + 3 < bytes.Count; i += 4) |
|||
uints.Add(bytes[i] | (uint)bytes[i + 1] << 8 | (uint)bytes[i + 2] << 16 | (uint)bytes[i + 3] << 24); |
|||
uints.Add(bitCount); |
|||
uints.Add(0); |
|||
// run rounds |
|||
uint a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476; |
|||
Func<uint, uint, uint> rol = (x, y) => x << (int)y | x >> 32 - (int)y; |
|||
for (int q = 0; q + 15 < uints.Count; q += 16) |
|||
{ |
|||
var chunk = uints.GetRange(q, 16); |
|||
uint aa = a, bb = b, cc = c, dd = d; |
|||
Action<Func<uint, uint, uint, uint>, uint[]> round = (f, y) => |
|||
{ |
|||
foreach (uint i in new[] { y[0], y[1], y[2], y[3] }) |
|||
{ |
|||
a = rol(a + f(b, c, d) + chunk[(int)(i + y[4])] + y[12], y[8]); |
|||
d = rol(d + f(a, b, c) + chunk[(int)(i + y[5])] + y[12], y[9]); |
|||
c = rol(c + f(d, a, b) + chunk[(int)(i + y[6])] + y[12], y[10]); |
|||
b = rol(b + f(c, d, a) + chunk[(int)(i + y[7])] + y[12], y[11]); |
|||
} |
|||
}; |
|||
round((x, y, z) => (x & y) | (~x & z), new uint[] { 0, 4, 8, 12, 0, 1, 2, 3, 3, 7, 11, 19, 0 }); |
|||
round((x, y, z) => (x & y) | (x & z) | (y & z), new uint[] { 0, 1, 2, 3, 0, 4, 8, 12, 3, 5, 9, 13, 0x5a827999 }); |
|||
round((x, y, z) => x ^ y ^ z, new uint[] { 0, 2, 1, 3, 0, 8, 4, 12, 3, 9, 11, 15, 0x6ed9eba1 }); |
|||
a += aa; b += bb; c += cc; d += dd; |
|||
} |
|||
// return hex encoded string |
|||
byte[] outBytes = new[] { a, b, c, d }.SelectMany(BitConverter.GetBytes).ToArray(); |
|||
return BitConverter.ToString(outBytes).Replace("-", "").ToLower(); |
|||
} |
|||
static void Main() { Console.WriteLine("Rosetta Code".Md4Hash()); } |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
|||
=={{header|C++}}== |
|||
<syntaxhighlight lang="c++"> |
|||
#include <algorithm> |
|||
#include <cstdint> |
|||
#include <iomanip> |
|||
#include <iostream> |
|||
#include <string> |
|||
#include <vector> |
|||
class MD4 { |
|||
public: |
|||
MD4() { |
|||
engine_reset(); |
|||
} |
|||
std::vector<int8_t> engine_digest(const std::string& text) { |
|||
engine_update(string_to_byte_vector(text), 0, text.length()); |
|||
const int32_t buffer_index = static_cast<int32_t>(count % BLOCK_LENGTH); |
|||
const int32_t padding_length = ( buffer_index < 56 ) ? 56 - buffer_index : 120 - buffer_index; |
|||
std::vector<int8_t> tail(padding_length + 8, 0); |
|||
tail[0] = static_cast<int8_t>(0x80); |
|||
for ( int32_t i = 0; i < 8; ++i ) { |
|||
tail[padding_length + i] = static_cast<int8_t>(unsigned_right_shift(count * 8, 8 * i)); |
|||
} |
|||
engine_update(tail, 0, tail.size()); |
|||
std::vector<int8_t> result(16, 0); |
|||
for ( int32_t i = 0; i < 4; ++i ) { |
|||
for ( int32_t j = 0; j < 4; ++j ) { |
|||
result[i * 4 + j] = static_cast<int8_t>(unsigned_right_shift(context[i], 8 * j)); |
|||
} |
|||
} |
|||
engine_reset(); |
|||
return result; |
|||
} |
|||
private: |
|||
void engine_update(const std::vector<int8_t>& message_bytes, |
|||
const int32_t& offset, const int32_t& message_length) { |
|||
if ( offset < 0 || message_length < 0 |
|||
|| (int64_t) offset + message_length > (int64_t) message_bytes.size() ) { |
|||
throw std::invalid_argument("Incorrect arguments for function engine_update"); |
|||
} |
|||
int32_t buffer_index = static_cast<int32_t>(count % BLOCK_LENGTH); |
|||
count += message_length; |
|||
const int32_t partial_length = BLOCK_LENGTH - buffer_index; |
|||
int32_t i = 0; |
|||
if ( message_length >= partial_length ) { |
|||
for ( int32_t j = 0; j < partial_length; ++j ) { |
|||
buffer[buffer_index + j] = message_bytes[offset + j]; |
|||
} |
|||
transform(buffer, 0); |
|||
i = partial_length; |
|||
while ( i + BLOCK_LENGTH - 1 < message_length ) { |
|||
transform(message_bytes, offset + i); |
|||
i += BLOCK_LENGTH; |
|||
} |
|||
buffer_index = 0; |
|||
} |
|||
if ( i < message_length ) { |
|||
for ( int32_t j = 0; j < message_length - i; ++j ) { |
|||
buffer[buffer_index + j] = message_bytes[offset + i + j]; |
|||
} |
|||
} |
|||
} |
|||
void transform(const std::vector<int8_t>& buffer, int32_t offset) { |
|||
for ( int32_t i = 0; i < 16; ++i ) { |
|||
extra[i] = ( ( buffer[offset + 0] & 0xff ) ) | |
|||
( ( buffer[offset + 1] & 0xff ) << 8 ) | |
|||
( ( buffer[offset + 2] & 0xff ) << 16 ) | |
|||
( ( buffer[offset + 3] & 0xff ) << 24 ); |
|||
offset += 4; |
|||
} |
|||
int32_t a = context[0]; |
|||
int32_t b = context[1]; |
|||
int32_t c = context[2]; |
|||
int32_t d = context[3]; |
|||
for ( const int32_t& i : { 0, 4, 8, 12 } ) { |
|||
a = ff(a, b, c, d, extra[i + 0], 3); |
|||
d = ff(d, a, b, c, extra[i + 1], 7); |
|||
c = ff(c, d, a, b, extra[i + 2], 11); |
|||
b = ff(b, c, d, a, extra[i + 3], 19); |
|||
} |
|||
for ( const int32_t& i : { 0, 1, 2, 3 } ) { |
|||
a = gg(a, b, c, d, extra[i + 0], 3); |
|||
d = gg(d, a, b, c, extra[i + 4], 5); |
|||
c = gg(c, d, a, b, extra[i + 8], 9); |
|||
b = gg(b, c, d, a, extra[i + 12], 13); |
|||
} |
|||
for ( const int32_t& i : { 0, 2, 1, 3 } ) { |
|||
a = hh(a, b, c, d, extra[i + 0], 3); |
|||
d = hh(d, a, b, c, extra[i + 8], 9); |
|||
c = hh(c, d, a, b, extra[i + 4], 11); |
|||
b = hh(b, c, d, a, extra[i + 12], 15); |
|||
} |
|||
context[0] += a; |
|||
context[1] += b; |
|||
context[2] += c; |
|||
context[3] += d; |
|||
} |
|||
void engine_reset() { |
|||
count = 0; |
|||
context.assign(4, 0); |
|||
context[0] = 0x67452301; |
|||
context[1] = 0xefcdab89; |
|||
context[2] = 0x98badcfe; |
|||
context[3] = 0x10325476; |
|||
extra.assign(16, 0); |
|||
buffer.assign(BLOCK_LENGTH, 0); |
|||
} |
|||
std::vector<int8_t> string_to_byte_vector(const std::string& text) { |
|||
std::vector<int8_t> bytes; |
|||
bytes.reserve(text.size()); |
|||
std::transform(text.begin(), text.end(), std::back_inserter(bytes), |
|||
[](char ch){ return static_cast<int8_t>(ch); }); |
|||
return bytes; |
|||
} |
|||
int32_t unsigned_right_shift(const int32_t& base, const int32_t& shift) { |
|||
if ( shift < 0 || shift >= 32 || base == 0 ) { |
|||
return 0; |
|||
} |
|||
return ( base > 0 ) ? base >> shift : static_cast<uint32_t>(base) >> shift; |
|||
} |
|||
int32_t rotate(const int32_t& t, const int32_t& s) { |
|||
return ( t << s ) | unsigned_right_shift(t, 32 - s); |
|||
} |
|||
int32_t ff(const int32_t& a, const int32_t& b, const int32_t& c, |
|||
const int32_t& d, const int32_t& x, const int32_t& s) { |
|||
return rotate(a + ( ( b & c ) | ( ~b & d ) ) + x, s); |
|||
} |
|||
int32_t gg(const int32_t& a, const int32_t& b, const int32_t& c, |
|||
const int32_t& d, const int32_t& x, const int32_t& s) { |
|||
return rotate(a + ( ( b & ( c | d ) ) | ( c & d ) ) + x + 0x5A827999, s); |
|||
} |
|||
int32_t hh(const int32_t& a, const int32_t& b, const int32_t& c, |
|||
const int32_t& d, const int32_t& x, const int32_t& s) { |
|||
return rotate(a + ( b ^ c ^ d ) + x + 0x6ED9EBA1, s); |
|||
} |
|||
uint64_t count; |
|||
std::vector<int32_t> context; |
|||
std::vector<int32_t> extra; |
|||
std::vector<int8_t> buffer; |
|||
const int32_t BLOCK_LENGTH = 64; |
|||
}; |
|||
int main() { |
|||
MD4 md4; |
|||
std::vector<int8_t> result = md4.engine_digest("Rosetta Code"); |
|||
for ( const int8_t& bb : result ) { |
|||
std::cout << std::hex << std::setfill('0') << std::setw(2) << ( bb & 0xff ); |
|||
} |
|||
std::cout << std::endl; |
|||
} |
|||
</syntaxhighlight> |
|||
{{ out }} |
|||
<pre> |
|||
a52bcfc6a0d0d300cdc5ddbfbefe478b |
|||
</pre> |
|||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
{{libheader|pandect}} |
{{libheader|pandect}} |
||
< |
<syntaxhighlight lang="clojure">(use 'pandect.core) |
||
(md4 "Rosetta Code")</ |
(md4 "Rosetta Code")</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
Line 75: | Line 767: | ||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
{{libheader|Ironclad}} |
{{libheader|Ironclad}} |
||
< |
<syntaxhighlight lang="lisp">(ql:quickload 'ironclad) |
||
(defun md4 (str) |
(defun md4 (str) |
||
(ironclad:byte-array-to-hex-string |
(ironclad:byte-array-to-hex-string |
||
Line 81: | Line 773: | ||
(ironclad:ascii-string-to-byte-array str)))) |
(ironclad:ascii-string-to-byte-array str)))) |
||
(md4 "Rosetta Code")</ |
(md4 "Rosetta Code")</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>"a52bcfc6a0d0d300cdc5ddbfbefe478b"</pre> |
<pre>"a52bcfc6a0d0d300cdc5ddbfbefe478b"</pre> |
||
=={{header|D}}== |
|||
A short but not efficient implementation. |
|||
{{trans|Ruby}} |
|||
<syntaxhighlight lang="d">import std.stdio, std.string, std.range; |
|||
ubyte[16] md4(const(ubyte)[] inData) pure nothrow { |
|||
enum f = (uint x, uint y, uint z) => (x & y) | (~x & z); |
|||
enum g = (uint x, uint y, uint z) => (x & y) | (x & z) | (y & z); |
|||
enum h = (uint x, uint y, uint z) => x ^ y ^ z; |
|||
enum r = (uint v, uint s) => (v << s) | (v >> (32 - s)); |
|||
immutable bitLen = ulong(inData.length) << 3; |
|||
inData ~= 0x80; |
|||
while (inData.length % 64 != 56) |
|||
inData ~= 0; |
|||
const data = cast(uint[])inData ~ [uint(bitLen & uint.max), uint(bitLen >> 32)]; |
|||
uint a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476; |
|||
foreach (const x; data.chunks(16)) { |
|||
immutable a2 = a, b2 = b, c2 = c, d2 = d; |
|||
foreach (immutable i; [0, 4, 8, 12]) { |
|||
a = r(a + f(b, c, d) + x[i+0], 3); |
|||
d = r(d + f(a, b, c) + x[i+1], 7); |
|||
c = r(c + f(d, a, b) + x[i+2], 11); |
|||
b = r(b + f(c, d, a) + x[i+3], 19); |
|||
} |
|||
foreach (immutable i; [0, 1, 2, 3]) { |
|||
a = r(a + g(b, c, d) + x[i+0] + 0x5a827999, 3); |
|||
d = r(d + g(a, b, c) + x[i+4] + 0x5a827999, 5); |
|||
c = r(c + g(d, a, b) + x[i+8] + 0x5a827999, 9); |
|||
b = r(b + g(c, d, a) + x[i+12] + 0x5a827999, 13); |
|||
} |
|||
foreach (immutable i; [0, 2, 1, 3]) { |
|||
a = r(a + h(b, c, d) + x[i+0] + 0x6ed9eba1, 3); |
|||
d = r(d + h(a, b, c) + x[i+8] + 0x6ed9eba1, 9); |
|||
c = r(c + h(d, a, b) + x[i+4] + 0x6ed9eba1, 11); |
|||
b = r(b + h(c, d, a) + x[i+12] + 0x6ed9eba1, 15); |
|||
} |
|||
a += a2, b += b2, c += c2, d += d2; |
|||
} |
|||
//return cast(ubyte[16])[a, b, c, d]; |
|||
immutable uint[4] result = [a, b, c, d]; |
|||
return cast(ubyte[16])result; |
|||
} |
|||
void main() { |
|||
writefln("%(%02x%)", "Rosetta Code".representation.md4); |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
|||
=={{header|Delphi}}== |
|||
{{libheader| System.SysUtils}} |
|||
{{libheader| DCPmd4}} |
|||
Thanks for David Barton for DCPcrypt v2.0 library, and StephenGenusa for store and share in github [https://github.com/StephenGenusa/DCPCrypt]. |
|||
<syntaxhighlight lang="delphi"> |
|||
program CalcMD4; |
|||
{$APPTYPE CONSOLE} |
|||
uses |
|||
System.SysUtils, |
|||
DCPmd4; |
|||
function MD4(const Str: string): string; |
|||
var |
|||
HashDigest: array of byte; |
|||
d: Byte; |
|||
begin |
|||
Result := ''; |
|||
with TDCP_md4.Create(nil) do |
|||
begin |
|||
Init; |
|||
UpdateStr(Str); |
|||
SetLength(HashDigest, GetHashSize div 8); |
|||
final(HashDigest[0]); |
|||
for d in HashDigest do |
|||
Result := Result + d.ToHexString(2); |
|||
Free; |
|||
end; |
|||
end; |
|||
begin |
|||
Writeln(MD4('Rosetta Code')); |
|||
readln; |
|||
end.</syntaxhighlight> |
|||
{{out}} |
|||
<pre>A52BCFC6A0D0D300CDC5DDBFBEFE478B</pre> |
|||
=={{header|Emacs Lisp}}== |
=={{header|Emacs Lisp}}== |
||
Line 90: | Line 872: | ||
<code>md4.el</code> by Taro Kawagishi, originally from [http://git.chise.org/elisp/flim/ FLIM] and included in recent Emacs, is an Elisp implementation of the MD4 algorithm. Its <code>md4</code> function returns the checksum as 16 binary bytes. <code>encode-hex-string</code> from <code>hex-util.el</code> can convert that to a hex string if desired. |
<code>md4.el</code> by Taro Kawagishi, originally from [http://git.chise.org/elisp/flim/ FLIM] and included in recent Emacs, is an Elisp implementation of the MD4 algorithm. Its <code>md4</code> function returns the checksum as 16 binary bytes. <code>encode-hex-string</code> from <code>hex-util.el</code> can convert that to a hex string if desired. |
||
< |
<syntaxhighlight lang="lisp">(require 'md4) |
||
(require 'hex-util) |
|||
(let* ((s "Rosetta Code") |
(let* ((s "Rosetta Code") |
||
(m (md4 s (length s)))) ;; m = 16 binary bytes |
(m (md4 s (length s)))) ;; m = 16 binary bytes |
||
(require 'hex-util) |
|||
(encode-hex-string m)) |
(encode-hex-string m)) |
||
=> |
=> |
||
"a52bcfc6a0d0d300cdc5ddbfbefe478b"</ |
"a52bcfc6a0d0d300cdc5ddbfbefe478b"</syntaxhighlight> |
||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
< |
<syntaxhighlight lang="erlang"> |
||
-module(md4). |
-module(md4). |
||
-export([md4/0]). |
-export([md4/0]). |
||
Line 106: | Line 888: | ||
<<MD4:128>> = crypto:md4("Rosetta Code"), |
<<MD4:128>> = crypto:md4("Rosetta Code"), |
||
io:fwrite("Rosetta Code => ~.16B~n",[MD4]). |
io:fwrite("Rosetta Code => ~.16B~n",[MD4]). |
||
</syntaxhighlight> |
|||
</lang> |
|||
<pre> |
<pre> |
||
Rosetta Code => A52BCFC6A0D0D300CDC5DDBFBEFE478B |
Rosetta Code => A52BCFC6A0D0D300CDC5DDBFBEFE478B |
||
Line 113: | Line 895: | ||
=={{header|Go}}== |
=={{header|Go}}== |
||
{{libheader|Go sub-repositories}} |
{{libheader|Go sub-repositories}} |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 124: | Line 906: | ||
h.Write([]byte("Rosetta Code")) |
h.Write([]byte("Rosetta Code")) |
||
fmt.Printf("%x\n", h.Sum(nil)) |
fmt.Printf("%x\n", h.Sum(nil)) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
a52bcfc6a0d0d300cdc5ddbfbefe478b |
a52bcfc6a0d0d300cdc5ddbfbefe478b |
||
</pre> |
</pre> |
||
=={{header|Haskell}}== |
|||
{{libheader|Cryptonite}} |
|||
<syntaxhighlight lang="haskell">#!/usr/bin/env runhaskell |
|||
import Data.ByteString.Char8 (pack) |
|||
import System.Environment (getArgs) |
|||
import Crypto.Hash |
|||
main :: IO () |
|||
main = print . md4 . pack . unwords =<< getArgs |
|||
where md4 x = hash x :: Digest MD4</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
$ ./md4.hs Rosetta Code |
|||
a52bcfc6a0d0d300cdc5ddbfbefe478b |
|||
</pre> |
|||
=={{header|J}}== |
|||
<syntaxhighlight lang="j"> require 'ide/qt' |
|||
gethash_jqtide_ 'MD4';'Rosetta Code' |
|||
a52bcfc6a0d0d300cdc5ddbfbefe478b</syntaxhighlight> |
|||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{libheader|BouncyCastle}} |
{{libheader|BouncyCastle}} |
||
< |
<syntaxhighlight lang="java">import org.bouncycastle.crypto.digests.MD4Digest; |
||
import org.bouncycastle.util.encoders.Hex; |
import org.bouncycastle.util.encoders.Hex; |
||
Line 147: | Line 951: | ||
System.out.println(); |
System.out.println(); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 153: | Line 957: | ||
</pre> |
</pre> |
||
===Without external libraries=== |
|||
<syntaxhighlight lang="java"> |
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
public final class MD4Task { |
|||
public static void main(String[] aArgs) { |
|||
String text = "Rosetta Code"; |
|||
MD4 md4 = new MD4(); |
|||
byte[] result = md4.engineDigest(text); |
|||
StringBuilder stringBuilder = new StringBuilder(); |
|||
for ( byte bb : result ) { |
|||
stringBuilder.append(String.format("%02x", bb)); |
|||
} |
|||
System.out.println(stringBuilder.toString()); |
|||
} |
|||
} |
|||
final class MD4 { |
|||
public MD4() { |
|||
engineReset(); |
|||
} |
|||
public byte[] engineDigest(String aText) { |
|||
engineUpdate(aText.getBytes(), 0, aText.length()); |
|||
final int bufferIndex = (int) ( count % BLOCK_LENGTH ); |
|||
final int paddingLength = ( bufferIndex < 56 ) ? 56 - bufferIndex : 120 - bufferIndex; |
|||
byte[] tail = new byte[paddingLength + 8]; |
|||
tail[0] = (byte) 0x80; |
|||
for ( int i = 0; i < 8; i++ ) { |
|||
tail[paddingLength + i] = (byte) ( ( count * 8 ) >>> ( 8 * i ) ); |
|||
} |
|||
engineUpdate(tail, 0, tail.length); |
|||
byte[] result = new byte[16]; |
|||
for ( int i = 0; i < 4; i++ ) { |
|||
for ( int j = 0; j < 4; j++ ) { |
|||
result[i * 4 + j] = (byte) ( context[i] >>> ( 8 * j ) ); |
|||
} |
|||
} |
|||
engineReset(); |
|||
return result; |
|||
} |
|||
private void engineUpdate(byte[] aMessageBytes, int aOffset, int aMessageLength) { |
|||
if ( aOffset < 0 || aMessageLength < 0 || (long) aOffset + aMessageLength > (long) aMessageBytes.length ) { |
|||
throw new ArrayIndexOutOfBoundsException("Incorrect arguments for method engineUpdate"); |
|||
} |
|||
int bufferIndex = (int) ( count % BLOCK_LENGTH ); |
|||
count += aMessageLength; |
|||
final int partialLength = BLOCK_LENGTH - bufferIndex; |
|||
int i = 0; |
|||
if ( aMessageLength >= partialLength ) { |
|||
System.arraycopy(aMessageBytes, aOffset, buffer, bufferIndex, partialLength); |
|||
transform(buffer, 0); |
|||
i = partialLength; |
|||
while ( i + BLOCK_LENGTH - 1 < aMessageLength ) { |
|||
transform(aMessageBytes, aOffset + i); |
|||
i += BLOCK_LENGTH; |
|||
} |
|||
bufferIndex = 0; |
|||
} |
|||
if ( i < aMessageLength ) { |
|||
System.arraycopy(aMessageBytes, aOffset + i, buffer, bufferIndex, aMessageLength - i); |
|||
} |
|||
} |
|||
private void transform (byte[] aBuffer, int aOffset) { |
|||
for ( int i = 0; i < 16; i++ ) { |
|||
extra[i] = ( ( aBuffer[aOffset++] & 0xff ) ) | |
|||
( ( aBuffer[aOffset++] & 0xff ) << 8 ) | |
|||
( ( aBuffer[aOffset++] & 0xff ) << 16 ) | |
|||
( ( aBuffer[aOffset++] & 0xff ) << 24 ); |
|||
} |
|||
int a = context[0]; |
|||
int b = context[1]; |
|||
int c = context[2]; |
|||
int d = context[3]; |
|||
for ( int i : List.of( 0, 4, 8, 12 ) ) { |
|||
a = ff(a, b, c, d, extra[i + 0], 3); |
|||
d = ff(d, a, b, c, extra[i + 1], 7); |
|||
c = ff(c, d, a, b, extra[i + 2], 11); |
|||
b = ff(b, c, d, a, extra[i + 3], 19); |
|||
} |
|||
for ( int i : List.of( 0, 1, 2, 3 ) ) { |
|||
a = gg(a, b, c, d, extra[i + 0], 3); |
|||
d = gg(d, a, b, c, extra[i + 4], 5); |
|||
c = gg(c, d, a, b, extra[i + 8], 9); |
|||
b = gg(b, c, d, a, extra[i + 12], 13); |
|||
} |
|||
for ( int i : List.of( 0, 2, 1, 3 ) ) { |
|||
a = hh(a, b, c, d, extra[i + 0], 3); |
|||
d = hh(d, a, b, c, extra[i + 8], 9); |
|||
c = hh(c, d, a, b, extra[i + 4], 11); |
|||
b = hh(b, c, d, a, extra[i + 12], 15); |
|||
} |
|||
context[0] += a; |
|||
context[1] += b; |
|||
context[2] += c; |
|||
context[3] += d; |
|||
} |
|||
private void engineReset() { |
|||
count = 0; |
|||
context[0] = 0x67452301; |
|||
context[1] = 0xefcdab89; |
|||
context[2] = 0x98badcfe; |
|||
context[3] = 0x10325476; |
|||
Arrays.fill(extra, 0); |
|||
Arrays.fill(buffer, (byte) 0); |
|||
} |
|||
private static int rotate(int t, int s) { |
|||
return t << s | t >>> ( 32 - s ); |
|||
} |
|||
private static int ff(int a, int b, int c, int d, int x, int s) { |
|||
return rotate(a + ( ( b & c ) | ( ~b & d ) ) + x, s); |
|||
} |
|||
private static int gg(int a, int b, int c, int d, int x, int s) { |
|||
return rotate(a + ( ( b & ( c | d ) ) | ( c & d ) ) + x + 0x5A827999, s); |
|||
} |
|||
private static int hh(int a, int b, int c, int d, int x, int s) { |
|||
return rotate(a + ( b ^ c ^ d ) + x + 0x6ED9EBA1, s); |
|||
} |
|||
private static final int BLOCK_LENGTH = 64; |
|||
private long count; |
|||
private int[] context = new int[4]; |
|||
private int[] extra = new int[16]; |
|||
private byte[] buffer = new byte[BLOCK_LENGTH]; |
|||
} |
|||
</syntaxhighlight> |
|||
{{ out }} |
|||
<pre> |
|||
a52bcfc6a0d0d300cdc5ddbfbefe478b |
|||
</pre> |
|||
=={{header|JavaScript}}== |
|||
<syntaxhighlight lang="javascript">const md4func = () => { |
|||
const hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ |
|||
const b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ |
|||
const chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ |
|||
const tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
|||
const hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; |
|||
/** |
|||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally |
|||
* to work around bugs in some JS interpreters. |
|||
*/ |
|||
const safe_add = (x, y) => { |
|||
const lsw = (x & 0xFFFF) + (y & 0xFFFF); |
|||
const msw = (x >> 16) + (y >> 16) + (lsw >> 16); |
|||
return (msw << 16) | (lsw & 0xFFFF); |
|||
}; |
|||
/** |
|||
* Bitwise rotate a 32-bit number to the left. |
|||
*/ |
|||
const rol = (num, cnt) => (num << cnt) | (num >>> (32 - cnt)); |
|||
/** |
|||
* Convert a string to an array of little-endian words |
|||
* If chrsz is ASCII, characters >255 have their hi-byte silently ignored. |
|||
*/ |
|||
const str2binl = str => { |
|||
const bin = Array(); |
|||
const mask = (1 << chrsz) - 1; |
|||
for (let i = 0; i < str.length * chrsz; i += chrsz) |
|||
bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (i % 32); |
|||
return bin; |
|||
}; |
|||
/** |
|||
* Convert an array of little-endian words to a string |
|||
*/ |
|||
const binl2str = bin => { |
|||
let str = ""; |
|||
const mask = (1 << chrsz) - 1; |
|||
for (let i = 0; i < bin.length * 32; i += chrsz) |
|||
str += String.fromCharCode((bin[i >> 5] >>> (i % 32)) & mask); |
|||
return str; |
|||
}; |
|||
/** |
|||
* Convert an array of little-endian words to a hex string. |
|||
*/ |
|||
const binl2hex = binarray => { |
|||
let str = ""; |
|||
for (let i = 0; i < binarray.length * 4; i++) { |
|||
str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) + |
|||
hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF); |
|||
} |
|||
return str; |
|||
}; |
|||
/** |
|||
* Convert an array of little-endian words to a base-64 string |
|||
*/ |
|||
const binl2b64 = binarray => { |
|||
let str = ""; |
|||
for (let i = 0; i < binarray.length * 4; i += 3) { |
|||
const triplet = (((binarray[i >> 2] >> 8 * (i % 4)) & 0xFF) << 16) |
|||
| (((binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4)) & 0xFF) << 8) |
|||
| ((binarray[i + 2 >> 2] >> 8 * ((i + 2) % 4)) & 0xFF); |
|||
for (let j = 0; j < 4; j++) { |
|||
if (i * 8 + j * 6 > binarray.length * 32) str += b64pad; |
|||
else str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F); |
|||
} |
|||
} |
|||
return str; |
|||
}; |
|||
/** |
|||
* Calculate the MD4 of an array of little-endian words, and a bit length |
|||
*/ |
|||
const core_md4 = (x, len) => { |
|||
x[len >> 5] |= 0x80 << (len % 32); |
|||
x[(((len + 64) >>> 9) << 4) + 14] = len; |
|||
let a = 1732584193; |
|||
let b = -271733879; |
|||
let c = -1732584194; |
|||
let d = 271733878; |
|||
for (let i = 0; i < x.length; i += 16) { |
|||
const olda = a; |
|||
const oldb = b; |
|||
const oldc = c; |
|||
const oldd = d; |
|||
a = md4_ff(a, b, c, d, x[i], 3); |
|||
d = md4_ff(d, a, b, c, x[i + 1], 7); |
|||
c = md4_ff(c, d, a, b, x[i + 2], 11); |
|||
b = md4_ff(b, c, d, a, x[i + 3], 19); |
|||
a = md4_ff(a, b, c, d, x[i + 4], 3); |
|||
d = md4_ff(d, a, b, c, x[i + 5], 7); |
|||
c = md4_ff(c, d, a, b, x[i + 6], 11); |
|||
b = md4_ff(b, c, d, a, x[i + 7], 19); |
|||
a = md4_ff(a, b, c, d, x[i + 8], 3); |
|||
d = md4_ff(d, a, b, c, x[i + 9], 7); |
|||
c = md4_ff(c, d, a, b, x[i + 10], 11); |
|||
b = md4_ff(b, c, d, a, x[i + 11], 19); |
|||
a = md4_ff(a, b, c, d, x[i + 12], 3); |
|||
d = md4_ff(d, a, b, c, x[i + 13], 7); |
|||
c = md4_ff(c, d, a, b, x[i + 14], 11); |
|||
b = md4_ff(b, c, d, a, x[i + 15], 19); |
|||
a = md4_gg(a, b, c, d, x[i], 3); |
|||
d = md4_gg(d, a, b, c, x[i + 4], 5); |
|||
c = md4_gg(c, d, a, b, x[i + 8], 9); |
|||
b = md4_gg(b, c, d, a, x[i + 12], 13); |
|||
a = md4_gg(a, b, c, d, x[i + 1], 3); |
|||
d = md4_gg(d, a, b, c, x[i + 5], 5); |
|||
c = md4_gg(c, d, a, b, x[i + 9], 9); |
|||
b = md4_gg(b, c, d, a, x[i + 13], 13); |
|||
a = md4_gg(a, b, c, d, x[i + 2], 3); |
|||
d = md4_gg(d, a, b, c, x[i + 6], 5); |
|||
c = md4_gg(c, d, a, b, x[i + 10], 9); |
|||
b = md4_gg(b, c, d, a, x[i + 14], 13); |
|||
a = md4_gg(a, b, c, d, x[i + 3], 3); |
|||
d = md4_gg(d, a, b, c, x[i + 7], 5); |
|||
c = md4_gg(c, d, a, b, x[i + 11], 9); |
|||
b = md4_gg(b, c, d, a, x[i + 15], 13); |
|||
a = md4_hh(a, b, c, d, x[i], 3); |
|||
d = md4_hh(d, a, b, c, x[i + 8], 9); |
|||
c = md4_hh(c, d, a, b, x[i + 4], 11); |
|||
b = md4_hh(b, c, d, a, x[i + 12], 15); |
|||
a = md4_hh(a, b, c, d, x[i + 2], 3); |
|||
d = md4_hh(d, a, b, c, x[i + 10], 9); |
|||
c = md4_hh(c, d, a, b, x[i + 6], 11); |
|||
b = md4_hh(b, c, d, a, x[i + 14], 15); |
|||
a = md4_hh(a, b, c, d, x[i + 1], 3); |
|||
d = md4_hh(d, a, b, c, x[i + 9], 9); |
|||
c = md4_hh(c, d, a, b, x[i + 5], 11); |
|||
b = md4_hh(b, c, d, a, x[i + 13], 15); |
|||
a = md4_hh(a, b, c, d, x[i + 3], 3); |
|||
d = md4_hh(d, a, b, c, x[i + 11], 9); |
|||
c = md4_hh(c, d, a, b, x[i + 7], 11); |
|||
b = md4_hh(b, c, d, a, x[i + 15], 15); |
|||
a = safe_add(a, olda); |
|||
b = safe_add(b, oldb); |
|||
c = safe_add(c, oldc); |
|||
d = safe_add(d, oldd); |
|||
} |
|||
return Array(a, b, c, d); |
|||
}; |
|||
/** |
|||
* These functions implement the basic operation for each round of the |
|||
* algorithm. |
|||
*/ |
|||
const md4_cmn = (q, a, b, x, s, t) => safe_add( |
|||
rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); |
|||
const md4_ff = (a, b, c, d, x, s) => md4_cmn( |
|||
(b & c) | ((~b) & d), a, 0, x, s, 0); |
|||
const md4_gg = (a, b, c, d, x, s) => md4_cmn( |
|||
(b & c) | (b & d) | (c & d), a, 0, x, s, 1518500249); |
|||
const md4_hh = (a, b, c, d, x, s) => md4_cmn( |
|||
b ^ c ^ d, a, 0, x, s, 1859775393); |
|||
/** |
|||
* Calculate the HMAC-MD4, of a key and some data |
|||
*/ |
|||
const core_hmac_md4 = (key, data) => { |
|||
let bkey = str2binl(key); |
|||
if (bkey.length > 16) { |
|||
bkey = core_md4(bkey, key.length * chrsz) |
|||
} |
|||
const ipad = Array(16); |
|||
const opad = Array(16); |
|||
for (let i = 0; i < 16; i++) { |
|||
ipad[i] = bkey[i] ^ 0x36363636; |
|||
opad[i] = bkey[i] ^ 0x5C5C5C5C; |
|||
} |
|||
const hash = core_md4( |
|||
ipad.concat(str2binl(data)), 512 + data.length * chrsz); |
|||
return core_md4(opad.concat(hash), 512 + 128); |
|||
}; |
|||
/** |
|||
* These are the functions you'll usually want to call |
|||
*/ |
|||
return { |
|||
hex_md4: s => binl2hex(core_md4(str2binl(s), s.length * chrsz)), |
|||
b64_md4: s => binl2b64(core_md4(str2binl(s), s.length * chrsz)), |
|||
str_md4: s => binl2str(core_md4(str2binl(s), s.length * chrsz)), |
|||
hex_hmac_md4: (key, data) => binl2hex(core_hmac_md4(key, data)), |
|||
b64_hmac_md4: (key, data) => binl2b64(core_hmac_md4(key, data)), |
|||
str_hmac_md4: (key, data) => binl2str(core_hmac_md4(key, data)), |
|||
}; |
|||
}; |
|||
const md4 = md4func(); |
|||
console.log(md4.hex_md4('Rosetta Code'));</syntaxhighlight> |
|||
{{out}} |
|||
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
|||
=={{header|Julia}}== |
|||
[https://github.com/staticfloat/Nettle.jl Nettle.jl] provides a variety of cryptographic functions including the <tt>MD4</tt> hash. |
|||
<syntaxhighlight lang="julia"> |
|||
using Nettle |
|||
msg = "Rosetta Code" |
|||
h = HashState(MD4) |
|||
update!(h, msg) |
|||
h = hexdigest!(h) |
|||
println("\"", msg, "\" => ", h) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
"Rosetta Code" => a52bcfc6a0d0d300cdc5ddbfbefe478b |
|||
</pre> |
|||
=={{header|Kotlin}}== |
|||
This is a translation of the Java code [http://www.java2s.com/Code/Java/Security/ImplementstheMD4messagedigestalgorithminJava.htm here]. In the interests of conciseness, I have removed the comments from the Kotlin version: |
|||
<syntaxhighlight lang="scala">// version 1.0.6 |
|||
import java.security.MessageDigest |
|||
class MD4() : MessageDigest("MD4"), Cloneable { |
|||
private val blockLength = 64 |
|||
private var context = IntArray(4) |
|||
private var count = 0L |
|||
private var buffer = ByteArray(blockLength) |
|||
private var x = IntArray(16) |
|||
init { |
|||
engineReset() |
|||
} |
|||
private constructor(md: MD4): this() { |
|||
context = md.context.clone() |
|||
buffer = md.buffer.clone() |
|||
count = md.count |
|||
} |
|||
override fun clone(): Any = MD4(this) |
|||
override fun engineReset() { |
|||
context[0] = 0x67452301 |
|||
context[1] = 0xefcdab89.toInt() |
|||
context[2] = 0x98badcfe.toInt() |
|||
context[3] = 0x10325476 |
|||
count = 0L |
|||
for (i in 0 until blockLength) buffer[i] = 0 |
|||
} |
|||
override fun engineUpdate(b: Byte) { |
|||
val i = (count % blockLength).toInt() |
|||
count++ |
|||
buffer[i] = b |
|||
if (i == blockLength - 1) transform(buffer, 0) |
|||
} |
|||
override fun engineUpdate(input: ByteArray, offset: Int, len: Int) { |
|||
if (offset < 0 || len < 0 || offset.toLong() + len > input.size.toLong()) |
|||
throw ArrayIndexOutOfBoundsException() |
|||
var bufferNdx = (count % blockLength).toInt() |
|||
count += len |
|||
val partLen = blockLength - bufferNdx |
|||
var i = 0 |
|||
if (len >= partLen) { |
|||
System.arraycopy(input, offset, buffer, bufferNdx, partLen) |
|||
transform(buffer, 0) |
|||
i = partLen |
|||
while (i + blockLength - 1 < len) { |
|||
transform(input, offset + i) |
|||
i += blockLength |
|||
} |
|||
bufferNdx = 0 |
|||
} |
|||
if (i < len) System.arraycopy(input, offset + i, buffer, bufferNdx, len - i) |
|||
} |
|||
override fun engineDigest(): ByteArray { |
|||
val bufferNdx = (count % blockLength).toInt() |
|||
val padLen = if (bufferNdx < 56) 56 - bufferNdx else 120 - bufferNdx |
|||
val tail = ByteArray(padLen + 8) |
|||
tail[0] = 0x80.toByte() |
|||
for (i in 0..7) tail[padLen + i] = ((count * 8) ushr (8 * i)).toByte() |
|||
engineUpdate(tail, 0, tail.size) |
|||
val result = ByteArray(16) |
|||
for (i in 0..3) |
|||
for (j in 0..3) |
|||
result[i * 4 + j] = (context[i] ushr (8 * j)).toByte() |
|||
engineReset() |
|||
return result |
|||
} |
|||
private fun transform (block: ByteArray, offset: Int) { |
|||
var offset2 = offset |
|||
for (i in 0..15) |
|||
x[i] = ((block[offset2++].toInt() and 0xff) ) or |
|||
((block[offset2++].toInt() and 0xff) shl 8 ) or |
|||
((block[offset2++].toInt() and 0xff) shl 16) or |
|||
((block[offset2++].toInt() and 0xff) shl 24) |
|||
var a = context[0] |
|||
var b = context[1] |
|||
var c = context[2] |
|||
var d = context[3] |
|||
a = ff(a, b, c, d, x[ 0], 3) |
|||
d = ff(d, a, b, c, x[ 1], 7) |
|||
c = ff(c, d, a, b, x[ 2], 11) |
|||
b = ff(b, c, d, a, x[ 3], 19) |
|||
a = ff(a, b, c, d, x[ 4], 3) |
|||
d = ff(d, a, b, c, x[ 5], 7) |
|||
c = ff(c, d, a, b, x[ 6], 11) |
|||
b = ff(b, c, d, a, x[ 7], 19) |
|||
a = ff(a, b, c, d, x[ 8], 3) |
|||
d = ff(d, a, b, c, x[ 9], 7) |
|||
c = ff(c, d, a, b, x[10], 11) |
|||
b = ff(b, c, d, a, x[11], 19) |
|||
a = ff(a, b, c, d, x[12], 3) |
|||
d = ff(d, a, b, c, x[13], 7) |
|||
c = ff(c, d, a, b, x[14], 11) |
|||
b = ff(b, c, d, a, x[15], 19) |
|||
a = gg(a, b, c, d, x[ 0], 3) |
|||
d = gg(d, a, b, c, x[ 4], 5) |
|||
c = gg(c, d, a, b, x[ 8], 9) |
|||
b = gg(b, c, d, a, x[12], 13) |
|||
a = gg(a, b, c, d, x[ 1], 3) |
|||
d = gg(d, a, b, c, x[ 5], 5) |
|||
c = gg(c, d, a, b, x[ 9], 9) |
|||
b = gg(b, c, d, a, x[13], 13) |
|||
a = gg(a, b, c, d, x[ 2], 3) |
|||
d = gg(d, a, b, c, x[ 6], 5) |
|||
c = gg(c, d, a, b, x[10], 9) |
|||
b = gg(b, c, d, a, x[14], 13) |
|||
a = gg(a, b, c, d, x[ 3], 3) |
|||
d = gg(d, a, b, c, x[ 7], 5) |
|||
c = gg(c, d, a, b, x[11], 9) |
|||
b = gg(b, c, d, a, x[15], 13) |
|||
a = hh(a, b, c, d, x[ 0], 3) |
|||
d = hh(d, a, b, c, x[ 8], 9) |
|||
c = hh(c, d, a, b, x[ 4], 11) |
|||
b = hh(b, c, d, a, x[12], 15) |
|||
a = hh(a, b, c, d, x[ 2], 3) |
|||
d = hh(d, a, b, c, x[10], 9) |
|||
c = hh(c, d, a, b, x[ 6], 11) |
|||
b = hh(b, c, d, a, x[14], 15) |
|||
a = hh(a, b, c, d, x[ 1], 3) |
|||
d = hh(d, a, b, c, x[ 9], 9) |
|||
c = hh(c, d, a, b, x[ 5], 11) |
|||
b = hh(b, c, d, a, x[13], 15) |
|||
a = hh(a, b, c, d, x[ 3], 3) |
|||
d = hh(d, a, b, c, x[11], 9) |
|||
c = hh(c, d, a, b, x[ 7], 11) |
|||
b = hh(b, c, d, a, x[15], 15) |
|||
context[0] += a |
|||
context[1] += b |
|||
context[2] += c |
|||
context[3] += d |
|||
} |
|||
private fun ff(a: Int, b: Int, c: Int, d: Int, x: Int, s: Int): Int { |
|||
val t = a + ((b and c) or (b.inv() and d)) + x |
|||
return (t shl s) or (t ushr (32 - s)) |
|||
} |
|||
private fun gg(a: Int, b: Int, c: Int, d: Int, x: Int, s: Int): Int { |
|||
val t = a + ((b and (c or d)) or (c and d)) + x + 0x5a827999 |
|||
return (t shl s) or (t ushr (32 - s)) |
|||
} |
|||
private fun hh(a: Int, b: Int, c: Int, d: Int, x: Int, s: Int): Int { |
|||
val t = a + (b xor c xor d) + x + 0x6ed9eba1 |
|||
return (t shl s) or (t ushr (32 - s)) |
|||
} |
|||
} |
|||
fun main(args: Array<String>) { |
|||
val text = "Rosetta Code" |
|||
val bytes = text.toByteArray(Charsets.US_ASCII) |
|||
val md: MessageDigest = MD4() |
|||
val digest = md.digest(bytes) |
|||
for (byte in digest) print("%02x".format(byte)) |
|||
println() |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
a52bcfc6a0d0d300cdc5ddbfbefe478b |
|||
</pre> |
|||
=={{header|Lasso}}== |
=={{header|Lasso}}== |
||
< |
<syntaxhighlight lang="lasso">cipher_digest('Rosetta Code', -digest='MD4')->encodeHex->asString</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> A52BCFC6A0D0D300CDC5DDBFBEFE478B </pre> |
<pre> A52BCFC6A0D0D300CDC5DDBFBEFE478B </pre> |
||
Line 165: | Line 1,538: | ||
{{libheader|LuaCrypto}} ([http://mkottman.github.io/luacrypto/ luarocks install LuaCrypto]) |
{{libheader|LuaCrypto}} ([http://mkottman.github.io/luacrypto/ luarocks install LuaCrypto]) |
||
< |
<syntaxhighlight lang="lua">#!/usr/bin/lua |
||
require "crypto" |
require "crypto" |
||
print(crypto.digest("MD4", "Rosetta Code"))</ |
print(crypto.digest("MD4", "Rosetta Code"))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
||
=={{header| |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
<syntaxhighlight lang="mathematica">Hash["Rosetta Code", "MD4", "HexString"]</syntaxhighlight> |
|||
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
|||
=={{header|Nim}}== |
|||
{{libheader|OpenSSL}} |
{{libheader|OpenSSL}} |
||
<syntaxhighlight lang="nim">import strutils |
|||
Compile with <code>nimrod -d:ssl c md4.nim</code>: |
|||
<lang nimrod>import strutils |
|||
const MD4Len = 16 |
const MD4Len = 16 |
||
Line 186: | Line 1,562: | ||
result = "" |
result = "" |
||
var s = MD4(s.cstring, s.len.culong) |
var s = MD4(s.cstring, s.len.culong) |
||
for i in 0 .. |
for i in 0 ..< MD4Len: |
||
result.add s[i].BiggestInt.toHex(2).toLower |
result.add s[i].BiggestInt.toHex(2).toLower |
||
echo MD4("Rosetta Code")</ |
echo MD4("Rosetta Code")</syntaxhighlight> |
||
{{out}} |
|||
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
|||
=={{header|PARI/GP}}== |
|||
Build a MD4 plugin using Linux system library and PARI's function interface. (Linux solution) |
|||
<syntaxhighlight lang="c">#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); |
|||
}</syntaxhighlight> |
|||
Compile with: gcc -Wall -O2 -fPIC -shared md4.c -o libmd4.so -lcrypt -lpari |
|||
Load plugin from your home directory into PARI: |
|||
<syntaxhighlight lang="parigp">install("plug_md4", "s", "MD4", "~/libmd4.so"); |
|||
MD4("Rosetta Code") </syntaxhighlight> |
|||
Output: "a52bcfc6a0d0d300cdc5ddbfbefe478b" |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
In-lining code from module [https://metacpan.org/pod/Digest::Perl::MD4 Digest::Perl::MD4], lightly edited for clarity. |
|||
<lang Perl>#!/usr/bin/perl |
|||
<syntaxhighlight lang="perl">sub md4 :prototype(@) { |
|||
use strict ; |
|||
my @input = grep { defined && length > 0 } split /(.{64})/s, join '', @_; |
|||
use warnings ; |
|||
push @input, '' if !@input || length($input[$#input]) >= 56; |
|||
use Digest::MD4 qw( md4_hex ) ; |
|||
my @A = (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476); # initial regs |
|||
print "Rosetta Code => " , md4_hex( "Rosetta Code" ) , "\n" ;</lang> |
|||
my @T = (0, 0x5A827999, 0x6ED9EBA1); |
|||
my @L = qw(3 7 11 19 3 5 9 13 3 9 11 15); # left rotate counts |
|||
my @O = (1, 4, 4, # x stride for input index |
|||
4, 1, 1, # y stride for input index |
|||
0, 0, 1); # bitwise reverse both indexes |
|||
my @I = map { |
|||
my $z = int $_/16; |
|||
my $x = $_%4; |
|||
my $y = int $_%16/4; |
|||
($x,$y) = (R($x),R($y)) if $O[6+$z]; |
|||
$O[$z] * $x + $O[3+$z] * $y |
|||
} 0..47; |
|||
my ($a,$b,$c,$d); |
|||
my($l,$p) = (0,0); |
|||
foreach (@input) { |
|||
my $r = length($_); |
|||
$l += $r; |
|||
$r++, $_.="\x80" if $r<64 && !$p++; |
|||
my @W = unpack 'V16', $_ . "\0"x7; |
|||
push @W, (0)x16 if @W < 16; |
|||
$W[14] = $l*8 if $r < 57; # add bit-length in low 32-bits |
|||
($a,$b,$c,$d) = @A; |
|||
for (0..47) { |
|||
my $z = int $_/16; |
|||
$a = L($L[4*($_>>4) + $_%4], |
|||
M(&{(sub{$b&$c|~$b&$d}, # F |
|||
sub{$b&$c|$b&$d|$c&$d}, # G |
|||
sub{$b^$c^$d} # H |
|||
)[$z]} |
|||
+ $a + $W[$I[$_]] + $T[$z])); |
|||
($a,$b,$c,$d) = ($d,$a,$b,$c); |
|||
} |
|||
my @v = ($a, $b, $c, $d); |
|||
$A[$_] = M($A[$_] + $v[$_]) for 0..3; |
|||
} |
|||
pack 'V4', @A; |
|||
} |
|||
sub L { # left-rotate |
|||
my ($n, $x) = @_; |
|||
$x<<$n | 2**$n - 1 & $x>>(32-$n); |
|||
} |
|||
sub M { # mod 2**32 |
|||
no integer; |
|||
my ($x) = @_; |
|||
my $m = 1+0xffffffff; |
|||
$x - $m * int $x/$m; |
|||
} |
|||
sub R { # reverse two bit number |
|||
my $n = pop; |
|||
($n&1)*2 + ($n&2)/2; |
|||
} |
|||
sub md4_hex :prototype(@) { # convert to hexadecimal |
|||
unpack 'H*', &md4; |
|||
} |
|||
print "Rosetta Code => " . md4_hex( "Rosetta Code" ) . "\n";</syntaxhighlight> |
|||
{{out}} |
{{out}} |
||
<pre>Rosetta Code => a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
<pre>Rosetta Code => a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
||
=={{header|Perl 6}}== |
|||
<lang perl6>sub md4($str) { |
|||
my @buf = $str.ords; |
|||
my $buflen = @buf.elems; |
|||
=={{header|Phix}}== |
|||
my \mask = (1 +< 32) - 1; |
|||
{{trans|D}} |
|||
my &f = -> $x, $y, $z { ($x +& $y) +| ($x +^ mask) +& $z } |
|||
{{trans|Ruby}} |
|||
my &g = -> $x, $y, $z { ($x +& $y) +| ($x +& $z) +| ($y +& $z) } |
|||
<!--<syntaxhighlight lang="phix">(notonline)--> |
|||
my &h = -> $x, $y, $z { $x +^ $y +^ $z } |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
my &r = -> $v, $s { (($v +< $s) +& mask) +| (($v +& mask) +> (32 - $s)) } |
|||
-- demo\rosetta\md4.exw |
|||
-- ==================== |
|||
sub pack-le (@a) { |
|||
-- |
|||
gather for @a -> $a,$b,$c,$d { take $d +< 24 + $c +< 16 + $b +< 8 + $a } |
|||
-- Non-optimised. If there is a genuine need for something faster, I can give #ilASM a bash. |
|||
} |
|||
-- MD4 is an obsolete hash function that computes a 128-bit message digest that sometimes appears in obsolete protocols. |
|||
-- Even the replacement, MD5 is now considered severly comprimised. |
|||
--</span> |
|||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (allocate/poke/peek)</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">+=</span><span style="color: #000000;">#100000000</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#100000000</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">bits</span><span style="color: #0000FF;">)</span> |
|||
my ($a, $b, $c, $d) = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476; |
|||
<span style="color: #000080;font-style:italic;">-- left rotate the bits of a 32-bit number by the specified number of bits</span> |
|||
<span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- trim to a 32-bit uint again</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">*</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bits</span><span style="color: #0000FF;">))+</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">/</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">-</span><span style="color: #000000;">bits</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)</span> |
|||
my $term = False; |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">or_bits</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">not_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">),</span><span style="color: #000000;">z</span><span style="color: #0000FF;">))</span> |
|||
my $last = False; |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
my $off = 0; |
|||
repeat until $last { |
|||
my @block = @buf[$off..$off+63]:v; $off += 64; |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)</span> |
|||
my @x; |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">or_all</span><span style="color: #0000FF;">({</span><span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">)),</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)})</span> |
|||
given +@block { |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
when 64 { |
|||
@x = pack-le @block; |
|||
} |
|||
when 56..63 { |
|||
$term = True; |
|||
@block.push(0x80); |
|||
@block.push(0 xx 63 - $_); |
|||
@x = pack-le @block; |
|||
} |
|||
when 0..55 { |
|||
@block.push($term ?? 0 !! 0x80); |
|||
@block.push(0 xx 55 - $_); |
|||
@x = pack-le @block; |
|||
my $bit_len = $buflen +< 3; |
|||
@x.push: $bit_len +& mask, $bit_len +> 32; |
|||
$last = True; |
|||
} |
|||
default { |
|||
die "oops"; |
|||
} |
|||
} |
|||
my ($aa, $bb, $cc, $dd) = $a, $b, $c, $d; |
|||
for 0, 4, 8, 12 -> \i { |
|||
$a = r($a + f($b, $c, $d) + @x[ i+0 ], 3); |
|||
$d = r($d + f($a, $b, $c) + @x[ i+1 ], 7); |
|||
$c = r($c + f($d, $a, $b) + @x[ i+2 ], 11); |
|||
$b = r($b + f($c, $d, $a) + @x[ i+3 ], 19); |
|||
} |
|||
for 0, 1, 2, 3 -> \i { |
|||
$a = r($a + g($b, $c, $d) + @x[ i+0 ] + 0x5a827999, 3); |
|||
$d = r($d + g($a, $b, $c) + @x[ i+4 ] + 0x5a827999, 5); |
|||
$c = r($c + g($d, $a, $b) + @x[ i+8 ] + 0x5a827999, 9); |
|||
$b = r($b + g($c, $d, $a) + @x[ i+12] + 0x5a827999, 13); |
|||
} |
|||
for 0, 2, 1, 3 -> \i { |
|||
$a = r($a + h($b, $c, $d) + @x[ i+0 ] + 0x6ed9eba1, 3); |
|||
$d = r($d + h($a, $b, $c) + @x[ i+8 ] + 0x6ed9eba1, 9); |
|||
$c = r($c + h($d, $a, $b) + @x[ i+4 ] + 0x6ed9eba1, 11); |
|||
$b = r($b + h($c, $d, $a) + @x[ i+12] + 0x6ed9eba1, 15); |
|||
} |
|||
$a = ($a + $aa) +& mask; |
|||
$b = ($b + $bb) +& mask; |
|||
$c = ($c + $cc) +& mask; |
|||
$d = ($d + $dd) +& mask; |
|||
} |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)</span> |
|||
sub b2l($n is copy) { |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">)),</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)</span> |
|||
my $x = 0; |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
for ^4 { |
|||
$x +<= 8; |
|||
$x += $n +& 0xff; |
|||
$n +>= 8; |
|||
} |
|||
$x; |
|||
} |
|||
b2l($a) +< 96 + |
|||
b2l($b) +< 64 + |
|||
b2l($c) +< 32 + |
|||
b2l($d); |
|||
} |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">md4</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">)</span> |
|||
sub MAIN { |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">bytes_to_add</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">64</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span><span style="color: #000000;">64</span><span style="color: #0000FF;">)</span> |
|||
my $str = 'Rosetta Code'; |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">bytes_to_add</span><span style="color: #0000FF;">=</span><span style="color: #000000;">64</span> <span style="color: #008080;">then</span> <span style="color: #000000;">bytes_to_add</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
say md4($str).base(16).lc; |
|||
<span style="color: #000000;">data</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">&</span><span style="color: #000000;">#80</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bytes_to_add</span><span style="color: #0000FF;">)&</span> |
|||
}</lang> |
|||
<span style="color: #7060A8;">int_to_bytes</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0x67452301</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0xefcdab89</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0x98badcfe</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0x10325476</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">m64</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">64</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">data</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #000000;">64</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #7060A8;">poke</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m64</span><span style="color: #0000FF;">,</span><span style="color: #000000;">data</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">..</span><span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">63</span><span style="color: #0000FF;">])</span> |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">z</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">peek4u</span><span style="color: #0000FF;">({</span><span style="color: #000000;">m64</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">a2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">by</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">19</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0x5a827999</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0x5a827999</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">8</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0x5a827999</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">12</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0x5a827999</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">}[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0x6ed9eba1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">8</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0x6ed9eba1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0x6ed9eba1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rol</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">h</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">12</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0x6ed9eba1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">a2</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">+</span><span style="color: #000000;">b2</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">+</span><span style="color: #000000;">c2</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">+</span><span style="color: #000000;">d2</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #7060A8;">poke4</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m64</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">peek</span><span style="color: #0000FF;">({</span><span style="color: #000000;">m64</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">hexify</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%02X"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #0000FF;">?</span><span style="color: #000000;">hexify</span><span style="color: #0000FF;">(</span><span style="color: #000000;">md4</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Rosetta Code"</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<pre> |
|||
"a52bcfc6a0d0d300cdc5ddbfbefe478b" |
|||
</pre> |
|||
=={{header|PHP}}== |
|||
<syntaxhighlight lang="php"> |
|||
echo hash('md4', "Rosetta Code"), "\n"; |
|||
</syntaxhighlight> |
|||
{{out}} |
{{out}} |
||
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
||
Line 298: | Line 1,785: | ||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
Library and implementation. |
Library and implementation. |
||
< |
<syntaxhighlight lang="picolisp">(de *Md4-W . |
||
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
||
1 5 9 13 2 6 10 14 3 7 11 15 4 8 12 16 |
1 5 9 13 2 6 10 14 3 7 11 15 4 8 12 16 |
||
Line 473: | Line 1,960: | ||
'(NIL (16)) ) ) ) ) ) |
'(NIL (16)) ) ) ) ) ) |
||
(bye)</ |
(bye)</syntaxhighlight> |
||
=={{header|PHP}}== |
|||
<lang php> |
|||
echo hash('md4', "Rosetta Code"), "\n"; |
|||
</lang> |
|||
{{out}} |
|||
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
Depending on how your python was compiled, 'hashlib' from python's standard library may provide md4 hashing. |
|||
{{libheader|hashlib}} |
{{libheader|hashlib}} |
||
< |
<syntaxhighlight lang="python">import hashlib |
||
print hashlib.new("md4",raw_input().encode('utf-16le')).hexdigest().upper()</ |
print hashlib.new("md4",raw_input().encode('utf-16le')).hexdigest().upper()</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang racket |
#lang racket |
||
(require (planet soegaard/digest:1:2/digest)) |
(require (planet soegaard/digest:1:2/digest)) |
||
(md4 #"Rosetta Code") |
(md4 #"Rosetta Code") |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
|||
Output: |
|||
<pre> |
|||
<lang racket> |
|||
"a52bcfc6a0d0d300cdc5ddbfbefe478b" |
"a52bcfc6a0d0d300cdc5ddbfbefe478b" |
||
</ |
</pre> |
||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
<syntaxhighlight lang="raku" line>sub md4($str) { |
|||
my buf8 $buf .= new: $str.encode; |
|||
my $buf-length = $buf.elems; |
|||
$buf.push: 0x80; |
|||
$buf.push: 0 until ($buf - (448 div 8)) %% (512 div 8); |
|||
# raku serializes in little endian by default |
|||
$buf.write-uint64: $buf.elems, $buf-length*8; |
|||
my (&f, &g, &h, &r) = |
|||
{ $^x +& $^y +| +^$x +& $^z }, |
|||
{ $^x +& $^y +| $x +& $^z +| $y +& $z }, |
|||
{ $^x +^ $^y +^ $^z }, |
|||
# for some reason we have to type v here |
|||
-> uint32 $v, $s { $v +< $s +| $v +> (32 - $s) } |
|||
my uint32 ($a, $b, $c, $d) = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476; |
|||
loop (my $pos = 0; $pos < $buf.elems; $pos+=64) { |
|||
my ($aa, $bb, $cc, $dd) = $a, $b, $c, $d; |
|||
for 0, 4, 8, 12 -> $i { |
|||
$a = r($a + f($b, $c, $d) + $buf.read-uint32($pos+($i+0)*4), 3); |
|||
$d = r($d + f($a, $b, $c) + $buf.read-uint32($pos+($i+1)*4), 7); |
|||
$c = r($c + f($d, $a, $b) + $buf.read-uint32($pos+($i+2)*4), 11); |
|||
$b = r($b + f($c, $d, $a) + $buf.read-uint32($pos+($i+3)*4), 19); |
|||
} |
|||
for 0, 1, 2, 3 -> $i { |
|||
$a = r($a + g($b, $c, $d) + $buf.read-uint32($pos+($i+0 )*4) + 0x5a827999, 3); |
|||
$d = r($d + g($a, $b, $c) + $buf.read-uint32($pos+($i+4 )*4) + 0x5a827999, 5); |
|||
$c = r($c + g($d, $a, $b) + $buf.read-uint32($pos+($i+8 )*4) + 0x5a827999, 9); |
|||
$b = r($b + g($c, $d, $a) + $buf.read-uint32($pos+($i+12)*4) + 0x5a827999, 13); |
|||
} |
|||
for 0, 2, 1, 3 -> $i { |
|||
$a = r($a + h($b, $c, $d) + $buf.read-uint32($pos+($i+0 )*4) + 0x6ed9eba1, 3); |
|||
$d = r($d + h($a, $b, $c) + $buf.read-uint32($pos+($i+4 )*4) + 0x6ed9eba1, 9); |
|||
$c = r($c + h($d, $a, $b) + $buf.read-uint32($pos+($i+8 )*4) + 0x6ed9eba1, 11); |
|||
$b = r($b + h($c, $d, $a) + $buf.read-uint32($pos+($i+12)*4) + 0x6ed9eba1, 15); |
|||
} |
|||
($a,$b,$c,$d) Z[+=] ($aa,$bb,$cc,$dd); |
|||
} |
|||
reduce { $^buf.write-uint32: $buf.elems, $^x; $buf }, buf8.new, $a, $b, $c, $d; |
|||
} |
|||
CHECK { |
|||
use Test; |
|||
plan 1; |
|||
is md4('Rosetta Code').list.fmt('%02X'), 'A5 2B CF C6 A0 D0 D3 00 CD C5 DD BF BE FE 47 8B'; |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>1..1 |
|||
ok 1 - |
|||
</pre> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
Use 'openssl' from Ruby's standard library. |
Use 'openssl' from Ruby's standard library. |
||
{{libheader|OpenSSL}} |
{{libheader|OpenSSL}} |
||
< |
<syntaxhighlight lang="ruby">require 'openssl' |
||
puts OpenSSL::Digest::MD4.hexdigest('Rosetta Code')</ |
puts OpenSSL::Digest::MD4.hexdigest('Rosetta Code')</syntaxhighlight> |
||
Implement MD4 in Ruby. |
Implement MD4 in Ruby. |
||
< |
<syntaxhighlight lang="ruby">require 'stringio' |
||
# Calculates MD4 message digest of _string_. Returns binary digest. |
# Calculates MD4 message digest of _string_. Returns binary digest. |
||
Line 573: | Line 2,107: | ||
str = 'Rosetta Code' |
str = 'Rosetta Code' |
||
printf "%s:\n %s\n", str, *md4(str).unpack('H*') |
printf "%s:\n %s\n", str, *md4(str).unpack('H*') |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Rosetta Code: |
<pre>Rosetta Code: |
||
a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
a52bcfc6a0d0d300cdc5ddbfbefe478b</pre> |
||
=={{header|Rust}}== |
|||
<syntaxhighlight lang="rust">// 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))); |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
md4("Rosetta Code") = a52bcfc6a0d0d300cdc5ddbfbefe478b |
|||
</pre> |
|||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
{{libheader|Scala}} |
|||
[[Category:Scala Implementations]]{{libheader|Scala}}<lang Scala>import org.bouncycastle.crypto.digests.MD4Digest |
|||
<syntaxhighlight lang="scala">import org.bouncycastle.crypto.digests.MD4Digest |
|||
object RosettaRIPEMD160 extends App { |
object RosettaRIPEMD160 extends App { |
||
Line 590: | Line 2,332: | ||
import scala.compat.Platform.currentTime |
import scala.compat.Platform.currentTime |
||
println(s"Successfully completed without errors. [total ${currentTime - executionStart} ms]") |
println(s"Successfully completed without errors. [total ${currentTime - executionStart} ms]") |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Seed7}}== |
=={{header|Seed7}}== |
||
< |
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i"; |
||
include "msgdigest.s7i"; |
include "msgdigest.s7i"; |
||
Line 599: | Line 2,341: | ||
begin |
begin |
||
writeln(hex(md4("Rosetta Code"))); |
writeln(hex(md4("Rosetta Code"))); |
||
end func;</ |
end func;</syntaxhighlight> |
||
{{out}} |
|||
<pre> |
|||
a52bcfc6a0d0d300cdc5ddbfbefe478b |
|||
</pre> |
|||
=={{header|Sidef}}== |
|||
{{trans|Perl}} |
|||
<syntaxhighlight lang="ruby">var digest = frequire('Digest::MD4'); |
|||
say digest.md4_hex('Rosetta Code');</syntaxhighlight> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 608: | Line 2,359: | ||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
{{tcllib|md4}} |
{{tcllib|md4}} |
||
< |
<syntaxhighlight lang="tcl">package require md4 |
||
# Use -hex option for hexadecimal output instead of binary |
# Use -hex option for hexadecimal output instead of binary |
||
puts [md4::md4 -hex "Rosetta Code"]</ |
puts [md4::md4 -hex "Rosetta Code"]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>A52BCFC6A0D0D300CDC5DDBFBEFE478B</pre> |
<pre>A52BCFC6A0D0D300CDC5DDBFBEFE478B</pre> |
||
=={{header|Wren}}== |
|||
{{trans|D}} |
|||
{{libheader|Wren-fmt}} |
|||
<syntaxhighlight lang="wren">import "./fmt" for Fmt |
|||
var toBytes = Fn.new { |val| |
|||
var bytes = List.filled(4, 0) |
|||
bytes[0] = val & 255 |
|||
bytes[1] = (val >> 8) & 255 |
|||
bytes[2] = (val >> 16) & 255 |
|||
bytes[3] = (val >> 24) & 255 |
|||
return bytes |
|||
} |
|||
var toInt = Fn.new { |bytes| bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24 } |
|||
var md4 = Fn.new { |initMsg| |
|||
var f = Fn.new { |x, y, z| (x & y) | (~x & z) } |
|||
var g = Fn.new { |x, y, z| (x & y) | (x & z) | (y & z) } |
|||
var h = Fn.new { |x, y, z| x ^ y ^ z } |
|||
var r = Fn.new { |v, s| (v << s) | (v >> (32 - s)) } |
|||
var a = 0x67452301 |
|||
var b = 0xefcdab89 |
|||
var c = 0x98badcfe |
|||
var d = 0x10325476 |
|||
var initBytes = initMsg.bytes |
|||
var initLen = initBytes.count |
|||
var newLen = initLen + 1 |
|||
while (newLen % 64 != 56) newLen = newLen + 1 |
|||
var msg = List.filled(newLen + 8, 0) |
|||
for (i in 0...initLen) msg[i] = initBytes[i] |
|||
msg[initLen] = 0x80 // remaining bytes already 0 |
|||
var lenBits = toBytes.call(initLen * 8) |
|||
for (i in newLen...newLen+4) msg[i] = lenBits[i-newLen] |
|||
var extraBits = toBytes.call(initLen >> 29) |
|||
for (i in newLen+4...newLen+8) msg[i] = extraBits[i-newLen-4] |
|||
var offset = 0 |
|||
var x = List.filled(16, 0) |
|||
while (offset < newLen) { |
|||
for (i in 0...16) x[i] = toInt.call(msg[offset+i*4...offset + i*4 + 4]) |
|||
var a2 = a |
|||
var b2 = b |
|||
var c2 = c |
|||
var d2 = d |
|||
for (i in [0, 4, 8, 12]) { |
|||
a = r.call(a + f.call(b, c, d) + x[i+0], 3) |
|||
d = r.call(d + f.call(a, b, c) + x[i+1], 7) |
|||
c = r.call(c + f.call(d, a, b) + x[i+2], 11) |
|||
b = r.call(b + f.call(c, d, a) + x[i+3], 19) |
|||
} |
|||
for (i in 0..3) { |
|||
a = r.call(a + g.call(b, c, d) + x[i+0] + 0x5a827999, 3) |
|||
d = r.call(d + g.call(a, b, c) + x[i+4] + 0x5a827999, 5) |
|||
c = r.call(c + g.call(d, a, b) + x[i+8] + 0x5a827999, 9) |
|||
b = r.call(b + g.call(c, d, a) + x[i+12] + 0x5a827999, 13) |
|||
} |
|||
for (i in [0, 2, 1, 3]) { |
|||
a = r.call(a + h.call(b, c, d) + x[i+0] + 0x6ed9eba1, 3) |
|||
d = r.call(d + h.call(a, b, c) + x[i+8] + 0x6ed9eba1, 9) |
|||
c = r.call(c + h.call(d, a, b) + x[i+4] + 0x6ed9eba1, 11) |
|||
b = r.call(b + h.call(c, d, a) + x[i+12] + 0x6ed9eba1, 15) |
|||
} |
|||
a = a + a2 |
|||
b = b + b2 |
|||
c = c + c2 |
|||
d = d + d2 |
|||
offset = offset + 64 |
|||
} |
|||
var digest = List.filled(16, 0) |
|||
var dBytes = toBytes.call(a) |
|||
for (i in 0...4) digest[i] = dBytes[i] |
|||
dBytes = toBytes.call(b) |
|||
for (i in 0...4) digest[i+4] = dBytes[i] |
|||
dBytes = toBytes.call(c) |
|||
for (i in 0...4) digest[i+8] = dBytes[i] |
|||
dBytes = toBytes.call(d) |
|||
for (i in 0...4) digest[i+12] = dBytes[i] |
|||
return digest |
|||
} |
|||
var strings = [ |
|||
"", |
|||
"a", |
|||
"abc", |
|||
"message digest", |
|||
"abcdefghijklmnopqrstuvwxyz", |
|||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", |
|||
"12345678901234567890123456789012345678901234567890123456789012345678901234567890", |
|||
"Rosetta Code" |
|||
] |
|||
for (s in strings) { |
|||
var digest = md4.call(s) |
|||
Fmt.print("$s <== '$0s'", Fmt.v("xz", 2, digest, 0, "", ""), s) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
31d6cfe0d16ae931b73c59d7e0c089c0 <== '' |
|||
bde52cb31de33e46245e05fbdbd6fb24 <== 'a' |
|||
a448017aaf21d8525fc10ae87aa6729d <== 'abc' |
|||
d9130a8164549fe818874806e1c7014b <== 'message digest' |
|||
d79e1c308aa5bbcdeea8ed63df412da9 <== 'abcdefghijklmnopqrstuvwxyz' |
|||
043f8582f241db351ce627e153e7f0e4 <== 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' |
|||
e33b4ddc9c38f2199c3e7b164fcc0536 <== '12345678901234567890123456789012345678901234567890123456789012345678901234567890' |
|||
a52bcfc6a0d0d300cdc5ddbfbefe478b <== 'Rosetta Code' |
|||
</pre> |
Latest revision as of 23:46, 12 June 2024
You are encouraged to solve this task according to the task description, using any language you may know.
Find the MD4 message digest of a string of octets. Use the ASCII encoded string “Rosetta Code” (without quotes). You may either call an MD4 library, or implement MD4 in your language.
MD4 is an obsolete hash function that computes a 128-bit message digest that sometimes appears in obsolete protocols.
RFC 1320 specifies the MD4 algorithm. RFC 6150 declares that MD4 is obsolete.
Ada
with Ada.Text_IO;
with CryptAda.Digests.Message_Digests.MD4;
with CryptAda.Digests.Hashes;
with CryptAda.Pragmatics;
with CryptAda.Utils.Format;
procedure RC_MD4 is
use CryptAda.Digests.Message_Digests;
use CryptAda.Digests;
use CryptAda.Pragmatics;
function To_Byte_Array (Item : String) return Byte_Array is
Result : Byte_Array (Item'Range);
begin
for I in Result'Range loop
Result (I) := Byte (Character'Pos (Item (I)));
end loop;
return Result;
end To_Byte_Array;
Text : constant String := "Rosetta Code";
Bytes : constant Byte_Array := To_Byte_Array (Text);
Handle : constant Message_Digest_Handle := MD4.Get_Message_Digest_Handle;
Pointer : constant Message_Digest_Ptr := Get_Message_Digest_Ptr (Handle);
Hash : Hashes.Hash;
begin
Digest_Start (Pointer);
Digest_Update (Pointer, Bytes);
Digest_End (Pointer, Hash);
Ada.Text_IO.Put_Line
("""" & Text & """: " & CryptAda.Utils.Format.To_Hex_String (Hashes.Get_Bytes (Hash)));
end RC_MD4;
- Output:
"Rosetta Code": A52BCFC6A0D0D300CDC5DDBFBEFE478B
AutoHotkey
Source: MD4 @github by jNizM
str := "Rosetta Code"
MsgBox, % "String:`n" (str) "`n`nMD4:`n" MD4(str)
; MD4 ===============================================================================
MD4(string, encoding = "utf-8")
{
return CalcStringHash(string, 0x8002, encoding)
}
; CalcAddrHash ======================================================================
CalcAddrHash(addr, length, algid, byref hash = 0, byref hashlength = 0)
{
static h := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D", "E", "F"]
static b := h.minIndex()
o := ""
if (DllCall("advapi32\CryptAcquireContext", "Ptr*", hProv, "Ptr", 0, "Ptr", 0, "UInt", 24, "UInt", 0xF0000000))
{
if (DllCall("advapi32\CryptCreateHash", "Ptr", hProv, "UInt", algid, "UInt", 0, "UInt", 0, "Ptr*", hHash))
{
if (DllCall("advapi32\CryptHashData", "Ptr", hHash, "Ptr", addr, "UInt", length, "UInt", 0))
{
if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", 0, "UInt*", hashlength, "UInt", 0))
{
VarSetCapacity(hash, hashlength, 0)
if (DllCall("advapi32\CryptGetHashParam", "Ptr", hHash, "UInt", 2, "Ptr", &hash, "UInt*", hashlength, "UInt", 0))
{
loop, % hashlength
{
v := NumGet(hash, A_Index - 1, "UChar")
o .= h[(v >> 4) + b] h[(v & 0xf) + b]
}
}
}
}
DllCall("advapi32\CryptDestroyHash", "Ptr", hHash)
}
DllCall("advapi32\CryPtreleaseContext", "Ptr", hProv, "UInt", 0)
}
return o
}
; CalcStringHash ====================================================================
CalcStringHash(string, algid, encoding = "utf-8", byref hash = 0, byref hashlength = 0)
{
chrlength := (encoding = "cp1200" || encoding = "utf-16") ? 2 : 1
length := (StrPut(string, encoding) - 1) * chrlength
VarSetCapacity(data, length, 0)
StrPut(string, &data, floor(length / chrlength), encoding)
return CalcAddrHash(&data, length, algid, hash, hashlength)
}
- Output:
String: Rosetta Code MD4: A52BCFC6A0D0D300CDC5DDBFBEFE478B
BASIC
FreeBASIC
' version 19-10-2016
' translation of the (pseudo) code in RFC 1320
' compile with: fbc -s console
Function MD4(test_str As String) As String
Dim As String message = test_str ' string are passed as ByRef
' some macro's
#Macro F(X, Y, Z)
(((X) And (Y)) Or ((Not(X)) And (Z)))
#EndMacro
#Macro G(X, Y, Z)
(((X) And (Y)) Or (((X) And (Z)) Or ((Y) And (Z))))
#EndMacro
#Macro H(X, Y, Z)
((X) Xor (Y) Xor (Z))
#EndMacro
' a little piece of inline asm to do a rotate left on a 32bit variable
#Macro ROtate_Left(x, n) ' rotate left
Asm
rol dword Ptr [x], n
End Asm
#EndMacro
' #Macro ROtate_left(x, n)
' x = x Shl n + x Shr (32 - n)
' #EndMacro
Dim As Long i
Dim As String answer, s1
Dim As ULongInt l = Len(message)
' set the first bit after the message to 1
message = message + Chr(1 Shl 7)
' add one char to the length
Dim As ULong padding = 64 - ((l +1) Mod (512 \ 8)) ' 512 \ 8 = 64 char.
' check if we have enough room for inserting the length
If padding < 8 Then padding = padding + 64
message = message + String(padding, Chr(0)) ' adjust length
Dim As ULong l1 = Len(message) ' new length
l = l * 8 ' orignal length in bits
' create ubyte ptr to point to l ( = length in bits)
Dim As UByte Ptr ub_ptr = Cast(UByte Ptr, @l)
For i = 0 To 7 'copy length of message to the last 8 bytes
message[l1 -8 + i] = ub_ptr[i]
Next
' unsigned 32bit integers only
Dim As UInteger<32> AA, A = &H67452301
Dim As UInteger<32> BB, B = &Hefcdab89
Dim As UInteger<32> CC, C = &H98badcfe
Dim As UInteger<32> DD, D = &H10325476
For i = 0 To (l1 -1) \ 64 ' split into 64 byte block
AA = A : BB = B : CC = C : DD = D
' x point to 64 byte block inside the string message
Dim As UInteger<32> Ptr x = Cast(UInteger<32> Ptr, @message[i*64])
' round 1
A = A + F(B, C, D) + x[ 0] : ROtate_Left(A, 3)
D = D + F(A, B, C) + x[ 1] : ROtate_Left(D, 7)
C = C + F(D, A, B) + x[ 2] : ROtate_Left(C, 11)
B = B + F(C, D, A) + x[ 3] : ROtate_Left(B, 19)
A = A + F(B, C, D) + x[ 4] : ROtate_Left(A, 3)
D = D + F(A, B, C) + x[ 5] : ROtate_Left(D, 7)
C = C + F(D, A, B) + x[ 6] : ROtate_Left(C, 11)
B = B + F(C, D, A) + x[ 7] : ROtate_Left(B, 19)
A = A + F(B, C, D) + x[ 8] : ROtate_Left(A, 3)
D = D + F(A, B, C) + x[ 9] : ROtate_Left(D, 7)
C = C + F(D, A, B) + x[10] : ROtate_Left(C, 11)
B = B + F(C, D, A) + x[11] : ROtate_Left(B, 19)
A = A + F(B, C, D) + x[12] : ROtate_Left(A, 3)
D = D + F(A, B, C) + x[13] : ROtate_Left(D, 7)
C = C + F(D, A, B) + x[14] : ROtate_Left(C, 11)
B = B + F(C, D, A) + x[15] : ROtate_Left(B, 19)
' round 2
A = A + G(B, C, D) + x[ 0] + &H5A827999 : ROtate_Left(A, 3)
D = D + G(A, B, C) + x[ 4] + &H5A827999 : ROtate_Left(D, 5)
C = C + G(D, A, B) + x[ 8] + &H5A827999 : ROtate_Left(C, 9)
B = B + G(C, D, A) + x[12] + &H5A827999 : ROtate_Left(B, 13)
A = A + G(B, C, D) + x[ 1] + &H5A827999 : ROtate_Left(A, 3)
D = D + G(A, B, C) + x[ 5] + &H5A827999 : ROtate_Left(D, 5)
C = C + G(D, A, B) + x[ 9] + &H5A827999 : ROtate_Left(C, 9)
B = B + G(C, D, A) + x[13] + &H5A827999 : ROtate_Left(B, 13)
A = A + G(B, C, D) + x[ 2] + &H5A827999 : ROtate_Left(A, 3)
D = D + G(A, B, C) + x[ 6] + &H5A827999 : ROtate_Left(D, 5)
C = C + G(D, A, B) + x[10] + &H5A827999 : ROtate_Left(C, 9)
B = B + G(C, D, A) + x[14] + &H5A827999 : ROtate_Left(B, 13)
A = A + G(B, C, D) + x[ 3] + &H5A827999 : ROtate_Left(A, 3)
D = D + G(A, B, C) + x[ 7] + &H5A827999 : ROtate_Left(D, 5)
C = C + G(D, A, B) + x[11] + &H5A827999 : ROtate_Left(C, 9)
B = B + G(C, D, A) + x[15] + &H5A827999 : ROtate_Left(B, 13)
' round 3
A = A + H(B, C, D) + x[ 0] + &H6ED9EBA1 : ROtate_Left(A, 3)
D = D + H(A, B, C) + x[ 8] + &H6ED9EBA1 : ROtate_Left(D, 9)
C = C + H(D, A, B) + x[ 4] + &H6ED9EBA1 : ROtate_Left(C, 11)
B = B + H(C, D, A) + x[12] + &H6ED9EBA1 : ROtate_Left(B, 15)
A = A + H(B, C, D) + x[ 2] + &H6ED9EBA1 : ROtate_Left(A, 3)
D = D + H(A, B, C) + x[10] + &H6ED9EBA1 : ROtate_Left(D, 9)
C = C + H(D, A, B) + x[ 6] + &H6ED9EBA1 : ROtate_Left(C, 11)
B = B + H(C, D, A) + x[14] + &H6ED9EBA1 : ROtate_Left(B, 15)
A = A + H(B, C, D) + x[ 1] + &H6ED9EBA1 : ROtate_Left(A, 3)
D = D + H(A, B, C) + x[ 9] + &H6ED9EBA1 : ROtate_Left(D, 9)
C = C + H(D, A, B) + x[ 5] + &H6ED9EBA1 : ROtate_Left(C, 11)
B = B + H(C, D, A) + x[13] + &H6ED9EBA1 : ROtate_Left(B, 15)
A = A + H(B, C, D) + x[ 3] + &H6ED9EBA1 : ROtate_Left(A, 3)
D = D + H(A, B, C) + x[11] + &H6ED9EBA1 : ROtate_Left(D, 9)
C = C + H(D, A, B) + x[ 7] + &H6ED9EBA1 : ROtate_Left(C, 11)
B = B + H(C, D, A) + x[15] + &H6ED9EBA1 : ROtate_Left(B, 15)
A += AA : B += BB : C += CC : D += DD
Next
' convert A, B, C and D in hex, then add low order first
s1 = Hex(A, 8)
For i = 7 To 1 Step -2 : answer +=Mid(s1, i, 2) : Next
s1 = Hex(B, 8)
For i = 7 To 1 Step -2 : answer +=Mid(s1, i, 2) : Next
s1 = Hex(C, 8)
For i = 7 To 1 Step -2 : answer +=Mid(s1, i, 2) : Next
s1 = Hex(D, 8)
For i = 7 To 1 Step -2 : answer +=Mid(s1, i, 2) : Next
Return LCase(answer)
End Function
' ------=< MAIN >=------
Dim As String test = "Rosetta Code"
Print
Print test; " => "; MD4(test)
' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End
- Output:
Rosetta Code => a52bcfc6a0d0d300cdc5ddbfbefe478b
C
/*
*
* 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);
}
- Output:
printf("%s\n", MD4("Rosetta Code", 12));
a52bcfc6a0d0d300cdc5ddbfbefe478b
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
static class Md4
{
public static string Md4Hash(this string input)
{
// get padded uints from bytes
List<byte> bytes = Encoding.ASCII.GetBytes(input).ToList();
uint bitCount = (uint)(bytes.Count) * 8;
bytes.Add(128);
while (bytes.Count % 64 != 56) bytes.Add(0);
var uints = new List<uint>();
for (int i = 0; i + 3 < bytes.Count; i += 4)
uints.Add(bytes[i] | (uint)bytes[i + 1] << 8 | (uint)bytes[i + 2] << 16 | (uint)bytes[i + 3] << 24);
uints.Add(bitCount);
uints.Add(0);
// run rounds
uint a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476;
Func<uint, uint, uint> rol = (x, y) => x << (int)y | x >> 32 - (int)y;
for (int q = 0; q + 15 < uints.Count; q += 16)
{
var chunk = uints.GetRange(q, 16);
uint aa = a, bb = b, cc = c, dd = d;
Action<Func<uint, uint, uint, uint>, uint[]> round = (f, y) =>
{
foreach (uint i in new[] { y[0], y[1], y[2], y[3] })
{
a = rol(a + f(b, c, d) + chunk[(int)(i + y[4])] + y[12], y[8]);
d = rol(d + f(a, b, c) + chunk[(int)(i + y[5])] + y[12], y[9]);
c = rol(c + f(d, a, b) + chunk[(int)(i + y[6])] + y[12], y[10]);
b = rol(b + f(c, d, a) + chunk[(int)(i + y[7])] + y[12], y[11]);
}
};
round((x, y, z) => (x & y) | (~x & z), new uint[] { 0, 4, 8, 12, 0, 1, 2, 3, 3, 7, 11, 19, 0 });
round((x, y, z) => (x & y) | (x & z) | (y & z), new uint[] { 0, 1, 2, 3, 0, 4, 8, 12, 3, 5, 9, 13, 0x5a827999 });
round((x, y, z) => x ^ y ^ z, new uint[] { 0, 2, 1, 3, 0, 8, 4, 12, 3, 9, 11, 15, 0x6ed9eba1 });
a += aa; b += bb; c += cc; d += dd;
}
// return hex encoded string
byte[] outBytes = new[] { a, b, c, d }.SelectMany(BitConverter.GetBytes).ToArray();
return BitConverter.ToString(outBytes).Replace("-", "").ToLower();
}
static void Main() { Console.WriteLine("Rosetta Code".Md4Hash()); }
}
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
C++
#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
class MD4 {
public:
MD4() {
engine_reset();
}
std::vector<int8_t> engine_digest(const std::string& text) {
engine_update(string_to_byte_vector(text), 0, text.length());
const int32_t buffer_index = static_cast<int32_t>(count % BLOCK_LENGTH);
const int32_t padding_length = ( buffer_index < 56 ) ? 56 - buffer_index : 120 - buffer_index;
std::vector<int8_t> tail(padding_length + 8, 0);
tail[0] = static_cast<int8_t>(0x80);
for ( int32_t i = 0; i < 8; ++i ) {
tail[padding_length + i] = static_cast<int8_t>(unsigned_right_shift(count * 8, 8 * i));
}
engine_update(tail, 0, tail.size());
std::vector<int8_t> result(16, 0);
for ( int32_t i = 0; i < 4; ++i ) {
for ( int32_t j = 0; j < 4; ++j ) {
result[i * 4 + j] = static_cast<int8_t>(unsigned_right_shift(context[i], 8 * j));
}
}
engine_reset();
return result;
}
private:
void engine_update(const std::vector<int8_t>& message_bytes,
const int32_t& offset, const int32_t& message_length) {
if ( offset < 0 || message_length < 0
|| (int64_t) offset + message_length > (int64_t) message_bytes.size() ) {
throw std::invalid_argument("Incorrect arguments for function engine_update");
}
int32_t buffer_index = static_cast<int32_t>(count % BLOCK_LENGTH);
count += message_length;
const int32_t partial_length = BLOCK_LENGTH - buffer_index;
int32_t i = 0;
if ( message_length >= partial_length ) {
for ( int32_t j = 0; j < partial_length; ++j ) {
buffer[buffer_index + j] = message_bytes[offset + j];
}
transform(buffer, 0);
i = partial_length;
while ( i + BLOCK_LENGTH - 1 < message_length ) {
transform(message_bytes, offset + i);
i += BLOCK_LENGTH;
}
buffer_index = 0;
}
if ( i < message_length ) {
for ( int32_t j = 0; j < message_length - i; ++j ) {
buffer[buffer_index + j] = message_bytes[offset + i + j];
}
}
}
void transform(const std::vector<int8_t>& buffer, int32_t offset) {
for ( int32_t i = 0; i < 16; ++i ) {
extra[i] = ( ( buffer[offset + 0] & 0xff ) ) |
( ( buffer[offset + 1] & 0xff ) << 8 ) |
( ( buffer[offset + 2] & 0xff ) << 16 ) |
( ( buffer[offset + 3] & 0xff ) << 24 );
offset += 4;
}
int32_t a = context[0];
int32_t b = context[1];
int32_t c = context[2];
int32_t d = context[3];
for ( const int32_t& i : { 0, 4, 8, 12 } ) {
a = ff(a, b, c, d, extra[i + 0], 3);
d = ff(d, a, b, c, extra[i + 1], 7);
c = ff(c, d, a, b, extra[i + 2], 11);
b = ff(b, c, d, a, extra[i + 3], 19);
}
for ( const int32_t& i : { 0, 1, 2, 3 } ) {
a = gg(a, b, c, d, extra[i + 0], 3);
d = gg(d, a, b, c, extra[i + 4], 5);
c = gg(c, d, a, b, extra[i + 8], 9);
b = gg(b, c, d, a, extra[i + 12], 13);
}
for ( const int32_t& i : { 0, 2, 1, 3 } ) {
a = hh(a, b, c, d, extra[i + 0], 3);
d = hh(d, a, b, c, extra[i + 8], 9);
c = hh(c, d, a, b, extra[i + 4], 11);
b = hh(b, c, d, a, extra[i + 12], 15);
}
context[0] += a;
context[1] += b;
context[2] += c;
context[3] += d;
}
void engine_reset() {
count = 0;
context.assign(4, 0);
context[0] = 0x67452301;
context[1] = 0xefcdab89;
context[2] = 0x98badcfe;
context[3] = 0x10325476;
extra.assign(16, 0);
buffer.assign(BLOCK_LENGTH, 0);
}
std::vector<int8_t> string_to_byte_vector(const std::string& text) {
std::vector<int8_t> bytes;
bytes.reserve(text.size());
std::transform(text.begin(), text.end(), std::back_inserter(bytes),
[](char ch){ return static_cast<int8_t>(ch); });
return bytes;
}
int32_t unsigned_right_shift(const int32_t& base, const int32_t& shift) {
if ( shift < 0 || shift >= 32 || base == 0 ) {
return 0;
}
return ( base > 0 ) ? base >> shift : static_cast<uint32_t>(base) >> shift;
}
int32_t rotate(const int32_t& t, const int32_t& s) {
return ( t << s ) | unsigned_right_shift(t, 32 - s);
}
int32_t ff(const int32_t& a, const int32_t& b, const int32_t& c,
const int32_t& d, const int32_t& x, const int32_t& s) {
return rotate(a + ( ( b & c ) | ( ~b & d ) ) + x, s);
}
int32_t gg(const int32_t& a, const int32_t& b, const int32_t& c,
const int32_t& d, const int32_t& x, const int32_t& s) {
return rotate(a + ( ( b & ( c | d ) ) | ( c & d ) ) + x + 0x5A827999, s);
}
int32_t hh(const int32_t& a, const int32_t& b, const int32_t& c,
const int32_t& d, const int32_t& x, const int32_t& s) {
return rotate(a + ( b ^ c ^ d ) + x + 0x6ED9EBA1, s);
}
uint64_t count;
std::vector<int32_t> context;
std::vector<int32_t> extra;
std::vector<int8_t> buffer;
const int32_t BLOCK_LENGTH = 64;
};
int main() {
MD4 md4;
std::vector<int8_t> result = md4.engine_digest("Rosetta Code");
for ( const int8_t& bb : result ) {
std::cout << std::hex << std::setfill('0') << std::setw(2) << ( bb & 0xff );
}
std::cout << std::endl;
}
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
Clojure
(use 'pandect.core)
(md4 "Rosetta Code")
- Output:
"a52bcfc6a0d0d300cdc5ddbfbefe478b"
Common Lisp
(ql:quickload 'ironclad)
(defun md4 (str)
(ironclad:byte-array-to-hex-string
(ironclad:digest-sequence :md4
(ironclad:ascii-string-to-byte-array str))))
(md4 "Rosetta Code")
- Output:
"a52bcfc6a0d0d300cdc5ddbfbefe478b"
D
A short but not efficient implementation.
import std.stdio, std.string, std.range;
ubyte[16] md4(const(ubyte)[] inData) pure nothrow {
enum f = (uint x, uint y, uint z) => (x & y) | (~x & z);
enum g = (uint x, uint y, uint z) => (x & y) | (x & z) | (y & z);
enum h = (uint x, uint y, uint z) => x ^ y ^ z;
enum r = (uint v, uint s) => (v << s) | (v >> (32 - s));
immutable bitLen = ulong(inData.length) << 3;
inData ~= 0x80;
while (inData.length % 64 != 56)
inData ~= 0;
const data = cast(uint[])inData ~ [uint(bitLen & uint.max), uint(bitLen >> 32)];
uint a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476;
foreach (const x; data.chunks(16)) {
immutable a2 = a, b2 = b, c2 = c, d2 = d;
foreach (immutable i; [0, 4, 8, 12]) {
a = r(a + f(b, c, d) + x[i+0], 3);
d = r(d + f(a, b, c) + x[i+1], 7);
c = r(c + f(d, a, b) + x[i+2], 11);
b = r(b + f(c, d, a) + x[i+3], 19);
}
foreach (immutable i; [0, 1, 2, 3]) {
a = r(a + g(b, c, d) + x[i+0] + 0x5a827999, 3);
d = r(d + g(a, b, c) + x[i+4] + 0x5a827999, 5);
c = r(c + g(d, a, b) + x[i+8] + 0x5a827999, 9);
b = r(b + g(c, d, a) + x[i+12] + 0x5a827999, 13);
}
foreach (immutable i; [0, 2, 1, 3]) {
a = r(a + h(b, c, d) + x[i+0] + 0x6ed9eba1, 3);
d = r(d + h(a, b, c) + x[i+8] + 0x6ed9eba1, 9);
c = r(c + h(d, a, b) + x[i+4] + 0x6ed9eba1, 11);
b = r(b + h(c, d, a) + x[i+12] + 0x6ed9eba1, 15);
}
a += a2, b += b2, c += c2, d += d2;
}
//return cast(ubyte[16])[a, b, c, d];
immutable uint[4] result = [a, b, c, d];
return cast(ubyte[16])result;
}
void main() {
writefln("%(%02x%)", "Rosetta Code".representation.md4);
}
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
Delphi
Thanks for David Barton for DCPcrypt v2.0 library, and StephenGenusa for store and share in github [1].
program CalcMD4;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
DCPmd4;
function MD4(const Str: string): string;
var
HashDigest: array of byte;
d: Byte;
begin
Result := '';
with TDCP_md4.Create(nil) do
begin
Init;
UpdateStr(Str);
SetLength(HashDigest, GetHashSize div 8);
final(HashDigest[0]);
for d in HashDigest do
Result := Result + d.ToHexString(2);
Free;
end;
end;
begin
Writeln(MD4('Rosetta Code'));
readln;
end.
- Output:
A52BCFC6A0D0D300CDC5DDBFBEFE478B
Emacs Lisp
md4.el
by Taro Kawagishi, originally from FLIM and included in recent Emacs, is an Elisp implementation of the MD4 algorithm. Its md4
function returns the checksum as 16 binary bytes. encode-hex-string
from hex-util.el
can convert that to a hex string if desired.
(require 'md4)
(require 'hex-util)
(let* ((s "Rosetta Code")
(m (md4 s (length s)))) ;; m = 16 binary bytes
(encode-hex-string m))
=>
"a52bcfc6a0d0d300cdc5ddbfbefe478b"
Erlang
-module(md4).
-export([md4/0]).
md4() ->
<<MD4:128>> = crypto:md4("Rosetta Code"),
io:fwrite("Rosetta Code => ~.16B~n",[MD4]).
Rosetta Code => A52BCFC6A0D0D300CDC5DDBFBEFE478B
Go
package main
import (
"golang.org/x/crypto/md4"
"fmt"
)
func main() {
h := md4.New()
h.Write([]byte("Rosetta Code"))
fmt.Printf("%x\n", h.Sum(nil))
}
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
Haskell
#!/usr/bin/env runhaskell
import Data.ByteString.Char8 (pack)
import System.Environment (getArgs)
import Crypto.Hash
main :: IO ()
main = print . md4 . pack . unwords =<< getArgs
where md4 x = hash x :: Digest MD4
- Output:
$ ./md4.hs Rosetta Code a52bcfc6a0d0d300cdc5ddbfbefe478b
J
require 'ide/qt'
gethash_jqtide_ 'MD4';'Rosetta Code'
a52bcfc6a0d0d300cdc5ddbfbefe478b
Java
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.util.encoders.Hex;
public class RosettaMD4
{
public static void main (String[] argv) throws Exception
{
byte[] r = "Rosetta Code".getBytes("US-ASCII");
MD4Digest d = new MD4Digest();
d.update (r, 0, r.length);
byte[] o = new byte[d.getDigestSize()];
d.doFinal (o, 0);
Hex.encode (o, System.out);
System.out.println();
}
}
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
Without external libraries
import java.util.Arrays;
import java.util.List;
public final class MD4Task {
public static void main(String[] aArgs) {
String text = "Rosetta Code";
MD4 md4 = new MD4();
byte[] result = md4.engineDigest(text);
StringBuilder stringBuilder = new StringBuilder();
for ( byte bb : result ) {
stringBuilder.append(String.format("%02x", bb));
}
System.out.println(stringBuilder.toString());
}
}
final class MD4 {
public MD4() {
engineReset();
}
public byte[] engineDigest(String aText) {
engineUpdate(aText.getBytes(), 0, aText.length());
final int bufferIndex = (int) ( count % BLOCK_LENGTH );
final int paddingLength = ( bufferIndex < 56 ) ? 56 - bufferIndex : 120 - bufferIndex;
byte[] tail = new byte[paddingLength + 8];
tail[0] = (byte) 0x80;
for ( int i = 0; i < 8; i++ ) {
tail[paddingLength + i] = (byte) ( ( count * 8 ) >>> ( 8 * i ) );
}
engineUpdate(tail, 0, tail.length);
byte[] result = new byte[16];
for ( int i = 0; i < 4; i++ ) {
for ( int j = 0; j < 4; j++ ) {
result[i * 4 + j] = (byte) ( context[i] >>> ( 8 * j ) );
}
}
engineReset();
return result;
}
private void engineUpdate(byte[] aMessageBytes, int aOffset, int aMessageLength) {
if ( aOffset < 0 || aMessageLength < 0 || (long) aOffset + aMessageLength > (long) aMessageBytes.length ) {
throw new ArrayIndexOutOfBoundsException("Incorrect arguments for method engineUpdate");
}
int bufferIndex = (int) ( count % BLOCK_LENGTH );
count += aMessageLength;
final int partialLength = BLOCK_LENGTH - bufferIndex;
int i = 0;
if ( aMessageLength >= partialLength ) {
System.arraycopy(aMessageBytes, aOffset, buffer, bufferIndex, partialLength);
transform(buffer, 0);
i = partialLength;
while ( i + BLOCK_LENGTH - 1 < aMessageLength ) {
transform(aMessageBytes, aOffset + i);
i += BLOCK_LENGTH;
}
bufferIndex = 0;
}
if ( i < aMessageLength ) {
System.arraycopy(aMessageBytes, aOffset + i, buffer, bufferIndex, aMessageLength - i);
}
}
private void transform (byte[] aBuffer, int aOffset) {
for ( int i = 0; i < 16; i++ ) {
extra[i] = ( ( aBuffer[aOffset++] & 0xff ) ) |
( ( aBuffer[aOffset++] & 0xff ) << 8 ) |
( ( aBuffer[aOffset++] & 0xff ) << 16 ) |
( ( aBuffer[aOffset++] & 0xff ) << 24 );
}
int a = context[0];
int b = context[1];
int c = context[2];
int d = context[3];
for ( int i : List.of( 0, 4, 8, 12 ) ) {
a = ff(a, b, c, d, extra[i + 0], 3);
d = ff(d, a, b, c, extra[i + 1], 7);
c = ff(c, d, a, b, extra[i + 2], 11);
b = ff(b, c, d, a, extra[i + 3], 19);
}
for ( int i : List.of( 0, 1, 2, 3 ) ) {
a = gg(a, b, c, d, extra[i + 0], 3);
d = gg(d, a, b, c, extra[i + 4], 5);
c = gg(c, d, a, b, extra[i + 8], 9);
b = gg(b, c, d, a, extra[i + 12], 13);
}
for ( int i : List.of( 0, 2, 1, 3 ) ) {
a = hh(a, b, c, d, extra[i + 0], 3);
d = hh(d, a, b, c, extra[i + 8], 9);
c = hh(c, d, a, b, extra[i + 4], 11);
b = hh(b, c, d, a, extra[i + 12], 15);
}
context[0] += a;
context[1] += b;
context[2] += c;
context[3] += d;
}
private void engineReset() {
count = 0;
context[0] = 0x67452301;
context[1] = 0xefcdab89;
context[2] = 0x98badcfe;
context[3] = 0x10325476;
Arrays.fill(extra, 0);
Arrays.fill(buffer, (byte) 0);
}
private static int rotate(int t, int s) {
return t << s | t >>> ( 32 - s );
}
private static int ff(int a, int b, int c, int d, int x, int s) {
return rotate(a + ( ( b & c ) | ( ~b & d ) ) + x, s);
}
private static int gg(int a, int b, int c, int d, int x, int s) {
return rotate(a + ( ( b & ( c | d ) ) | ( c & d ) ) + x + 0x5A827999, s);
}
private static int hh(int a, int b, int c, int d, int x, int s) {
return rotate(a + ( b ^ c ^ d ) + x + 0x6ED9EBA1, s);
}
private static final int BLOCK_LENGTH = 64;
private long count;
private int[] context = new int[4];
private int[] extra = new int[16];
private byte[] buffer = new byte[BLOCK_LENGTH];
}
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
JavaScript
const md4func = () => {
const hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
const b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
const chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
const tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
/**
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
const safe_add = (x, y) => {
const lsw = (x & 0xFFFF) + (y & 0xFFFF);
const msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
};
/**
* Bitwise rotate a 32-bit number to the left.
*/
const rol = (num, cnt) => (num << cnt) | (num >>> (32 - cnt));
/**
* Convert a string to an array of little-endian words
* If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
*/
const str2binl = str => {
const bin = Array();
const mask = (1 << chrsz) - 1;
for (let i = 0; i < str.length * chrsz; i += chrsz)
bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (i % 32);
return bin;
};
/**
* Convert an array of little-endian words to a string
*/
const binl2str = bin => {
let str = "";
const mask = (1 << chrsz) - 1;
for (let i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i >> 5] >>> (i % 32)) & mask);
return str;
};
/**
* Convert an array of little-endian words to a hex string.
*/
const binl2hex = binarray => {
let str = "";
for (let i = 0; i < binarray.length * 4; i++) {
str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) +
hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF);
}
return str;
};
/**
* Convert an array of little-endian words to a base-64 string
*/
const binl2b64 = binarray => {
let str = "";
for (let i = 0; i < binarray.length * 4; i += 3) {
const triplet = (((binarray[i >> 2] >> 8 * (i % 4)) & 0xFF) << 16)
| (((binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4)) & 0xFF) << 8)
| ((binarray[i + 2 >> 2] >> 8 * ((i + 2) % 4)) & 0xFF);
for (let j = 0; j < 4; j++) {
if (i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F);
}
}
return str;
};
/**
* Calculate the MD4 of an array of little-endian words, and a bit length
*/
const core_md4 = (x, len) => {
x[len >> 5] |= 0x80 << (len % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
let a = 1732584193;
let b = -271733879;
let c = -1732584194;
let d = 271733878;
for (let i = 0; i < x.length; i += 16) {
const olda = a;
const oldb = b;
const oldc = c;
const oldd = d;
a = md4_ff(a, b, c, d, x[i], 3);
d = md4_ff(d, a, b, c, x[i + 1], 7);
c = md4_ff(c, d, a, b, x[i + 2], 11);
b = md4_ff(b, c, d, a, x[i + 3], 19);
a = md4_ff(a, b, c, d, x[i + 4], 3);
d = md4_ff(d, a, b, c, x[i + 5], 7);
c = md4_ff(c, d, a, b, x[i + 6], 11);
b = md4_ff(b, c, d, a, x[i + 7], 19);
a = md4_ff(a, b, c, d, x[i + 8], 3);
d = md4_ff(d, a, b, c, x[i + 9], 7);
c = md4_ff(c, d, a, b, x[i + 10], 11);
b = md4_ff(b, c, d, a, x[i + 11], 19);
a = md4_ff(a, b, c, d, x[i + 12], 3);
d = md4_ff(d, a, b, c, x[i + 13], 7);
c = md4_ff(c, d, a, b, x[i + 14], 11);
b = md4_ff(b, c, d, a, x[i + 15], 19);
a = md4_gg(a, b, c, d, x[i], 3);
d = md4_gg(d, a, b, c, x[i + 4], 5);
c = md4_gg(c, d, a, b, x[i + 8], 9);
b = md4_gg(b, c, d, a, x[i + 12], 13);
a = md4_gg(a, b, c, d, x[i + 1], 3);
d = md4_gg(d, a, b, c, x[i + 5], 5);
c = md4_gg(c, d, a, b, x[i + 9], 9);
b = md4_gg(b, c, d, a, x[i + 13], 13);
a = md4_gg(a, b, c, d, x[i + 2], 3);
d = md4_gg(d, a, b, c, x[i + 6], 5);
c = md4_gg(c, d, a, b, x[i + 10], 9);
b = md4_gg(b, c, d, a, x[i + 14], 13);
a = md4_gg(a, b, c, d, x[i + 3], 3);
d = md4_gg(d, a, b, c, x[i + 7], 5);
c = md4_gg(c, d, a, b, x[i + 11], 9);
b = md4_gg(b, c, d, a, x[i + 15], 13);
a = md4_hh(a, b, c, d, x[i], 3);
d = md4_hh(d, a, b, c, x[i + 8], 9);
c = md4_hh(c, d, a, b, x[i + 4], 11);
b = md4_hh(b, c, d, a, x[i + 12], 15);
a = md4_hh(a, b, c, d, x[i + 2], 3);
d = md4_hh(d, a, b, c, x[i + 10], 9);
c = md4_hh(c, d, a, b, x[i + 6], 11);
b = md4_hh(b, c, d, a, x[i + 14], 15);
a = md4_hh(a, b, c, d, x[i + 1], 3);
d = md4_hh(d, a, b, c, x[i + 9], 9);
c = md4_hh(c, d, a, b, x[i + 5], 11);
b = md4_hh(b, c, d, a, x[i + 13], 15);
a = md4_hh(a, b, c, d, x[i + 3], 3);
d = md4_hh(d, a, b, c, x[i + 11], 9);
c = md4_hh(c, d, a, b, x[i + 7], 11);
b = md4_hh(b, c, d, a, x[i + 15], 15);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
};
/**
* These functions implement the basic operation for each round of the
* algorithm.
*/
const md4_cmn = (q, a, b, x, s, t) => safe_add(
rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
const md4_ff = (a, b, c, d, x, s) => md4_cmn(
(b & c) | ((~b) & d), a, 0, x, s, 0);
const md4_gg = (a, b, c, d, x, s) => md4_cmn(
(b & c) | (b & d) | (c & d), a, 0, x, s, 1518500249);
const md4_hh = (a, b, c, d, x, s) => md4_cmn(
b ^ c ^ d, a, 0, x, s, 1859775393);
/**
* Calculate the HMAC-MD4, of a key and some data
*/
const core_hmac_md4 = (key, data) => {
let bkey = str2binl(key);
if (bkey.length > 16) {
bkey = core_md4(bkey, key.length * chrsz)
}
const ipad = Array(16);
const opad = Array(16);
for (let i = 0; i < 16; i++) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
const hash = core_md4(
ipad.concat(str2binl(data)), 512 + data.length * chrsz);
return core_md4(opad.concat(hash), 512 + 128);
};
/**
* These are the functions you'll usually want to call
*/
return {
hex_md4: s => binl2hex(core_md4(str2binl(s), s.length * chrsz)),
b64_md4: s => binl2b64(core_md4(str2binl(s), s.length * chrsz)),
str_md4: s => binl2str(core_md4(str2binl(s), s.length * chrsz)),
hex_hmac_md4: (key, data) => binl2hex(core_hmac_md4(key, data)),
b64_hmac_md4: (key, data) => binl2b64(core_hmac_md4(key, data)),
str_hmac_md4: (key, data) => binl2str(core_hmac_md4(key, data)),
};
};
const md4 = md4func();
console.log(md4.hex_md4('Rosetta Code'));
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
Julia
Nettle.jl provides a variety of cryptographic functions including the MD4 hash.
using Nettle
msg = "Rosetta Code"
h = HashState(MD4)
update!(h, msg)
h = hexdigest!(h)
println("\"", msg, "\" => ", h)
- Output:
"Rosetta Code" => a52bcfc6a0d0d300cdc5ddbfbefe478b
Kotlin
This is a translation of the Java code here. In the interests of conciseness, I have removed the comments from the Kotlin version:
// version 1.0.6
import java.security.MessageDigest
class MD4() : MessageDigest("MD4"), Cloneable {
private val blockLength = 64
private var context = IntArray(4)
private var count = 0L
private var buffer = ByteArray(blockLength)
private var x = IntArray(16)
init {
engineReset()
}
private constructor(md: MD4): this() {
context = md.context.clone()
buffer = md.buffer.clone()
count = md.count
}
override fun clone(): Any = MD4(this)
override fun engineReset() {
context[0] = 0x67452301
context[1] = 0xefcdab89.toInt()
context[2] = 0x98badcfe.toInt()
context[3] = 0x10325476
count = 0L
for (i in 0 until blockLength) buffer[i] = 0
}
override fun engineUpdate(b: Byte) {
val i = (count % blockLength).toInt()
count++
buffer[i] = b
if (i == blockLength - 1) transform(buffer, 0)
}
override fun engineUpdate(input: ByteArray, offset: Int, len: Int) {
if (offset < 0 || len < 0 || offset.toLong() + len > input.size.toLong())
throw ArrayIndexOutOfBoundsException()
var bufferNdx = (count % blockLength).toInt()
count += len
val partLen = blockLength - bufferNdx
var i = 0
if (len >= partLen) {
System.arraycopy(input, offset, buffer, bufferNdx, partLen)
transform(buffer, 0)
i = partLen
while (i + blockLength - 1 < len) {
transform(input, offset + i)
i += blockLength
}
bufferNdx = 0
}
if (i < len) System.arraycopy(input, offset + i, buffer, bufferNdx, len - i)
}
override fun engineDigest(): ByteArray {
val bufferNdx = (count % blockLength).toInt()
val padLen = if (bufferNdx < 56) 56 - bufferNdx else 120 - bufferNdx
val tail = ByteArray(padLen + 8)
tail[0] = 0x80.toByte()
for (i in 0..7) tail[padLen + i] = ((count * 8) ushr (8 * i)).toByte()
engineUpdate(tail, 0, tail.size)
val result = ByteArray(16)
for (i in 0..3)
for (j in 0..3)
result[i * 4 + j] = (context[i] ushr (8 * j)).toByte()
engineReset()
return result
}
private fun transform (block: ByteArray, offset: Int) {
var offset2 = offset
for (i in 0..15)
x[i] = ((block[offset2++].toInt() and 0xff) ) or
((block[offset2++].toInt() and 0xff) shl 8 ) or
((block[offset2++].toInt() and 0xff) shl 16) or
((block[offset2++].toInt() and 0xff) shl 24)
var a = context[0]
var b = context[1]
var c = context[2]
var d = context[3]
a = ff(a, b, c, d, x[ 0], 3)
d = ff(d, a, b, c, x[ 1], 7)
c = ff(c, d, a, b, x[ 2], 11)
b = ff(b, c, d, a, x[ 3], 19)
a = ff(a, b, c, d, x[ 4], 3)
d = ff(d, a, b, c, x[ 5], 7)
c = ff(c, d, a, b, x[ 6], 11)
b = ff(b, c, d, a, x[ 7], 19)
a = ff(a, b, c, d, x[ 8], 3)
d = ff(d, a, b, c, x[ 9], 7)
c = ff(c, d, a, b, x[10], 11)
b = ff(b, c, d, a, x[11], 19)
a = ff(a, b, c, d, x[12], 3)
d = ff(d, a, b, c, x[13], 7)
c = ff(c, d, a, b, x[14], 11)
b = ff(b, c, d, a, x[15], 19)
a = gg(a, b, c, d, x[ 0], 3)
d = gg(d, a, b, c, x[ 4], 5)
c = gg(c, d, a, b, x[ 8], 9)
b = gg(b, c, d, a, x[12], 13)
a = gg(a, b, c, d, x[ 1], 3)
d = gg(d, a, b, c, x[ 5], 5)
c = gg(c, d, a, b, x[ 9], 9)
b = gg(b, c, d, a, x[13], 13)
a = gg(a, b, c, d, x[ 2], 3)
d = gg(d, a, b, c, x[ 6], 5)
c = gg(c, d, a, b, x[10], 9)
b = gg(b, c, d, a, x[14], 13)
a = gg(a, b, c, d, x[ 3], 3)
d = gg(d, a, b, c, x[ 7], 5)
c = gg(c, d, a, b, x[11], 9)
b = gg(b, c, d, a, x[15], 13)
a = hh(a, b, c, d, x[ 0], 3)
d = hh(d, a, b, c, x[ 8], 9)
c = hh(c, d, a, b, x[ 4], 11)
b = hh(b, c, d, a, x[12], 15)
a = hh(a, b, c, d, x[ 2], 3)
d = hh(d, a, b, c, x[10], 9)
c = hh(c, d, a, b, x[ 6], 11)
b = hh(b, c, d, a, x[14], 15)
a = hh(a, b, c, d, x[ 1], 3)
d = hh(d, a, b, c, x[ 9], 9)
c = hh(c, d, a, b, x[ 5], 11)
b = hh(b, c, d, a, x[13], 15)
a = hh(a, b, c, d, x[ 3], 3)
d = hh(d, a, b, c, x[11], 9)
c = hh(c, d, a, b, x[ 7], 11)
b = hh(b, c, d, a, x[15], 15)
context[0] += a
context[1] += b
context[2] += c
context[3] += d
}
private fun ff(a: Int, b: Int, c: Int, d: Int, x: Int, s: Int): Int {
val t = a + ((b and c) or (b.inv() and d)) + x
return (t shl s) or (t ushr (32 - s))
}
private fun gg(a: Int, b: Int, c: Int, d: Int, x: Int, s: Int): Int {
val t = a + ((b and (c or d)) or (c and d)) + x + 0x5a827999
return (t shl s) or (t ushr (32 - s))
}
private fun hh(a: Int, b: Int, c: Int, d: Int, x: Int, s: Int): Int {
val t = a + (b xor c xor d) + x + 0x6ed9eba1
return (t shl s) or (t ushr (32 - s))
}
}
fun main(args: Array<String>) {
val text = "Rosetta Code"
val bytes = text.toByteArray(Charsets.US_ASCII)
val md: MessageDigest = MD4()
val digest = md.digest(bytes)
for (byte in digest) print("%02x".format(byte))
println()
}
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
Lasso
cipher_digest('Rosetta Code', -digest='MD4')->encodeHex->asString
- Output:
A52BCFC6A0D0D300CDC5DDBFBEFE478B
Lua
#!/usr/bin/lua
require "crypto"
print(crypto.digest("MD4", "Rosetta Code"))
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
Mathematica /Wolfram Language
Hash["Rosetta Code", "MD4", "HexString"]
a52bcfc6a0d0d300cdc5ddbfbefe478b
Nim
import strutils
const MD4Len = 16
proc MD4(d: cstring, n: culong, md: cstring = nil): cstring {.cdecl, dynlib: "libssl.so", importc.}
proc MD4(s: string): string =
result = ""
var s = MD4(s.cstring, s.len.culong)
for i in 0 ..< MD4Len:
result.add s[i].BiggestInt.toHex(2).toLower
echo MD4("Rosetta Code")
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
PARI/GP
Build a MD4 plugin using Linux system library and PARI's function interface. (Linux solution)
#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);
}
Compile with: gcc -Wall -O2 -fPIC -shared md4.c -o libmd4.so -lcrypt -lpari
Load plugin from your home directory into PARI:
install("plug_md4", "s", "MD4", "~/libmd4.so");
MD4("Rosetta Code")
Output: "a52bcfc6a0d0d300cdc5ddbfbefe478b"
Perl
In-lining code from module Digest::Perl::MD4, lightly edited for clarity.
sub md4 :prototype(@) {
my @input = grep { defined && length > 0 } split /(.{64})/s, join '', @_;
push @input, '' if !@input || length($input[$#input]) >= 56;
my @A = (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476); # initial regs
my @T = (0, 0x5A827999, 0x6ED9EBA1);
my @L = qw(3 7 11 19 3 5 9 13 3 9 11 15); # left rotate counts
my @O = (1, 4, 4, # x stride for input index
4, 1, 1, # y stride for input index
0, 0, 1); # bitwise reverse both indexes
my @I = map {
my $z = int $_/16;
my $x = $_%4;
my $y = int $_%16/4;
($x,$y) = (R($x),R($y)) if $O[6+$z];
$O[$z] * $x + $O[3+$z] * $y
} 0..47;
my ($a,$b,$c,$d);
my($l,$p) = (0,0);
foreach (@input) {
my $r = length($_);
$l += $r;
$r++, $_.="\x80" if $r<64 && !$p++;
my @W = unpack 'V16', $_ . "\0"x7;
push @W, (0)x16 if @W < 16;
$W[14] = $l*8 if $r < 57; # add bit-length in low 32-bits
($a,$b,$c,$d) = @A;
for (0..47) {
my $z = int $_/16;
$a = L($L[4*($_>>4) + $_%4],
M(&{(sub{$b&$c|~$b&$d}, # F
sub{$b&$c|$b&$d|$c&$d}, # G
sub{$b^$c^$d} # H
)[$z]}
+ $a + $W[$I[$_]] + $T[$z]));
($a,$b,$c,$d) = ($d,$a,$b,$c);
}
my @v = ($a, $b, $c, $d);
$A[$_] = M($A[$_] + $v[$_]) for 0..3;
}
pack 'V4', @A;
}
sub L { # left-rotate
my ($n, $x) = @_;
$x<<$n | 2**$n - 1 & $x>>(32-$n);
}
sub M { # mod 2**32
no integer;
my ($x) = @_;
my $m = 1+0xffffffff;
$x - $m * int $x/$m;
}
sub R { # reverse two bit number
my $n = pop;
($n&1)*2 + ($n&2)/2;
}
sub md4_hex :prototype(@) { # convert to hexadecimal
unpack 'H*', &md4;
}
print "Rosetta Code => " . md4_hex( "Rosetta Code" ) . "\n";
- Output:
Rosetta Code => a52bcfc6a0d0d300cdc5ddbfbefe478b
Phix
-- -- demo\rosetta\md4.exw -- ==================== -- -- Non-optimised. If there is a genuine need for something faster, I can give #ilASM a bash. -- MD4 is an obsolete hash function that computes a 128-bit message digest that sometimes appears in obsolete protocols. -- Even the replacement, MD5 is now considered severly comprimised. -- without js -- (allocate/poke/peek) function r32(atom a) if a<0 then a+=#100000000 end if return remainder(a,#100000000) end function function rol(atom word, integer bits) -- left rotate the bits of a 32-bit number by the specified number of bits word = r32(word) -- trim to a 32-bit uint again return r32(word*power(2,bits))+floor(word/power(2,32-bits)) end function function f(atom x,y,z) return or_bits(and_bits(x,y),and_bits(not_bits(x),z)) end function function g(atom x,y,z) return or_all({r32(and_bits(x,y)),and_bits(x,z),and_bits(y,z)}) end function function h(atom x,y,z) return xor_bits(r32(xor_bits(x,y)),z) end function function md4(sequence data) integer bytes_to_add = 64-remainder(length(data)+9,64) if bytes_to_add=64 then bytes_to_add = 0 end if data = dataP&repeat(0,bytes_to_add)& int_to_bytes(length(data)*8,8) atom a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476 atom m64 = allocate(64,true) integer i for x=1 to length(data)-1 by 64 do poke(m64,data[x..x+63]) sequence z = peek4u({m64,16}) atom a2 = a, b2 = b, c2 = c, d2 = d for i=0 to 12 by 4 do a = rol(a + f(b, c, d) + z[i+1], 3) d = rol(d + f(a, b, c) + z[i+2], 7) c = rol(c + f(d, a, b) + z[i+3], 11) b = rol(b + f(c, d, a) + z[i+4], 19) end for for i=1 to 4 do a = rol(a + g(b, c, d) + z[i+0] + 0x5a827999, 3) d = rol(d + g(a, b, c) + z[i+4] + 0x5a827999, 5) c = rol(c + g(d, a, b) + z[i+8] + 0x5a827999, 9) b = rol(b + g(c, d, a) + z[i+12] + 0x5a827999, 13) end for for j=1 to 4 do i = {1, 3, 2, 4}[j] a = rol(a + h(b, c, d) + z[i+0] + 0x6ed9eba1, 3) d = rol(d + h(a, b, c) + z[i+8] + 0x6ed9eba1, 9) c = rol(c + h(d, a, b) + z[i+4] + 0x6ed9eba1, 11) b = rol(b + h(c, d, a) + z[i+12] + 0x6ed9eba1, 15) end for a = r32(a+a2) b = r32(b+b2) c = r32(c+c2) d = r32(d+d2) end for poke4(m64,{a,b,c,d}) return peek({m64,16}) end function function hexify(sequence s) for i=1 to length(s) do s[i] = sprintf("%02X",s[i]) end for return join(s,"") end function ?hexify(md4("Rosetta Code")) {} = wait_key()
- Output:
"a52bcfc6a0d0d300cdc5ddbfbefe478b"
PHP
echo hash('md4', "Rosetta Code"), "\n";
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
PicoLisp
Library and implementation.
(de *Md4-W .
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 5 9 13 2 6 10 14 3 7 11 15 4 8 12 16
1 9 5 13 3 11 7 15 2 10 6 14 4 12 8 16 .))
(de *Md4-R1 . (3 7 11 19 .))
(de *Md4-R2 . (3 5 9 13 .))
(de *Md4-R3 . (3 9 11 15 .))
(de mod32 (N)
(& N `(hex "FFFFFFFF")) )
(de not32 (N)
(x| N `(hex "FFFFFFFF")) )
(de add32 @
(mod32 (pass +)) )
(de leftRotate (X C)
(| (mod32 (>> (- C) X)) (>> (- 32 C) X)) )
(de md4 (Str)
(let Len (length Str)
(setq Str
(conc
(need
(- 8 (* 64 (/ (+ Len 1 8 63) 64))) # Pad to 64-8 bytes
(conc
(mapcar char (chop Str)) # Works only with ASCII characters
(cons `(hex "80")) ) # '1' bit
0 ) # Pad with '0'
(make
(setq Len (* 8 Len))
(do 8
(link (& Len 255))
(setq Len (>> 8 Len )) ) ) ) ) )
(let
(H0 `(hex "67452301")
H1 `(hex "EFCDAB89")
H2 `(hex "98BADCFE")
H3 `(hex "10325476")
R2 `(hex "5A827999")
R3 `(hex "6ED9EBA1") )
(while Str
(let
(A H0 B H1 C H2 D H3
W (make
(do 16
(link
(apply |
(mapcar >> (0 -8 -16 -24) (cut 4 'Str)) ) ) ) ) )
(for I 12
(cond
((>= 4 I)
(setq
A (leftRotate
(add32
A
(| (& B C) (& (not32 B) D))
(get W (pop '*Md4-W)) )
(pop '*Md4-R1) )
D (leftRotate
(add32
D
(| (& A B) (& (not32 A) C))
(get W (pop '*Md4-W)) )
(pop '*Md4-R1) )
C (leftRotate
(add32
C
(| (& D A) (& (not32 D) B))
(get W (pop '*Md4-W)) )
(pop '*Md4-R1) )
B (leftRotate
(add32
B
(| (& C D) (& (not32 C) A))
(get W (pop '*Md4-W)) )
(pop '*Md4-R1) ) ) )
((>= 8 I)
(setq
A (leftRotate
(add32
A
(|
(& B (| C D))
(& C D) )
(get W (pop '*Md4-W))
R2 )
(pop '*Md4-R2) )
D (leftRotate
(add32
D
(|
(& A (| B C))
(& B C) )
(get W (pop '*Md4-W))
R2 )
(pop '*Md4-R2) )
C (leftRotate
(add32
C
(|
(& D (| A B))
(& A B) )
(get W (pop '*Md4-W))
R2 )
(pop '*Md4-R2) )
B (leftRotate
(add32
B
(|
(& C (| D A))
(& D A) )
(get W (pop '*Md4-W))
R2 )
(pop '*Md4-R2) ) ) )
(T
(setq
A (leftRotate
(add32
A
(x| B C D)
(get W (pop '*Md4-W))
R3 )
(pop '*Md4-R3) )
D (leftRotate
(add32
D
(x| A B C)
(get W (pop '*Md4-W))
R3 )
(pop '*Md4-R3) )
C (leftRotate
(add32
C
(x| D A B)
(get W (pop '*Md4-W))
R3 )
(pop '*Md4-R3) )
B (leftRotate
(add32
B
(x| C D A)
(get W (pop '*Md4-W))
R3 )
(pop '*Md4-R3) ) ) ) ) )
(setq
H0 (add32 H0 A)
H1 (add32 H1 B)
H2 (add32 H2 C)
H3 (add32 H3 D) ) ) )
(make
(for N (list H0 H1 H2 H3)
(do 4
(link (& N 255))
(setq N (>> 8 N)) ) ) ) ) )
(let Str "Rosetta Code"
(println
(pack
(mapcar
'((B) (pad 2 (hex B)))
(md4 Str) ) ) )
(println
(pack
(mapcar
'((B) (pad 2 (hex B)))
(native
"libcrypto.so"
"MD4"
'(B . 16)
Str
(length Str)
'(NIL (16)) ) ) ) ) )
(bye)
Python
Depending on how your python was compiled, 'hashlib' from python's standard library may provide md4 hashing.
import hashlib
print hashlib.new("md4",raw_input().encode('utf-16le')).hexdigest().upper()
Racket
#lang racket
(require (planet soegaard/digest:1:2/digest))
(md4 #"Rosetta Code")
- Output:
"a52bcfc6a0d0d300cdc5ddbfbefe478b"
Raku
(formerly Perl 6)
sub md4($str) {
my buf8 $buf .= new: $str.encode;
my $buf-length = $buf.elems;
$buf.push: 0x80;
$buf.push: 0 until ($buf - (448 div 8)) %% (512 div 8);
# raku serializes in little endian by default
$buf.write-uint64: $buf.elems, $buf-length*8;
my (&f, &g, &h, &r) =
{ $^x +& $^y +| +^$x +& $^z },
{ $^x +& $^y +| $x +& $^z +| $y +& $z },
{ $^x +^ $^y +^ $^z },
# for some reason we have to type v here
-> uint32 $v, $s { $v +< $s +| $v +> (32 - $s) }
my uint32 ($a, $b, $c, $d) = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476;
loop (my $pos = 0; $pos < $buf.elems; $pos+=64) {
my ($aa, $bb, $cc, $dd) = $a, $b, $c, $d;
for 0, 4, 8, 12 -> $i {
$a = r($a + f($b, $c, $d) + $buf.read-uint32($pos+($i+0)*4), 3);
$d = r($d + f($a, $b, $c) + $buf.read-uint32($pos+($i+1)*4), 7);
$c = r($c + f($d, $a, $b) + $buf.read-uint32($pos+($i+2)*4), 11);
$b = r($b + f($c, $d, $a) + $buf.read-uint32($pos+($i+3)*4), 19);
}
for 0, 1, 2, 3 -> $i {
$a = r($a + g($b, $c, $d) + $buf.read-uint32($pos+($i+0 )*4) + 0x5a827999, 3);
$d = r($d + g($a, $b, $c) + $buf.read-uint32($pos+($i+4 )*4) + 0x5a827999, 5);
$c = r($c + g($d, $a, $b) + $buf.read-uint32($pos+($i+8 )*4) + 0x5a827999, 9);
$b = r($b + g($c, $d, $a) + $buf.read-uint32($pos+($i+12)*4) + 0x5a827999, 13);
}
for 0, 2, 1, 3 -> $i {
$a = r($a + h($b, $c, $d) + $buf.read-uint32($pos+($i+0 )*4) + 0x6ed9eba1, 3);
$d = r($d + h($a, $b, $c) + $buf.read-uint32($pos+($i+4 )*4) + 0x6ed9eba1, 9);
$c = r($c + h($d, $a, $b) + $buf.read-uint32($pos+($i+8 )*4) + 0x6ed9eba1, 11);
$b = r($b + h($c, $d, $a) + $buf.read-uint32($pos+($i+12)*4) + 0x6ed9eba1, 15);
}
($a,$b,$c,$d) Z[+=] ($aa,$bb,$cc,$dd);
}
reduce { $^buf.write-uint32: $buf.elems, $^x; $buf }, buf8.new, $a, $b, $c, $d;
}
CHECK {
use Test;
plan 1;
is md4('Rosetta Code').list.fmt('%02X'), 'A5 2B CF C6 A0 D0 D3 00 CD C5 DD BF BE FE 47 8B';
}
- Output:
1..1 ok 1 -
Ruby
Use 'openssl' from Ruby's standard library.
require 'openssl'
puts OpenSSL::Digest::MD4.hexdigest('Rosetta Code')
Implement MD4 in Ruby.
require 'stringio'
# Calculates MD4 message digest of _string_. Returns binary digest.
# For hexadecimal digest, use +*md4(str).unpack('H*')+.
def md4(string)
# functions
mask = (1 << 32) - 1
f = proc {|x, y, z| x & y | x.^(mask) & z}
g = proc {|x, y, z| x & y | x & z | y & z}
h = proc {|x, y, z| x ^ y ^ z}
r = proc {|v, s| (v << s).&(mask) | (v.&(mask) >> (32 - s))}
# initial hash
a, b, c, d = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
bit_len = string.size << 3
string += "\x80"
while (string.size % 64) != 56
string += "\0"
end
string = string.force_encoding('ascii-8bit') + [bit_len & mask, bit_len >> 32].pack("V2")
if string.size % 64 != 0
fail "failed to pad to correct length"
end
io = StringIO.new(string)
block = ""
while io.read(64, block)
x = block.unpack("V16")
# Process this block.
aa, bb, cc, dd = a, b, c, d
[0, 4, 8, 12].each {|i|
a = r[a + f[b, c, d] + x[i], 3]; i += 1
d = r[d + f[a, b, c] + x[i], 7]; i += 1
c = r[c + f[d, a, b] + x[i], 11]; i += 1
b = r[b + f[c, d, a] + x[i], 19]
}
[0, 1, 2, 3].each {|i|
a = r[a + g[b, c, d] + x[i] + 0x5a827999, 3]; i += 4
d = r[d + g[a, b, c] + x[i] + 0x5a827999, 5]; i += 4
c = r[c + g[d, a, b] + x[i] + 0x5a827999, 9]; i += 4
b = r[b + g[c, d, a] + x[i] + 0x5a827999, 13]
}
[0, 2, 1, 3].each {|i|
a = r[a + h[b, c, d] + x[i] + 0x6ed9eba1, 3]; i += 8
d = r[d + h[a, b, c] + x[i] + 0x6ed9eba1, 9]; i -= 4
c = r[c + h[d, a, b] + x[i] + 0x6ed9eba1, 11]; i += 8
b = r[b + h[c, d, a] + x[i] + 0x6ed9eba1, 15]
}
a = (a + aa) & mask
b = (b + bb) & mask
c = (c + cc) & mask
d = (d + dd) & mask
end
[a, b, c, d].pack("V4")
end
if __FILE__ == $0
# Print an example MD4 digest.
str = 'Rosetta Code'
printf "%s:\n %s\n", str, *md4(str).unpack('H*')
end
- Output:
Rosetta Code: a52bcfc6a0d0d300cdc5ddbfbefe478b
Rust
// 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)));
}
- Output:
md4("Rosetta Code") = a52bcfc6a0d0d300cdc5ddbfbefe478b
Scala
import org.bouncycastle.crypto.digests.MD4Digest
object RosettaRIPEMD160 extends App {
val (raw, messageDigest) = ("Rosetta Code".getBytes("US-ASCII"), new MD4Digest())
messageDigest.update(raw, 0, raw.length)
val out = Array.fill[Byte](messageDigest.getDigestSize())(0)
messageDigest.doFinal(out, 0)
assert(out.map("%02x".format(_)).mkString == "a52bcfc6a0d0d300cdc5ddbfbefe478b")
import scala.compat.Platform.currentTime
println(s"Successfully completed without errors. [total ${currentTime - executionStart} ms]")
}
Seed7
$ include "seed7_05.s7i";
include "msgdigest.s7i";
const proc: main is func
begin
writeln(hex(md4("Rosetta Code")));
end func;
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
Sidef
var digest = frequire('Digest::MD4');
say digest.md4_hex('Rosetta Code');
- Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b
Tcl
package require md4
# Use -hex option for hexadecimal output instead of binary
puts [md4::md4 -hex "Rosetta Code"]
- Output:
A52BCFC6A0D0D300CDC5DDBFBEFE478B
Wren
import "./fmt" for Fmt
var toBytes = Fn.new { |val|
var bytes = List.filled(4, 0)
bytes[0] = val & 255
bytes[1] = (val >> 8) & 255
bytes[2] = (val >> 16) & 255
bytes[3] = (val >> 24) & 255
return bytes
}
var toInt = Fn.new { |bytes| bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24 }
var md4 = Fn.new { |initMsg|
var f = Fn.new { |x, y, z| (x & y) | (~x & z) }
var g = Fn.new { |x, y, z| (x & y) | (x & z) | (y & z) }
var h = Fn.new { |x, y, z| x ^ y ^ z }
var r = Fn.new { |v, s| (v << s) | (v >> (32 - s)) }
var a = 0x67452301
var b = 0xefcdab89
var c = 0x98badcfe
var d = 0x10325476
var initBytes = initMsg.bytes
var initLen = initBytes.count
var newLen = initLen + 1
while (newLen % 64 != 56) newLen = newLen + 1
var msg = List.filled(newLen + 8, 0)
for (i in 0...initLen) msg[i] = initBytes[i]
msg[initLen] = 0x80 // remaining bytes already 0
var lenBits = toBytes.call(initLen * 8)
for (i in newLen...newLen+4) msg[i] = lenBits[i-newLen]
var extraBits = toBytes.call(initLen >> 29)
for (i in newLen+4...newLen+8) msg[i] = extraBits[i-newLen-4]
var offset = 0
var x = List.filled(16, 0)
while (offset < newLen) {
for (i in 0...16) x[i] = toInt.call(msg[offset+i*4...offset + i*4 + 4])
var a2 = a
var b2 = b
var c2 = c
var d2 = d
for (i in [0, 4, 8, 12]) {
a = r.call(a + f.call(b, c, d) + x[i+0], 3)
d = r.call(d + f.call(a, b, c) + x[i+1], 7)
c = r.call(c + f.call(d, a, b) + x[i+2], 11)
b = r.call(b + f.call(c, d, a) + x[i+3], 19)
}
for (i in 0..3) {
a = r.call(a + g.call(b, c, d) + x[i+0] + 0x5a827999, 3)
d = r.call(d + g.call(a, b, c) + x[i+4] + 0x5a827999, 5)
c = r.call(c + g.call(d, a, b) + x[i+8] + 0x5a827999, 9)
b = r.call(b + g.call(c, d, a) + x[i+12] + 0x5a827999, 13)
}
for (i in [0, 2, 1, 3]) {
a = r.call(a + h.call(b, c, d) + x[i+0] + 0x6ed9eba1, 3)
d = r.call(d + h.call(a, b, c) + x[i+8] + 0x6ed9eba1, 9)
c = r.call(c + h.call(d, a, b) + x[i+4] + 0x6ed9eba1, 11)
b = r.call(b + h.call(c, d, a) + x[i+12] + 0x6ed9eba1, 15)
}
a = a + a2
b = b + b2
c = c + c2
d = d + d2
offset = offset + 64
}
var digest = List.filled(16, 0)
var dBytes = toBytes.call(a)
for (i in 0...4) digest[i] = dBytes[i]
dBytes = toBytes.call(b)
for (i in 0...4) digest[i+4] = dBytes[i]
dBytes = toBytes.call(c)
for (i in 0...4) digest[i+8] = dBytes[i]
dBytes = toBytes.call(d)
for (i in 0...4) digest[i+12] = dBytes[i]
return digest
}
var strings = [
"",
"a",
"abc",
"message digest",
"abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
"Rosetta Code"
]
for (s in strings) {
var digest = md4.call(s)
Fmt.print("$s <== '$0s'", Fmt.v("xz", 2, digest, 0, "", ""), s)
}
- Output:
31d6cfe0d16ae931b73c59d7e0c089c0 <== '' bde52cb31de33e46245e05fbdbd6fb24 <== 'a' a448017aaf21d8525fc10ae87aa6729d <== 'abc' d9130a8164549fe818874806e1c7014b <== 'message digest' d79e1c308aa5bbcdeea8ed63df412da9 <== 'abcdefghijklmnopqrstuvwxyz' 043f8582f241db351ce627e153e7f0e4 <== 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' e33b4ddc9c38f2199c3e7b164fcc0536 <== '12345678901234567890123456789012345678901234567890123456789012345678901234567890' a52bcfc6a0d0d300cdc5ddbfbefe478b <== 'Rosetta Code'
- Programming Tasks
- Solutions by Programming Task
- Checksums
- Ada
- CryptAda
- AutoHotkey
- BASIC
- FreeBASIC
- C
- C sharp
- C++
- Clojure
- Pandect
- Common Lisp
- Ironclad
- D
- Delphi
- System.SysUtils
- DCPmd4
- Emacs Lisp
- Erlang
- Go
- Go sub-repositories
- Haskell
- Cryptonite
- J
- Java
- BouncyCastle
- JavaScript
- Julia
- Kotlin
- Lasso
- Lua
- LuaCrypto
- Mathematica
- Wolfram Language
- Nim
- OpenSSL
- PARI/GP
- Perl
- Phix
- PHP
- PicoLisp
- Python
- Hashlib
- Racket
- Raku
- Ruby
- Rust
- Scala
- Seed7
- Sidef
- Tcl
- Tcllib
- Wren
- Wren-fmt