Hello,

Attached is a patch to add and enable the use of the GOST cipher. My 
copyright assignment papers have finally gone in so this is okay to be 
committed. I've posted this to the list before, this is a slightly 
modified version so it can still be applied after all those patches 
Raif committed.

Also attached is a small program to test the cipher and make sure it's 
actually working (it is).
-- 
Morgon Kanter           <[EMAIL PROTECTED]>
Index: classpath/gnu/java/security/Registry.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/security/Registry.java,v
retrieving revision 1.7
diff -a -u -r1.7 Registry.java
--- classpath/gnu/java/security/Registry.java	24 Jun 2006 00:12:17 -0000	1.7
+++ classpath/gnu/java/security/Registry.java	27 Jun 2006 22:04:58 -0000
@@ -62,6 +62,8 @@
 
   String DES_CIPHER = "des";
 
+  String GOST_CIPHER = "gost";
+
   String KHAZAD_CIPHER = "khazad";
 
   String RIJNDAEL_CIPHER = "rijndael";
@@ -84,6 +86,11 @@
   /** TripleDES is also known as DESede. */
   String DESEDE_CIPHER = "desede";
 
+  /** GOST is also known as GOST 28147-89. */
+  String GOST2814789_CIPHER = "gost2814789";
+
+  String GOST28147_89_CIPHER = "gost28147-89";
+
   /** CAST5 is also known as CAST-128. */
   String CAST128_CIPHER = "cast128";
 
Index: classpath/gnu/java/security/util/Util.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/java/security/util/Util.java,v
retrieving revision 1.3
diff -a -u -r1.3 Util.java
--- classpath/gnu/java/security/util/Util.java	24 Jun 2006 00:09:26 -0000	1.3
+++ classpath/gnu/java/security/util/Util.java	27 Jun 2006 22:04:58 -0000
@@ -60,6 +60,53 @@
     super();
   }
 
