Re: Using jce1_2-do.jar

Sharon Liu (Sharon.Liu@eng.sun.com)
Wed, 21 Jul 1999 16:51:25 -0700 (PDT)

Message-Id: <199907212351.QAA25655@shorter.eng.sun.com>
Date: Wed, 21 Jul 1999 16:51:25 -0700 (PDT)
From: Sharon Liu <Sharon.Liu@eng.sun.com>
Subject: Re: Using jce1_2-do.jar
To: java-security@java.sun.com, mark.baushke@solipsa.com

--Drift_of_Hogs_723_000
Content-Type: TEXT/plain; charset="us-ascii"
Content-MD5: squxRHcjUaFS24U4mE4LrQ==
X-Sun-Content-Length: 8941

Mark,

The Message Authentication Code (MAC) is different from the Message
Digest.

To generate a MD5 digest, you don't need JCE. You should use the
java.security.MessageDigest in Java 2 SDK (which used to be called JDK).

To our understanding, some cryptographic services are subject to US
export control regulation (e.g., cipher, MAC, etc.); some are not (e.g.,
digital signature, message digest, etc.). We have those crypto services
not subject to export controls in Java 2 SDK; and those subject to
export controls in the JCE.

The attached java program uses MessageDigest. And the
output is:

% java MD5Test 'Hi There'
data = "Hi There"
digest = 5b49b515f3173e4540b7d39bb57a4482

So the java code generates the same digest as your perl code.

Thanks,
Sharon

