[Webfunds-commits] java/webfunds/util Armoury.java Base64Coder.java CRC.java

Ian Grigg iang@cypherpunks.ai
Sun, 18 Mar 2001 19:20:58 -0400 (AST)


iang        01/03/18 19:20:58

  Modified:    webfunds/sox Encodable.java Utils.java
               webfunds/util Armoury.java Base64Coder.java CRC.java
  Added:       webfunds/sox ArmouredPayment.java
  Removed:     webfunds/sox/utils Base64.java
  Log:
  1. moved all armoury stuff out of sox into new directory webfunds.util;
  2. moved all Payment armoury code into new webfunds.sox.ArmouredPayment;
  3. moved the getCertificate method into Armoury, from sox.Utils, zotted others.

Revision  Changes    Path
1.25      +4 -2      java/webfunds/sox/Encodable.java

Index: Encodable.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/sox/Encodable.java,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- Encodable.java	2000/08/08 00:16:55	1.24
+++ Encodable.java	2001/03/18 23:20:56	1.25
@@ -1,5 +1,5 @@
 /*
- * $Id: Encodable.java,v 1.24 2000/08/08 00:16:55 gelderen Exp $
+ * $Id: Encodable.java,v 1.25 2001/03/18 23:20:56 iang Exp $
  *
  * Copyright (c) Systemics Ltd 1995-1999 on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
@@ -12,6 +12,8 @@
 
 import java.security.cert.Certificate;
 
+import webfunds.util.Armoury;
+
 import webfunds.utils.Diagnostics;
 
 /**
@@ -251,7 +253,7 @@
     Certificate readCertificate(DataInputStream dis)
         throws IOException
     {
-        return Utils.getCertificate( readByteArray(dis) );
+        return Armoury.getCertificate( readByteArray(dis) );
     }
 
 



1.21      +6 -3      java/webfunds/sox/Utils.java

Index: Utils.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/sox/Utils.java,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- Utils.java	2000/11/30 13:45:12	1.20
+++ Utils.java	2001/03/18 23:20:56	1.21
@@ -1,5 +1,5 @@
 /*
- * $Id: Utils.java,v 1.20 2000/11/30 13:45:12 iang Exp $
+ * $Id: Utils.java,v 1.21 2001/03/18 23:20:56 iang Exp $
  *
  * Copyright (c) Systemics Ltd 1995-1999 on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
@@ -43,6 +43,8 @@
     }
 
 
+    /**
+     * XXX: now in webfunds.util.Armoury;
     public static Certificate getCertificate(byte[] data) throws IOException {
 
         try {
@@ -73,6 +75,7 @@
             throw new IOException("unknown cert type\n\n" + s + "\n\n");
         }
     }
+     */
 
 
     /**
@@ -81,12 +84,12 @@
      * @param filename The filename containing the certificate
      * @return The Certificate from the file
      * @excep An input error occurred reading from the file
-     */
     public static Certificate getCertificateFromFile(String filename)
         throws IOException
     {
         return Utils.getCertificate(getDataFromFile(filename));
     }
+     */
 
     /**
      * Read a PrivateKey object from a file
@@ -94,12 +97,12 @@
      * @param filename The filename containing the certificate
      * @return The PrivateKey from the file
      * @excep An input error occurred reading from the file
-     */
     public static PrivateKey getPrivateKeyFromFile(String filename)
         throws IOException, InvalidKeyException
     {
         return Crypto.decodePrivateKey(getDataFromFile(filename));
     }
+     */
 
 
 



1.1                  java/webfunds/sox/ArmouredPayment.java

Index: ArmouredPayment.java
===================================================================
/* $Id: ArmouredPayment.java,v 1.1 2001/03/18 23:20:56 iang Exp $
 *
 * Copyright (c) 1995-2001 Systemics Inc. on behalf of
 * The WebFunds Development Team. All Rights Reserved.
 */
package webfunds.sox;


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import webfunds.util.Armoury;

/**
 *  I think the pattern is probably wrong here, but I need
 *  to move the armouring of the payment closer to the action
 *  (and the higher level application code doesn't so much care.)
 *
 *  At a later time, it might be nice to set some paramaters
 *  as to how to produce the payments and decode them.
 */