+   /**
+    * <p>Copies an integer into an array of bytes. The leftmost (most
+    * significant) 8 bits of <code>from</code> become <code>to[off]</code>,
+    * the next 8 bits become <code>to[off+1]</code>, etc.</p>
+    *
+    * <p>If the number of bytes in <code>to</code> from the offset to
+    * the end is less than four AND the corresponding bits in
+    * <code>from</code> are also missing, the method will proceed and
+    * copy them correctly. However, if the bits in <code>from</code>
+    * that would normally go into the element in <code>to</code> if it
+    * were available are NOT zero, the method will throw an
+    * <code>IllegalArgumentException</code>.</p>
+    *
+    * @param from the integer to copy.
+    * @param to the byte array to copy to.
+    * @param off the offset for the array <code>to</code>.
+    * @throws IllegalArgumentException if there aren't four elements available
+    *         in <code>to</code> (but see above).
+    */
+   public static void copyIntToBytes(int from, byte[] to, int off)
+   {
+     int max;
+     int i;
+ 
+     if((to.length - off) < 4)
+       {
+         if(((to.length - off) == 3) && ((from & 0xFF000000) != 0)
+         || ((to.length - off) == 2) && ((from & 0xFFFF0000) != 0)
+         || ((to.length - off) == 1) && ((from & 0xFFFFFF00) != 0))
+           {
+             throw new IllegalArgumentException("Not enough bytes in 'to' " +
+                                                "to copy 'from'.");
+           }
+ 
+         max = to.length - off;
+       }
+     else
+       {
+         max = 4;
+       }
+ 
+     for(i=0;i<max;i++)
+       {
+         to[off+i] = (byte)((from >>> (24 - 8*i)) & 0x000000FF);
+       }
+   }
+  
   /**
    * Returns a string of hexadecimal digits from a byte array. Each byte is
    * converted to 2 hex symbols; zero(es) included.
@@ -150,6 +197,36 @@
     return new String(buf);
   }
 
+   /**
+    * <p>Returns an integer representation of an array of
+    * four <code>byte</code>s. If there are less than four
+    * bytes available, the integer will be padded with zeroes
+    * on the right.</p>
+    *
+    * @param array the array of four bytes.
+    * @param off the offset of the array ar.
+    */
+   public static int toIntFromBytes(final byte[] array, int off)
+   {
+     int ret;
+     int max;
+     int i;
+ 
+     if((array.length - off) < 4)
+       max = array.length - off;
+     else
+       max = 4;
+ 
+     ret = 0;
+     for(i=0;i<max;i++)
+       {
+         ret <<= 8;
+         ret |= (((int)array[off+i]) & 0x000000FF);
+       }
+ 
+     return ret;
+   }
+  
   /**
    * <p>
    * Returns a byte array from a string of hexadecimal digits.
Index: classpath/gnu/javax/crypto/cipher/CipherFactory.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/javax/crypto/cipher/CipherFactory.java,v
retrieving revision 1.2
diff -a -u -r1.2 CipherFactory.java
--- classpath/gnu/javax/crypto/cipher/CipherFactory.java	25 Jun 2006 12:01:33 -0000	1.2
+++ classpath/gnu/javax/crypto/cipher/CipherFactory.java	27 Jun 2006 22:04:58 -0000
@@ -77,6 +77,8 @@
       result = new Blowfish();
     else if (name.equalsIgnoreCase(DES_CIPHER))
       result = new DES();
+    else if (name.equalsIgnoreCase(GOST_CIPHER))
+      result = new GOST();
     else if (name.equalsIgnoreCase(KHAZAD_CIPHER))
       result = new Khazad();
     else if (name.equalsIgnoreCase(RIJNDAEL_CIPHER)
@@ -116,6 +118,7 @@
     hs.add(ANUBIS_CIPHER);
     hs.add(BLOWFISH_CIPHER);
     hs.add(DES_CIPHER);
+    hs.add(GOST_CIPHER);
     hs.add(KHAZAD_CIPHER);
     hs.add(RIJNDAEL_CIPHER);
     hs.add(SERPENT_CIPHER);
Index: classpath/gnu/javax/crypto/cipher/GOST.java
===================================================================
RCS file: classpath/gnu/javax/crypto/cipher/GOST.java
diff -N classpath/gnu/javax/crypto/cipher/GOST.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ classpath/gnu/javax/crypto/cipher/GOST.java	27 Jun 2006 22:04:58 -0000
@@ -0,0 +1,274 @@
+/* GOST.java -- An implementation of GOST
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.  */
+
+
+package gnu.javax.crypto.cipher;
+
+import gnu.java.security.Registry;
+import gnu.java.security.util.Util;
+
+import java.security.InvalidKeyException;
+import java.util.Collections;
+import java.util.Iterator;
+
+/**
+ * <p>Gosudarstvennyi Standard (GOST) 28147-89, or just "GOST". GOST is
+ * a 64-bit block cipher with a 256-bit key, developed in the former
+ * Soviet Union as an analog to the United States's DES.</p>
+ *
+ * <p>This version is based on the description given in [1] and [2].
+ * The S-Boxes used are from "an application for the Central Bank of
+ * the Russian Federation", as given in [1]. No source code was 
+ * consulted while implementing this.</p>
+ *
+ * <p>References:</p>
+ * <ol>
+ *    <li>Bruce Schneier, <i>Applied Cryptography: Protocols, Algorithms,
+ *    and Source Code in C, Second Edition</i>. (1996 John Wiley and Sons)
+ *    ISBN 0-471-11709-9. Pages 331-334.</li>
+ *    <li>GOST 28147-89: Cryptographic Protection for Data Processing Systems, 
+ *    <i>Government Standard of the U.S.S.R.</i> Translated by Aleksandr
+ *    Malchik, retrieved from
+ *    http://www.vipul.net/gost/papers/russian-des.ps.gz.</li>
+ * </ol>
+ */
+public class GOST
+    extends BaseCipher
+{
+
+  // Constants and variables
+  // ------------------------------------------------------------------
+
+  private static final int BLOCK_SIZE = 8;
+  private static final int KEY_SIZE = 32;
+
+  private static final int ENCRYPT = 0;
+  private static final int DECRYPT = 1;
+
+  // S-Boxes (8 boxes, 16 entries each)
+  private static final byte[][] S = {
+    {  4, 10,  9,  2, 13,  8,  0, 14,
+       6, 11,  1, 12,  7, 15,  5,  3 },
+    { 14, 11,  4, 12,  6, 13, 15, 10,
+       2,  3,  8,  1,  0,  7,  5,  9 },
+    {  5,  8,  1, 13, 10,  3,  4,  2,
+      14, 15, 12,  7,  6,  0,  9, 11 },
+    {  7, 13, 10,  1,  0,  8,  9, 15,
+      14,  4,  6, 12, 11,  2,  5,  3 },
+    {  6, 12,  7,  1,  5, 15, 13,  8,
+       4, 10,  9, 14,  0,  3, 11,  2 },
+    {  4, 11, 10,  0,  7,  2,  1, 13,
+       3,  6,  8,  5,  9, 12, 15, 14 },
+    { 13, 11,  4,  1,  3, 15,  5,  9,
+       0, 10, 14,  7,  6,  8,  2, 12 },
+    {  1, 15, 13,  0,  5,  7, 10,  4,
+       9,  2,  3, 14,  6, 11,  8, 12 }
+  };
+
+  // Constructors
+  // ------------------------------------------------------------------
+
+  /** Default 0-argument constructor. */
+  public GOST()
+  {
+    super(Registry.GOST_CIPHER, BLOCK_SIZE, KEY_SIZE);
+  }
+
+  // Class methods
+  // ------------------------------------------------------------------
+
+  /**
+   * <p>The GOST "F" function.</p>
+   * 
+   * @param x the block half.
+   * @param round the round number.
+   * @param key the GOST key-context.
+   */
+  private int F(int x, int round, final Context key)
+  {
+    byte[] chunks = new byte[8];
+    int i;
+
+    // Add the block half and i'th subkey, mod 2^32.
+    x += key.sk[round];
+
+    // Break the block-half into 4-bit chunks, and run them through
+    // the S-Boxes.
+    for(i = 0; i < 8; i++)
+      {
+        chunks[i] = (byte)((x >>> (28 - 4*i)) & 0x0000000F);
+        chunks[i] = S[i][((int)chunks[i]) & 0x0000000F];
+      }
+
+    // Recombine into an integer.
+    x = 0;
+    for(i = 0; i < 8; i++)
+      {
+        x <<= 4;
+        x |= ((int)chunks[i]) & 0x0000000F;
+      }
+
+    // Left-circular shift by 11 bits.
+    x = (x << 11) | (x >>> (32 - 11));
+
+    return x;
+  }
+
+  /**
+   * <p>The function called by <code>encrypt()</code> and
+   * <code>decrypt()</code>.</p>
+   * 
+   * @param block the block we're operating on. This gets mutated from block[o]
+   * to block[o+8].
+   * @param off the offset for <code>block</code>
+   * @param key the GOST key-context
+   * @param func simple static enumeration to tell us if we're encrypting (0)
+   * or decrypting(1).
+   */
+  private void gostfunc(byte[] block, int off, final Context key, int func)
+  {
+    int left;
+    int right;
+    int tmp;
+    int i;
+    
+    // Copy the block to left and right.
+    left  = Util.toIntFromBytes(block, off);
+    right = Util.toIntFromBytes(block, off+4);
+
+    // Now for the main event.
+    for(i = 0; i < 32; i++)
+      {
+        if(func == ENCRYPT)
+          {
+            right ^= F(left, i, (Context)key);
+          }
+        else
+          {
+            right ^= F(left, 31-i, (Context)key);
+          }
+
+        // Do the Feistel switch.
+        tmp = left;
+        left = right;
+        right = tmp;
+      }
+
+    // Copy to output; last switch is undone.
+    Util.copyIntToBytes(right, block, off);
+    Util.copyIntToBytes(left, block, off+4);
+  }
+
+  // Instance methods implementing BaseCipher
+  // ------------------------------------------------------------------
+
+  public Object clone()
+  {
+    return new GOST();
+  }
+
+  public Iterator blockSizes()
+  {
+    return Collections.singleton(new Integer(BLOCK_SIZE)).iterator();
+  }
+
+  public Iterator keySizes()
+  {
+    return Collections.singleton(new Integer(KEY_SIZE)).iterator();
+  }
+
+  public Object makeKey(byte[] kb, int bs)
+    throws InvalidKeyException
+  {
+    if(kb == null || kb.length != KEY_SIZE)
+      throw new InvalidKeyException("GOST keys must be " + KEY_SIZE +
+                                    " bytes long.");
+
+    return new Context(kb);
+  }
+
+  public void encrypt(byte[] in, int inOffset, byte[] out, int outOffset,
+                      Object k, int bs)
+  {
+    System.arraycopy(in, inOffset, out, outOffset, 8);
+    gostfunc(out, outOffset, (Context)k, ENCRYPT);
+  }
+
+  public void decrypt(byte[] in, int inOffset, byte[] out, int outOffset,
+                      Object k, int bs)
+  {
+    System.arraycopy(in, inOffset, out, outOffset, 8);
+    gostfunc(out, outOffset, (Context)k, DECRYPT);
+  }
+
+  // Inner classes
+  // ------------------------------------------------------------------
+
+  /**
+   * <p>Class to represent the GOST subkeys.</p>
+   */
+  private class Context
+  {
+    public final int sk[]; // The round subkeys, 32 of them.
+
+    /**
+     * <p>Initializes the context and runs the key schedule.</p>
+     */
+    public Context(byte[] key)
+    {
+      /* The used subkeys go as follows:
+       * Round:  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+       * Subkey: 0 1 2 3 4 5 6 7 0 1  2  3  4  5  6  7
+       * Round:  16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+       * Subkey:  0  1  2  3  4  5  6  7  7  6  5  4  3  2  1  0
+       */
+      sk = new int[32];
+
+      int i;
+      int j;
+
+      for(i=0;i<8;i++)
+        {
+          sk[i] = Util.toIntFromBytes(key, i*4);
+          sk[i + 8] = sk[i];
+          sk[i + 16] = sk[i];
+          sk[31 - i] = sk[i];
+        }
+    }
+  }
+
+}
Index: classpath/gnu/javax/crypto/jce/GnuCrypto.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/javax/crypto/jce/GnuCrypto.java,v
retrieving revision 1.5
diff -a -u -r1.5 GnuCrypto.java
--- classpath/gnu/javax/crypto/jce/GnuCrypto.java	26 Jun 2006 13:30:13 -0000	1.5
+++ classpath/gnu/javax/crypto/jce/GnuCrypto.java	27 Jun 2006 22:04:58 -0000
@@ -75,8 +75,12 @@
         put("Cipher.BLOWFISH",
             gnu.javax.crypto.jce.cipher.BlowfishSpi.class.getName());
         put("Cipher.BLOWFISH ImplementedIn", "Software");