> To: java-security@java.sun.com
> cc: "Mark D. Baushke" <mark.baushke@solipsa.com>
> Subject: Using jce1_2-do.jar
> X-Phone: +1 408 248-9426 (Home)
>
> Greetings,
>
> I tried to find something relevant on the
> http://java.sun.com/cgi-bin/bugreport.cgi
> page for reporting this problem, but I was unable to find anything
> related to jce at all, so I am sending my question via e-mail to you
> directly. If this is not the correct place, please let me know how to
> proceed.
>
> Problem statement:
>
> I need to be able to generate a simple MD5 hash of the same
> arbitrary text in both java and perl and get the same result.
>
> Version information:
>
> For perl, I am using perl 5.005_03 with MD5-1.7 from the CPAN archive.
> For java, I am using jdk1.2 java and jce1_2-do.jar from your site.
> (http://java.sun.com/products/jce/)
>
> For the tests show below, I was running on intel hardware with a
> RedHat Linux 6.0 operating system. My perl test gives the same
> answer on both Sparc and Intel hardware.
>
> Reproducing the test:
>
> % unshar < path-to-this-message
> % perl HmacMD5Test.perl 'Hi There'
> data = "Hi There"
> digest = 5b49b515f3173e4540b7d39bb57a4482
> % javac -g HmacMD5Test.java
> % java HmacMD5Test 'Hi There'
> key = javax.crypto.spec.SecretKeySpec@c2f22036
> data = "Hi There"
> digest = 72c33c78cac0b7a581ac263a344ed01d
> % echo -n 'Hi There' | md5
> 5b49b515f3173e4540b7d39bb57a4482
> %
>
> Analysis:
>
> As you can see, I do not get the same digest result. I am hoping that
> this is a bit of pilot error on my part and that you will be able to
> tell me what I need to do to get things to work.
>
> If you have any suggestions for how to modify the way I use the
> javax.crypto.Mac class so that I get the desired result, please let me
> know.
>
> Thanks,
> -- Mark
>
> PS: The md5 program used in the test above is from 'fingerprint'
> utility posted to the net some years ago.
>
> #!/bin/sh
> # This is a shell archive (produced by GNU sharutils 4.2).
> # To extract the files from this archive, save it to some FILE, remove
> # everything before the `!/bin/sh' line above, then type `sh FILE'.
> #
> # Made on 1999-07-20 22:28 PDT by <mark.baushke@solipsa.com>.
> # Source directory was `/tmp'.
> #
> # Existing files will *not* be overwritten unless `-c' is specified.
> #
> # This shar contains:
> # length mode name
> # ------ ---------- ------------------------------------------
> # 1920 -rw-r--r-- HmacMD5Test.java
> # 178 -rwxr-xr-x HmacMD5Test.perl
> #
> save_IFS="${IFS}"
> IFS="${IFS}:"
> gettext_dir=FAILED
> locale_dir=FAILED
> first_param="$1"
> for dir in $PATH
> do
> if test "$gettext_dir" = FAILED && test -f $dir/gettext \
> && ($dir/gettext --version >/dev/null 2>&1)
> then
> set `$dir/gettext --version 2>&1`
> if test "$3" = GNU
> then
> gettext_dir=$dir
> fi
> fi
> if test "$locale_dir" = FAILED && test -f $dir/shar \
> && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
> then
> locale_dir=`$dir/shar --print-text-domain-dir`
> fi
> done
> IFS="$save_IFS"
> if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
> then
> echo=echo
> else
> TEXTDOMAINDIR=$locale_dir
> export TEXTDOMAINDIR
> TEXTDOMAIN=sharutils
> export TEXTDOMAIN
> echo="$gettext_dir/gettext -s"
> fi
> touch -am 1231235999 $$.touch >/dev/null 2>&1
> if test ! -f 1231235999 && test -f $$.touch; then
> shar_touch=touch
> else
> shar_touch=:
> echo
> $echo 'WARNING: not restoring timestamps. Consider getting and'
> $echo "installing GNU \`touch', distributed in GNU File Utilities..."
> echo
> fi
> rm -f 1231235999 $$.touch
> #
> if mkdir _sh25060; then
> $echo 'x -' 'creating lock directory'
> else
> $echo 'failed to create lock directory'
> exit 1
> fi
> # ============= HmacMD5Test.java ==============
> if test -f 'HmacMD5Test.java' && test "$first_param" != -c; then
> $echo 'x -' SKIPPING 'HmacMD5Test.java' '(file already exists)'
> else
> $echo 'x -' extracting 'HmacMD5Test.java' '(text)'
> sed 's/^X//' << 'SHAR_EOF' > 'HmacMD5Test.java' &&
> /*
> X *------------------------------------------------------------------
> X * HmacMD5Test -- a trivial test of an Hmac-MD5
> X *
> X * July 1999, Mark D. Baushke
> X *
> X * Copyright (c) 1999 by Solipsa Corporation
> X * All rights reserved.
> X *------------------------------------------------------------------
> X */
> X
> import java.io.*;
> import javax.crypto.*;
> import java.security.*;
> X
> public class HmacMD5Test {
> X public static void main(String[] args) {
> X Mac mac;
> X
> X try {
> X // Install SunJCE provider
> X Provider sunJce = new com.sun.crypto.provider.SunJCE();
> X Security.addProvider(sunJce);
> X // Generate secret key for HMAC-MD5
> X KeyGenerator kg = KeyGenerator.getInstance("HmacMD5");
> X SecretKey sk = kg.generateKey();
> X mac = Mac.getInstance("HmacMD5");
> X
> X /*
> X * Now go ahead and process the command line args using
> X * each one as data to generate a digest.
> X */
> X for (int i = 0; i < args.length; i++) { // Command-line args
> X mac.init(sk);
> X byte[] mydigest = mac.doFinal(args[i].getBytes());
> X System.out.println("key = " + sk);
> X System.out.println("data = \"" + args[i] + "\"");
> X System.out.println("digest = " + toHexString(mydigest));
> X }
> X }
> X catch (Exception e) {
> X System.out.println(e);
> X System.exit(1);
> X }
> X }
> X
> X /*
> X * Converts a byte to hex digit and writes to the supplied buffer
> X */
> X static private void byte2hex(byte b, StringBuffer buf) {
> X char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
> X '9', 'a', 'b', 'c', 'd', 'e', 'f' };
> X int high = ((b & 0xf0) >> 4);
> X int low = (b & 0x0f);
> X buf.append(hexChars[high]);
> X buf.append(hexChars[low]);
> X }
> X
> X /*
> X * Converts a byte array to hex string
> X */
> X static private String toHexString(byte[] block) {
> X StringBuffer buf = new StringBuffer();
> X
> X int len = block.length;
> X
> X for (int i = 0; i < len; i++) {
> X byte2hex(block[i], buf);
> X }
> X return buf.toString();
> X }
> }
> SHAR_EOF
> $shar_touch -am 0720222199 'HmacMD5Test.java' &&
> chmod 0644 'HmacMD5Test.java' ||
> $echo 'restore of' 'HmacMD5Test.java' 'failed'
> if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
> && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
> md5sum -c << SHAR_EOF >/dev/null 2>&1 \
> || $echo 'HmacMD5Test.java:' 'MD5 check failed'
> 2d94324a601520f9f9409ccdc7579ebc HmacMD5Test.java
> SHAR_EOF
> else
> shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'HmacMD5Test.java'`"
> test 1920 -eq "$shar_count" ||
> $echo 'HmacMD5Test.java:' 'original size' '1920,' 'current size'
"$shar_count!"
> fi
> fi
> # ============= HmacMD5Test.perl ==============
> if test -f 'HmacMD5Test.perl' && test "$first_param" != -c; then
> $echo 'x -' SKIPPING 'HmacMD5Test.perl' '(file already exists)'
> else
> $echo 'x -' extracting 'HmacMD5Test.perl' '(text)'
> sed 's/^X//' << 'SHAR_EOF' > 'HmacMD5Test.perl' &&
> #!/usr/bin/perl
> X
> use Digest::MD5 qw(md5_hex);
> X
> foreach $arg (@ARGV) {
> X $mydigest = md5_hex($arg);
> X print('data = "', $arg, '"', "\n",
> X 'digest = ', $mydigest, "\n");
> }
> SHAR_EOF
> $shar_touch -am 0720222799 'HmacMD5Test.perl' &&
> chmod 0755 'HmacMD5Test.perl' ||
> $echo 'restore of' 'HmacMD5Test.perl' 'failed'
> if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
> && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
> md5sum -c << SHAR_EOF >/dev/null 2>&1 \
> || $echo 'HmacMD5Test.perl:' 'MD5 check failed'
> 48783e53f1c0192b68bbbca20efb4471 HmacMD5Test.perl
> SHAR_EOF
> else
> shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'HmacMD5Test.perl'`"
> test 178 -eq "$shar_count" ||
> $echo 'HmacMD5Test.perl:' 'original size' '178,' 'current size'
"$shar_count!"
> fi
> fi
> rm -fr _sh25060
> exit 0