public class ArmouredPayment
    extends Encodable
{
    public final static String       ORIGINAL_VERSION = "2.0.0",
                                     CURRENT_VERSION  = "2.0.1";


    public final static String SOX_MESSAGE = "SOX MESSAGE";

    private AbstractPayment pay;
    public AbstractPayment getPay()                 { return pay; }

    private String     errors = "";
    public String      getDecodeErrors()            { return errors; }


    public ArmouredPayment(AbstractPayment pay)
    {
        if (pay == null)
            throw new IllegalArgumentException("null");
        this.pay = pay;
    }

    /**
     *  Make a decoder from a byte array.
     *
     *  @param SOXPacketException the data was bad
     */
    public ArmouredPayment(byte[] data)
        throws SOXPacketException
    {
        decode(data);
    }

    /**
     *  Recover an ArmouredPayment from an input stream.
     *
     *  @param SOXPacketException the data was bad
     */
    public ArmouredPayment(InputStream is)
        throws SOXPacketException
    { 
        try {
            decode(is);
        } catch (IOException ex) {
            throw new SOXPacketException("IOException: " + ex);
        }
    }



////// Recover, Save /////////////////////////////////////

    /**
     *  Make an ASCII-armoured message from a payment, a la PGP armouring.
     *  @throws IllegalArgumentException if no AbstractPayment available
     */
    public void encode(OutputStream os)
        throws IOException
    {
        if (pay == null)
            throw new IllegalArgumentException("null");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        pay.encode(bos);

        String s = Armoury.encode(SOX_MESSAGE, bos.toByteArray());

        os.write(s.getBytes());
    }

    /**
     *  Decoder of SOX armoured messages.
     *
     *  XXX: This is back to front, overrides normal Encodable method
     *  as de-armouring is done on byte arrays not streams.
     *
     *  @throws SOXPacketException if the payment failed to recover,
     */
    public void decode(InputStream is)
        throws SOXPacketException, IOException
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buf = new byte[256];
        int got;

        do
        {
            got = is.read(buf);
            if (got > 0)
                baos.write(buf, 0, got);

        } while (got > 0);

        decode(baos.toByteArray());
    }

    /**
     *  Decoder of SOX armoured messages.
     *
     *  XXX: This is back to front, overrides normal Encodable method
     *  as de-armouring is done on byte arrays not streams.
     *
     *  @throws SOXPacketException if the payment failed to recover,
     */
    public void decode(byte[] data)
        throws SOXPacketException
    {
        if (data == null)
            throw new IllegalArgumentException("null");

        byte[] buf = decodeBytes(data);
        if (buf == null)
            throw new SOXPacketException("cannot decode");

        pay = PaymentFactory.decode(buf);
    }

    /*
     *  Smart decoder of the byte array.
     */
    private byte[] decodeBytes(byte[] buf)
    {
        errors = "";

        byte[] b;
        String s = new String(buf);

        //
        // Here, get smart.  For the moment, there are only two methods.
        //
        try {
            b = Armoury.decode(s);
            return b;
        } catch (Exception ex) { }

        errors += "failed on Armoury.decode (" + Armoury.getErrors() +
               "), trying decodeByteArray";

        try {
            b = Armoury.decodeByteArray(SOX_MESSAGE, s);
            return b;
        } catch (Exception ex) { }

        errors += "\n" + "failed on Armoury.decodeByteArray (" +
                  Armoury.getErrors() + ")";

        return null;
    }