-        put("Cipher.DES", gnu.javax.crypto.jce.cipher.DESSpi.class.getName());
+        put("Cipher.DES",
+            gnu.javax.crypto.jce.cipher.DESSpi.class.getName());
         put("Cipher.DES ImplementedIn", "Software");
+        put("Cipher.GOST",
+            gnu.javax.crypto.jce.cipher.GOSTSpi.class.getName());
+        put("Cipher.GOST ImplementedIn", "Software");
         put("Cipher.KHAZAD",
             gnu.javax.crypto.jce.cipher.KhazadSpi.class.getName());
         put("Cipher.KHAZAD ImplementedIn", "Software");
@@ -116,6 +120,8 @@
             gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.Cast5.class.getName());
         put("Cipher.PBEWithHMacHavalAndDES",
             gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.DES.class.getName());
+        put("Cipher.PBEWithHMacHavalAndGOST",
+            gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.GOST.class.getName());
         put("Cipher.PBEWithHMacHavalAndKhazad",
             gnu.javax.crypto.jce.cipher.PBES2.HMacHaval.Khazad.class.getName());
         put("Cipher.PBEWithHMacHavalAndSerpent",
@@ -137,6 +143,8 @@
             gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.Cast5.class.getName());
         put("Cipher.PBEWithHMacMD2AndDES",
             gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.DES.class.getName());
