[4.2] Patch: FYI: java.security update
Tom Tromey
tromey@redhat.com
Thu Jan 25 00:12:00 GMT 2007
I'm checking this in on the 4.2 branch.
Marco asked me to put this in. This fixes a few java.security bugs.
Marco, thanks for preparing this.
These fixes are all in Classpath and svn trunk already.
Tom
Index: ChangeLog
from Marco Trudel <mtrudel@gmx.ch>
* java/security/Security.java
Imported the version from GNU classpath 0.92 (kept GCJ differences).
* classpath/gnu/javax/crypto/pad/PKCS7.java (unpad): Removed an
unnecessary test.
* classpath/javax/crypto/CipherOutputStream.java: Re-implemented.
* classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java
(engineUpdate(byte[], int, int)): Always keep data for unpadding
in padded decryption mode and check if it is a complete block.
(engineUpdate(byte[], int, int, byte[], int)): Likewise.
(engineDoFinal(byte[], int, int)): In padded decryption mode, take
partially processed data into account.
Index: java/security/Security.java
===================================================================
--- java/security/Security.java (revision 121089)
+++ java/security/Security.java (working copy)
@@ -61,7 +61,7 @@
/**
* This class centralizes all security properties and common security methods.
- * One of its primary uses is to manage providers.
+ * One of its primary uses is to manage security providers.
*
* @author Mark Benvenuto (ivymccough@worldnet.att.net)
*/
@@ -102,7 +102,12 @@
System.err.println
(" Falling back to standard GNU security provider");
}
+ // Note that this matches our classpath.security file.
providers.addElement (new gnu.java.security.provider.Gnu());
+ providers.addElement(new gnu.javax.crypto.jce.GnuCrypto());
+ providers.addElement(new gnu.javax.crypto.jce.GnuSasl());
+ providers.addElement(new gnu.javax.net.ssl.provider.Jessie());
+ providers.addElement(new gnu.javax.security.auth.callback.GnuCallbacks());
}
}
// This class can't be instantiated.
@@ -111,9 +116,9 @@
}
/**
- * Tries to load the vender specific security providers from the given
- * base URL. Returns true if the resource could be read and completely
- * parsed successfully, false otherwise.
+ * Tries to load the vender specific security providers from the given base
+ * URL. Returns true if the resource could be read and completely parsed
+ * successfully, false otherwise.
*/
private static boolean loadProviders(String baseUrl, String vendor)
{
@@ -134,7 +139,8 @@
Exception exception = null;
try
{
- providers.addElement(Class.forName(name).newInstance());
+ ClassLoader sys = ClassLoader.getSystemClassLoader();
+ providers.addElement(Class.forName(name, true, sys).newInstance());
}
catch (ClassNotFoundException x)
{
@@ -167,22 +173,18 @@
}
/**
- * Gets a specified property for an algorithm. The algorithm name should be a
- * standard name. See Appendix A in the Java Cryptography Architecture API
- * Specification & Reference for information about standard algorithm
- * names. One possible use is by specialized algorithm parsers, which may map
- * classes to algorithms which they understand (much like {@link Key} parsers
- * do).
- *
- * @param algName the algorithm name.
- * @param propName the name of the property to get.
- * @return the value of the specified property.
- * @deprecated This method used to return the value of a proprietary property
- * in the master file of the "SUN" Cryptographic Service Provider in order to
- * determine how to parse algorithm-specific parameters. Use the new
- * provider-based and algorithm-independent {@link AlgorithmParameters} and
- * {@link KeyFactory} engine classes (introduced in the Java 2 platform)
- * instead.
+ * Returns the value associated to a designated property name for a given
+ * algorithm.
+ *
+ * @param algName
+ * the algorithm name.
+ * @param propName
+ * the name of the property to return.
+ * @return the value of the specified property or <code>null</code> if none
+ * found.
+ * @deprecated Use the provider-based and algorithm-independent
+ * {@link AlgorithmParameters} and {@link KeyFactory} engine
+ * classes instead.
*/
public static String getAlgorithmProperty(String algName, String propName)
{
@@ -205,37 +207,21 @@
}
/**
- * <p>Adds a new provider, at a specified position. The position is the
- * preference order in which providers are searched for requested algorithms.
- * Note that it is not guaranteed that this preference will be respected. The
- * position is 1-based, that is, <code>1</code> is most preferred, followed by
- * <code>2</code>, and so on.</p>
- *
- * <p>If the given provider is installed at the requested position, the
- * provider that used to be at that position, and all providers with a
- * position greater than position, are shifted up one position (towards the
- * end of the list of installed providers).</p>
- *
- * <p>A provider cannot be added if it is already installed.</p>
- *
- * <p>First, if there is a security manager, its <code>checkSecurityAccess()
- * </code> method is called with the string <code>"insertProvider."+provider.
- * getName()</code> to see if it's ok to add a new provider. If the default
- * implementation of <code>checkSecurityAccess()</code> is used (i.e., that
- * method is not overriden), then this will result in a call to the security
- * manager's <code>checkPermission()</code> method with a
- * <code>SecurityPermission("insertProvider."+provider.getName())</code>
- * permission.</p>
- *
- * @param provider the provider to be added.
- * @param position the preference position that the caller would like for
- * this provider.
- * @return the actual preference position in which the provider was added, or
- * <code>-1</code> if the provider was not added because it is already
- * installed.
- * @throws SecurityException if a security manager exists and its
- * {@link SecurityManager#checkSecurityAccess(String)} method denies access
- * to add a new provider.
+ * Inserts a new designated {@link Provider} at a designated (1-based)
+ * position in the current list of installed {@link Provider}s,
+ *
+ * @param provider
+ * the new {@link Provider} to add.
+ * @param position
+ * the position (starting from 1) of where to install
+ * <code>provider</code>.
+ * @return the actual position, in the list of installed Providers. Returns
+ * <code>-1</code> if <code>provider</code> was laready in the
+ * list. The actual position may be different than the desired
+ * <code>position</code>.
+ * @throws SecurityException
+ * if a {@link SecurityManager} is installed and it disallows this
+ * operation.
* @see #getProvider(String)
* @see #removeProvider(String)
* @see SecurityPermission
@@ -265,24 +251,17 @@
}
/**
- * <p>Adds a provider to the next position available.</p>
- *
- * <p>First, if there is a security manager, its <code>checkSecurityAccess()
- * </code> method is called with the string <code>"insertProvider."+provider.
- * getName()</code> to see if it's ok to add a new provider. If the default
- * implementation of <code>checkSecurityAccess()</code> is used (i.e., that
- * method is not overriden), then this will result in a call to the security
- * manager's <code>checkPermission()</code> method with a
- * <code>SecurityPermission("insertProvider."+provider.getName())</code>
- * permission.</p>
- *
- * @param provider the provider to be added.
- * @return the preference position in which the provider was added, or
- * <code>-1</code> if the provider was not added because it is already
- * installed.
- * @throws SecurityException if a security manager exists and its
- * {@link SecurityManager#checkSecurityAccess(String)} method denies access
- * to add a new provider.
+ * Appends the designated new {@link Provider} to the current list of
+ * installed {@link Provider}s.
+ *
+ * @param provider
+ * the new {@link Provider} to append.
+ * @return the position (starting from 1) of <code>provider</code> in the
+ * current list of {@link Provider}s, or <code>-1</code> if
+ * <code>provider</code> was already there.
+ * @throws SecurityException
+ * if a {@link SecurityManager} is installed and it disallows this
+ * operation.
* @see #getProvider(String)
* @see #removeProvider(String)
* @see SecurityPermission
@@ -293,26 +272,14 @@
}
/**
- * <p>Removes the provider with the specified name.</p>
- *
- * <p>When the specified provider is removed, all providers located at a
- * position greater than where the specified provider was are shifted down
- * one position (towards the head of the list of installed providers).</p>
- *
- * <p>This method returns silently if the provider is not installed.</p>
- *
- * <p>First, if there is a security manager, its <code>checkSecurityAccess()
- * </code> method is called with the string <code>"removeProvider."+name</code>
- * to see if it's ok to remove the provider. If the default implementation of
- * <code>checkSecurityAccess()</code> is used (i.e., that method is not
- * overriden), then this will result in a call to the security manager's
- * <code>checkPermission()</code> method with a <code>SecurityPermission(
- * "removeProvider."+name)</code> permission.</p>
- *
- * @param name the name of the provider to remove.
- * @throws SecurityException if a security manager exists and its
- * {@link SecurityManager#checkSecurityAccess(String)} method denies access
- * to remove the provider.
+ * Removes an already installed {@link Provider}, given its name, from the
+ * current list of installed {@link Provider}s.
+ *
+ * @param name
+ * the name of an already installed {@link Provider} to remove.
+ * @throws SecurityException
+ * if a {@link SecurityManager} is installed and it disallows this
+ * operation.
* @see #getProvider(String)
* @see #addProvider(Provider)
*/
@@ -334,9 +301,9 @@
}
/**
- * Returns an array containing all the installed providers. The order of the
- * providers in the array is their preference order.
- *
+ * Returns the current list of installed {@link Provider}s as an array
+ * ordered according to their installation preference order.
+ *
* @return an array of all the installed providers.
*/
public static Provider[] getProviders()
@@ -347,11 +314,13 @@
}
/**
- * Returns the provider installed with the specified name, if any. Returns
- * <code>null</code> if no provider with the specified name is installed.
- *
- * @param name the name of the provider to get.
- * @return the provider of the specified name.
+ * Returns an already installed {@link Provider} given its name.
+ *
+ * @param name
+ * the name of an already installed {@link Provider}.
+ * @return the {@link Provider} known by <code>name</code>. Returns
+ * <code>null</code> if the current list of {@link Provider}s does
+ * not include one named <code>name</code>.
* @see #removeProvider(String)
* @see #addProvider(Provider)
*/
@@ -377,18 +346,16 @@
}
/**
- * <p>Gets a security property value.</p>
- *
- * <p>First, if there is a security manager, its <code>checkPermission()</code>
- * method is called with a <code>SecurityPermission("getProperty."+key)</code>
- * permission to see if it's ok to retrieve the specified security property
- * value.</p>
- *
- * @param key the key of the property being retrieved.
- * @return the value of the security property corresponding to key.
- * @throws SecurityException if a security manager exists and its
- * {@link SecurityManager#checkPermission(Permission)} method denies access
- * to retrieve the specified security property value.
+ * Returns the value associated with a Security propery.
+ *
+ * @param key
+ * the key of the property to fetch.
+ * @return the value of the Security property associated with
+ * <code>key</code>. Returns <code>null</code> if no such property
+ * was found.
+ * @throws SecurityException
+ * if a {@link SecurityManager} is installed and it disallows this
+ * operation.
* @see #setProperty(String, String)
* @see SecurityPermission
*/
@@ -407,18 +374,15 @@
}
/**
- * <p>Sets a security property value.</p>
- *
- * <p>First, if there is a security manager, its <code>checkPermission()</code>
- * method is called with a <code>SecurityPermission("setProperty."+key)</code>
- * permission to see if it's ok to set the specified security property value.
- * </p>
- *
- * @param key the name of the property to be set.
- * @param datum the value of the property to be set.
- * @throws SecurityException if a security manager exists and its
- * {@link SecurityManager#checkPermission(Permission)} method denies access
- * to set the specified security property value.
+ * Sets or changes a designated Security property to a designated value.
+ *
+ * @param key
+ * the name of the property to set.
+ * @param datum
+ * the new value of the property.
+ * @throws SecurityException
+ * if a {@link SecurityManager} is installed and it disallows this
+ * operation.
* @see #getProperty(String)
* @see SecurityPermission
*/
@@ -435,19 +399,16 @@
}
/**
- * Returns a Set of Strings containing the names of all available algorithms
- * or types for the specified Java cryptographic service (e.g., Signature,
- * MessageDigest, Cipher, Mac, KeyStore). Returns an empty Set if there is no
- * provider that supports the specified service. For a complete list of Java
- * cryptographic services, please see the Java Cryptography Architecture API
- * Specification & Reference. Note: the returned set is immutable.
- *
- * @param serviceName the name of the Java cryptographic service (e.g.,
- * Signature, MessageDigest, Cipher, Mac, KeyStore). Note: this parameter is
- * case-insensitive.
- * @return a Set of Strings containing the names of all available algorithms
- * or types for the specified Java cryptographic service or an empty set if
- * no provider supports the specified service.
+ * For a given <i>service</i> (e.g. Signature, MessageDigest, etc...) this
+ * method returns the {@link Set} of all available algorithm names (instances
+ * of {@link String}, from all currently installed {@link Provider}s.
+ *
+ * @param serviceName
+ * the case-insensitive name of a service (e.g. Signature,
+ * MessageDigest, etc).
+ * @return a {@link Set} of {@link String}s containing the names of all
+ * algorithm names provided by all of the currently installed
+ * {@link Provider}s.
* @since 1.4
*/
public static Set getAlgorithms(String serviceName)
@@ -480,53 +441,48 @@
}
/**
- * <p>Returns an array containing all installed providers that satisfy the
- * specified selection criterion, or <code>null</code> if no such providers
- * have been installed. The returned providers are ordered according to their
- * preference order.</p>
- *
- * <p>A cryptographic service is always associated with a particular
- * algorithm or type. For example, a digital signature service is always
- * associated with a particular algorithm (e.g., <i>DSA</i>), and a
- * CertificateFactory service is always associated with a particular
- * certificate type (e.g., <i>X.509</i>).</p>
- *
- * <p>The selection criterion must be specified in one of the following two
- * formats:</p>
- *
+ * Returns an array of currently installed {@link Provider}s, ordered
+ * according to their installation preference order, which satisfy a given
+ * <i>selection</i> criterion.
+ *
+ * <p>This implementation recognizes a <i>selection</i> criterion written in
+ * one of two following forms:</p>
+ *
* <ul>
- * <li><p><crypto_service>.<algorithm_or_type></p>
- * <p>The cryptographic service name must not contain any dots.</p>
- * <p>A provider satisfies the specified selection criterion iff the
- * provider implements the specified algorithm or type for the specified
- * cryptographic service.</p>
- * <p>For example, "CertificateFactory.X.509" would be satisfied by any
- * provider that supplied a CertificateFactory implementation for X.509
- * certificates.</p></li>
- *
- * <li><p><crypto_service>.<algorithm_or_type> <attribute_name>:<attribute_value></p>
- * <p>The cryptographic service name must not contain any dots. There must
- * be one or more space charaters between the the <algorithm_or_type>
- * and the <attribute_name>.</p>
- * <p>A provider satisfies this selection criterion iff the provider
- * implements the specified algorithm or type for the specified
- * cryptographic service and its implementation meets the constraint
- * expressed by the specified attribute name/value pair.</p>
- * <p>For example, "Signature.SHA1withDSA KeySize:1024" would be satisfied
- * by any provider that implemented the SHA1withDSA signature algorithm
- * with a keysize of 1024 (or larger).</p></li>
+ * <li><crypto_service>.<algorithm_or_type>: Where
+ * <i>crypto_service</i> is a case-insensitive string, similar to what has
+ * been described in the {@link #getAlgorithms(String)} method, and
+ * <i>algorithm_or_type</i> is a known case-insensitive name of an
+ * Algorithm, or one of its aliases.
+ *
+ * <p>For example, "CertificateFactory.X.509" would return all the installed
+ * {@link Provider}s which provide a <i>CertificateFactory</i>
+ * implementation of <i>X.509</i>.</p></li>
+ *
+ * <li><crypto_service>.<algorithm_or_type> <attribute_name>:<value>:
+ * Where <i>crypto_service</i> is a case-insensitive string, similar to what
+ * has been described in the {@link #getAlgorithms(String)} method,
+ * <i>algorithm_or_type</i> is a case-insensitive known name of an Algorithm
+ * or one of its aliases, <i>attribute_name</i> is a case-insensitive
+ * property name with no whitespace characters, and no dots, in-between, and
+ * <i>value</i> is a {@link String} with no whitespace characters in-between.
+ *
+ * <p>For example, "Signature.Sha1WithDSS KeySize:1024" would return all the
+ * installed {@link Provider}s which declared their ability to provide
+ * <i>Signature</i> services, using the <i>Sha1WithDSS</i> algorithm with
+ * key sizes of <i>1024</i>.</p></li>
* </ul>
- *
- * <p>See Appendix A in the Java Cryptogaphy Architecture API Specification
- * & Reference for information about standard cryptographic service names,
- * standard algorithm names and standard attribute names.</p>
- *
- * @param filter the criterion for selecting providers. The filter is case-
- * insensitive.
- * @return all the installed providers that satisfy the selection criterion,
- * or null if no such providers have been installed.
- * @throws InvalidParameterException if the filter is not in the required
- * format.
+ *
+ * @param filter
+ * the <i>selection</i> criterion for selecting among the installed
+ * {@link Provider}s.
+ * @return all the installed {@link Provider}s which satisfy the <i>selection</i>
+ * criterion. Returns <code>null</code> if no installed
+ * {@link Provider}s were found which satisfy the <i>selection</i>
+ * criterion. Returns ALL installed {@link Provider}s if
+ * <code>filter</code> is <code>null</code> or is an empty string.
+ * @throws InvalidParameterException
+ * if an exception occurs while parsing the <code>filter</code>.
* @see #getProviders(Map)
*/
public static Provider[] getProviders(String filter)
@@ -547,48 +503,47 @@
return getProviders(map);
}
- /**
- * <p>Returns an array containing all installed providers that satisfy the
- * specified selection criteria, or <code>null</code> if no such providers
- * have been installed. The returned providers are ordered according to their
- * preference order.</p>
- *
- * <p>The selection criteria are represented by a map. Each map entry
- * represents a selection criterion. A provider is selected iff it satisfies
- * all selection criteria. The key for any entry in such a map must be in one
- * of the following two formats:</p>
- *
- * <ul>
- * <li><p><crypto_service>.<algorithm_or_type></p>
- * <p>The cryptographic service name must not contain any dots.</p>
- * <p>The value associated with the key must be an empty string.</p>
- * <p>A provider satisfies this selection criterion iff the provider
- * implements the specified algorithm or type for the specified
- * cryptographic service.</p></li>
- *
- * <li><p><crypto_service>.<algorithm_or_type> <attribute_name></p>
- * <p>The cryptographic service name must not contain any dots. There must
- * be one or more space charaters between the <algorithm_or_type> and
- * the <attribute_name>.</p>
- * <p>The value associated with the key must be a non-empty string. A
- * provider satisfies this selection criterion iff the provider implements
- * the specified algorithm or type for the specified cryptographic service
- * and its implementation meets the constraint expressed by the specified
- * attribute name/value pair.</p></li>
- * </ul>
- *
- * <p>See Appendix A in the Java Cryptogaphy Architecture API Specification
- * & Reference for information about standard cryptographic service names,
- * standard algorithm names and standard attribute names.</p>
- *
- * @param filter the criteria for selecting providers. The filter is case-
- * insensitive.
- * @return all the installed providers that satisfy the selection criteria,
- * or <code>null</code> if no such providers have been installed.
- * @throws InvalidParameterException if the filter is not in the required
- * format.
- * @see #getProviders(String)
- */
+ /**
+ * Returns an array of currently installed {@link Provider}s which satisfy a
+ * set of <i>selection</i> criteria.
+ *
+ * <p>The <i>selection</i> criteria are defined in a {@link Map} where each
+ * element specifies a <i>selection</i> querry. The <i>Keys</i> in this
+ * {@link Map} must be in one of the two following forms:</p>
+ *
+ * <ul>
+ * <li><crypto_service>.<algorithm_or_type>: Where
+ * <i>crypto_service</i> is a case-insensitive string, similar to what has
+ * been described in the {@link #getAlgorithms(String)} method, and
+ * <i>algorithm_or_type</i> is a case-insensitive known name of an
+ * Algorithm, or one of its aliases. The <i>value</i> of the entry in the
+ * {@link Map} for such a <i>Key</i> MUST be the empty string.
+ * {@link Provider}s which provide an implementation for the designated
+ * <i>service algorithm</i> are included in the result.</li>
+ *
+ * <li><crypto_service>.<algorithm_or_type> <attribute_name>:
+ * Where <i>crypto_service</i> is a case-insensitive string, similar to what
+ * has been described in the {@link #getAlgorithms(String)} method,
+ * <i>algorithm_or_type</i> is a case-insensitive known name of an Algorithm
+ * or one of its aliases, and <i>attribute_name</i> is a case-insensitive
+ * property name with no whitespace characters, and no dots, in-between. The
+ * <i>value</i> of the entry in this {@link Map} for such a <i>Key</i> MUST
+ * NOT be <code>null</code> or an empty string. {@link Provider}s which
+ * declare the designated <i>attribute_name</i> and <i>value</i> for the
+ * designated <i>service algorithm</i> are included in the result.</li>
+ * </ul>
+ *
+ * @param filter
+ * a {@link Map} of <i>selection querries</i>.
+ * @return all currently installed {@link Provider}s which satisfy ALL the
+ * <i>selection</i> criteria defined in <code>filter</code>.
+ * Returns ALL installed {@link Provider}s if <code>filter</code>
+ * is <code>null</code> or empty.
+ * @throws InvalidParameterException
+ * if an exception is encountered while parsing the syntax of the
+ * {@link Map}'s <i>keys</i>.
+ * @see #getProviders(String)
+ */
public static Provider[] getProviders(Map filter)
{
if (providers == null || providers.isEmpty())
Index: classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java
===================================================================
--- classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java (revision 121089)
+++ classpath/gnu/javax/crypto/jce/cipher/CipherAdapter.java (working copy)
@@ -373,14 +373,24 @@
engineInit(opmode, key, spec, random);
}
- protected byte[] engineUpdate(byte[] input, int off, int len)
+ protected byte[] engineUpdate(byte[] input, int inOff, int inLen)
{
+ if (inLen == 0) // nothing to process
+ return new byte[0];
final int blockSize = mode.currentBlockSize();
- final int count = (partLen + len) / blockSize;
- final byte[] out = new byte[count * blockSize];
+ int blockCount = (partLen + inLen) / blockSize;
+
+ // always keep data for unpadding in padded decryption mode;
+ // might even be a complete block
+ if (pad != null
+ && ((Integer) attributes.get(IMode.STATE)).intValue() == IMode.DECRYPTION
+ && (partLen + inLen) % blockSize == 0)
+ blockCount--;
+
+ final byte[] out = new byte[blockCount * blockSize];
try
{
- engineUpdate(input, off, len, out, 0);
+ engineUpdate(input, inOff, inLen, out, 0);
}
catch (ShortBufferException x) // should not happen
{
@@ -395,7 +405,15 @@
if (inLen == 0) // nothing to process
return 0;
final int blockSize = mode.currentBlockSize();
- final int blockCount = (partLen + inLen) / blockSize;
+ int blockCount = (partLen + inLen) / blockSize;
+
+ // always keep data for unpadding in padded decryption mode;
+ // might even be a complete block
+ if (pad != null
+ && ((Integer) attributes.get(IMode.STATE)).intValue() == IMode.DECRYPTION
+ && (partLen + inLen) % blockSize == 0)
+ blockCount--;
+
final int result = blockCount * blockSize;
if (result > out.length - outOff)
throw new ShortBufferException();
@@ -447,16 +465,21 @@
break;
case IMode.DECRYPTION:
int padLen;
+ byte[] buf3 = new byte[buf.length + partLen];
try
{
- padLen = pad.unpad(buf, 0, buf.length);
+ if (partLen != mode.currentBlockSize())
+ throw new WrongPaddingException();
+ System.arraycopy(buf, 0, buf3, 0, buf.length);
+ mode.update(partBlock, 0, buf3, buf.length);
+ padLen = pad.unpad(buf3, 0, buf3.length);
}
catch (WrongPaddingException wpe)
{
throw new BadPaddingException(wpe.getMessage());
}
- result = new byte[buf.length - padLen];
- System.arraycopy(buf, 0, result, 0, result.length);
+ result = new byte[buf3.length - padLen];
+ System.arraycopy(buf3, 0, result, 0, result.length);
break;
default:
throw new IllegalStateException();
Index: classpath/gnu/javax/crypto/pad/PKCS7.java
===================================================================
--- classpath/gnu/javax/crypto/pad/PKCS7.java (revision 121089)
+++ classpath/gnu/javax/crypto/pad/PKCS7.java (working copy)
@@ -100,8 +100,8 @@
throws WrongPaddingException
{
int limit = offset + length;
- int result = in[limit - 1] & 0xFF;
- for (int i = 0; i < result; i++)
+ int result = in[--limit] & 0xFF;
+ for (int i = 0; i < result - 1; i++)
if (result != (in[--limit] & 0xFF))
throw new WrongPaddingException();
if (Configuration.DEBUG)
Index: classpath/javax/crypto/CipherOutputStream.java
===================================================================
--- classpath/javax/crypto/CipherOutputStream.java (revision 121089)
+++ classpath/javax/crypto/CipherOutputStream.java (working copy)
@@ -50,54 +50,20 @@
*/
public class CipherOutputStream extends FilterOutputStream
{
-
- // Fields.
- // ------------------------------------------------------------------------
-
/** The underlying cipher. */
private Cipher cipher;
- private byte[][] inBuffer;
-
- private int inLength;
-
- private byte[] outBuffer;
-
- private static final int FIRST_TIME = 0;
- private static final int SECOND_TIME = 1;
- private static final int SEASONED = 2;
- private int state;
-
- /** True if the cipher is a stream cipher (blockSize == 1) */
- private boolean isStream;
-
- // Constructors.
- // ------------------------------------------------------------------------
-
/**
- * Create a new cipher output stream. The cipher argument must have
- * already been initialized.
+ * Create a new cipher output stream. The cipher argument must have already
+ * been initialized.
*
- * @param out The sink for transformed data.
+ * @param out The sink for transformed data.
* @param cipher The cipher to transform data with.
*/
public CipherOutputStream(OutputStream out, Cipher cipher)
{
super(out);
- if (cipher != null)
- {
- this.cipher = cipher;
- if (!(isStream = cipher.getBlockSize() == 1))
- {
- inBuffer = new byte[2][];
- inBuffer[0] = new byte[cipher.getBlockSize()];
- inBuffer[1] = new byte[cipher.getBlockSize()];
- inLength = 0;
- state = FIRST_TIME;
- }
- }
- else
- this.cipher = new NullCipher();
+ this.cipher = (cipher != null) ? cipher : new NullCipher();
}
/**
@@ -110,52 +76,36 @@
super(out);
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Close this output stream, and the sink output stream.
+ * <p>
+ * This method will first invoke the {@link Cipher#doFinal()} method of the
+ * underlying {@link Cipher}, and writes the output of that method to the
+ * sink output stream.
*
- * <p>This method will first invoke the {@link Cipher#doFinal()}
- * method of the underlying {@link Cipher}, and writes the output of
- * that method to the sink output stream.
- *
- * @throws java.io.IOException If an I/O error occurs, or if an error
- * is caused by finalizing the transformation.
+ * @throws IOException If an I/O error occurs, or if an error is caused by
+ * finalizing the transformation.
*/
public void close() throws IOException
{
try
{
- int len;
- if (state != FIRST_TIME)
- {
- len = cipher.update(inBuffer[0], 0, inBuffer[0].length, outBuffer);
- out.write(outBuffer, 0, len);
- }
- len = cipher.doFinal(inBuffer[0], 0, inLength, outBuffer);
- out.write(outBuffer, 0, len);
+ out.write(cipher.doFinal());
+ out.flush();
+ out.close();
}
- catch (javax.crypto.IllegalBlockSizeException ibse)
+ catch (Exception cause)
{
- throw new IOException(ibse.toString());
+ IOException ioex = new IOException(String.valueOf(cause));
+ ioex.initCause(cause);
+ throw ioex;
}
- catch (javax.crypto.BadPaddingException bpe)
- {
- throw new IOException(bpe.toString());
- }
- catch (ShortBufferException sbe)
- {
- throw new IOException(sbe.toString());
- }
- out.flush();
- out.close();
}
/**
* Flush any pending output.
*
- * @throws java.io.IOException If an I/O error occurs.
+ * @throws IOException If an I/O error occurs.
*/
public void flush() throws IOException
{
@@ -166,38 +116,20 @@
* Write a single byte to the output stream.
*
* @param b The next byte.
- * @throws java.io.IOException If an I/O error occurs, or if the
- * underlying cipher is not in the correct state to transform
- * data.
+ * @throws IOException If an I/O error occurs, or if the underlying cipher is
+ * not in the correct state to transform data.
*/
public void write(int b) throws IOException
{
- if (isStream)
- {
- byte[] buf = new byte[] { (byte) b };
- try
- {
- cipher.update(buf, 0, 1, buf, 0);
- }
- catch (ShortBufferException sbe)
- {
- throw new IOException(sbe.toString());
- }
- out.write(buf);
- return;
- }
- inBuffer[1][inLength++] = (byte) b;
- if (inLength == inBuffer[1].length)
- process();
+ write(new byte[] { (byte) b }, 0, 1);
}
/**
* Write a byte array to the output stream.
*
* @param buf The next bytes.
- * @throws java.io.IOException If an I/O error occurs, or if the
- * underlying cipher is not in the correct state to transform
- * data.
+ * @throws IOException If an I/O error occurs, or if the underlying cipher is
+ * not in the correct state to transform data.
*/
public void write(byte[] buf) throws IOException
{
@@ -210,59 +142,11 @@
* @param buf The next bytes.
* @param off The offset in the byte array to start.
* @param len The number of bytes to write.
- * @throws java.io.IOException If an I/O error occurs, or if the
- * underlying cipher is not in the correct state to transform
- * data.
+ * @throws IOException If an I/O error occurs, or if the underlying cipher is
+ * not in the correct state to transform data.
*/
public void write(byte[] buf, int off, int len) throws IOException
{
- if (isStream)
- {
- out.write(cipher.update(buf, off, len));
- return;
- }
- int count = 0;
- while (count < len)
- {
- int l = Math.min(inBuffer[1].length - inLength, len - count);
- System.arraycopy(buf, off+count, inBuffer[1], inLength, l);
- count += l;
- inLength += l;
- if (inLength == inBuffer[1].length)
- process();
- }
+ out.write(cipher.update(buf, off, len));
}
-
- // Own method.
- // -------------------------------------------------------------------------
-
- private void process() throws IOException
- {
- if (state == SECOND_TIME)
- {
- state = SEASONED;
- }
- else
- {
- byte[] temp = inBuffer[0];
- inBuffer[0] = inBuffer[1];
- inBuffer[1] = temp;
- }
- if (state == FIRST_TIME)
- {
- inLength = 0;
- state = SECOND_TIME;
- return;
- }
- try
- {
- cipher.update(inBuffer[0], 0, inBuffer[0].length, outBuffer);
- }
- catch (ShortBufferException sbe)
- {
- throw new IOException(sbe.toString());
- }
- out.write(outBuffer);
- inLength = 0;
- }
}
More information about the Java-patches
mailing list