////// Self-Test //////////////////////////////////

    public String toString()
    {
        String s = "ArmouredPayment V" + CURRENT_VERSION + "   " + pay;
        return s;
    }

    public boolean equals(java.lang.Object obj)
    {
        if (obj == null || !(obj instanceof ArmouredPayment))
            return false;

        ArmouredPayment other = (ArmouredPayment)obj;

        AbstractPayment it = other.pay;
        if (it == null) {
            if (pay != null)
                return false ;
        } else {
            if (!it.equals(pay))
                return false;
        }

        return true;
    }

    public static ArmouredPayment example()
    {
        AbstractPayment p = PaymentFactory.example();
        ArmouredPayment armour = new ArmouredPayment(p);
        return armour;
    }

    public static void main(String[] args)
    {
        int num = 2000;
        String type = "-c";
        if (args.length > 0)
        {
            int a = 0;
            if (args[a].startsWith("-"))
            {
                type = args[a++];
            }

            if (a < args.length)
            {
                Integer i = null;
                try {
                    i = new Integer(args[a]);
                } catch (Exception e) {
                    e.printStackTrace();
                    System.exit(1);
                }
                num = i.intValue();
            }
        }

        try {
            if (type.equals("-t") || type.equals("-i"))
            {
                while (true)
                {
                    if (type.equals("-t"))
                        readWrite();
                    else if (type.equals("-i"))
                        input();
                }
            }
            else
            {
                for (int i = 0; i < num; i++)
                {
                    if (type.equals("-c"))
                        cycle();
                    else if (type.equals("-o"))
                        output();
                }
            }
        } catch(Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
        System.out.flush();          // last buffered lump still there
        System.out.close();
        System.exit(0);
    }

    protected static void cycle()
        throws Exception
    {
        ArmouredPayment p = example();
        System.err.println("Writing: " + p);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 
        p.encode(baos);
        byte[] buf = baos.toByteArray();
        System.err.println(new String(buf));
 
        ArmouredPayment q = new ArmouredPayment(buf);
        if (!p.equals(q))
        {   
            throw new RuntimeException("FAILED:\n\n"+q+"\n\n"+p+"\nEND\n");
        }
    }

    protected static void output()
        throws Exception
    { 
        ArmouredPayment b = example();
        b.encode(System.out);
    }
       
    protected static void readWrite()   
        throws Exception
    {
        ArmouredPayment b = null;
            b = new ArmouredPayment(System.in);
        System.err.println("Read: " + b);
        b.encode(System.out);
    }  

    protected static void input()
        throws Exception
    { 
        ArmouredPayment b = null;
            b = new ArmouredPayment(System.in);
        System.err.println("Read: " + b);
    }
}



1.32      +168 -58   java/webfunds/util/Armoury.java

Index: Armoury.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/util/Armoury.java,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- Armoury.java	2001/02/27 01:23:29	1.31
+++ Armoury.java	2001/03/18 23:20:57	1.32
@@ -1,18 +1,35 @@
-/* $Id: Armoury.java,v 1.31 2001/02/27 01:23:29 iang Exp $
+/* $Id: Armoury.java,v 1.32 2001/03/18 23:20:57 iang Exp $
  *
- * Copyright (c) Systemics Inc. 1995-2000 on behalf of
+ * Copyright (c) 1995-2001 Systemics Inc. on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
  */
-package webfunds.sox;
+package webfunds.util;
  
-import java.io.*;
-import java.security.*;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.DataInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.BufferedWriter;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+
+import java.security.PublicKey;
+import java.security.PrivateKey;
+import java.security.InvalidKeyException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
 
+/* XXX: reverse dependencies on SOX, need to be fixed when Certs removed. */
+import webfunds.sox.Crypto;
+import webfunds.sox.SOXKeyException;
 
-import webfunds.sox.utils.Base64;
 
+
+
 /**
  * This class provides methods for encoding and decoding data in MIME base64
  * format.  Also included are many convenience methods for encoding and
@@ -23,29 +40,30 @@
  * the base 64 encoded data.  The return value represents a sequence of
  * characters, and depending upon the method, can be either a byte array
  * or String, since these characters are from a subset of both the Unicode
- * and ASCII character repertoires.  Base64 encoding encodes 6 binary bits
- * per character, using the characters 'A'-'Z', 'a'-'z', '0'-'9', '+', '/',
- * and '=' (for padding).
+ * and ASCII character repertoires.
  *
  * <p>
- * <b>References:</b>
- * <ol>
- *   <li> RFC 2045, <cite>Multipurpose Internet Mail Extensions (MIME) Part One,
- *        Format of Internet Message Bodies</cite>,
- *        "Section 6.8 Base64 Content-Transfer-Encoding,"
- *        <a href="http://www.imc.org/rfc2045">http://www.imc.org/rfc2045</a>
- * </ol>
+ * See Base64Coder for details on how Base64 works.
  *
- * @version $Revision: 1.31 $
+ * @version $Revision: 1.32 $
  */
 public abstract class Armoury
 {
     /**
      *  Platform-dependant newline for the outgoing displayed payment
      *  (not to be used in calculation of sigs, etc).
+     *  Note that if the armoured payment is so to be pasted into a
+     *  cut&paste buffer, Java has a bug in it that assumes Unix
+     *  newlines, so use the webfunds.utils.ClipboardHelper to
+     *  filter the payment into the correct format.
      */
     static final String newline = System.getProperty("line.separator");
 
+    static final String
+                        DASHES = "-----",
+                        dashEND = DASHES + "END ",
+                        dashBEGIN = DASHES + "BEGIN ";
+
 //
 //  This is a bit dumb, we should make the encoder an object
 //  so that we can diagnose the failed results.
@@ -67,15 +85,22 @@
         return "line == " + linecount;
     }
 