+        put("Cipher.PBEWithHMacMD2AndGOST",
+            gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.GOST.class.getName());
         put("Cipher.PBEWithHMacMD2AndKhazad",
             gnu.javax.crypto.jce.cipher.PBES2.HMacMD2.Khazad.class.getName());
         put("Cipher.PBEWithHMacMD2AndSerpent",
@@ -179,6 +187,8 @@
             gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.Cast5.class.getName());
         put("Cipher.PBEWithHMacMD5AndDES",
             gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.DES.class.getName());
+        put("Cipher.PBEWithHMacMD5AndGOST",
+            gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.GOST.class.getName());
         put("Cipher.PBEWithHMacMD5AndKhazad",
             gnu.javax.crypto.jce.cipher.PBES2.HMacMD5.Khazad.class.getName());
         put("Cipher.PBEWithHMacMD5AndSerpent",
@@ -200,6 +210,8 @@
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.Cast5.class.getName());
         put("Cipher.PBEWithHMacSHA1AndDES",
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.DES.class.getName());
+        put("Cipher.PBEWithHMacSHA1AndGOST",
+            gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.GOST.class.getName());
         put("Cipher.PBEWithHMacSHA1AndKhazad",
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA1.Khazad.class.getName());
         put("Cipher.PBEWithHMacSHA1AndSerpent",
@@ -222,6 +234,8 @@
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.Cast5.class.getName());
         put("Cipher.PBEWithHMacSHA256AndDES",
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.DES.class.getName());
+        put("Cipher.PBEWithHMacSHA256AndGOST",
+            gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.GOST.class.getName());
         put("Cipher.PBEWithHMacSHA256AndKhazad",
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA256.Khazad.class.getName());
         put("Cipher.PBEWithHMacSHA256AndSerpent",
@@ -243,6 +257,8 @@
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.Cast5.class.getName());
         put("Cipher.PBEWithHMacSHA384AndDES",
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.DES.class.getName());
+        put("Cipher.PBEWithHMacSHA384AndGOST",
+            gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.GOST.class.getName());
         put("Cipher.PBEWithHMacSHA384AndKhazad",
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA384.Khazad.class.getName());
         put("Cipher.PBEWithHMacSHA384AndSerpent",
@@ -264,6 +280,8 @@
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.Cast5.class.getName());
         put("Cipher.PBEWithHMacSHA512AndDES",
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.DES.class.getName());
+        put("Cipher.PBEWithHMacSHA512AndGOST",
+            gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.GOST.class.getName());
         put("Cipher.PBEWithHMacSHA512AndKhazad",
             gnu.javax.crypto.jce.cipher.PBES2.HMacSHA512.Khazad.class.getName());
         put("Cipher.PBEWithHMacSHA512AndSerpent",
@@ -285,6 +303,8 @@
             gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.Cast5.class.getName());
         put("Cipher.PBEWithHMacTigerAndDES",
             gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.DES.class.getName());