--Drift_of_Hogs_723_000
Content-Type: TEXT/plain; name="MD5Test.java"; charset="us-ascii"; x-unix-mode="0644"
Content-Description: MD5Test.java
Content-MD5: vv3nCoyBG/4Oi+flVeMnhA==
X-Sun-Content-Length: 1464

/*
*------------------------------------------------------------------
* MD5Test -- a trivial test of an MD5
*
*------------------------------------------------------------------
*/

import java.io.*;
import java.security.*;

public class MD5Test {
public static void main(String[] args) {

try {
MessageDigest md = MessageDigest.getInstance("MD5");

/*
* Now go ahead and process the command line args using
* each one as data to generate a digest.
*/
for (int i = 0; i < args.length; i++) { // Command-line args
byte[] mydigest = md.digest(args[i].getBytes());
System.out.println("data = \"" + args[i] + "\"");
System.out.println("digest = " + toHexString(mydigest));
}
}
catch (Exception e) {
System.out.println(e);
System.exit(1);
}
}

/*
* Converts a byte to hex digit and writes to the supplied buffer
*/
static private void byte2hex(byte b, StringBuffer buf) {
char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f' };
int high = ((b & 0xf0) >> 4);
int low = (b & 0x0f);
buf.append(hexChars[high]);
buf.append(hexChars[low]);
}

/*
* Converts a byte array to hex string
*/
static private String toHexString(byte[] block) {
StringBuffer buf = new StringBuffer();

int len = block.length;

for (int i = 0; i < len; i++) {
byte2hex(block[i], buf);
}
return buf.toString();
}
}

--Drift_of_Hogs_723_000--