This is the mail archive of the java-patches@sourceware.cygnus.com mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

PATCH: SHA for Serialization


Folks,
The following patch provides the necessary SHA algorithm (from Classpath) 
for getting the serialVersionUID right in serialization.
--warrenl

2000-06-28  Warren Levy  <warrenl@cygnus.com>

        * gnu/java/security/provider/Gnu.java: New file.
        * gnu/java/security/provider/SHA.java: New file.
        * gnu/java/security/provider/SHA1PRNG.java: New file.
        * Makefile.am: Added the above files.
        * Makefile.in: Rebuilt.

        * java/io/ObjectStreamClass.java (setUID): Use Gnu SHA instead of SHS.



Index: Makefile.am
===================================================================
RCS file: /cvs/java/libgcj/libjava/Makefile.am,v
retrieving revision 1.67
diff -u -p -r1.67 Makefile.am
--- Makefile.am	2000/06/28 01:31:41	1.67
+++ Makefile.am	2000/06/28 11:03:23
@@ -615,6 +615,9 @@ gnu/java/io/ObjectIdentityWrapper.java \
 gnu/java/lang/reflect/TypeSignature.java \
 gnu/java/lang/ArrayHelper.java \
 gnu/java/lang/ClassHelper.java \
+gnu/java/security/provider/Gnu.java \
+gnu/java/security/provider/SHA.java \
+gnu/java/security/provider/SHA1PRNG.java \
 java/io/BufferedInputStream.java \
 java/io/BufferedOutputStream.java \
 java/io/BufferedReader.java \
Index: Makefile.in
===================================================================
RCS file: /cvs/java/libgcj/libjava/Makefile.in,v
retrieving revision 1.74
diff -u -p -r1.74 Makefile.in
--- Makefile.in	2000/06/28 01:31:41	1.74
+++ Makefile.in	2000/06/28 11:03:23
@@ -385,6 +385,9 @@ gnu/java/io/ObjectIdentityWrapper.java \
 gnu/java/lang/reflect/TypeSignature.java \
 gnu/java/lang/ArrayHelper.java \
 gnu/java/lang/ClassHelper.java \
+gnu/java/security/provider/Gnu.java \
+gnu/java/security/provider/SHA.java \
+gnu/java/security/provider/SHA1PRNG.java \
 java/io/BufferedInputStream.java \
 java/io/BufferedOutputStream.java \
 java/io/BufferedReader.java \
@@ -963,7 +966,10 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_D
 .deps/gnu/java/io/NullOutputStream.P \
 .deps/gnu/java/io/ObjectIdentityWrapper.P \
 .deps/gnu/java/lang/ArrayHelper.P .deps/gnu/java/lang/ClassHelper.P \
-.deps/gnu/java/lang/reflect/TypeSignature.P .deps/interpret.P \
+.deps/gnu/java/lang/reflect/TypeSignature.P \
+.deps/gnu/java/security/provider/Gnu.P \
+.deps/gnu/java/security/provider/SHA.P \
+.deps/gnu/java/security/provider/SHA1PRNG.P .deps/interpret.P \
 .deps/java/awt/AWTError.P .deps/java/awt/AWTEvent.P \
 .deps/java/awt/AWTException.P .deps/java/awt/ActiveEvent.P \
 .deps/java/awt/Adjustable.P .deps/java/awt/BorderLayout.P \