+        put("Cipher.PBEWithHMacTigerAndGOST",
+            gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.GOST.class.getName());
         put("Cipher.PBEWithHMacTigerAndKhazad",
             gnu.javax.crypto.jce.cipher.PBES2.HMacTiger.Khazad.class.getName());
         put("Cipher.PBEWithHMacTigerAndSerpent",
@@ -306,6 +326,8 @@
             gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Cast5.class.getName());
         put("Cipher.PBEWithHMacWhirlpoolAndDES",
             gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.DES.class.getName());
+        put("Cipher.PBEWithHMacWhirlpoolAndGOST",
+            gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.GOST.class.getName());
         put("Cipher.PBEWithHMacWhirlpoolAndKhazad",
             gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Khazad.class.getName());
         put("Cipher.PBEWithHMacWhirlpoolAndSerpent",
@@ -348,6 +370,8 @@
             gnu.javax.crypto.jce.key.Cast5SecretKeyFactoryImpl.class.getName());
         put("SecretKeyFactory.DES",
             gnu.javax.crypto.jce.key.DESSecretKeyFactoryImpl.class.getName());
+        put("SecretKeyFactory.GOST",
+            gnu.javax.crypto.jce.key.GOSTSecretKeyFactoryImpl.class.getName());
         put("SecretKeyFactory.Khazad",
             gnu.javax.crypto.jce.key.KhazadSecretKeyFactoryImpl.class.getName());
         put("SecretKeyFactory.Rijndael",
@@ -375,6 +399,8 @@
             gnu.javax.crypto.jce.key.Cast5KeyGeneratorImpl.class.getName());
         put("KeyGenerator.DES",
             gnu.javax.crypto.jce.key.DESKeyGeneratorImpl.class.getName());
