MD4: Difference between revisions

From Rosetta Code
Content added Content deleted
(+ D entry)
(Nimrod -> Nim)
Line 229: Line 229:
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre>
<pre>a52bcfc6a0d0d300cdc5ddbfbefe478b</pre>


=={{header|Nimrod}}==
=={{header|Nim}}==
{{libheader|OpenSSL}}
{{libheader|OpenSSL}}
Compile with <code>nimrod -d:ssl c md4.nim</code>:
Compile with <code>nim -d:ssl c md4.nim</code>:
<lang nimrod>import strutils
<lang nim>import strutils


const MD4Len = 16
const MD4Len = 16

Revision as of 23:17, 3 January 2015

Task
MD4
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.

AutoHotkey

Source: MD4 @github by jNizM <lang AutoHotkey>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)

}</lang>

Output:
String:    Rosetta Code
MD4:       A52BCFC6A0D0D300CDC5DDBFBEFE478B

Clojure

Library: pandect

<lang clojure>(use 'pandect.core) (md4 "Rosetta Code")</lang>

Output:
"a52bcfc6a0d0d300cdc5ddbfbefe478b"

Common Lisp

Library: Ironclad

<lang 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")</lang>

Output:
"a52bcfc6a0d0d300cdc5ddbfbefe478b"

D

A short but not efficient implementation.

Translation of: Ruby

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

}</lang>

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.

<lang Lisp>(require 'md4) (let* ((s "Rosetta Code")

      (m  (md4 s (length s)))) ;; m = 16 binary bytes
 (require 'hex-util)
 (encode-hex-string m))

=> "a52bcfc6a0d0d300cdc5ddbfbefe478b"</lang>

Erlang

<lang erlang> -module(md4). -export([md4/0]).

md4() ->

   <<MD4:128>> = crypto:md4("Rosetta Code"),
   io:fwrite("Rosetta Code => ~.16B~n",[MD4]).

</lang>

Rosetta Code => A52BCFC6A0D0D300CDC5DDBFBEFE478B

Go

<lang 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))

}</lang>

Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b

Java

Library: BouncyCastle

<lang 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();
   }

}</lang>

Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b


Lasso

<lang Lasso>cipher_digest('Rosetta Code', -digest='MD4')->encodeHex->asString</lang>

Output:
 A52BCFC6A0D0D300CDC5DDBFBEFE478B 

Lua

Works with: Lua 5.1.4
Library: LuaCrypto

(luarocks install LuaCrypto)

<lang Lua>#!/usr/bin/lua

require "crypto"

print(crypto.digest("MD4", "Rosetta Code"))</lang>

Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b

Nim

Library: OpenSSL

Compile with nim -d:ssl c md4.nim: <lang 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")</lang>

Perl

<lang Perl>#!/usr/bin/perl use strict ; use warnings ; use Digest::MD4 qw( md4_hex ) ;

print "Rosetta Code => " , md4_hex( "Rosetta Code" ) , "\n" ;</lang>

Output:
Rosetta Code => a52bcfc6a0d0d300cdc5ddbfbefe478b

Perl 6

<lang perl6>sub md4($str) {

   my @buf = $str.ords;
   my $buflen = @buf.elems;
   my \mask = (1 +< 32) - 1;
   my &f = -> $x, $y, $z { ($x +& $y) +| ($x +^ mask) +& $z }
   my &g = -> $x, $y, $z { ($x +& $y) +| ($x +& $z) +| ($y +& $z) }
   my &h = -> $x, $y, $z { $x +^ $y +^ $z }
   my &r = -> $v, $s { (($v +< $s) +& mask) +| (($v +& mask) +> (32 - $s)) }
   sub pack-le (@a) {
       gather for @a -> $a,$b,$c,$d { take $d +< 24 + $c +< 16 + $b +< 8 + $a }
   }

   my ($a, $b, $c, $d) = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476;

   my $term = False;
   my $last = False;
   my $off = 0;
   repeat until $last {
       my @block = @buf[$off..$off+63]:v; $off += 64;

       my @x;
       given +@block {

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;

   }

   sub b2l($n is copy) {

my $x = 0; for ^4 { $x +<= 8; $x += $n +& 0xff; $n +>= 8; } $x;

   }
   b2l($a) +< 96 +
   b2l($b) +< 64 +
   b2l($c) +< 32 +
   b2l($d);

}

sub MAIN {

   my $str = 'Rosetta Code';
   say md4($str).base(16).lc;

}</lang>

Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b

PicoLisp

Library and implementation. <lang picolisp>(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)</lang>

PHP

<lang php> echo hash('md4', "Rosetta Code"), "\n"; </lang>

Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b


Python

Use 'hashlib' from python's standard library.

Library: hashlib

<lang python>import hashlib print hashlib.new("md4",raw_input().encode('utf-16le')).hexdigest().upper()</lang>

Racket

<lang racket>

  1. lang racket

(require (planet soegaard/digest:1:2/digest)) (md4 #"Rosetta Code") </lang>

Output:
"a52bcfc6a0d0d300cdc5ddbfbefe478b"

Ruby

Use 'openssl' from Ruby's standard library.

Library: OpenSSL

<lang ruby>require 'openssl' puts OpenSSL::Digest::MD4.hexdigest('Rosetta Code')</lang>

Implement MD4 in Ruby.

<lang ruby>require 'stringio'

  1. Calculates MD4 message digest of _string_. Returns binary digest.
  2. 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</lang>

Output:
Rosetta Code:
  a52bcfc6a0d0d300cdc5ddbfbefe478b

Scala

Library: Scala

<lang 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]")

}</lang>

Seed7

<lang seed7>$ include "seed7_05.s7i";

 include "msgdigest.s7i";

const proc: main is func

 begin
   writeln(hex(md4("Rosetta Code")));
 end func;</lang>
Output:
a52bcfc6a0d0d300cdc5ddbfbefe478b

Tcl

Library: Tcllib (Package: md4)

<lang tcl>package require md4

  1. Use -hex option for hexadecimal output instead of binary

puts [md4::md4 -hex "Rosetta Code"]</lang>

Output:
A52BCFC6A0D0D300CDC5DDBFBEFE478B