+    static void logmsg(String s)
+    {
+         System.err.println("        Armoury: " + s);
+    }
+
     /**
      * Encode <i>data</i> as a String using base64 encoding.
      *
      * @param data the data to be encoded
      * @return the encoded data as a String
      */
-    public static String encodeWithChecksum(byte[] buf)
+    private static String encodeWithChecksum(byte[] buf)
     {
-        return Base64.encode(buf)+"="+encodeChecksum(buf); 
+        Base64Coder b64 = new Base64Coder();
+        byte[] checksum = getChecksum(buf);
+        return b64.encode(buf) + "=" + new String(b64.encode(checksum));
     }
 
     /**
@@ -107,7 +132,7 @@
             switch (state)
             {
             case WAITING:
-                if (s.startsWith("-----BEGIN"))
+                if (s.startsWith(dashBEGIN))
                 {
                     state = PACKET_START;
                     break;
@@ -126,23 +151,23 @@
                     int csum = decodeChecksum(s);
 
                     s = dis.readLine();
-                    if (!s.startsWith("-----END"))
+                    if (!s.startsWith(dashEND))
                         // Change this to a real exception
-                        throw new RuntimeException("no END after checksum");
+                        throw new IOException("no "+dashEND+"after checksum");
 
                     // Get the data and packet as byte arrays
-                    byte[] packet = Base64.decode(packet_str);
+                    Base64Coder b64 = new Base64Coder();
+                    byte[] packet = b64.decode(packet_str);
 
                     // Verify checksum
                     if (csum != CRC.checksum(packet))
-                        throw new RuntimeException("invalid checksum");
+                        throw new IOException("invalid checksum");
                         
                     return packet;
                 }
-                else if (s.startsWith("-----END"))
+                else if (s.startsWith(dashEND))
                 {
-                    throw new RuntimeException("END without checksum");
-                    //byte[] packet = Base64.decode(packet_str);
+                    throw new IOException(dashEND+"without checksum");
                 }
 
                 packet_str += s;
@@ -157,16 +182,26 @@
         return null;    // EOF
     }
  
-    public static String encodeChecksum(byte[] buf)
+    public static byte[] getChecksum(byte[] buf)
     {
         byte checksum[] = new byte[3];
         int csum = CRC.checksum(buf);
         checksum[0] = (byte)(csum >>> 16);
         checksum[1] = (byte)(csum >>> 8);
         checksum[2] = (byte)csum;
-        return Base64.encode(checksum); 
+        return checksum; 
     }
 
+    /**
+     *  deprecated?
+     */
+    public static String encodeChecksum(byte[] buf)
+    {
+        byte checksum[] = getChecksum(buf);
+        Base64Coder b64 = new Base64Coder();
+        return b64.encode(checksum); 
+    }
+
     public static int decodeChecksum(String s)
         // throws InvalidChecksumException
     {
@@ -176,7 +211,8 @@
 
         byte[] asc_sum = new byte[4];
         s.getBytes(1, 5, asc_sum, 0);
-        byte[] binsum = Base64.decode(asc_sum);
+        Base64Coder b64 = new Base64Coder();
+        byte[] binsum = b64.decode(asc_sum);
         int sum = ((((int)binsum[0] & 0xFF) << 16)
             | (((int)binsum[1] & 0xFF) << 8)
             | ((int)binsum[2]) & 0xFF);
@@ -194,7 +230,7 @@
      * Determine if this header can be found
      *
      * @param header the string following the "BEGIN" on the ascii armour.
-     * @param buf a String containing the Base64 encoded data
+     * @param buf a String containing the Base 64 encoded data
      * @return true if the "BEGIN" header can be found
      * @exception IOException if <code>buf</code> contains invalid
      *          characters, or is incorrectly padded.
@@ -203,17 +239,17 @@
         throws IOException
     {
         // Find start of ASCII armour
-        return (buf.indexOf( "-----BEGIN "+type+"-----" ) != -1);
+        return (buf.indexOf( dashBEGIN + type + DASHES ) != -1);
     }
 
 
     /**
-     * Decode some Base64 encoded data, first of all searching for
+     * Decode some Base 64 encoded data, first of all searching for
      * the appropriate "BEGIN" line, and reading up until the "END" line.
      *
      * @param header the string following the "BEGIN" and "END" on the
      * ascii armouring.
-     * @param buf a String containing the Base64 encoded data
+     * @param buf a String containing the Base 64 encoded data
      * @return the decoded ascii-armoured data, as a byte array
      * @exception IOException if <code>buf</code> contains invalid
      *          characters, or is incorrectly padded.
@@ -225,12 +261,12 @@
         try
         {
             // Find start of ASCII armour
-            int start = buf.indexOf( "-----BEGIN "+type+"-----" ) ;
+            int start = buf.indexOf( dashBEGIN + type + DASHES ) ;
             if (start == -1)
                 return null;
     
             buf = buf.substring(start); // So that we don't pick up a trailing END
-            int end = buf.indexOf( "----END "+type+"-----" );
+            int end = buf.indexOf( dashEND+type+DASHES );
             if (end < 0)
                 return null;
     
@@ -304,7 +340,9 @@
             {
                 bytes3[--z] = bytes2[i];
             }
-            buf = "-----BEGIN "+type+"-----\n" + new String(bytes3) + "\n-----END "+type+"-----";
+            buf = dashBEGIN + type + DASHES + "\n" +
+                  new String(bytes3) +
+                  "\n" + dashEND + type + DASHES;
             retval = decode(buf);
         }
         catch(Exception ex)
@@ -320,7 +358,7 @@
     {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 
-        byte[] dec_table = Base64.getDecodeTable();
+        byte[] dec_table = Base64Coder.getDecodeTable();
 
         for (int i = 0; i < bytes.length; i++)
         {
@@ -332,10 +370,25 @@
         }
         return baos.toByteArray();
     }
-        
+
+    /**
+     * Encode data (as a byte array) into ascii-armoured Base 64
+     * encoded data, with "BEGIN" and "END" lines, and
+     * default platform newline and 51 chars per line.
+     *
+     * @param data a byte array containing the data to be encoded
+     * @return the encoded base64 ascii-armoured data, as a String
+     */
+    public static String encode(String type, byte[] data)
+    {
+        return encode(type, data, 51,
+                      "Version: 2.0.1" + newline +
+                      "Comment: SOX by Systemics",
+                      newline);
+	    }
 
     /**
-     * Encode data (as a byte array) into ascii-armoured Base64
+     * Encode data (as a byte array) into ascii-armoured Base 64
      * encoded data, with "BEGIN" and "END" lines.
      *
      * @param header the string following the "BEGIN" and "END" on the
@@ -343,21 +396,46 @@
      * @param data a byte array containing the data to be encoded
      * @return the encoded base64 ascii-armoured data, as a String
      */
-    public static String encode(String type, byte[] data)
+    public static String encode(String type, byte[] data, int maxline)
     {
-        return encode(type, data, "Version: 2.0.0" + newline + "Comment: SOX by Systemics");
+        return encode(type, data, maxline,
+                      "Version: 2.0.1" + newline +
+                      "Comment: SOX by Systemics",
+                      newline);
     }
 
-    public static String encode(String type, byte[] data, String headers)
-    {
-        return  newline + "-----BEGIN "+type+"-----" + newline +
-                headers + newline + newline + encodeWithChecksum(data) +
-                "-----END "+type+"-----" + newline;
+    /**
+     * Encode data (as a byte array) into ascii-armoured Base 64
+     * encoded data, with "BEGIN" and "END" lines.
+     *
+     * @param header the string following the "BEGIN" and "END" on the
+     * ascii armour.
+     * @param data a byte array containing the data to be encoded
+     * @return the encoded base64 ascii-armoured data, as a String
+     */
+    public static String encode(String type,
+                                byte[] data,
+                                int maxline,
+                                String headers,
+                                String newline)
+    {
+        Base64Coder b64 = new Base64Coder();
+        b64.setMaximumLineLength(maxline);
+        b64.setNewline(newline);
+        
+        byte[] checksum = getChecksum(data);
+        String encoded = b64.encode(data) + "=" + b64.encode(checksum);
+
+        String s =  newline + dashBEGIN + type + DASHES + newline +
+                headers + newline + newline +
+                encoded +
+                dashEND + type + DASHES + newline;
+        return s;
     }
 
 
     /**
-     * Encode a Certificate object, using ascii-armoured Base64 encoding
+     * Encode a Certificate object, using ascii-armoured base64 encoding
      *
      * @param cert the certificate object to be encoded
      * @return the ascii-armoured certificate
@@ -375,9 +453,41 @@
                 "Unexpected IOException ("+e.getMessage()+")");
         }
     }
+
+    public static Certificate getCertificate(byte[] data) throws IOException {
+
+        try {
+            try {
+                logmsg("getCertificate, trying OpenPGP...");
+                CertificateFactory cf =
+                    CertificateFactory.getInstance("OpenPGP");
+                ByteArrayInputStream bais = new ByteArrayInputStream(data);
+                Certificate cert = cf.generateCertificate(bais);
+                logmsg("  OpenPGP Certificate being returned...");
+                return cert;
+            } catch(CertificateException e) {
+                logmsg("  OpenPGP failed, trying X.509...");
+                CertificateFactory cf = CertificateFactory.getInstance("X.509");
+                ByteArrayInputStream bais = new ByteArrayInputStream(data);
+                Certificate cert = cf.generateCertificate(bais);
+                logmsg("  X.509 Certificate being returned...");
+                return cert;
+            }
+        } catch(CertificateException e) {
+            String s;
+            if (data.length < 200)
+                s = (new String(data, 0, 99)) +
+                    " \\\n....\n" +
+                    (new String(data, data.length-100, data.length-1));
+            else
+                s = new String(data);
+            throw new IOException("unknown cert type\n\n" + s + "\n\n");
+        }
+    }
+
       
     /**
-     * Decode a Certificate object from ascii-armoured Base64 encoding
+     * Decode a Certificate object from ascii-armoured base64 encoding
      *
      * @param buf a String containing the ascii-armoured certificate 
      * @return the Certificate object
@@ -387,7 +497,7 @@
     {
         try
         {
-            return Utils.getCertificate( decode(buf) );
+            return getCertificate( decode(buf) );
         }
         catch (IOException ex)
         {
@@ -405,7 +515,7 @@
 
 
     /**
-     * Encode a PublicKey object using ascii-armoured Base64 encoding
+     * Encode a PublicKey object using ascii-armoured base64 encoding
      * <p>
      *
      * @param key the PublicKey object to be encoded
@@ -419,7 +529,7 @@
 
 
     /**
-     * Encode a PrivateKey object using ascii-armoured Base64 encoding
+     * Encode a PrivateKey object using ascii-armoured base64 encoding
      *
      * @param key the PrivateKey object to be encoded
      * @return the base64 encoded PrivateKey object
@@ -432,7 +542,7 @@
 
 
     /**
-     * Decode an PrivateKey object from ascii-armoured Base64 encoding
+     * Decode an PrivateKey object from ascii-armoured base64 encoding
      *
      * @param buf a String containing the base64 encoded PrivateKey
      * @return the PrivateKey object
@@ -455,7 +565,7 @@
 
     /**
      * Encode a Signature (stored in a byte array) using
-     * ascii-armoured Base64 encoding
+     * ascii-armoured base64 encoding
      *
      * @param keyPair the KeyPair object to be encoded
      * @return the base64 encoded KeyPair object
@@ -467,7 +577,7 @@
 
 
     /**
-     * Decode a Signature from ascii-armoured Base64 encoding
+     * Decode a Signature from ascii-armoured base64 encoding
      *
      * @param buf a String containing the base64 encoded signature
      * @return the signature (stored in a byte array)
@@ -489,7 +599,7 @@
         throws IOException,FileNotFoundException ,java.security.KeyException
     {
         BufferedReader bufr = new BufferedReader(new InputStreamReader (new ByteArrayInputStream(data)));
-        String result = "-----BEGIN "+"SIGNED DATA"+"-----" + newline;
+        String result = dashBEGIN + "SIGNED DATA" + DASHES + newline;
 
         String line;
         while ((line = bufr.readLine()) != null)
@@ -541,7 +651,7 @@
                 bufw.newLine();
             }
       
-            if (line.equals("-----BEGIN SIGNED DATA-----"))
+            if (line.equals(dashBEGIN + "SIGNED DATA" + DASHES))
                 record = true;
         }
         bufw.flush();
@@ -573,7 +683,7 @@
         while ((line = bufr.readLine()) != null)
         {
             line = "x" + line;
-// PLONK! FOLLOWING CALL IS NO-OP.  BUT CANNOT CHANGE BECAUSE
+// XXX:  PLONK! FOLLOWING CALL IS NO-OP.  BUT CANNOT CHANGE BECAUSE
 // HASHES AND SIGS ARE OUT THERE!
             line.trim();
             line = line.substring(1); // Remove the 'x'



1.6       +101 -43   java/webfunds/util/Base64Coder.java

Index: Base64Coder.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/util/Base64Coder.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- Base64Coder.java	2001/02/27 01:23:47	1.5
+++ Base64Coder.java	2001/03/18 23:20:57	1.6
@@ -1,25 +1,83 @@
 /*
- * $Id: Base64Coder.java,v 1.5 2001/02/27 01:23:47 iang Exp $
+ * $Id: Base64Coder.java,v 1.6 2001/03/18 23:20:57 iang Exp $
  *
  * Copyright (c) 1995-1999 Systemics Inc on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
  */
  
-package webfunds.sox.utils;
+package webfunds.util;
  
-public class Base64 
+/**
+ *  This class provides methods for encoding and decoding data in MIME base64
+ *  format.
+ *  <p>      
+ *  All of the methods either take a byte array, or a String.
+ *  and return a byte array or String (depending upon the method) containing
+ *  only the base 64 encoded data.  The return value represents a sequence of
+ *  characters, and depending upon the method, can be either a byte array
+ *  or String, since these characters are from a subset of both the Unicode
+ *  and ASCII character repertoires.  Base64 encoding encodes 6 binary bits
+ *  per character, using the characters 'A'-'Z', 'a'-'z', '0'-'9', '+', '/',
+ *  and '=' (for padding).
+ *
+ *  <p>
+ *  <b>References:</b>
+ *  <ol>
+ *   <li> RFC 2045, <cite>Multipurpose Internet Mail Extensions (MIME) Part One,
+ *        Format of Internet Message Bodies</cite>,
+ *        "Section 6.8 Base64 Content-Transfer-Encoding,"
+ *        <a href="http://www.imc.org/rfc2045">http://www.imc.org/rfc2045</a>
+ *  </ol> 
+ *
+ *  <p>
+ *  Users are Armoury.java and Contract.java.
+ *  <p>
+ *  Repository copied from webfunds/sox/utils/Base64.java at 1.5.
+ */   
+public class Base64Coder
 { 
-    // private Base64() { }  // why this?  So no extension possible?
-     
-    //
-    // Following data is protected so subclass can change mapping,
-    // as is done by Base64File.java for filenames.
-    //
     /**
+     *  The newline used on encodes is by default the
+     *  system property one.
+     */
+
+    protected String newline    = System.getProperty("line.separator");
+
+    /**
+     *  Each line is encoded as numGroups groups, where each group
+     *  is 4 Base64 letters making up a 3-byte binary sequence.
+     *
+     *  Current default of 19 gives 57 ascii chars written per line.
+     */
+    protected int    numGroups   = 19;
+    
+    /**
+     *  Set up Coder with default paramaters, which are thought
+     *  to be best for all circumstances (although these are mostly
+     *  historical...).
+     */
+    public Base64Coder() { }
+
+    /** @return the current set newline for encoding (default is property) */
+    public String getNewline()                      { return newline; }
+    /** set the newline string sequence for encoding */
+    public void setNewline(String s)                { newline = s; }
+    /** @return the current number of groups for each line */
+    public int getNumberOfGroups()                  { return numGroups; }
+    /** set the number of groups per encoded line */
+    public void setNumberOfGroups(int i)            { numGroups = i; }
+    /** @return the current number of Base 64 characters for each line */
+    public int getMaximumLineLength()               { return numGroups * 4; }
+    /** set the number of Base 64 characters per encoded line */
+    public void setMaximumLineLength(int i)         { numGroups = i / 4; }
+
+
+
+    /**
      * Filler byte is used to round up.
      */
-    protected final static byte filler = 0x3d;
-    protected final static char fillerChar = '=';
+    private final static byte filler = 0x3d;
+    private final static char fillerChar = '=';
 
     /**
      * Maps 6 bit integers to a specific char.
@@ -68,62 +126,59 @@
     public static byte[] getDecodeTable() { return dec_table ; }
  
     /**
-     * Encode a byte array into Base 64.
+     *  Encode a byte array into Base 64.
      */
-    public static String encode(byte buf[]) 
+    public String encode(byte buf[]) 
     {
-        return enc(buf);
+        return enc(buf, numGroups, newline);
     }
 
     /**
-     * Encode a string into Base 64.
+     *  Encode a string into Base 64.
      */
-    public static String encode(String s) 
+    public String encode(String s) 
     {
-        //int len = s.length();
-        // byte[] buf = new byte[len];
-        // s.getBytes(0, len, buf, 0);   // deprecated method?
-
         byte[] buf = s.getBytes();
-        return enc(buf);
+        return enc(buf, numGroups, newline);
     }
 
     /**
-     * Decode a Base 64 string.
-     * Ignores trailing whitespace and newlines
+     *  Decode a Base 64 string.
+     *  Ignores trailing whitespace and newlines
      */
-    public static byte[] decode(String msg) 
+    public byte[] decode(String msg) 
     {
-        //int len = msg.length();
-        // byte[] buf = new byte[len];
-        // msg.getBytes(0, len, buf, 0);
-
         byte[] buf = msg.getBytes();
         return dec(buf);
     }
 
     /**
-     * Decode a Base 64 byte array.
-     * Ignores trailing whitespace and newlines
+     *  Decode a Base 64 byte array.
+     *  Ignores trailing whitespace and newlines
      */
-    public static byte[] decode(byte buf[]) 
+    public byte[] decode(byte buf[]) 
     {
         return dec(buf);
     }
 
 
 
-    protected static String newline = System.getProperty("line.separator");
 
     /**
-     * Encodes into lines of 57?
+     *  Encodes into numGroups groups, where each group is 4 Base64 letters
+     *  making up a 3-byte binary sequence.
+     *
+     *  @param buf binary sequence to be encoded
+     *  @param numGroups number of groups to use per line
+     *  @param nl is the newline to be appended to each line
      */
-    protected static String enc(byte buf[])
+    protected static String enc(byte buf[], int numGroups, String nl)
     {
         int i = 0; 
+        final int lineLen = numGroups * 3;
         StringBuffer buffer = new StringBuffer(); 
-        int len = buf.length; 
-        int delta = len % 3; 
+        final int len = buf.length; 
+        int delta = len % 3;         // what fraction of group left over
 
         byte a, b, c;
         for (int count = len / 3; count > 0; count--) 
@@ -136,8 +191,8 @@
             buffer.append(enc_table[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]); 
             buffer.append(enc_table[c & 0x3F]); 
 
-            if (i != 0 && i%57 == 0)
-                buffer.append(newline);
+            if ((i != 0) && ((i % lineLen) == 0))
+                buffer.append(nl);
         }
 
         if (delta == 1) 
@@ -158,7 +213,7 @@
             buffer.append(fillerChar); 
         }
 
-        buffer.append(newline);
+        buffer.append(nl);
         return buffer.toString(); 
     }
 
@@ -245,11 +300,13 @@
         args = null;
 
         String msg = "Aladdin:open sesame! ";
+
+        Base64Coder base64 = new Base64Coder();
 
-        String m = encode(msg);
+        String m = base64.encode(msg);
         System.out.println("Encoded = "+m);
 
-        String d = new String(decode(m));
+        String d = new String(base64.decode(m));
         System.out.println("Decoded = "+d);
 
         msg += msg;
@@ -257,10 +314,11 @@
         msg += msg;
         msg += msg;
 
-        m = encode(msg);
+        base64.setNumberOfGroups(13);
+        m = base64.encode(msg);
         System.out.println("Encoded = "+m);
 
-        d = new String(decode(m));
+        d = new String(base64.decode(m));
         System.out.println("Decoded = "+d);
     }
 }



1.4       +2 -2      java/webfunds/util/CRC.java

Index: CRC.java
===================================================================
RCS file: /home/webfunds/cvsroot/java/webfunds/util/CRC.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- CRC.java	1999/09/30 20:56:14	1.3
+++ CRC.java	2001/03/18 23:20:57	1.4
@@ -1,11 +1,11 @@
 /*
- * $Id: CRC.java,v 1.3 1999/09/30 20:56:14 iang Exp $
+ * $Id: CRC.java,v 1.4 2001/03/18 23:20:57 iang Exp $
  *
  * Copyright (c) Systemics Ltd 1995-1999 on behalf of
  * the WebFunds Development Team.  All Rights Reserved.
  */
 
-package webfunds.sox;
+package webfunds.util;
 
 /**
  * This class performs the CRC check as required by pgp base64 Encoded packets.