+        put("KeyGenerator.GOST",
+            gnu.javax.crypto.jce.key.GOSTKeyGeneratorImpl.class.getName());
         put("KeyGenerator.Khazad",
             gnu.javax.crypto.jce.key.KhazadKeyGeneratorImpl.class.getName());
         put("KeyGenerator.Rijndael",
@@ -424,6 +450,8 @@
             gnu.javax.crypto.jce.mac.OMacCast5Impl.class.getName());
         put("Mac.OMAC-DES",
             gnu.javax.crypto.jce.mac.OMacDESImpl.class.getName());
+        put("Mac.OMAC-GOST",
+            gnu.javax.crypto.jce.mac.OMacGOSTImpl.class.getName());
         put("Mac.OMAC-KHAZAD",
             gnu.javax.crypto.jce.mac.OMacKhazadImpl.class.getName());
         put("Mac.OMAC-RIJNDAEL",
@@ -452,6 +480,8 @@
         put("Alg.Alias.Cipher.3DES", "TRIPLEDES");
         put("Alg.Alias.Cipher.DES-EDE", "TRIPLEDES");
         put("Alg.Alias.Cipher.DESede", "TRIPLEDES");
+        put("Alg.Alias.Cipher.GOST2814789", "GOST");
+        put("Alg.Alias.Cipher.GOST28147-89", "GOST");
         put("Alg.Alias.Cipher.CAST128", "CAST5");
         put("Alg.Alias.Cipher.CAST-128", "CAST5");
         put("Alg.Alias.Mac.HMAC-SHS", "HMAC-SHA160");
Index: classpath/gnu/javax/crypto/jce/cipher/GOSTSpi.java
===================================================================
RCS file: classpath/gnu/javax/crypto/jce/cipher/GOSTSpi.java
diff -N classpath/gnu/javax/crypto/jce/cipher/GOSTSpi.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ classpath/gnu/javax/crypto/jce/cipher/GOSTSpi.java	27 Jun 2006 22:04:58 -0000
@@ -0,0 +1,58 @@
+/* GOST.java -- 
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.  */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The implementation of the GOST <i>Service Provider Interface</i>
+ * (<b>SPI</b>) adapter.
+ */
+public final class GOSTSpi
+    extends CipherAdapter
+{
+
+  // Constructors.
+  // ------------------------------------------------------------------
+
+  public GOSTSpi()
+  {
+    super(Registry.GOST_CIPHER);
+  }
+}
Index: classpath/gnu/javax/crypto/jce/cipher/PBES2.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/javax/crypto/jce/cipher/PBES2.java,v
retrieving revision 1.4
diff -a -u -r1.4 PBES2.java
--- classpath/gnu/javax/crypto/jce/cipher/PBES2.java	26 Jun 2006 13:30:14 -0000	1.4
+++ classpath/gnu/javax/crypto/jce/cipher/PBES2.java	27 Jun 2006 22:04:58 -0000
@@ -187,6 +187,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacSHA1
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacSHA1
     {
@@ -291,6 +300,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacMD5
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacMD5
     {
@@ -395,6 +413,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacMD2
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacMD2
     {
@@ -499,6 +526,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacMD4
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacMD4
     {
@@ -603,6 +639,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacHaval
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacHaval
     {
@@ -707,6 +752,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacRipeMD128
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacRipeMD128
     {
@@ -811,6 +865,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacRipeMD160
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacRipeMD160
     {
@@ -915,6 +978,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacSHA256
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacSHA256
     {
@@ -1019,6 +1091,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacSHA384
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacSHA384
     {
@@ -1123,6 +1204,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacSHA512
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacSHA512
     {
@@ -1227,6 +1317,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacTiger
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacTiger
     {
@@ -1331,6 +1430,15 @@
       }
     }
 
+    public static class GOST
+        extends HMacWhirlpool
+    {
+      public GOST()
+      {
+        super("GOST");
+      }
+    }
+
     public static class Khazad
         extends HMacWhirlpool
     {
Index: classpath/gnu/javax/crypto/jce/key/GOSTKeyGeneratorImpl.java
===================================================================
RCS file: classpath/gnu/javax/crypto/jce/key/GOSTKeyGeneratorImpl.java
diff -N classpath/gnu/javax/crypto/jce/key/GOSTKeyGeneratorImpl.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ classpath/gnu/javax/crypto/jce/key/GOSTKeyGeneratorImpl.java	27 Jun 2006 22:04:58 -0000
@@ -0,0 +1,58 @@
+/* Filename -- GOST key generator.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.  */
+
+
+package gnu.javax.crypto.jce.key;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.GOST;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+public class GOSTKeyGeneratorImpl
+    extends SecretKeyGeneratorImpl
+{
+
+  // Constructors.
+  // ------------------------------------------------------------------
+
+  public GOSTKeyGeneratorImpl()
+  {
+    super(Registry.GOST_CIPHER);
+  }
+}
Index: classpath/gnu/javax/crypto/jce/key/GOSTSecretKeyFactoryImpl.java
===================================================================
RCS file: classpath/gnu/javax/crypto/jce/key/GOSTSecretKeyFactoryImpl.java
diff -N classpath/gnu/javax/crypto/jce/key/GOSTSecretKeyFactoryImpl.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ classpath/gnu/javax/crypto/jce/key/GOSTSecretKeyFactoryImpl.java	27 Jun 2006 22:04:58 -0000
@@ -0,0 +1,48 @@
+/* GOSTSecretKeyFactoryImpl.java -- GOST key factory.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.  */
+
+
+package gnu.javax.crypto.jce.key;
+
+
+public class GOSTSecretKeyFactoryImpl
+    extends SecretKeyFactoryImpl
+{
+  public GOSTSecretKeyFactoryImpl()
+  {
+  }
+}
Index: classpath/gnu/javax/crypto/jce/mac/OMacGOSTImpl.java
===================================================================
RCS file: classpath/gnu/javax/crypto/jce/mac/OMacGOSTImpl.java
diff -N classpath/gnu/javax/crypto/jce/mac/OMacGOSTImpl.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ classpath/gnu/javax/crypto/jce/mac/OMacGOSTImpl.java	27 Jun 2006 22:04:58 -0000
@@ -0,0 +1,54 @@
+/* Filename -- OMAC-GOST adapter.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a 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 of the License, 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; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.  */
+
+
+package gnu.javax.crypto.jce.mac;
+
+import gnu.java.security.Registry;
+
+public class OMacGOSTImpl
+    extends MacAdapter
+{
+
+  // Constructor.
+  // ------------------------------------------------------------------
+
+  public OMacGOSTImpl()
+  {
+    super(Registry.OMAC_PREFIX + Registry.GOST_CIPHER);
+  }
+}
import gnu.java.security.util.Util;
import gnu.javax.crypto.cipher.CipherFactory;
import gnu.javax.crypto.cipher.IBlockCipher;

import java.util.Arrays;
import java.util.HashMap;

public class GOSTTest
{
  final static String[][] vectors = {
    // Key on the first line, then plaintext, ciphertext on the next.
    { "0000000000000000000000000000000000000000000000000000000000000000",
      "0000000000000000", "4D33070B0ECA1A54"
    }, {
      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
      "0000000000000000", "D80A5C2FA13EAAA8"
    }, {
      "0000000000000000000000000000000000000000000000000000000000000000",
      "FFFFFFFFFFFFFFFF", "5F3A0A2CA300E3A1"
    }, {
      "FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000",
      "0000000000000000", "24ECF9F795ECEFE4"
    }, {
      "FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000",
      "FFFFFFFFFFFFFFFF", "8922F469908A1BB9"
    }, {
      "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
      "0000000000000000", "70EB39FAA7D1BC6A",
    }, {
      "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
      "0101010101010101", "D4DF90642E66CEFB"
    }, {
      "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
      "0202020202020202", "D89A3023B59575E7"
    }, {
      "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
      "0303030303030303", "0107EC8FD6D72A46"
    }, {
      "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
      "0123456789ABCDEF", "0FD484EBE6DD3331"
    }, {
      "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF",
      "FFFFFFFFFFFFFFFF", "EB84BA0A2A255692"
    }, {
      "DC75CB65164ADF60D9AC3413F0F82EB51EEA7E5AA6A9CFA87F078364BEBCB997",
      "77270240AF99820B", "C3DD180E4E48E931"
    }, {
      "4C43644793062DE230F51F1EE30776CBE9A8BFF7716AC8139003774BEB60FB59",
      "83FDDBE77B54E22D", "B35FF68E12799956"
    }, {
      "6DDB7EB93C5DFB1C6AEDD69E518533693021E0CB901F5708C87DAC9CBA5F5100",
      "F74E1987EA081871", "B8BD0E7DE4C896B1"
    }, {
      "B2F58105F836F01093BD58928E1CA47C29FE4CFD577306D2A604114A300D0DF0",
      "A2EF359CB3E407DB", "713F8B94E84BEACA"
    }, {
      "B4617F418BF9F909E9EB7AB1C106D116A3104C6C081D1E66C30CF3891392B38D",
      "8BF1C6AB8F9DDA57", "2C055C29DBB7DA0A"
    }, {
      "7C682324045F7A7EB55CBCD36FB71EE98CB6F2C62E2890F00904B367B45E44FA",
      "15C0D3A37DE654B8", "2A425ADC968EDAF0"
    }, {
      "3D6E4B051065C1D2E4935AEC13694F4E2370E0516EA1B62DD575FECC1A801C5F",
      "6B43289808255194", "35872C78846A667C"
    }, {
      "D103176B73A8597B34F10B591925039EC80195C8303BFB36687EB86BC978A4C7",
      "9738CF96112F5501", "186E2AD26876511C"
    }, {
      "8A33F288B7C2FE35FC1D3014FDBD4D5318A97F1129B1A40892006B3F999E94A2",
      "8D0E065FC4D01751", "C0CC2713D08598C4"
    }
  };

  public static void main(String[] arguments) throws Exception
  {
    IBlockCipher cipher = CipherFactory.getInstance("GOST");
    byte[] key = null;
    byte[] ptext1 = null;
    byte[] ptext2 = new byte[8];
    byte[] ctext1 = null;
    byte[] ctext2 = new byte[8];
    boolean correct = true;

    for(int i = 0; i < vectors.length; i++)
      {
        HashMap attributes = new HashMap();
        key = Util.toBytesFromString(vectors[i][0]);
        attributes.put(IBlockCipher.KEY_MATERIAL, key);
        cipher.reset();
        cipher.init(attributes);
        
        ptext1 = Util.toBytesFromString(vectors[i][1]);
        ctext1 = Util.toBytesFromString(vectors[i][2]);
        System.arraycopy(ptext1, 0, ptext2, 0, 8);
        System.arraycopy(ctext1, 0, ctext2, 0, 8);

        cipher.encryptBlock(ptext1, 0, ctext2, 0);
        cipher.decryptBlock(ctext2, 0, ptext2, 0);

        if(!(Arrays.equals(ptext1, ptext2))) correct = false;
        if(!(Arrays.equals(ctext1, ctext2))) correct = false;
        if(!(correct))
          {
            System.out.println("Encryption/decryption failure on vector " + i + ".");
            System.out.println("Original Plaintext: " + vectors[i][1]);
            System.out.println("");
            System.out.println("Correct ciphertext: " + vectors[i][2]);
            System.out.println("Output  ciphertext: " + Util.toString(ctext2));
            System.out.println("");
            System.out.println("Correct plaintext : " + vectors[i][1]);
            System.out.println("Output  plaintext : " + Util.toString(ptext2));
            System.out.println("");
          }
        ptext2[0] = 0; ptext2[1] = 0; ptext2[2] = 0; ptext2[3] = 0;
        ptext2[4] = 0; ptext2[5] = 0; ptext2[6] = 0; ptext2[7] = 0;
        ctext2[0] = 0; ctext2[1] = 0; ctext2[2] = 0; ctext2[3] = 0;
        ctext2[4] = 0; ctext2[5] = 0; ctext2[6] = 0; ctext2[7] = 0;
        correct = true;
      }
  }
}

Attachment: pgpuR22B4iEwj.pgp
Description: PGP signature

Reply via email to