From ce57ab760f69de6db452def7ffbf5b114a2d8694 Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 10 Mar 2006 21:46:48 +0000 Subject: Imported GNU Classpath 0.90 * scripts/makemake.tcl: Set gnu/java/awt/peer/swing to ignore. * gnu/classpath/jdwp/VMFrame.java (SIZE): New constant. * java/lang/VMCompiler.java: Use gnu.java.security.hash.MD5. * java/lang/Math.java: New override file. * java/lang/Character.java: Merged from Classpath. (start, end): Now 'int's. (canonicalName): New field. (CANONICAL_NAME, NO_SPACES_NAME, CONSTANT_NAME): New constants. (UnicodeBlock): Added argument. (of): New overload. (forName): New method. Updated unicode blocks. (sets): Updated. * sources.am: Regenerated. * Makefile.in: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@111942 138bc75d-0d04-0410-961f-82ee72b054a4 --- .../classpath/gnu/java/security/util/Base64.java | 396 ++++++++++++ .../classpath/gnu/java/security/util/DerUtil.java | 64 ++ .../gnu/java/security/util/ExpirableObject.java | 172 +++++ .../gnu/java/security/util/FormatUtil.java | 140 +++++ libjava/classpath/gnu/java/security/util/PRNG.java | 156 +++++ .../classpath/gnu/java/security/util/Prime2.java | 417 +++++++++++++ .../classpath/gnu/java/security/util/Sequence.java | 149 +++++ .../gnu/java/security/util/SimpleList.java | 171 +++++ libjava/classpath/gnu/java/security/util/Util.java | 692 +++++++++++++++++++++ 9 files changed, 2357 insertions(+) create mode 100644 libjava/classpath/gnu/java/security/util/Base64.java create mode 100644 libjava/classpath/gnu/java/security/util/DerUtil.java create mode 100644 libjava/classpath/gnu/java/security/util/ExpirableObject.java create mode 100644 libjava/classpath/gnu/java/security/util/FormatUtil.java create mode 100644 libjava/classpath/gnu/java/security/util/PRNG.java create mode 100644 libjava/classpath/gnu/java/security/util/Prime2.java create mode 100644 libjava/classpath/gnu/java/security/util/Sequence.java create mode 100644 libjava/classpath/gnu/java/security/util/SimpleList.java create mode 100644 libjava/classpath/gnu/java/security/util/Util.java (limited to 'libjava/classpath/gnu/java/security/util') diff --git a/libjava/classpath/gnu/java/security/util/Base64.java b/libjava/classpath/gnu/java/security/util/Base64.java new file mode 100644 index 00000000000..f9998c38f48 --- /dev/null +++ b/libjava/classpath/gnu/java/security/util/Base64.java @@ -0,0 +1,396 @@ +/* Base64.java -- + Copyright (C) 2003, 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.java.security.util; + +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +/** + * Most of this implementation is from Robert Harder's public domain Base64 + * code (version 1.4.1 available from <http://iharder.net/xmlizable>). + */ +public class Base64 +{ + + // Debugging methods and variables + // ------------------------------------------------------------------------- + + private static final String NAME = "Base64"; + + private static final boolean DEBUG = true; + + private static final int debuglevel = 9; + + private static final PrintWriter err = new PrintWriter(System.out, true); + + private static void debug(String s) + { + err.println(">>> " + NAME + ": " + s); + } + + // Constants and variables + // ------------------------------------------------------------------------- + + /** Maximum line length (76) of Base64 output. */ + private static final int MAX_LINE_LENGTH = 76; + + /** The new line character (\n) as one byte. */ + private static final byte NEW_LINE = (byte) '\n'; + + /** The equals sign (=) as a byte. */ + private static final byte EQUALS_SIGN = (byte) '='; + + private static final byte WHITE_SPACE_ENC = -5; // white space in encoding + + private static final byte EQUALS_SIGN_ENC = -1; // equals sign in encoding + + /** The 64 valid Base64 values. */ + private static final byte[] ALPHABET = { (byte) 'A', (byte) 'B', (byte) 'C', + (byte) 'D', (byte) 'E', (byte) 'F', + (byte) 'G', (byte) 'H', (byte) 'I', + (byte) 'J', (byte) 'K', (byte) 'L', + (byte) 'M', (byte) 'N', (byte) 'O', + (byte) 'P', (byte) 'Q', (byte) 'R', + (byte) 'S', (byte) 'T', (byte) 'U', + (byte) 'V', (byte) 'W', (byte) 'X', + (byte) 'Y', (byte) 'Z', (byte) 'a', + (byte) 'b', (byte) 'c', (byte) 'd', + (byte) 'e', (byte) 'f', (byte) 'g', + (byte) 'h', (byte) 'i', (byte) 'j', + (byte) 'k', (byte) 'l', (byte) 'm', + (byte) 'n', (byte) 'o', (byte) 'p', + (byte) 'q', (byte) 'r', (byte) 's', + (byte) 't', (byte) 'u', (byte) 'v', + (byte) 'w', (byte) 'x', (byte) 'y', + (byte) 'z', (byte) '0', (byte) '1', + (byte) '2', (byte) '3', (byte) '4', + (byte) '5', (byte) '6', (byte) '7', + (byte) '8', (byte) '9', (byte) '+', + (byte) '/' }; + + /** + * Translates a Base64 value to either its 6-bit reconstruction value or a + * negative number indicating some other meaning. + */ + private static final byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 + -5, -5, // Whitespace: Tab and Linefeed + -9, -9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9, -9, -9, -9, -9, -9, -9, -9, -9, + -9, -9, -9, -9, // Decimal 14 - 26 + -9, -9, -9, -9, -9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9, -9, -9, -9, -9, -9, -9, -9, -9, + -9, // Decimal 33 - 42 + 62, // Plus sign at decimal 43 + -9, -9, -9, // Decimal 44 - 46 + 63, // Slash at decimal 47 + 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, // Numbers zero through nine + -9, -9, -9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9, -9, -9, // Decimal 62 - 64 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, // Letters 'A' through 'N' + 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, // Letters 'O' through 'Z' + -9, -9, -9, -9, -9, -9, // Decimal 91 - 96 + 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, // Letters 'a' through 'm' + 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, // Letters 'n' through 'z' + -9, -9, -9, -9 // Decimal 123 - 126 + }; + + // Constructor(s) + // ------------------------------------------------------------------------- + + /** Trivial private ctor to enfore Singleton pattern. */ + private Base64() + { + super(); + } + + // Class methods + // ------------------------------------------------------------------------- + + /** + * Encodes a byte array into Base64 notation. Equivalent to calling + * encode(source, 0, source.length). + * + * @param src the data to convert. + */ + public static final String encode(final byte[] src) + { + return encode(src, 0, src.length, true); + } + + /** + * Encodes a byte array into Base64 notation. + * + * @param src the data to convert. + * @param off offset in array where conversion should begin. + * @param len length of data to convert. + * @param breakLines break lines at 80 characters or less. + */ + public static final String encode(final byte[] src, final int off, + final int len, final boolean breakLines) + { + final int len43 = len * 4 / 3; + final byte[] outBuff = new byte[len43 // Main 4:3 + + ((len % 3) > 0 ? 4 : 0) // Account for padding + + (breakLines ? (len43 / MAX_LINE_LENGTH) + : 0)]; // New lines + int d = 0; + int e = 0; + final int len2 = len - 2; + int lineLength = 0; + for (; d < len2; d += 3, e += 4) + { + encode3to4(src, d + off, 3, outBuff, e); + lineLength += 4; + if (breakLines && lineLength == MAX_LINE_LENGTH) + { + outBuff[e + 4] = NEW_LINE; + e++; + lineLength = 0; + } + } + + if (d < len) + { // padding needed + encode3to4(src, d + off, len - d, outBuff, e); + e += 4; + } + + return new String(outBuff, 0, e); + } + + /** + * Decodes data from Base64 notation. + * + * @param s the string to decode. + * @return the decoded data. + */ + public static final byte[] decode(final String s) + throws UnsupportedEncodingException + { + final byte[] bytes; + bytes = s.getBytes("US-ASCII"); + return decode(bytes, 0, bytes.length); + } + + /** + * Decodes Base64 content in byte array format and returns the decoded byte + * array. + * + * @param src the Base64 encoded data. + * @param off the offset of where to begin decoding. + * @param len the length of characters to decode. + * @return the decoded data. + * @throws IllegalArgumentException if src contains an illegal + * Base-64 character. + */ + public static byte[] decode(final byte[] src, final int off, final int len) + { + final int len34 = len * 3 / 4; + final byte[] outBuff = new byte[len34]; // Upper limit on size of output + int outBuffPosn = 0; + final byte[] b4 = new byte[4]; + int b4Posn = 0; + int i; + byte sbiCrop, sbiDecode; + for (i = off; i < off + len; i++) + { + sbiCrop = (byte) (src[i] & 0x7F); // Only the low seven bits + sbiDecode = DECODABET[sbiCrop]; + if (sbiDecode >= WHITE_SPACE_ENC) + { // White space, Equals sign or better + if (sbiDecode >= EQUALS_SIGN_ENC) + { + b4[b4Posn++] = sbiCrop; + if (b4Posn > 3) + { + outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn); + b4Posn = 0; + // If that was the equals sign, break out of 'for' loop + if (sbiCrop == EQUALS_SIGN) + break; + } // end if: quartet built + } // end if: equals sign or better + } + else + { + throw new IllegalArgumentException("Illegal BASE-64 character at #" + + i + ": " + src[i] + + "(decimal)"); + } + } + + final byte[] result = new byte[outBuffPosn]; + System.arraycopy(outBuff, 0, result, 0, outBuffPosn); + return result; + } + + /** + *

Encodes up to three bytes of the array src and writes + * the resulting four Base64 bytes to dest. The source and + * destination arrays can be manipulated anywhere along their length by + * specifying sOffset and dOffset.

+ * + *

This method does not check to make sure the arrays are large enough to + * accomodate sOffset + 3 for the src array or + * dOffset + 4 for the dest array. The actual + * number of significant bytes in the input array is given by + * numBytes.

+ * + * @param src the array to convert. + * @param sOffset the index where conversion begins. + * @param numBytes the number of significant bytes in your array. + * @param dest the array to hold the conversion. + * @param dOffset the index where output will be put. + * @return the destination array. + */ + private static final byte[] encode3to4(final byte[] src, final int sOffset, + final int numBytes, final byte[] dest, + final int dOffset) + { + // 1 2 3 + // 01234567890123456789012345678901 Bit position + // --------000000001111111122222222 Array position from threeBytes + // --------| || || || | Six bit groups to index ALPHABET + // >>18 >>12 >> 6 >> 0 Right shift necessary + // 0x3F 0x3F 0x3F Additional AND + + // Create buffer with zero-padding if there are only one or two + // significant bytes passed in the array. + // We have to shift left 24 in order to flush out the 1's that appear + // when Java treats a value as negative that is cast from a byte to an int. + final int inBuff = (numBytes > 0 ? ((src[sOffset] << 24) >>> 8) : 0) + | (numBytes > 1 ? ((src[sOffset + 1] << 24) >>> 16) : 0) + | (numBytes > 2 ? ((src[sOffset + 2] << 24) >>> 24) : 0); + switch (numBytes) + { + case 3: + dest[dOffset] = ALPHABET[(inBuff >>> 18)]; + dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F]; + dest[dOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3F]; + dest[dOffset + 3] = ALPHABET[(inBuff) & 0x3F]; + break; + case 2: + dest[dOffset] = ALPHABET[(inBuff >>> 18)]; + dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F]; + dest[dOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3F]; + dest[dOffset + 3] = EQUALS_SIGN; + break; + case 1: + dest[dOffset] = ALPHABET[(inBuff >>> 18)]; + dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F]; + dest[dOffset + 2] = EQUALS_SIGN; + dest[dOffset + 3] = EQUALS_SIGN; + break; + } + return dest; + } + + /** + *

Decodes four bytes from array src and writes the + * resulting bytes (up to three of them) to dest.

+ * + *

The source and destination arrays can be manipulated anywhere along + * their length by specifying sOffset and dOffset. + *

+ * + *

This method does not check to make sure your arrays are large enough + * to accomodate sOffset + 4 for the src array or + * dOffset + 3 for the dest array. This method + * returns the actual number of bytes that were converted from the Base64 + * encoding.

+ * + * @param src the array to convert. + * @param sOffset the index where conversion begins. + * @param dest the array to hold the conversion. + * @param dOffset the index where output will be put. + * @return the number of decoded bytes converted. + */ + private static final int decode4to3(final byte[] src, final int sOffset, + final byte[] dest, final int dOffset) + { + if (src[sOffset + 2] == EQUALS_SIGN) + { // Example: Dk== + final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18) + | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12); + dest[dOffset] = (byte) (outBuff >>> 16); + return 1; + } + + if (src[sOffset + 3] == EQUALS_SIGN) + { // Example: DkL= + final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18) + | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12) + | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6); + dest[dOffset] = (byte) (outBuff >>> 16); + dest[dOffset + 1] = (byte) (outBuff >>> 8); + return 2; + } + + try + { // Example: DkLE + final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18) + | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12) + | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6) + | ((DECODABET[src[sOffset + 3]] & 0xFF)); + dest[dOffset] = (byte) (outBuff >> 16); + dest[dOffset + 1] = (byte) (outBuff >> 8); + dest[dOffset + 2] = (byte) outBuff; + return 3; + } + catch (Exception x) + { + if (DEBUG && debuglevel > 8) + { + debug("" + src[sOffset] + ": " + (DECODABET[src[sOffset]])); + debug("" + src[sOffset + 1] + ": " + (DECODABET[src[sOffset + 1]])); + debug("" + src[sOffset + 2] + ": " + (DECODABET[src[sOffset + 2]])); + debug("" + src[sOffset + 3] + ": " + (DECODABET[src[sOffset + 3]])); + } + return -1; + } + } +} diff --git a/libjava/classpath/gnu/java/security/util/DerUtil.java b/libjava/classpath/gnu/java/security/util/DerUtil.java new file mode 100644 index 00000000000..26232ba9843 --- /dev/null +++ b/libjava/classpath/gnu/java/security/util/DerUtil.java @@ -0,0 +1,64 @@ +/* DerUtil.java -- Utility methods for DER read/write operations + Copyright (C) 2006 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., 51 Franklin Street, 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.java.security.util; + +import gnu.java.security.der.DEREncodingException; +import gnu.java.security.der.DERValue; + +import java.math.BigInteger; + +/** + * Utility methods for DER encoding handling. + */ +public abstract class DerUtil +{ + public static final void checkIsConstructed(DERValue v, String msg) + throws DEREncodingException + { + if (! v.isConstructed()) + throw new DEREncodingException(msg); + } + + public static final void checkIsBigInteger(DERValue v, String msg) + throws DEREncodingException + { + if (! (v.getValue() instanceof BigInteger)) + throw new DEREncodingException(msg); + } +} diff --git a/libjava/classpath/gnu/java/security/util/ExpirableObject.java b/libjava/classpath/gnu/java/security/util/ExpirableObject.java new file mode 100644 index 00000000000..2d4452015af --- /dev/null +++ b/libjava/classpath/gnu/java/security/util/ExpirableObject.java @@ -0,0 +1,172 @@ +/* ExpirableObject.java -- an object that is automatically destroyed. + Copyright (C) 2004, 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.java.security.util; + +import java.util.Timer; +import java.util.TimerTask; + +import javax.security.auth.DestroyFailedException; +import javax.security.auth.Destroyable; + +/** + * The base class for objects with sensitive data that are automatically + * destroyed after a timeout elapses. On creation, an object that extends + * this class will automatically be added to a {@link Timer} object that, + * once a timeout elapses, will automatically call the {@link + * Destroyable#destroy()} method. + * + *

Concrete subclasses must implement the {@link doDestroy()} method + * instead of {@link Destroyable#destroy()}; the behavior of that method + * should match exactly the behavior desired of destroy(). + * + *

Note that if a {@link DestroyFailedException} occurs when the timeout + * expires, it will not be reported. + * + * @see Destroyable + */ +public abstract class ExpirableObject implements Destroyable +{ + + // Constants and fields. + // ------------------------------------------------------------------------- + + /** + * The default timeout, used in the default constructor. + */ + public static final long DEFAULT_TIMEOUT = 3600000L; + + /** + * The timer that expires instances. + */ + private static final Timer EXPIRER = new Timer(true); + + /** + * A reference to the task that will destroy this object when the timeout + * expires. + */ + private final Destroyer destroyer; + + // Constructors. + // ------------------------------------------------------------------------- + + /** + * Create a new expirable object that will expire after one hour. + */ + protected ExpirableObject() + { + this(DEFAULT_TIMEOUT); + } + + /** + * Create a new expirable object that will expire after the specified + * timeout. + * + * @param delay The delay before expiration. + * @throws IllegalArgumentException If delay is negative, or if + * delay + System.currentTimeMillis() is negative. + */ + protected ExpirableObject(final long delay) + { + destroyer = new Destroyer(this); + EXPIRER.schedule(destroyer, delay); + } + + // Instance methods. + // ------------------------------------------------------------------------- + + /** + * Destroys this object. This method calls {@link doDestroy}, then, if + * no exception is thrown, cancels the task that would destroy this object + * when the timeout is reached. + * + * @throws DestroyFailedException If this operation fails. + */ + public final void destroy() throws DestroyFailedException + { + doDestroy(); + destroyer.cancel(); + } + + /** + * Subclasses must implement this method instead of the {@link + * Destroyable#destroy()} method. + * + * @throws DestroyFailedException If this operation fails. + */ + protected abstract void doDestroy() throws DestroyFailedException; + + // Inner classes. + // ------------------------------------------------------------------------- + + /** + * The task that destroys the target when the timeout elapses. + */ + private final class Destroyer extends TimerTask + { + + // Fields. + // ----------------------------------------------------------------------- + + private final ExpirableObject target; + + // Constructor. + // ----------------------------------------------------------------------- + + Destroyer(final ExpirableObject target) + { + super(); + this.target = target; + } + + // Instance methods. + // ----------------------------------------------------------------------- + + public void run() + { + try + { + if (!target.isDestroyed()) + target.doDestroy(); + } + catch (DestroyFailedException dfe) + { + } + } + } +} diff --git a/libjava/classpath/gnu/java/security/util/FormatUtil.java b/libjava/classpath/gnu/java/security/util/FormatUtil.java new file mode 100644 index 00000000000..eed669cc3a4 --- /dev/null +++ b/libjava/classpath/gnu/java/security/util/FormatUtil.java @@ -0,0 +1,140 @@ +/* FormatUtil.java -- Encoding and decoding format utility methods + Copyright (C) 2006 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., 51 Franklin Street, 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.java.security.util; + +import gnu.java.security.Registry; + +/** + * Encoding and decoding format utility methods. + */ +public class FormatUtil +{ + /** Trivial constructor to enforce Singleton pattern. */ + private FormatUtil() + { + super(); + } + + /** + * Returns the fully qualified name of the designated encoding ID. + * + * @param formatID the unique identifier of the encoding format. + * @return the fully qualified name of the designated format. Returns + * null if no such encoding format is known. + */ + public static final String getEncodingName(int formatID) + { + String result = null; + switch (formatID) + { + case Registry.RAW_ENCODING_ID: + result = Registry.RAW_ENCODING; + break; + case Registry.X509_ENCODING_ID: + result = Registry.X509_ENCODING; + break; + case Registry.PKCS8_ENCODING_ID: + result = Registry.PKCS8_ENCODING; + break; + case Registry.ASN1_ENCODING_ID: + result = Registry.ASN1_ENCODING; + break; + } + + return result; + } + + /** + * Returns the short name of the designated encoding ID. This is used by the + * JCE Adapters. + * + * @param formatID the unique identifier of the encoding format. + * @return the short name of the designated format. Returns null + * if no such encoding format is known. + */ + public static final String getEncodingShortName(int formatID) + { + String result = null; + switch (formatID) + { + case Registry.RAW_ENCODING_ID: + result = Registry.RAW_ENCODING_SHORT_NAME; + break; + case Registry.X509_ENCODING_ID: + result = Registry.X509_ENCODING_SORT_NAME; + break; + case Registry.PKCS8_ENCODING_ID: + result = Registry.PKCS8_ENCODING_SHORT_NAME; + break; + case Registry.ASN1_ENCODING_ID: + result = Registry.ASN1_ENCODING_SHORT_NAME; + break; + } + + return result; + } + + /** + * Returns the identifier of the encoding format given its short name. + * + * @param name the case-insensitive canonical short name of an encoding + * format. + * @return the identifier of the designated encoding format, or 0 + * if the name does not correspond to any known format. + */ + public static final int getFormatID(String name) + { + if (name == null) + return 0; + + name = name.trim(); + if (name.length() == 0) + return 0; + + int result = 0; + if (name.equalsIgnoreCase(Registry.RAW_ENCODING_SHORT_NAME)) + result = Registry.RAW_ENCODING_ID; + else if (name.equalsIgnoreCase(Registry.X509_ENCODING_SORT_NAME)) + result = Registry.X509_ENCODING_ID; + else if (name.equalsIgnoreCase(Registry.PKCS8_ENCODING_SHORT_NAME)) + result = Registry.PKCS8_ENCODING_ID; + + return result; + } +} diff --git a/libjava/classpath/gnu/java/security/util/PRNG.java b/libjava/classpath/gnu/java/security/util/PRNG.java new file mode 100644 index 00000000000..138cc6bcb0c --- /dev/null +++ b/libjava/classpath/gnu/java/security/util/PRNG.java @@ -0,0 +1,156 @@ +/* PRNG.java -- A Utility methods for default source of randomness + Copyright (C) 2006 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., 51 Franklin Street, 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.java.security.util; + +import java.util.HashMap; + +import gnu.java.security.prng.IRandom; +import gnu.java.security.prng.LimitReachedException; +import gnu.java.security.prng.MDGenerator; + +/** + * A useful hash-based (SHA) pseudo-random number generator used + * throughout this library. + * + * @see MDGenerator + */ +public class PRNG +{ + // Constans and fields + // -------------------------------------------------------------------------- + + /** The underlying {@link IRandom}. */ + private IRandom delegate; + + // Constructor(s) + // -------------------------------------------------------------------------- + + /** + * Private constructor to enforce using the Factory method. + * + * @param delegate + * the undelying {@link IRandom} object used. + */ + private PRNG(IRandom delegate) + { + super(); + + this.delegate = delegate; + } + + // Class methods + // -------------------------------------------------------------------------- + + public static final PRNG getInstance() + { + IRandom delegate = new MDGenerator(); + try + { + HashMap map = new HashMap(); + // initialise it with a seed + long t = System.currentTimeMillis(); + byte[] seed = new byte[] { + (byte) (t >>> 56), (byte) (t >>> 48), + (byte) (t >>> 40), (byte) (t >>> 32), + (byte) (t >>> 24), (byte) (t >>> 16), + (byte) (t >>> 8), (byte) t}; + map.put(MDGenerator.SEEED, seed); + delegate.init(map); // default is to use SHA-1 hash + } + catch (Exception x) + { + throw new ExceptionInInitializerError(x); + } + + return new PRNG(delegate); + } + + // Instance methods + // -------------------------------------------------------------------------- + + /** + * Completely fills the designated buffer with random data + * generated by the underlying delegate. + * + * @param buffer + * the place holder of random bytes generated by the underlying + * delegate. On output, the contents of buffer are + * replaced with pseudo-random data, iff the buffer + * size is not zero. + */ + public void nextBytes(byte[] buffer) + { + nextBytes(buffer, 0, buffer.length); + } + + /** + * Fills the designated buffer, starting from byte at position + * offset with, at most, length bytes of random + * data generated by the underlying delegate. + * + * @see IRandom#nextBytes + */ + public void nextBytes(byte[] buffer, int offset, int length) + { + try + { + delegate.nextBytes(buffer, offset, length); + } + catch (LimitReachedException x) // re-initialise with a seed + { + try + { + HashMap map = new HashMap(); + long t = System.currentTimeMillis(); + byte[] seed = new byte[] { + (byte)(t >>> 56), (byte)(t >>> 48), + (byte)(t >>> 40), (byte)(t >>> 32), + (byte)(t >>> 24), (byte)(t >>> 16), + (byte)(t >>> 8), (byte) t }; + map.put(MDGenerator.SEEED, seed); + delegate.init(map); // default is to use SHA-1 hash + delegate.nextBytes(buffer, offset, length); + } + catch (Exception y) + { + throw new ExceptionInInitializerError(y); + } + } + } +} diff --git a/libjava/classpath/gnu/java/security/util/Prime2.java b/libjava/classpath/gnu/java/security/util/Prime2.java new file mode 100644 index 00000000000..6e46f5fcadc --- /dev/null +++ b/libjava/classpath/gnu/java/security/util/Prime2.java @@ -0,0 +1,417 @@ +/* Prime2.java -- + Copyright (C) 2001, 2002, 2003, 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.java.security.util; + +import java.io.PrintWriter; +import java.lang.ref.WeakReference; +import java.math.BigInteger; +import java.util.Map; +import java.util.WeakHashMap; + +/** + *

A collection of prime number related utilities used in this library.

+ */ +public class Prime2 +{ + + // Debugging methods and variables + // ------------------------------------------------------------------------- + + private static final String NAME = "prime"; + + private static final boolean DEBUG = false; + + private static final int debuglevel = 5; + + private static final PrintWriter err = new PrintWriter(System.out, true); + + private static void debug(String s) + { + err.println(">>> " + NAME + ": " + s); + } + + // Constants and variables + // ------------------------------------------------------------------------- + + private static final int DEFAULT_CERTAINTY = 20; // XXX is this a good value? + + private static final BigInteger ZERO = BigInteger.ZERO; + + private static final BigInteger ONE = BigInteger.ONE; + + private static final BigInteger TWO = BigInteger.valueOf(2L); + + /** + * The first SMALL_PRIME primes: Algorithm P, section 1.3.2, The Art of + * Computer Programming, Donald E. Knuth. + */ + private static final int SMALL_PRIME_COUNT = 1000; + + private static final BigInteger[] SMALL_PRIME = new BigInteger[SMALL_PRIME_COUNT]; + static + { + long time = -System.currentTimeMillis(); + SMALL_PRIME[0] = TWO; + int N = 3; + int J = 0; + int prime; + P2: while (true) + { + SMALL_PRIME[++J] = BigInteger.valueOf(N); + if (J >= 999) + { + break P2; + } + P4: while (true) + { + N += 2; + P6: for (int K = 1; true; K++) + { + prime = SMALL_PRIME[K].intValue(); + if ((N % prime) == 0) + { + continue P4; + } + else if ((N / prime) <= prime) + { + continue P2; + } + } + } + } + time += System.currentTimeMillis(); + if (DEBUG && debuglevel > 8) + { + StringBuffer sb; + for (int i = 0; i < (SMALL_PRIME_COUNT / 10); i++) + { + sb = new StringBuffer(); + for (int j = 0; j < 10; j++) + { + sb.append(String.valueOf(SMALL_PRIME[i * 10 + j])).append(" "); + } + debug(sb.toString()); + } + } + if (DEBUG && debuglevel > 4) + { + debug("Generating first " + String.valueOf(SMALL_PRIME_COUNT) + + " primes took: " + String.valueOf(time) + " ms."); + } + } + + private static final Map knownPrimes = new WeakHashMap(); + + // Constructor(s) + // ------------------------------------------------------------------------- + + /** Trivial constructor to enforce Singleton pattern. */ + private Prime2() + { + super(); + } + + // Class methods + // ------------------------------------------------------------------------- + + /** + *

Trial division for the first 1000 small primes.

+ * + *

Returns true if at least one small prime, among the first + * 1000 ones, was found to divide the designated number. Retuens false + * otherwise.

+ * + * @param w the number to test. + * @return true if at least one small prime was found to divide + * the designated number. + */ + public static boolean hasSmallPrimeDivisor(BigInteger w) + { + BigInteger prime; + for (int i = 0; i < SMALL_PRIME_COUNT; i++) + { + prime = SMALL_PRIME[i]; + if (w.mod(prime).equals(ZERO)) + { + if (DEBUG && debuglevel > 4) + { + debug(prime.toString(16) + " | " + w.toString(16) + "..."); + } + return true; + } + } + if (DEBUG && debuglevel > 4) + { + debug(w.toString(16) + " has no small prime divisors..."); + } + return false; + } + + /** + *

Java port of Colin Plumb primality test (Euler Criterion) + * implementation for a base of 2 --from bnlib-1.1 release, function + * primeTest() in prime.c. this is his comments.

+ * + *

"Now, check that bn is prime. If it passes to the base 2, it's prime + * beyond all reasonable doubt, and everything else is just gravy, but it + * gives people warm fuzzies to do it.

+ * + *

This starts with verifying Euler's criterion for a base of 2. This is + * the fastest pseudoprimality test that I know of, saving a modular squaring + * over a Fermat test, as well as being stronger. 7/8 of the time, it's as + * strong as a strong pseudoprimality test, too. (The exception being when + * bn == 1 mod 8 and 2 is a quartic residue, i.e. + * bn is of the form a^2 + (8*b)^2.) The precise + * series of tricks used here is not documented anywhere, so here's an + * explanation. Euler's criterion states that if p is prime + * then a^((p-1)/2) is congruent to Jacobi(a,p), + * modulo p. Jacobi(a, p) is a function which is + * +1 if a is a square modulo p, and -1 + * if it is not. For a = 2, this is particularly simple. It's + * +1 if p == +/-1 (mod 8), and -1 if + * m == +/-3 (mod 8). If p == 3 (mod 4), then all + * a strong test does is compute 2^((p-1)/2). and see if it's + * +1 or -1. (Euler's criterion says which + * it should be.) If p == 5 (mod 8), then 2^((p-1)/2) + * is -1, so the initial step in a strong test, looking at + * 2^((p-1)/4), is wasted --you're not going to find a + * +/-1 before then if it is prime, and it shouldn't + * have either of those values if it isn't. So don't bother.

+ * + *

The remaining case is p == 1 (mod 8). In this case, we + * expect 2^((p-1)/2) == 1 (mod p), so we expect that the + * square root of this, 2^((p-1)/4), will be +/-1 (mod p) + * . Evaluating this saves us a modular squaring 1/4 of the time. If + * it's -1, a strong pseudoprimality test would call p + * prime as well. Only if the result is +1, indicating that + * 2 is not only a quadratic residue, but a quartic one as well, + * does a strong pseudoprimality test verify more things than this test does. + * Good enough.

+ * + *

We could back that down another step, looking at 2^((p-1)/8) + * if there was a cheap way to determine if 2 were expected to + * be a quartic residue or not. Dirichlet proved that 2 is a + * quadratic residue iff p is of the form a^2 + (8*b^2). + * All primes == 1 (mod 4) can be expressed as a^2 + + * (2*b)^2, but I see no cheap way to evaluate this condition."

+ * + * @param bn the number to test. + * @return true iff the designated number passes Euler criterion + * as implemented by Colin Plumb in his bnlib version 1.1. + */ + public static boolean passEulerCriterion(final BigInteger bn) + { + BigInteger bn_minus_one = bn.subtract(ONE); + BigInteger e = bn_minus_one; + // l is the 3 least-significant bits of e + int l = e.and(BigInteger.valueOf(7L)).intValue(); + int j = 1; // Where to start in prime array for strong prime tests + BigInteger a; + int k; + + if (l != 0) + { + e = e.shiftRight(1); + a = TWO.modPow(e, bn); + if (l == 6) // bn == 7 mod 8, expect +1 + { + if (a.bitLength() != 1) + { + debugBI("Fails Euler criterion #1", bn); + return false; // Not prime + } + k = 1; + } + else // bn == 3 or 5 mod 8, expect -1 == bn-1 + { + a = a.add(ONE); + if (a.compareTo(bn) != 0) + { + debugBI("Fails Euler criterion #2", bn); + return false; // Not prime + } + k = 1; + if ((l & 4) != 0) // bn == 5 mod 8, make odd for strong tests + { + e = e.shiftRight(1); + k = 2; + } + } + } + else // bn == 1 mod 8, expect 2^((bn-1)/4) == +/-1 mod bn + { + e = e.shiftRight(2); + a = TWO.modPow(e, bn); + if (a.bitLength() == 1) + j = 0; // Re-do strong prime test to base 2 + else + { + a = a.add(ONE); + if (a.compareTo(bn) != 0) + { + debugBI("Fails Euler criterion #3", bn); + return false; // Not prime + } + } + // bnMakeOdd(n) = d * 2^s. Replaces n with d and returns s. + k = e.getLowestSetBit(); + e = e.shiftRight(k); + k += 2; + } + // It's prime! Now go on to confirmation tests + + // Now, e = (bn-1)/2^k is odd. k >= 1, and has a given value with + // probability 2^-k, so its expected value is 2. j = 1 in the usual case + // when the previous test was as good as a strong prime test, but 1/8 of + // the time, j = 0 because the strong prime test to the base 2 needs to + // be re-done. + for (int i = j; i < 7; i++) // try only the first 7 primes + { + a = SMALL_PRIME[i]; + a = a.modPow(e, bn); + if (a.bitLength() == 1) + continue; // Passed this test + + l = k; + while (true) + { +// a = a.add(ONE); +// if (a.compareTo(w) == 0) { // Was result bn-1? + if (a.compareTo(bn_minus_one) == 0) // Was result bn-1? + break; // Prime + + if (--l == 0) // Reached end, not -1? luck? + { + debugBI("Fails Euler criterion #4", bn); + return false; // Failed, not prime + } + // This portion is executed, on average, once +// a = a.subtract(ONE); // Put a back where it was + a = a.modPow(TWO, bn); + if (a.bitLength() == 1) + { + debugBI("Fails Euler criterion #5", bn); + return false; // Failed, not prime + } + } + // It worked (to the base primes[i]) + } + debugBI("Passes Euler criterion", bn); + return true; + } + + public static boolean isProbablePrime(BigInteger w) + { + return isProbablePrime(w, DEFAULT_CERTAINTY); + } + + /** + * Wrapper around {@link BigInteger#isProbablePrime(int)} with few pre-checks. + * + * @param w the integer to test. + * @param certainty the certainty with which to compute the test. + */ + public static boolean isProbablePrime(BigInteger w, int certainty) + { + // Nonnumbers are not prime. + if (w == null) + return false; + + // eliminate trivial cases when w == 0 or 1 + if (w.equals(ZERO) || w.equals(ONE)) + return false; + + // Test if w is a known small prime. + for (int i = 0; i < SMALL_PRIME_COUNT; i++) + if (w.equals(SMALL_PRIME[i])) + { + if (DEBUG && debuglevel > 4) + debug(w.toString(16) + " is a small prime"); + return true; + } + + // Check if it's already a known prime + WeakReference obj = (WeakReference) knownPrimes.get(w); + if (obj != null && w.equals(obj.get())) + { + if (DEBUG && debuglevel > 4) + debug("found in known primes"); + return true; + } + + // trial division with first 1000 primes + if (hasSmallPrimeDivisor(w)) + { + if (DEBUG && debuglevel > 4) + debug(w.toString(16) + " has a small prime divisor. Rejected..."); + return false; + } + +// Euler's criterion. +// if (passEulerCriterion(w)) { +// if (DEBUG && debuglevel > 4) { +// debug(w.toString(16)+" passes Euler's criterion..."); +// } +// } else { +// if (DEBUG && debuglevel > 4) { +// debug(w.toString(16)+" fails Euler's criterion. Rejected..."); +// } +// return false; +// } +// +// if (DEBUG && debuglevel > 4) +// { +// debug(w.toString(16) + " is probable prime. Accepted..."); +// } + + boolean result = w.isProbablePrime(certainty); + if (result && certainty > 0) // store it in the known primes weak hash-map + knownPrimes.put(w, new WeakReference(w)); + + return result; + } + + // helper methods ----------------------------------------------------------- + + private static final void debugBI(String msg, BigInteger bn) + { + if (DEBUG && debuglevel > 4) + debug("*** " + msg + ": 0x" + bn.toString(16)); + } +} diff --git a/libjava/classpath/gnu/java/security/util/Sequence.java b/libjava/classpath/gnu/java/security/util/Sequence.java new file mode 100644 index 00000000000..5edc7942ef9 --- /dev/null +++ b/libjava/classpath/gnu/java/security/util/Sequence.java @@ -0,0 +1,149 @@ +/* Sequence.java -- a sequence of integers. + Copyright (C) 2004, 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.java.security.util; + +import java.util.AbstractList; +import java.util.LinkedList; + +/** + * A monotonic sequence of integers in the finite field 232. + */ +public final class Sequence extends AbstractList +{ + + // Field. + // ------------------------------------------------------------------------ + + private final Integer[] sequence; + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Create a sequence of integers from 0 to end, with an increment + * of 1. If end is less than 0, then the sequence will wrap around + * through all positive integers then negative integers until the end + * value is reached. Naturally, this will result in an enormous object, + * so don't do this. + * + * @param end The ending value. + */ + public Sequence(int end) + { + this(0, end, 1); + } + + /** + * Create a sequence of integers from start to end, with an + * increment of 1. If end is less than start, then the sequence + * will wrap around until the end value is reached. Naturally, this will + * result in an enormous object, so don't do this. + * + * @param start The starting value. + * @param end The ending value. + */ + public Sequence(int start, int end) + { + this(start, end, 1); + } + + /** + * Create a sequence of integers from start to end, with an + * increment of span. If end is less than start, then + * the sequence will wrap around until the end value is reached. Naturally, + * this will result in an enormous object, so don't do this. + * + *

span can be negative, resulting in a decresing sequence. + * + *

If span is 0, then the sequence will contain {start, + * end} if start != end, or just the singleton + * start if start == end. + * + * @param start The starting value. + * @param end The ending value. + * @param span The increment value. + */ + public Sequence(int start, int end, int span) + { + if (span == 0) + { + if (start != end) + { + sequence = new Integer[] { new Integer(start), new Integer(end) }; + } + else + { + sequence = new Integer[] { new Integer(start) }; + } + } + else + { + LinkedList l = new LinkedList(); + for (int i = start; i != end; i += span) + { + l.add(new Integer(i)); + } + l.add(new Integer(end)); + sequence = (Integer[]) l.toArray(new Integer[l.size()]); + } + } + + // Instance methods. + // ------------------------------------------------------------------------ + + public Object get(int index) + { + if (index < 0 || index >= size()) + { + throw new IndexOutOfBoundsException("index=" + index + ", size=" + + size()); + } + return sequence[index]; + } + + public int size() + { + return sequence.length; + } + + public Object[] toArray() + { + return (Object[]) sequence.clone(); + } +} diff --git a/libjava/classpath/gnu/java/security/util/SimpleList.java b/libjava/classpath/gnu/java/security/util/SimpleList.java new file mode 100644 index 00000000000..b2525c4b8e2 --- /dev/null +++ b/libjava/classpath/gnu/java/security/util/SimpleList.java @@ -0,0 +1,171 @@ +/* SimpleList.java -- simple way to make tuples. + Copyright (C) 2004, 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.java.security.util; + +import java.util.AbstractList; +import java.util.Collection; +import java.util.Iterator; + +/** + * A simple way to create immutable n-tuples. This class can be created with + * up to four elements specified via one of the constructors, or with a + * collection of arbitrary size. + */ +public final class SimpleList extends AbstractList +{ + + // Fields. + // ------------------------------------------------------------------------ + + private final Object[] elements; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a singleton list. + * + * @param e1 The first element. + */ + public SimpleList(final Object element) + { + elements = new Object[1]; + elements[0] = element; + } + + /** + * Create an ordered pair (2-tuple). + * + * @param e1 The first element. + * @param e2 The second element. + */ + public SimpleList(final Object e1, final Object e2) + { + elements = new Object[2]; + elements[0] = e1; + elements[1] = e2; + } + + /** + * Create a 3-tuple. + * + * @param e1 The first element. + * @param e2 The second element. + * @param e3 The third element. + */ + public SimpleList(final Object e1, final Object e2, final Object e3) + { + elements = new Object[3]; + elements[0] = e1; + elements[1] = e2; + elements[2] = e3; + } + + /** + * Create a 4-tuple. + * + * @param e1 The first element. + * @param e2 The second element. + * @param e3 The third element. + * @param e4 The fourth element. + */ + public SimpleList(final Object e1, final Object e2, final Object e3, + final Object e4) + { + elements = new Object[4]; + elements[0] = e1; + elements[1] = e2; + elements[2] = e3; + elements[3] = e4; + } + + /** + * Create the empty list. + */ + public SimpleList() + { + elements = null; + } + + /** + * Create an n-tuple of arbitrary size. Even if the supplied collection has + * no natural order, the created n-tuple will have the order that the + * elements are returned by the collection's iterator. + * + * @param c The collection. + */ + public SimpleList(Collection c) + { + elements = new Object[c.size()]; + int i = 0; + for (Iterator it = c.iterator(); it.hasNext() && i < elements.length;) + { + elements[i++] = it.next(); + } + } + + // Instance methods. + // ------------------------------------------------------------------------ + + public int size() + { + if (elements == null) + return 0; + return elements.length; + } + + public Object get(int index) + { + if (elements == null) + { + throw new IndexOutOfBoundsException("list is empty"); + } + if (index < 0 || index >= elements.length) + { + throw new IndexOutOfBoundsException("index=" + index + ", size=" + + size()); + } + return elements[index]; + } + + public String toString() + { + return SimpleList.class.getName() + "(" + size() + ") " + super.toString(); + } +} diff --git a/libjava/classpath/gnu/java/security/util/Util.java b/libjava/classpath/gnu/java/security/util/Util.java new file mode 100644 index 00000000000..53f8e3c2cca --- /dev/null +++ b/libjava/classpath/gnu/java/security/util/Util.java @@ -0,0 +1,692 @@ +/* Util.java -- various utility routines. + Copyright (C) 2001, 2002, 2003, 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.java.security.util; + +import java.math.BigInteger; + +/** + *

A collection of utility methods used throughout this project.

+ * + * @version $Revision: 1.1 $ + */ +public class Util +{ + + // Constants and variables + // ------------------------------------------------------------------------- + + // Hex charset + private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); + + // Base-64 charset + private static final String BASE64_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; + + private static final char[] BASE64_CHARSET = BASE64_CHARS.toCharArray(); + + // Constructor(s) + // ------------------------------------------------------------------------- + + /** Trivial constructor to enforce Singleton pattern. */ + private Util() + { + super(); + } + + // Class methods + // ------------------------------------------------------------------------- + + /** + *

Returns a string of hexadecimal digits from a byte array. Each byte is + * converted to 2 hex symbols; zero(es) included.

+ * + *

This method calls the method with same name and three arguments as:

+ * + *
+   *    toString(ba, 0, ba.length);
+   * 
+ * + * @param ba the byte array to convert. + * @return a string of hexadecimal characters (two for each byte) + * representing the designated input byte array. + */ + public static String toString(byte[] ba) + { + return toString(ba, 0, ba.length); + } + + /** + *

Returns a string of hexadecimal digits from a byte array, starting at + * offset and consisting of length bytes. Each byte + * is converted to 2 hex symbols; zero(es) included.

+ * + * @param ba the byte array to convert. + * @param offset the index from which to start considering the bytes to + * convert. + * @param length the count of bytes, starting from the designated offset to + * convert. + * @return a string of hexadecimal characters (two for each byte) + * representing the designated input byte sub-array. + */ + public static final String toString(byte[] ba, int offset, int length) + { + char[] buf = new char[length * 2]; + for (int i = 0, j = 0, k; i < length;) + { + k = ba[offset + i++]; + buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; + buf[j++] = HEX_DIGITS[k & 0x0F]; + } + return new String(buf); + } + + /** + *

Returns a string of hexadecimal digits from a byte array. Each byte is + * converted to 2 hex symbols; zero(es) included. The argument is + * treated as a large little-endian integer and is returned as a + * large big-endian integer.

+ * + *

This method calls the method with same name and three arguments as:

+ * + *
+   *    toReversedString(ba, 0, ba.length);
+   * 
+ * + * @param ba the byte array to convert. + * @return a string of hexadecimal characters (two for each byte) + * representing the designated input byte array. + */ + public static String toReversedString(byte[] ba) + { + return toReversedString(ba, 0, ba.length); + } + + /** + *

Returns a string of hexadecimal digits from a byte array, starting at + * offset and consisting of length bytes. Each byte + * is converted to 2 hex symbols; zero(es) included.

+ * + *

The byte array is treated as a large little-endian integer, and + * is returned as a large big-endian integer.

+ * + * @param ba the byte array to convert. + * @param offset the index from which to start considering the bytes to + * convert. + * @param length the count of bytes, starting from the designated offset to + * convert. + * @return a string of hexadecimal characters (two for each byte) + * representing the designated input byte sub-array. + */ + public static final String toReversedString(byte[] ba, int offset, int length) + { + char[] buf = new char[length * 2]; + for (int i = offset + length - 1, j = 0, k; i >= offset;) + { + k = ba[offset + i--]; + buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; + buf[j++] = HEX_DIGITS[k & 0x0F]; + } + return new String(buf); + } + + /** + *

Returns a byte array from a string of hexadecimal digits.

+ * + * @param s a string of hexadecimal ASCII characters + * @return the decoded byte array from the input hexadecimal string. + */ + public static byte[] toBytesFromString(String s) + { + int limit = s.length(); + byte[] result = new byte[((limit + 1) / 2)]; + int i = 0, j = 0; + if ((limit % 2) == 1) + { + result[j++] = (byte) fromDigit(s.charAt(i++)); + } + while (i < limit) + { + result[j] = (byte) (fromDigit(s.charAt(i++)) << 4); + result[j++] |= (byte) fromDigit(s.charAt(i++)); + } + return result; + } + + /** + *

Returns a byte array from a string of hexadecimal digits, interpreting + * them as a large big-endian integer and returning it as a large + * little-endian integer.

+ * + * @param s a string of hexadecimal ASCII characters + * @return the decoded byte array from the input hexadecimal string. + */ + public static byte[] toReversedBytesFromString(String s) + { + int limit = s.length(); + byte[] result = new byte[((limit + 1) / 2)]; + int i = 0; + if ((limit % 2) == 1) + { + result[i++] = (byte) fromDigit(s.charAt(--limit)); + } + while (limit > 0) + { + result[i] = (byte) fromDigit(s.charAt(--limit)); + result[i++] |= (byte) (fromDigit(s.charAt(--limit)) << 4); + } + return result; + } + + /** + *

Returns a number from 0 to 15 corresponding + * to the designated hexadecimal digit.

+ * + * @param c a hexadecimal ASCII symbol. + */ + public static int fromDigit(char c) + { + if (c >= '0' && c <= '9') + { + return c - '0'; + } + else if (c >= 'A' && c <= 'F') + { + return c - 'A' + 10; + } + else if (c >= 'a' && c <= 'f') + { + return c - 'a' + 10; + } + else + throw new IllegalArgumentException("Invalid hexadecimal digit: " + c); + } + + /** + *

Returns a string of 8 hexadecimal digits (most significant digit first) + * corresponding to the unsigned integer n.

+ * + * @param n the unsigned integer to convert. + * @return a hexadecimal string 8-character long. + */ + public static String toString(int n) + { + char[] buf = new char[8]; + for (int i = 7; i >= 0; i--) + { + buf[i] = HEX_DIGITS[n & 0x0F]; + n >>>= 4; + } + return new String(buf); + } + + /** + *

Returns a string of hexadecimal digits from an integer array. Each int + * is converted to 4 hex symbols.

+ */ + public static String toString(int[] ia) + { + int length = ia.length; + char[] buf = new char[length * 8]; + for (int i = 0, j = 0, k; i < length; i++) + { + k = ia[i]; + buf[j++] = HEX_DIGITS[(k >>> 28) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 24) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 20) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 16) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 12) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 8) & 0x0F]; + buf[j++] = HEX_DIGITS[(k >>> 4) & 0x0F]; + buf[j++] = HEX_DIGITS[k & 0x0F]; + } + return new String(buf); + } + + /** + *

Returns a string of 16 hexadecimal digits (most significant digit first) + * corresponding to the unsigned long n.

+ * + * @param n the unsigned long to convert. + * @return a hexadecimal string 16-character long. + */ + public static String toString(long n) + { + char[] b = new char[16]; + for (int i = 15; i >= 0; i--) + { + b[i] = HEX_DIGITS[(int) (n & 0x0FL)]; + n >>>= 4; + } + return new String(b); + } + + /** + *

Similar to the toString() method except that the Unicode + * escape character is inserted before every pair of bytes. Useful to + * externalise byte arrays that will be constructed later from such strings; + * eg. s-box values.

+ * + * @throws ArrayIndexOutOfBoundsException if the length is odd. + */ + public static String toUnicodeString(byte[] ba) + { + return toUnicodeString(ba, 0, ba.length); + } + + /** + *

Similar to the toString() method except that the Unicode + * escape character is inserted before every pair of bytes. Useful to + * externalise byte arrays that will be constructed later from such strings; + * eg. s-box values.

+ * + * @throws ArrayIndexOutOfBoundsException if the length is odd. + */ + public static final String toUnicodeString(byte[] ba, int offset, int length) + { + StringBuffer sb = new StringBuffer(); + int i = 0; + int j = 0; + int k; + sb.append('\n').append("\""); + while (i < length) + { + sb.append("\\u"); + + k = ba[offset + i++]; + sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]); + sb.append(HEX_DIGITS[k & 0x0F]); + + k = ba[offset + i++]; + sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]); + sb.append(HEX_DIGITS[k & 0x0F]); + + if ((++j % 8) == 0) + { + sb.append("\"+").append('\n').append("\""); + } + } + sb.append("\"").append('\n'); + return sb.toString(); + } + + /** + *

Similar to the toString() method except that the Unicode + * escape character is inserted before every pair of bytes. Useful to + * externalise integer arrays that will be constructed later from such + * strings; eg. s-box values.

+ * + * @throws ArrayIndexOutOfBoundsException if the length is not a multiple of 4. + */ + public static String toUnicodeString(int[] ia) + { + StringBuffer sb = new StringBuffer(); + int i = 0; + int j = 0; + int k; + sb.append('\n').append("\""); + while (i < ia.length) + { + k = ia[i++]; + sb.append("\\u"); + sb.append(HEX_DIGITS[(k >>> 28) & 0x0F]); + sb.append(HEX_DIGITS[(k >>> 24) & 0x0F]); + sb.append(HEX_DIGITS[(k >>> 20) & 0x0F]); + sb.append(HEX_DIGITS[(k >>> 16) & 0x0F]); + sb.append("\\u"); + sb.append(HEX_DIGITS[(k >>> 12) & 0x0F]); + sb.append(HEX_DIGITS[(k >>> 8) & 0x0F]); + sb.append(HEX_DIGITS[(k >>> 4) & 0x0F]); + sb.append(HEX_DIGITS[k & 0x0F]); + + if ((++j % 4) == 0) + { + sb.append("\"+").append('\n').append("\""); + } + } + sb.append("\"").append('\n'); + return sb.toString(); + } + + public static byte[] toBytesFromUnicode(String s) + { + int limit = s.length() * 2; + byte[] result = new byte[limit]; + char c; + for (int i = 0; i < limit; i++) + { + c = s.charAt(i >>> 1); + result[i] = (byte) (((i & 1) == 0) ? c >>> 8 : c); + } + return result; + } + + /** + *

Dumps a byte array as a string, in a format that is easy to read for + * debugging. The string m is prepended to the start of each + * line.

+ * + *

If offset and length are omitted, the whole + * array is used. If m is omitted, nothing is prepended to each + * line.

+ * + * @param data the byte array to be dumped. + * @param offset the offset within data to start from. + * @param length the number of bytes to dump. + * @param m a string to be prepended to each line. + * @return a string containing the result. + */ + public static String dumpString(byte[] data, int offset, int length, String m) + { + if (data == null) + { + return m + "null\n"; + } + StringBuffer sb = new StringBuffer(length * 3); + if (length > 32) + { + sb.append(m).append("Hexadecimal dump of ").append(length).append( + " bytes...\n"); + } + // each line will list 32 bytes in 4 groups of 8 each + int end = offset + length; + String s; + int l = Integer.toString(length).length(); + if (l < 4) + { + l = 4; + } + for (; offset < end; offset += 32) + { + if (length > 32) + { + s = " " + offset; + sb.append(m).append(s.substring(s.length() - l)).append(": "); + } + int i = 0; + for (; i < 32 && offset + i + 7 < end; i += 8) + { + sb.append(toString(data, offset + i, 8)).append(' '); + } + if (i < 32) + { + for (; i < 32 && offset + i < end; i++) + { + sb.append(byteToString(data[offset + i])); + } + } + sb.append('\n'); + } + return sb.toString(); + } + + public static String dumpString(byte[] data) + { + return (data == null) ? "null\n" : dumpString(data, 0, data.length, ""); + } + + public static String dumpString(byte[] data, String m) + { + return (data == null) ? "null\n" : dumpString(data, 0, data.length, m); + } + + public static String dumpString(byte[] data, int offset, int length) + { + return dumpString(data, offset, length, ""); + } + + /** + *

Returns a string of 2 hexadecimal digits (most significant digit first) + * corresponding to the lowest 8 bits of n.

+ * + * @param n the byte value to convert. + * @return a string of 2 hex characters representing the input. + */ + public static String byteToString(int n) + { + char[] buf = { HEX_DIGITS[(n >>> 4) & 0x0F], HEX_DIGITS[n & 0x0F] }; + return new String(buf); + } + + /** + *

Converts a designated byte array to a Base-64 representation, with the + * exceptions that (a) leading 0-byte(s) are ignored, and (b) the character + * '.' (dot) shall be used instead of "+' (plus).

+ * + *

Used by SASL password file manipulation primitives.

+ * + * @param buffer an arbitrary sequence of bytes to represent in Base-64. + * @return unpadded (without the '=' character(s)) Base-64 representation of + * the input. + */ + public static final String toBase64(byte[] buffer) + { + int len = buffer.length, pos = len % 3; + byte b0 = 0, b1 = 0, b2 = 0; + switch (pos) + { + case 1: + b2 = buffer[0]; + break; + case 2: + b1 = buffer[0]; + b2 = buffer[1]; + break; + } + StringBuffer sb = new StringBuffer(); + int c; + boolean notleading = false; + do + { + c = (b0 & 0xFC) >>> 2; + if (notleading || c != 0) + { + sb.append(BASE64_CHARSET[c]); + notleading = true; + } + c = ((b0 & 0x03) << 4) | ((b1 & 0xF0) >>> 4); + if (notleading || c != 0) + { + sb.append(BASE64_CHARSET[c]); + notleading = true; + } + c = ((b1 & 0x0F) << 2) | ((b2 & 0xC0) >>> 6); + if (notleading || c != 0) + { + sb.append(BASE64_CHARSET[c]); + notleading = true; + } + c = b2 & 0x3F; + if (notleading || c != 0) + { + sb.append(BASE64_CHARSET[c]); + notleading = true; + } + if (pos >= len) + { + break; + } + else + { + try + { + b0 = buffer[pos++]; + b1 = buffer[pos++]; + b2 = buffer[pos++]; + } + catch (ArrayIndexOutOfBoundsException x) + { + break; + } + } + } + while (true); + + if (notleading) + { + return sb.toString(); + } + return "0"; + } + + /** + *

The inverse function of the above.

+ * + *

Converts a string representing the encoding of some bytes in Base-64 + * to their original form.

+ * + * @param str the Base-64 encoded representation of some byte(s). + * @return the bytes represented by the str. + * @throws NumberFormatException if str is null, or + * str contains an illegal Base-64 character. + * @see #toBase64(byte[]) + */ + public static final byte[] fromBase64(String str) + { + int len = str.length(); + if (len == 0) + { + throw new NumberFormatException("Empty string"); + } + byte[] a = new byte[len + 1]; + int i, j; + for (i = 0; i < len; i++) + { + try + { + a[i] = (byte) BASE64_CHARS.indexOf(str.charAt(i)); + } + catch (ArrayIndexOutOfBoundsException x) + { + throw new NumberFormatException("Illegal character at #" + i); + } + } + i = len - 1; + j = len; + try + { + while (true) + { + a[j] = a[i]; + if (--i < 0) + { + break; + } + a[j] |= (a[i] & 0x03) << 6; + j--; + a[j] = (byte) ((a[i] & 0x3C) >>> 2); + if (--i < 0) + { + break; + } + a[j] |= (a[i] & 0x0F) << 4; + j--; + a[j] = (byte) ((a[i] & 0x30) >>> 4); + if (--i < 0) + { + break; + } + a[j] |= (a[i] << 2); + j--; + a[j] = 0; + if (--i < 0) + { + break; + } + } + } + catch (Exception ignored) + { + } + + try + { // ignore leading 0-bytes + while (a[j] == 0) + { + j++; + } + } + catch (Exception x) + { + return new byte[1]; // one 0-byte + } + byte[] result = new byte[len - j + 1]; + System.arraycopy(a, j, result, 0, len - j + 1); + return result; + } + + // BigInteger utilities ---------------------------------------------------- + + /** + *

Treats the input as the MSB representation of a number, and discards + * leading zero elements. For efficiency, the input is simply returned if no + * leading zeroes are found.

+ * + * @param n the {@link BigInteger} to trim. + * @return the byte array representation of the designated {@link BigInteger} + * with no leading 0-bytes. + */ + public static final byte[] trim(BigInteger n) + { + byte[] in = n.toByteArray(); + if (in.length == 0 || in[0] != 0) + { + return in; + } + int len = in.length; + int i = 1; + while (in[i] == 0 && i < len) + { + ++i; + } + byte[] result = new byte[len - i]; + System.arraycopy(in, i, result, 0, len - i); + return result; + } + + /** + *

Returns a hexadecimal dump of the trimmed bytes of a {@link BigInteger}. + *

+ * + * @param x the {@link BigInteger} to display. + * @return the string representation of the designated {@link BigInteger}. + */ + public static final String dump(BigInteger x) + { + return dumpString(trim(x)); + } +} -- cgit v1.2.3