Index: gnu/java/security/provider/Gnu.java
===================================================================
RCS file: Gnu.java
diff -N Gnu.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ Gnu.java	Wed Jun 28 04:03:23 2000
@@ -0,0 +1,79 @@
+/* Gnu.java --- Gnu provider main class
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+ 
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.security.provider;
+import java.security.Provider;
+
+public final class Gnu extends Provider
+{
+  public Gnu()
+  {
+    super( "GNU", 1.0, "GNU provider v1.0 implementing SHA-1, MD5, DSA");
+
+    // Signature
+    put("Signature.SHA1withDSA", "gnu.java.security.provider.DSASignature");
+
+    put("Alg.Alias.Signature.DSS", "SHA1withDSA");
+    put("Alg.Alias.Signature.DSA", "SHA1withDSA");
+    put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA");
+    put("Alg.Alias.Signature.DSAwithSHA", "SHA1withDSA");
+    put("Alg.Alias.Signature.DSAwithSHA1", "SHA1withDSA");
+    put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
+    put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA");
+    put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA");
+    put("Alg.Alias.Signature.OID.1.2.840.10040.4.3", "SHA1withDSA");
+    put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
+    put("Alg.Alias.Signature.1.3.14.3.2.13", "SHA1withDSA");
+    put("Alg.Alias.Signature.1.3.14.3.2.27", "SHA1withDSA");
+
+    // Key Pair Generator
+    put("KeyPairGenerator.DSA", "gnu.java.security.provider.DSAKeyPairGenerator");
+
+    put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA");
+    put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
+    put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");
+
+    // Message Digests
+    put("MessageDigest.SHA", "gnu.java.security.provider.SHA");
+    put("MessageDigest.MD5", "gnu.java.security.provider.MD5");
+
+    // Format "Alias", "Actual Name"
+    put("Alg.Alias.MessageDigest.SHA1", "SHA");
+    put("Alg.Alias.MessageDigest.SHA-1", "SHA");
+
+    // Algorithm Parameters
+    put("AlgorithmParameters.DSA", "gnu.java.security.provider.DSAAlgorithmParameters");
+
+    // Algorithm Parameter Generator
+    put("AlgorithmParameterGenerator.DSA", "gnu.java.security.provider.DSAAlgorithmParameterGenerator");
+
+    // SecureRandom
+    put("SecureRandom.SHA1PRNG", "gnu.java.security.provider.SHA1PRNG");
+
+
+  }
+}
Index: gnu/java/security/provider/SHA.java
===================================================================
RCS file: SHA.java
diff -N SHA.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ SHA.java	Wed Jun 28 04:03:23 2000
@@ -0,0 +1,227 @@
+/* SHA.java -- Class implementing the SHA-1 algorithm as specified in [1].
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+ 
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+  
+package gnu.java.security.provider;
+
+import java.security.MessageDigest;
+
+/**
+   This class implements the SHA-1 algorithm as described in [1].
+
+   [1] Federal Information Processing Standards Publication 180-1.
+   Specifications for the Secure Hash Standard.  April 17, 1995.
+
+   @see java.security.MessageDigest
+*/
+public class SHA extends MessageDigest implements Cloneable
+{
+  public SHA ()
+  {
+    super("SHA");
+    engineReset ();
+  }
+
+  public int engineGetDigestLength()
+  {
+    return 16;
+  }
+
+  public void engineUpdate (byte b)
+  {
+    int i = (int)bytecount % 64;
+    int shift = (3 - i % 4) * 8;
+    int idx = i / 4;
+
+    // if you could index ints, this would be: W[idx][shift/8] = b
+    W[idx] = (W[idx] & ~(0xff << shift)) | ((b & 0xff) << shift);
+
+    // if we've filled up a block, then process it
+    if ((++ bytecount) % 64 == 0)
+      munch ();
+  }
+
+  // This could be optimized.
+  public void engineUpdate (byte bytes[], int off, int len)
+  {
+    if (len < 0)
+      throw new ArrayIndexOutOfBoundsException ();
+
+    int end = off + len;
+    while (off < end)
+      engineUpdate (bytes[off++]);
+  }
+
+  public void engineReset ()
+  {
+    bytecount = 0;
+    // magic numbers from [1] p. 10.
+    H0 = 0x67452301;
+    H1 = 0xefcdab89;
+    H2 = 0x98badcfe;
+    H3 = 0x10325476;
+    H4 = 0xc3d2e1f0;
+  }
+
+  public byte[] engineDigest ()
+  {
+    long bitcount = bytecount * 8;
+    engineUpdate ((byte)0x80); // 10000000 in binary; the start of the padding
+
+    // add the rest of the padding to fill this block out, but leave 8
+    // bytes to put in the original bytecount
+    while ((int)bytecount % 64 != 56)
+      engineUpdate ((byte)0);
+
+    // add the length of the original, unpadded block to the end of
+    // the padding
+    W[14] = (int)(bitcount >>> 32);
+    W[15] = (int)bitcount;
+    bytecount += 8;
+
+    // digest the fully padded block
+    munch ();
+
+    byte[] result
+      = new byte[] {(byte)(H0 >>> 24), (byte)(H0 >>> 16),
+		    (byte)(H0 >>> 8), (byte)H0,
+		    (byte)(H1 >>> 24), (byte)(H1 >>> 16),
+		    (byte)(H1 >>> 8), (byte)H1,
+		    (byte)(H2 >>> 24), (byte)(H2 >>> 16),
+		    (byte)(H2 >>> 8), (byte)H2,
+		    (byte)(H3 >>> 24), (byte)(H3 >>> 16),
+		    (byte)(H3 >>> 8), (byte)H3,
+		    (byte)(H4 >>> 24), (byte)(H4 >>> 16),
+		    (byte)(H4 >>> 8), (byte)H4};
+    
+    engineReset ();
+    return result;
+  }
+
+  // Process a single block.  This is pretty much copied verbatim from
+  // [1] pp. 9, 10.
+  private void munch ()
+  {
+    for (int t = 16; t < 80; ++ t)
+      {
+	int Wt = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
+	W[t] = Wt << 1 | Wt >>> 31;
+      }
+
+    int A = H0;
+    int B = H1;
+    int C = H2;
+    int D = H3;
+    int E = H4;
+
+    for (int t = 0; t < 20; ++ t)
+      {
+	int TEMP = (A << 5 | A >>> 27) // S^5(A)
+	  + ((B & C) | (~B & D))       // f_t(B,C,D)
+	  + E + W[t]
+	  + 0x5a827999;                // K_t
+
+	E = D;
+	D = C;
+	C = B << 30 | B >>> 2;         // S^30(B)
+	B = A;
+	A = TEMP;
+      }
+
+    for (int t = 20; t < 40; ++ t)
+      {
+	int TEMP = (A << 5 | A >>> 27) // S^5(A)
+	  + (B ^ C ^ D)                // f_t(B,C,D)
+	  + E + W[t]                   
+	  + 0x6ed9eba1;                // K_t
+
+	E = D;
+	D = C;
+	C = B << 30 | B >>> 2;         // S^30(B)
+	B = A;
+	A = TEMP;
+      }
+
+    for (int t = 40; t < 60; ++ t)
+      {
+	int TEMP = (A << 5 | A >>> 27) // S^5(A)
+	  + (B & C | B & D | C & D)    // f_t(B,C,D)
+	  + E + W[t]
+	  + 0x8f1bbcdc;                // K_t
+
+	E = D;
+	D = C;
+	C = B << 30 | B >>> 2;         // S^30(B)
+	B = A;
+	A = TEMP;
+      }
+
+    for (int t = 60; t < 80; ++ t)
+      {
+	int TEMP = (A << 5 | A >>> 27) // S^5(A)
+	  + (B ^ C ^ D)                // f_t(B,C,D)
+	  + E + W[t]
+	  + 0xca62c1d6;                // K_t
+
+	E = D;
+	D = C;
+	C = B << 30 | B >>> 2;         // S^30(B)
+	B = A;
+	A = TEMP;
+      }
+
+    H0 += A;
+    H1 += B;
+    H2 += C;
+    H3 += D;
+    H4 += E;
+  }
+  
+  public Object clone ()
+  {
+    return new SHA (this);
+  }
+
+  private SHA (SHA copy)
+  {
+    this ();
+    bytecount = copy.bytecount;
+    H0 = copy.H0;
+    H1 = copy.H1;
+    H2 = copy.H2;
+    H3 = copy.H3;
+    H4 = copy.H4;
+    System.arraycopy (copy.W, 0, W, 0, 80);
+  }
+  
+  private final int W[] = new int[80];
+  private long bytecount;
+  private int H0;
+  private int H1;
+  private int H2;
+  private int H3;
+  private int H4;
+}
Index: gnu/java/security/provider/SHA1PRNG.java
===================================================================
RCS file: SHA1PRNG.java
diff -N SHA1PRNG.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ SHA1PRNG.java	Wed Jun 28 04:03:23 2000
@@ -0,0 +1,109 @@
+/* SHA1PRNG.java --- Secure Random SPI SHA1PRNG
+   Copyright (C) 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+ 
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+As a special exception, if you link this library with other files to
+produce an executable, this library does not by itself cause the
+resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why the
+executable file might be covered by the GNU General Public License. */
+
+
+package gnu.java.security.provider;
+
+import java.util.Random;
+// import java.security.SecureRandomSpi;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.io.Serializable;
+
+// public class SHA1PRNG extends SecureRandomSpi implements Serializable
+public class SHA1PRNG implements Serializable
+{
+  MessageDigest digest;
+  byte seed[];
+  byte data[];
+  int seedpos;
+  int datapos;
+
+  public SHA1PRNG()
+  {
+    try {
+      digest = MessageDigest.getInstance("SHA");
+    } catch ( NoSuchAlgorithmException nsae) {
+      System.out.println("Failed to find SHA Message Digest: " + nsae);
+      nsae.printStackTrace();
+    }
+
+    seed = new byte[20];
+    seedpos = 0;
+    data = new byte[40];
+    datapos = 0;
+
+    new Random().nextBytes(seed);
+
+    byte digestdata[];
+    digestdata = digest.digest( data );
+    System.arraycopy( digestdata, 0, data, 0, 20);
+
+  }
+
+  public void engineSetSeed(byte[] seed)
+  {
+    for(int i = 0; i < seed.length; i++)
+      this.seed[seedpos++ % 20] ^= seed[i];
+    seedpos %= 20;
+
+  }
+
+  public void engineNextBytes(byte[] bytes)
+  {
+
+    if( bytes.length < (20 - datapos) ) {
+      System.arraycopy( bytes, 0, data, datapos, bytes.length);
+      datapos += bytes.length;
+      return;
+    }
+
+    int i, blen = bytes.length, bpos = 0;
+    byte digestdata[];
+    while( bpos < blen ) {
+      i = 20 - datapos;
+      System.arraycopy( bytes, bpos, data, datapos, i);
+      bpos += i;
+      datapos += i;
+      if( datapos >= 20) {
+	//System.out.println( (0 + 20) + "\n" + (20 + 20) );
+	System.arraycopy( seed, 0, data, 20, 20);
+	digestdata = digest.digest( data );
+	System.arraycopy( digestdata, 0, data, 0, 20);
+	datapos = 0;
+      }
+    }
+
+  }
+
+  public byte[] engineGenerateSeed(int numBytes)
+  {
+    byte tmp[] = new byte[numBytes];
+	
+    engineNextBytes( tmp );
+    return tmp;
+  }
+}
Index: java/io/ObjectStreamClass.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/io/ObjectStreamClass.java,v
retrieving revision 1.1
diff -u -p -r1.1 ObjectStreamClass.java
--- ObjectStreamClass.java	2000/05/19 17:55:31	1.1
+++ ObjectStreamClass.java	2000/06/28 11:03:23
@@ -36,13 +36,14 @@ import java.lang.reflect.Modifier;
 import java.security.DigestOutputStream;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.security.Security;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Hashtable;
 import java.util.Vector;
 import gnu.java.io.NullOutputStream;
 import gnu.java.lang.reflect.TypeSignature;
-import gnu.gcj.io.SimpleSHSStream;
+import gnu.java.security.provider.Gnu;
 
 
 public class ObjectStreamClass implements Serializable
@@ -420,20 +421,21 @@ public class ObjectStreamClass implement
       MessageDigest md = null;
       DigestOutputStream digest_out = null;
       DataOutputStream data_out = null;
-      SimpleSHSStream simple = null;
 
       try 
 	{
 	  md = MessageDigest.getInstance ("SHA");
-	  digest_out = new DigestOutputStream (nullOutputStream, md);
-	  data_out = new DataOutputStream (digest_out);	  
 	}
       catch (NoSuchAlgorithmException e)
 	{
-	  simple = new SimpleSHSStream (nullOutputStream);
-	  data_out = new DataOutputStream (simple);
+	  // If a provider already provides SHA, use it; otherwise, use this.
+	  Gnu gnuProvider = new Gnu();
+	  Security.addProvider(gnuProvider);
+	  md = MessageDigest.getInstance ("SHA");
 	}
 
+      digest_out = new DigestOutputStream (nullOutputStream, md);
+      data_out = new DataOutputStream (digest_out);
       data_out.writeUTF (cl.getName ());
 
       int modifiers = cl.getModifiers ();
@@ -522,7 +524,7 @@ public class ObjectStreamClass implement
       }
 
       data_out.close ();
-      byte[] sha = md != null ? md.digest () : simple.digest ();
+      byte[] sha = md.digest ();
       long result = 0;
       int len = sha.length < 8 ? sha.length : 8;
       for (int i=0; i < len; i++)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]