Add spongy castle sources to libraries folder

This commit is contained in:
Dominik Schürmann
2014-01-27 14:00:22 +01:00
parent 8ca42b9bf9
commit 5aec25ac05
4258 changed files with 848014 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
package javax.crypto;
import java.security.GeneralSecurityException;
/**
* This exception is thrown when a particular padding mechanism is
* expected for the input data but the data is not padded properly
*
*/
public class BadPaddingException
extends GeneralSecurityException
{
private static final long serialVersionUID = -5315033893984728443L;
/**
* Constructs a BadPaddingException with no detail
* message. A detail message is a String that describes this
* particular exception.
*/
public BadPaddingException()
{
}
/**
* Constructs a BadPaddingException with the specified
* detail message. A detail message is a String that describes
* this particular exception, which may, for example, specify which
* algorithm is not available.
*
* @param msg the detail message.
*/
public BadPaddingException(
String msg)
{
super(msg);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,349 @@
package javax.crypto;
import java.io.InputStream;
import java.io.IOException;
import java.io.FilterInputStream;
/**
* A CipherInputStream is composed of an InputStream and a Cipher so
* that read() methods return data that are read in from the
* underlying InputStream but have been additionally processed by the
* Cipher. The Cipher must be fully initialized before being used by
* a CipherInputStream.
* <p>
* For example, if the Cipher is initialized for decryption, the
* CipherInputStream will attempt to read in data and decrypt them,
* before returning the decrypted data.
* <p>
* This class adheres strictly to the semantics, especially the
* failure semantics, of its ancestor classes
* java.io.FilterInputStream and java.io.InputStream. This class has
* exactly those methods specified in its ancestor classes, and
* overrides them all. Moreover, this class catches all exceptions
* that are not thrown by its ancestor classes. In particular, the
* <code>skip</code> method skips, and the <code>available</code>
* method counts only data that have been processed by the encapsulated Cipher.
* <p>
* It is crucial for a programmer using this class not to use
* methods that are not defined or overriden in this class (such as a
* new method or constructor that is later added to one of the super
* classes), because the design and implementation of those methods
* are unlikely to have considered security impact with regard to
* CipherInputStream.
*
* @since JCE1.2
* @see InputStream
* @see FilterInputStream
* @see Cipher
* @see CipherOutputStream
*/
public class CipherInputStream
extends FilterInputStream
{
private Cipher c;
private byte[] buf;
private byte[] inBuf;
private int bufOff;
private int maxBuf;
private boolean finalized;
private static final int INPUT_BUF_SIZE = 2048;
/**
* Constructs a CipherInputStream from an InputStream and a
* Cipher.
*/
public CipherInputStream(
InputStream is,
Cipher c)
{
super(is);
this.c = c;
buf = new byte[c.getOutputSize(INPUT_BUF_SIZE)];
inBuf = new byte[INPUT_BUF_SIZE];
}
/**
* Constructs a CipherInputStream from an InputStream without
* specifying a Cipher. This has the effect of constructing a
* CipherInputStream using a NullCipher.
*/
protected CipherInputStream(
InputStream is)
{
this(is, new NullCipher());
}
/**
* grab the next chunk of input from the underlying input stream
*/
private int nextChunk()
throws IOException
{
int available = super.available();
// must always try to read 1 byte!
// some buggy InputStreams return < 0!
if (available <= 0)
{
available = 1;
}
if (available > inBuf.length)
{
available = super.read(inBuf, 0, inBuf.length);
}
else
{
available = super.read(inBuf, 0, available);
}
if (available < 0)
{
if (finalized)
{
return -1;
}
try
{
buf = c.doFinal();
}
catch (Exception e)
{
throw new IOException("error processing stream: " + e.toString());
}
bufOff = 0;
if (buf != null)
{
maxBuf = buf.length;
}
else
{
maxBuf = 0;
}
finalized = true;
if (bufOff == maxBuf)
{
return -1;
}
}
else
{
bufOff = 0;
try
{
maxBuf = c.update(inBuf, 0, available, buf, 0);
}
catch (Exception e)
{
throw new IOException("error processing stream: " + e.toString());
}
if (maxBuf == 0) // not enough bytes read for first block...
{
return nextChunk();
}
}
return maxBuf;
}
/**
* Reads the next byte of data from this input stream. The value
* byte is returned as an <code>int</code> in the range
* <code>0</code> to <code>255</code>. If no byte is available
* because the end of the stream has been reached, the value
* <code>-1</code> is returned. This method blocks until input data
* is available, the end of the stream is detected, or an exception
* is thrown.
*
* @return the next byte of data, or <code>-1</code> if the end of the
* stream is reached.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public int read()
throws IOException
{
if (bufOff == maxBuf)
{
if (nextChunk() < 0)
{
return -1;
}
}
return buf[bufOff++] & 0xff;
}
/**
* Reads up to <code>b.length</code> bytes of data from this input
* stream into an array of bytes.
* <p>
* The <code>read</code> method of <code>InputStream</code> calls
* the <code>read</code> method of three arguments with the arguments
* <code>b</code>, <code>0</code>, and <code>b.length</code>.
*
* @param b the buffer into which the data is read.
* @return the total number of bytes read into the buffer, or
* <code>-1</code> is there is no more data because the end of
* the stream has been reached.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
* @see #read(byte[], int, int)
*/
public int read(
byte[] b)
throws IOException
{
return read(b, 0, b.length);
}
/**
* Reads up to <code>len</code> bytes of data from this input stream
* into an array of bytes. This method blocks until some input is
* available. If the first argument is <code>null,</code> up to
* <code>len</code> bytes are read and discarded.
*
* @param b the buffer into which the data is read.
* @param off the start offset of the data.
* @param len the maximum number of bytes read.
* @return the total number of bytes read into the buffer, or <code>-1</code>
* if there is no more data because the end of the stream has been reached.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
* @see #read()
*/
public int read(
byte[] b,
int off,
int len)
throws IOException
{
if (bufOff == maxBuf)
{
if (nextChunk() < 0)
{
return -1;
}
}
int available = maxBuf - bufOff;
if (len > available)
{
System.arraycopy(buf, bufOff, b, off, available);
bufOff = maxBuf;
return available;
}
else
{
System.arraycopy(buf, bufOff, b, off, len);
bufOff += len;
return len;
}
}
/**
* Skips <code>n</code> bytes of input from the bytes that can be read
* from this input stream without blocking.
* <p>
* Fewer bytes than requested might be skipped.
* The actual number of bytes skipped is equal to <code>n</code> or
* the result of a call to <a href = "#available()"><code>available</code></a>,
* whichever is smaller.
* If <code>n</code> is less than zero, no bytes are skipped.
* <p>
* The actual number of bytes skipped is returned.
*
* @param n the number of bytes to be skipped.
* @return the actual number of bytes skipped.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public long skip(
long n)
throws IOException
{
if (n <= 0)
{
return 0;
}
int available = maxBuf - bufOff;
if (n > available)
{
bufOff = maxBuf;
return available;
}
else
{
bufOff += (int)n;
return (int)n;
}
}
/**
* Returns the number of bytes that can be read from this input
* stream without blocking. The <code>available</code> method of
* <code>InputStream</code> returns <code>0</code>. This method
* <B>should</B> be overridden by subclasses.
*
* @return the number of bytes that can be read from this input stream
* without blocking.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public int available()
throws IOException
{
return maxBuf - bufOff;
}
/**
* Closes this input stream and releases any system resources
* associated with the stream.
* <p>
* The <code>close</code> method of <code>CipherInputStream</code>
* calls the <code>close</code> method of its underlying input
* stream.
*
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public void close()
throws IOException
{
super.close();
}
/**
* Tests if this input stream supports the <code>mark</code>
* and <code>reset</code> methods, which it does not.
*
* @return <code>false</code>, since this class does not support the
* <code>mark</code> and <code>reset</code> methods.
* @since JCE1.2
* @see #mark(int)
* @see #reset()
*/
public boolean markSupported()
{
return false;
}
}

View File

@@ -0,0 +1,191 @@
package javax.crypto;
import java.io.OutputStream;
import java.io.IOException;
import java.io.FilterOutputStream;
/**
* A CipherOutputStream is composed of an OutputStream and a Cipher so
* that write() methods first process the data before writing them out
* to the underlying OutputStream. The cipher must be fully
* initialized before being used by a CipherOutputStream.
* <p>
* For example, if the cipher is initialized for encryption, the
* CipherOutputStream will attempt to encrypt data before writing out the
* encrypted data.
* <p>
* This class adheres strictly to the semantics, especially the
* failure semantics, of its ancestor classes
* java.io.OutputStream and java.io.FilterOutputStream. This class
* has exactly those methods specified in its ancestor classes, and
* overrides them all. Moreover, this class catches all exceptions
* that are not thrown by its ancestor classes.
* <p>
* It is crucial for a programmer using this class not to use
* methods that are not defined or overriden in this class (such as a
* new method or constructor that is later added to one of the super
* classes), because the design and implementation of those methods
* are unlikely to have considered security impact with regard to
* CipherOutputStream.
*
* @since JCE1.2
* @see OutputStream
* @see FilterOutputStream
* @see Cipher
* @see CipherInputStream
*/
public class CipherOutputStream
extends FilterOutputStream
{
private Cipher c;
private byte[] oneByte = new byte[1];
/**
* Constructs a CipherOutputStream from an OutputStream and a
* Cipher.
*/
public CipherOutputStream(
OutputStream os,
Cipher c)
{
super(os);
this.c = c;
}
/**
* Constructs a CipherOutputStream from an OutputStream without
* specifying a Cipher. This has the effect of constructing a
* CipherOutputStream using a NullCipher.
*/
protected CipherOutputStream(
OutputStream os)
{
this(os, new NullCipher());
}
/**
* Writes the specified byte to this output stream.
*
* @param b the <code>byte</code>.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public void write(
int b)
throws IOException
{
oneByte[0] = (byte)b;
byte[] bytes = c.update(oneByte, 0, 1);
if (bytes != null)
{
out.write(bytes, 0, bytes.length);
}
}
/**
* Writes <code>b.length</code> bytes from the specified byte array
* to this output stream.
* <p>
* The <code>write</code> method of
* <code>CipherOutputStream</code> calls the <code>write</code>
* method of three arguments with the three arguments
* <code>b</code>, <code>0</code>, and <code>b.length</code>.
*
* @param b the data.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
* @see #write(byte[], int, int)
*/
public void write(
byte[] b)
throws IOException
{
write(b, 0, b.length);
}
/**
* Writes <code>len</code> bytes from the specified byte array
* starting at offset <code>off</code> to this output stream.
*
* @param b the data.
* @param off the start offset in the data.
* @param len the number of bytes to write.
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public void write(
byte[] b,
int off,
int len)
throws IOException
{
byte[] bytes = c.update(b, off, len);
if (bytes != null)
{
out.write(bytes, 0, bytes.length);
}
}
/**
* Flushes this output stream by forcing any buffered output bytes
* that have already been processed by the encapsulated cipher object
* to be written out.
*
* <p>
* Any bytes buffered by the encapsulated cipher
* and waiting to be processed by it will not be written out. For example,
* if the encapsulated cipher is a block cipher, and the total number of
* bytes written using one of the <code>write</code> methods is less than
* the cipher's block size, no bytes will be written out.
*
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public void flush()
throws IOException
{
super.flush();
}
/**
* Closes this output stream and releases any system resources
* associated with this stream.
* <p>
* This method invokes the <code>doFinal</code> method of the encapsulated
* cipher object, which causes any bytes buffered by the encapsulated
* cipher to be processed. The result is written out by calling the
* <code>flush</code> method of this output stream.
* <p>
* This method resets the encapsulated cipher object to its initial state
* and calls the <code>close</code> method of the underlying output
* stream.
*
* @exception IOException if an I/O error occurs.
* @since JCE1.2
*/
public void close()
throws IOException
{
try
{
byte[] bytes = c.doFinal();
if (bytes != null)
{
out.write(bytes, 0, bytes.length);
}
}
catch (Exception e)
{
throw new IOException("Error closing stream: " + e.toString());
}
flush();
super.close();
}
}

View File

@@ -0,0 +1,606 @@
package javax.crypto;
import java.security.Key;
import java.security.SecureRandom;
import java.security.InvalidKeyException;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>Cipher</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a particular cipher algorithm.
* <p>
* In order to create an instance of <code>Cipher</code>, which
* encapsulates an instance of this <code>CipherSpi</code> class, an
* application calls one of the
* <a href = "Cipher.html#getInstance(java.lang.String)">getInstance</a>
* factory methods of the
* <a href = "Cipher.html">Cipher</a> engine class and specifies the requested
* <i>transformation</i>.
* Optionally, the application may also specify the name of a provider.
* <p>
* A <i>transformation</i> is a string that describes the operation (or
* set of operations) to be performed on the given input, to produce some
* output. A transformation always includes the name of a cryptographic
* algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and
* padding scheme.
* <p>
* A transformation is of the form:
* <p>
* <ul>
* <li>"<i>algorithm/mode/padding</i>" or
* <p>
* <li>"<i>algorithm</i>"
* </ul>
*
* <P> (in the latter case,
* provider-specific default values for the mode and padding scheme are used).
* For example, the following is a valid transformation:<p>
*
* <pre>
* Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
* </pre>
*
* <p>A provider may supply a separate class for each combination
* of <i>algorithm/mode/padding</i>, or may decide to provide more generic
* classes representing sub-transformations corresponding to
* <i>algorithm</i> or <i>algorithm/mode</i> or <i>algorithm//padding</i>
* (note the double slashes),
* in which case the requested mode and/or padding are set automatically by
* the <code>getInstance</code> methods of <code>Cipher</code>, which invoke
* the <a href = "#engineSetMode(java.lang.String)">engineSetMode</a> and
* <a href = "#engineSetPadding(java.lang.String)">engineSetPadding</a>
* methods of the provider's subclass of <code>CipherSpi</code>.
*
* <p>A <code>Cipher</code> property in a provider master class may have one of
* the following formats:
*
* <ul>
*
* <li>
* <pre>
* // provider's subclass of "CipherSpi" implements "algName" with
* // pluggable mode and padding
* <code>Cipher.</code><i>algName</i>
* </pre>
*
* <li>
* <pre>
* // provider's subclass of "CipherSpi" implements "algName" in the
* // specified "mode", with pluggable padding
* <code>Cipher.</code><i>algName/mode</i>
* </pre>
*
* <li>
* <pre>
* // provider's subclass of "CipherSpi" implements "algName" with the
* // specified "padding", with pluggable mode
* <code>Cipher.</code><i>algName//padding</i>
* </pre>
*
* <li>
* <pre>
* // provider's subclass of "CipherSpi" implements "algName" with the
* // specified "mode" and "padding"
* <code>Cipher.</code><i>algName/mode/padding</i>
* </pre>
*
* </ul>
*
* <p>For example, a provider may supply a subclass of <code>CipherSpi</code>
* that implements <i>DES/ECB/PKCS5Padding</i>, one that implements
* <i>DES/CBC/PKCS5Padding</i>, one that implements
* <i>DES/CFB/PKCS5Padding</i>, and yet another one that implements
* <i>DES/OFB/PKCS5Padding</i>. That provider would have the following
* <code>Cipher</code> properties in its master class:<p>
*
* <ul>
*
* <li>
* <pre>
* <code>Cipher.</code><i>DES/ECB/PKCS5Padding</i>
* </pre>
*
* <li>
* <pre>
* <code>Cipher.</code><i>DES/CBC/PKCS5Padding</i>
* </pre>
*
* <li>
* <pre>
* <code>Cipher.</code><i>DES/CFB/PKCS5Padding</i>
* </pre>
*
* <li>
* <pre>
* <code>Cipher.</code><i>DES/OFB/PKCS5Padding</i>
* </pre>
*
* </ul>
*
* <p>Another provider may implement a class for each of the above modes
* (i.e., one class for <i>ECB</i>, one for <i>CBC</i>, one for <i>CFB</i>,
* and one for <i>OFB</i>), one class for <i>PKCS5Padding</i>,
* and a generic <i>DES</i> class that subclasses from <code>CipherSpi</code>.
* That provider would have the following
* <code>Cipher</code> properties in its master class:<p>
*
* <ul>
*
* <li>
* <pre>
* <code>Cipher.</code><i>DES</i>
* </pre>
*
* </ul>
*
* <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
* engine class follows these rules in order to instantiate a provider's
* implementation of <code>CipherSpi</code> for a
* transformation of the form "<i>algorithm</i>":
*
* <ol>
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the specified "<i>algorithm</i>".
* <p>If the answer is YES, instantiate this
* class, for whose mode and padding scheme default values (as supplied by
* the provider) are used.
* <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
* exception.
* </ol>
*
* <p>The <code>getInstance</code> factory method of the <code>Cipher</code>
* engine class follows these rules in order to instantiate a provider's
* implementation of <code>CipherSpi</code> for a
* transformation of the form "<i>algorithm/mode/padding</i>":
*
* <ol>
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the specified "<i>algorithm/mode/padding</i>" transformation.
* <p>If the answer is YES, instantiate it.
* <p>If the answer is NO, go to the next step.<p>
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the sub-transformation "<i>algorithm/mode</i>".
* <p>If the answer is YES, instantiate it, and call
* <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
* <p>If the answer is NO, go to the next step.<p>
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the sub-transformation "<i>algorithm//padding</i>" (note the double
* slashes).
* <p>If the answer is YES, instantiate it, and call
* <code>engineSetMode(<i>mode</i>)</code> on the new instance.
* <p>If the answer is NO, go to the next step.<p>
* <li>
* Check if the provider has registered a subclass of <code>CipherSpi</code>
* for the sub-transformation "<i>algorithm</i>".
* <p>If the answer is YES, instantiate it, and call
* <code>engineSetMode(<i>mode</i>)</code> and
* <code>engineSetPadding(<i>padding</i>)</code> on the new instance.
* <p>If the answer is NO, throw a <code>NoSuchAlgorithmException</code>
* exception.
* </ol>
*
* @see KeyGenerator
* @see SecretKey
*/
public abstract class CipherSpi
{
public CipherSpi()
{
}
/**
* Sets the mode of this cipher.
*
* @param mode the cipher mode
* @exception NoSuchAlgorithmException if the requested cipher mode does not exist
*/
protected abstract void engineSetMode(
String mode)
throws NoSuchAlgorithmException;
/**
* Sets the padding mechanism of this cipher.
*
* @param padding the padding mechanism
* @exception NoSuchPaddingException if the requested padding mechanism does not exist
*/
protected abstract void engineSetPadding(
String padding)
throws NoSuchPaddingException;
/**
* Returns the block size (in bytes).
*
* @return the block size (in bytes), or 0 if the underlying algorithm is not a block cipher
*/
protected abstract int engineGetBlockSize();
/**
* Returns the length in bytes that an output buffer would
* need to be in order to hold the result of the next <code>update</code>
* or <code>doFinal</code> operation, given the input length
* <code>inputLen</code> (in bytes).
* <p>
* This call takes into account any unprocessed (buffered) data from a
* previous <code>update</code> call, and padding.
* <p>
* The actual output length of the next <code>update</code> or
* <code>doFinal</code> call may be smaller than the length returned by
* this method.
*
* @param inputLen the input length (in bytes)
* @return the required output buffer size (in bytes)
*/
protected abstract int engineGetOutputSize(
int inputLen);
/**
* Returns the initialization vector (IV) in a new buffer.
* <p>
* This is useful in the context of password-based encryption or
* decryption, where the IV is derived from a user-provided passphrase.
*
* @return the initialization vector in a new buffer, or null if the
* underlying algorithm does not use an IV, or if the IV has not yet
* been set.
*/
protected abstract byte[] engineGetIV();
/**
* Returns the parameters used with this cipher.
* <p>
* The returned parameters may be the same that were used to initialize
* this cipher, or may contain a combination of default and random
* parameter values used by the underlying cipher implementation if this
* cipher requires algorithm parameters but was not initialized with any.
*
* @return the parameters used with this cipher, or null if this cipher
* does not use any parameters.
*/
protected abstract AlgorithmParameters engineGetParameters();
/**
* Initializes this cipher with a key and a source
* of randomness.
* <p>
* The cipher is initialized for one of the following four operations:
* encryption, decryption, key wrapping or key unwrapping, depending on
* the value of <code>opmode</code>.
* <p>
* If this cipher requires any algorithm parameters that cannot be
* derived from the given <code>key</code>, the underlying cipher
* implementation is supposed to generate the required parameters itself
* (using provider-specific default or random values) if it is being
* initialized for encryption or key wrapping, and raise an
* <code>InvalidKeyException</code> if it is being
* initialized for decryption or key unwrapping.
* The generated parameters can be retrieved using
* <a href = "#engineGetParameters()">engineGetParameters</a> or
* <a href = "#engineGetIV()">engineGetIV</a> (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from <code>random</code>.
*
* <p>Note that when a Cipher object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing
* it.
* @param opmode the operation mode of this cipher (this is one of
* the following:
* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
* @param key the encryption key
* @param random the source of randomness
* @exception InvalidKeyException if the given key is inappropriate for
* initializing this cipher, or if this cipher is being initialized for
* decryption and requires algorithm parameters that cannot be
* determined from the given key.
*/
protected abstract void engineInit(
int opmode,
Key key,
SecureRandom random)
throws InvalidKeyException;
/**
* Initializes this cipher with a key, a set of
* algorithm parameters, and a source of randomness.
* <p>
* The cipher is initialized for one of the following four operations:
* encryption, decryption, key wrapping or key unwrapping, depending on
* the value of <code>opmode</code>.
* <p>
* If this cipher requires any algorithm parameters and
* <code>params</code> is null, the underlying cipher implementation is
* supposed to generate the required parameters itself (using
* provider-specific default or random values) if it is being
* initialized for encryption or key wrapping, and raise an
* <code>InvalidAlgorithmParameterException</code> if it is being
* initialized for decryption or key unwrapping.
* The generated parameters can be retrieved using
* <a href = "#engineGetParameters()">engineGetParameters</a> or
* <a href = "#engineGetIV()">engineGetIV</a> (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from <code>random</code>.
* <p>
* Note that when a Cipher object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing
* it.
*
* @param opmode the operation mode of this cipher (this is one of the following:
* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
* <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
* @param key the encryption key
* @param params the algorithm parameters
* @param random the source of randomness
* @exception InvalidKeyException if the given key is inappropriate for initializing this cipher
* @exception InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate
* for this cipher, or if this cipher is being initialized for decryption and requires
* algorithm parameters and <code>params</code> is null.
*/
protected abstract void engineInit(
int opmode,
Key key,
AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Initializes this cipher with a key, a set of
* algorithm parameters, and a source of randomness.
* <p>
* The cipher is initialized for one of the following four operations:
* encryption, decryption, key wrapping or key unwrapping, depending on
* the value of <code>opmode</code>.
* <p>
* If this cipher requires any algorithm parameters and
* <code>params</code> is null, the underlying cipher implementation is
* supposed to generate the required parameters itself (using
* provider-specific default or random values) if it is being
* initialized for encryption or key wrapping, and raise an
* <code>InvalidAlgorithmParameterException</code> if it is being
* initialized for decryption or key unwrapping.
* The generated parameters can be retrieved using
* <a href = "#engineGetParameters()">engineGetParameters</a> or
* <a href = "#engineGetIV()">engineGetIV</a> (if the parameter is an IV).
* <p>
* If this cipher (including its underlying feedback or padding scheme)
* requires any random bytes (e.g., for parameter generation), it will get
* them from <code>random</code>.
* <p>
* Note that when a Cipher object is initialized, it loses all
* previously-acquired state. In other words, initializing a Cipher is
* equivalent to creating a new instance of that Cipher and initializing it.
*
* @param opmode the operation mode of this cipher (this is one of the following:
* <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, <code>WRAP_MODE</code>
* or <code>UNWRAP_MODE</code>)
* @param key the encryption key
* @param params the algorithm parameters
* @param random the source of randomness
* @exception InvalidKeyException if the given key is inappropriate for initializing this cipher
* @exception InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate
* for this cipher, or if this cipher is being initialized for decryption and requires
* algorithm parameters and <code>params</code> is null.
*/
protected abstract void engineInit(
int opmode,
Key key,
AlgorithmParameters params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialized), processing another data
* part.
* <p>
* The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code> inclusive, are processed,
* and the result is stored in a new buffer.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input starts
* @param inputLen the input length
* @return the new buffer with the result, or null if the underlying cipher is a
* block cipher and the input data is too short to result in a new block.
*/
protected abstract byte[] engineUpdate(
byte[] input,
int inputOffset,
int inputLen);
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialized), processing another data
* part.
* <p>
* The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code> inclusive, are processed,
* and the result is stored in the <code>output</code> buffer, starting at
* <code>outputOffset</code> inclusive.
* <p>
* If the <code>output</code> buffer is too small to hold the result,
* a <code>ShortBufferException</code> is thrown.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input starts
* @param inputLen the input length
* @param output the buffer for the result
* @param outputOffset the offset in <code>output</code> where the result is stored
* @return the number of bytes stored in <code>output</code>
* @exception ShortBufferException if the given output buffer is too small to hold the result
*/
protected abstract int engineUpdate(
byte[] input,
int inputOffset,
int inputLen,
byte[] output,
int outputOffset)
throws ShortBufferException;
/**
* Encrypts or decrypts data in a single-part operation, or finishes a multiple-part operation.
* The data is encrypted or decrypted, depending on how this cipher was initialized.
* <p>
* The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code> inclusive, and any input
* bytes that may have been buffered during a previous <code>update</code>
* operation, are processed, with padding (if requested) being applied.
* The result is stored in a new buffer.
* <p>
* A call to this method resets this cipher object to the state
* it was in when previously initialized via a call to <code>engineInit</code>.
* That is, the object is reset and available to encrypt or decrypt
* (depending on the operation mode that was specified in the call to
* <code>engineInit</code>) more data.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input starts
* @param inputLen the input length
* @return the new buffer with the result
* @exception IllegalBlockSizeException if this cipher is a block cipher, no padding has been requested
* (only in encryption mode), and the total input length of the data processed by this cipher is not a
* multiple of block size
* @exception BadPaddingException if this cipher is in decryption mode, and (un)padding has been requested,
* but the decrypted data is not bounded by the appropriate padding bytes
*/
protected abstract byte[] engineDoFinal(
byte[] input,
int inputOffset,
int inputLen)
throws IllegalBlockSizeException, BadPaddingException;
/**
* Encrypts or decrypts data in a single-part operation,
* or finishes a multiple-part operation.
* The data is encrypted or decrypted, depending on how this cipher was
* initialized.
* <p>
* The first <code>inputLen</code> bytes in the <code>input</code>
* buffer, starting at <code>inputOffset</code> inclusive, and any input
* bytes that may have been buffered during a previous <code>update</code>
* operation, are processed, with padding (if requested) being applied.
* The result is stored in the <code>output</code> buffer, starting at
* <code>outputOffset</code> inclusive.
* <p>
* If the <code>output</code> buffer is too small to hold the result,
* a <code>ShortBufferException</code> is thrown.
* <p>
* A call to this method resets this cipher object to the state
* it was in when previously initialized via a call to
* <code>engineInit</code>.
* That is, the object is reset and available to encrypt or decrypt
* (depending on the operation mode that was specified in the call to
* <code>engineInit</code>) more data.
*
* @param input the input buffer
* @param inputOffset the offset in <code>input</code> where the input starts
* @param inputLen the input length
* @param output the buffer for the result
* @param outputOffset the offset in <code>output</code> where the result is stored
* @return the number of bytes stored in <code>output</code>
* @exception IllegalBlockSizeException if this cipher is a block cipher, no padding has been
* requested (only in encryption mode), and the total input length of the data processed by this
* cipher is not a multiple of block size
* @exception ShortBufferException if the given output buffer is too small to hold the result
* @exception BadPaddingException if this cipher is in decryption mode, and (un)padding has been requested,
* but the decrypted data is not bounded by the appropriate padding bytes
*/
protected abstract int engineDoFinal(
byte[] input,
int inputOffset,
int inputLen,
byte[] output,
int outputOffset)
throws ShortBufferException, IllegalBlockSizeException, BadPaddingException;
/**
* Wrap a key.
* <p>
* This concrete method has been added to this previously-defined
* abstract class. (For backwards compatibility, it cannot be abstract.)
* It may be overridden by a provider to wrap a key.
* Such an override is expected to throw an IllegalBlockSizeException or
* InvalidKeyException (under the specified circumstances),
* if the given key cannot be wrapped.
* If this method is not overridden, it always throws an
* UnsupportedOperationException.
*
* @param key the key to be wrapped.
* @return the wrapped key.
* @exception IllegalBlockSizeException if this cipher is a block cipher, no padding has been requested,
* and the length of the encoding of the key to be wrapped is not a multiple of the block size.
* @exception InvalidKeyException if it is impossible or unsafe to wrap the key with this cipher (e.g.,
* a hardware protected key is being passed to a software-only cipher).
*/
protected byte[] engineWrap(
Key key)
throws IllegalBlockSizeException, InvalidKeyException
{
throw new UnsupportedOperationException("Underlying cipher does not support key wrapping");
}
/**
* Unwrap a previously wrapped key.
*
* <p>This concrete method has been added to this previously-defined
* abstract class. (For backwards compatibility, it cannot be abstract.)
* It may be overridden by a provider to unwrap a previously wrapped key.
* Such an override is expected to throw an InvalidKeyException if
* the given wrapped key cannot be unwrapped.
* If this method is not overridden, it always throws an
* UnsupportedOperationException.
*
* @param wrappedKey the key to be unwrapped.
* @param wrappedKeyAlgorithm the algorithm associated with the wrapped key.
* @param wrappedKeyType the type of the wrapped key. This is one of <code>SECRET_KEY</code>,
* <code>PRIVATE_KEY</code>, or <code>PUBLIC_KEY</code>.
* @return the unwrapped key.
* @exception InvalidKeyException if <code>wrappedKey</code> does not represent a wrapped key,
* or if the algorithm associated with the wrapped key is different from <code>wrappedKeyAlgorithm</code>
* and/or its key type is different from <code>wrappedKeyType</code>.
* @exception NoSuchAlgorithmException - if no installed providers can create keys for the
* <code>wrappedKeyAlgorithm</code>.
*/
protected java.security.Key engineUnwrap(
byte[] wrappedKey,
String wrappedKeyAlgorithm,
int wrappedKeyType)
throws InvalidKeyException, NoSuchAlgorithmException
{
throw new UnsupportedOperationException("Underlying cipher does not support key unwrapping");
}
/**
* Returns the key size of the given key object.
* <p>
* This concrete method has been added to this previously-defined
* abstract class. It throws an <code>UnsupportedOperationException</code>
* if it is not overridden by the provider.
*
* @param key the key object.
* @return the key size of the given key object.
* @exception InvalidKeyException if <code>key</code> is invalid.
*/
protected int engineGetKeySize(
Key key)
throws InvalidKeyException
{
throw new UnsupportedOperationException("Key size unavailable");
}
}

View File

@@ -0,0 +1,234 @@
package javax.crypto;
import java.io.*;
import java.security.*;
import java.security.spec.*;
import org.spongycastle.asn1.ASN1InputStream;
import org.spongycastle.asn1.DEROutputStream;
import org.spongycastle.asn1.ASN1Sequence;
import org.spongycastle.asn1.DERObjectIdentifier;
import org.spongycastle.asn1.x509.AlgorithmIdentifier;
/**
* This class implements the <code>EncryptedPrivateKeyInfo</code> type
* as defined in PKCS #8.
* <p>Its ASN.1 definition is as follows:
*
* <pre>
* EncryptedPrivateKeyInfo ::= SEQUENCE {
* encryptionAlgorithm AlgorithmIdentifier,
* encryptedData OCTET STRING }
*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL }
* </pre>
*/
public class EncryptedPrivateKeyInfo
{
private org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo infoObj;
private AlgorithmParameters algP;
/*
* Constructs (i.e., parses) an <code>EncryptedPrivateKeyInfo</code> from
* its ASN.1 encoding.
*
* @param encoded the ASN.1 encoding of this object.
* @exception NullPointerException if the <code>encoded</code> is null.
* @exception IOException if error occurs when parsing the ASN.1 encoding.
*/
public EncryptedPrivateKeyInfo(
byte[] encoded)
throws NullPointerException, IOException
{
if (encoded == null)
{
throw new NullPointerException("parameters null");
}
ByteArrayInputStream bIn = new ByteArrayInputStream(encoded);
ASN1InputStream dIn = new ASN1InputStream(bIn);
infoObj = org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo.getInstance((ASN1Sequence)dIn.readObject());
try
{
algP = this.getParameters();
}
catch (NoSuchAlgorithmException e)
{
throw new IOException("can't create parameters: " + e.toString());
}
}
/*
* Constructs an <code>EncryptedPrivateKeyInfo</code> from the
* encryption algorithm name and the encrypted data.
* <p>Note: the <code>encrypedData</code> is cloned when constructing
* this object.
* <p>
* If encryption algorithm has associated parameters use the constructor
* with AlgorithmParameters as the parameter.
*
* @param algName algorithm name.
* @param encryptedData encrypted data.
* @exception NullPointerException if <code>algName</code> or <code>encryptedData</code> is null.
* @exception IllegalArgumentException if <code>encryptedData</code> is empty, i.e. 0-length.
* @exception NoSuchAlgorithmException if the specified algName is not supported.
*/
public EncryptedPrivateKeyInfo(
String algName,
byte[] encryptedData)
throws NullPointerException, IllegalArgumentException, NoSuchAlgorithmException
{
if (algName == null || encryptedData == null)
{
throw new NullPointerException("parameters null");
}
org.spongycastle.asn1.x509.AlgorithmIdentifier kAlgId = new AlgorithmIdentifier(new DERObjectIdentifier(algName), null);
infoObj = new org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, (byte[])encryptedData.clone());
algP = this.getParameters();
}
/**
* Constructs an <code>EncryptedPrivateKeyInfo</code> from the
* encryption algorithm parameters and the encrypted data.
* <p>Note: the <code>encrypedData</code> is cloned when constructing
* this object.
*
* @param algParams the algorithm parameters for the encryption
* algorithm. <code>algParams.getEncoded()</code> should return
* the ASN.1 encoded bytes of the <code>parameters</code> field
* of the <code>AlgorithmIdentifer</code> component of the
* <code>EncryptedPrivateKeyInfo</code> type.
* @param encryptedData encrypted data.
* @exception NullPointerException if <code>algParams</code> or <code>encryptedData</code> is null.
* @exception IllegalArgumentException if <code>encryptedData</code> is empty, i.e. 0-length.
* @exception NoSuchAlgorithmException if the specified algName of the specified <code>algParams</code> parameter is not supported.
*/
public EncryptedPrivateKeyInfo(
AlgorithmParameters algParams,
byte[] encryptedData)
throws NullPointerException, IllegalArgumentException, NoSuchAlgorithmException
{
if (algParams == null || encryptedData == null)
{
throw new NullPointerException("parameters null");
}
org.spongycastle.asn1.x509.AlgorithmIdentifier kAlgId = null;
try
{
ByteArrayInputStream bIn = new ByteArrayInputStream(algParams.getEncoded());
ASN1InputStream dIn = new ASN1InputStream(bIn);
kAlgId = new AlgorithmIdentifier(
new DERObjectIdentifier(algParams.getAlgorithm()), dIn.readObject());
}
catch (IOException e)
{
throw new IllegalArgumentException("error in encoding: " + e.toString());
}
infoObj = new org.spongycastle.asn1.pkcs.EncryptedPrivateKeyInfo(kAlgId, (byte[])encryptedData.clone());
algP = this.getParameters();
}
/**
* Returns the encryption algorithm.
*
* @returns the algorithm name.
*/
public String getAlgName()
{
return infoObj.getEncryptionAlgorithm().getObjectId().getId();
}
private AlgorithmParameters getParameters()
throws NoSuchAlgorithmException
{
AlgorithmParameters ap = AlgorithmParameters.getInstance(this.getAlgName());
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
DEROutputStream dOut = new DEROutputStream(bOut);
try
{
dOut.writeObject(infoObj.getEncryptionAlgorithm().getParameters());
dOut.close();
ap.init(bOut.toByteArray());
}
catch (IOException e)
{
throw new NoSuchAlgorithmException("unable to parse parameters");
}
return ap;
}
/**
* Returns the algorithm parameters used by the encryption algorithm.
*
* @returns the algorithm parameters.
*/
public AlgorithmParameters getAlgParameters()
{
return algP;
}
/**
* Returns a copy of the encrypted data.
*
* @returns a copy of the encrypted data.
*/
public byte[] getEncryptedData()
{
return infoObj.getEncryptedData();
}
/**
* Extract the enclosed PKCS8EncodedKeySpec object from the
* encrypted data and return it.
*
* @return the PKCS8EncodedKeySpec object.
* @exception InvalidKeySpecException if the given cipher is
* inappropriate for the encrypted data or the encrypted
* data is corrupted and cannot be decrypted.
*/
public PKCS8EncodedKeySpec getKeySpec(
Cipher c)
throws InvalidKeySpecException
{
try
{
return new PKCS8EncodedKeySpec(c.doFinal(this.getEncryptedData()));
}
catch (Exception e)
{
throw new InvalidKeySpecException("can't get keySpec: " + e.toString());
}
}
/**
* Returns the ASN.1 encoding of this object.
*
* @returns the ASN.1 encoding.
* @throws IOException if error occurs when constructing its ASN.1 encoding.
*/
public byte[] getEncoded()
throws IOException
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
DEROutputStream dOut = new DEROutputStream(bOut);
dOut.writeObject(infoObj);
dOut.close();
return bOut.toByteArray();
}
}

View File

@@ -0,0 +1,9 @@
package javax.crypto;
/**
* this is a place holder class, no exemption mechanism facility is
* required in this modified version of the JCE
*/
public class ExemptionMechanism
{
}

View File

@@ -0,0 +1,34 @@
package javax.crypto;
import java.security.GeneralSecurityException;
/**
* This is the generic ExemptionMechanism exception.
*
*/
public class ExemptionMechanismException
extends GeneralSecurityException
{
private static final long serialVersionUID = 1572699429277957109L;
/**
* Constructs a ExemptionMechanismException with no detailed message.
* (A detailed message is a String that describes this particular exception.)
*/
public ExemptionMechanismException()
{
}
/**
* Constructs a ExemptionMechanismException with the specified
* detailed message. (A detailed message is a String that describes
* this particular exception.)
*
* @param msg the detailed message.
*/
public ExemptionMechanismException(
String msg)
{
super(msg);
}
}

View File

@@ -0,0 +1,36 @@
package javax.crypto;
import java.security.GeneralSecurityException;
/**
* This exception is thrown when the length of data provided to a block
* cipher is incorrect, i.e., does not match the block size of the cipher.
*
*/
public class IllegalBlockSizeException
extends GeneralSecurityException
{
private static final long serialVersionUID = -1965144811953540392L;
/**
* Constructs an IllegalBlockSizeException with no detail message.
* (A detail message is a String that describes this particular
* exception.)
*/
public IllegalBlockSizeException()
{
}
/**
* Constructs an IllegalBlockSizeException with the specified
* detail message. (A detail message is a String that describes
* this particular exception.)
*
* @param msg the detail message.
*/
public IllegalBlockSizeException(
String msg)
{
super(msg);
}
}

View File

@@ -0,0 +1,202 @@
package javax.crypto;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;
import java.util.Locale;
class JCEUtil
{
static class Implementation
{
Object engine;
Provider provider;
Implementation(
Object engine,
Provider provider)
{
this.engine = engine;
this.provider = provider;
}
Object getEngine()
{
return engine;
}
Provider getProvider()
{
return provider;
}
}
/**
* see if we can find an algorithm (or its alias and what it represents) in
* the property table for the given provider.
*
* @return null if no algorithm found, an Implementation if it is.
*/
static private Implementation findImplementation(
String baseName,
String algorithm,
Provider prov)
{
String alias;
while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null)
{
algorithm = alias;
}
String className = prov.getProperty(baseName + "." + algorithm);
if (className != null)
{
try
{
Class cls;
ClassLoader clsLoader = prov.getClass().getClassLoader();
if (clsLoader != null)
{
cls = clsLoader.loadClass(className);
}
else
{
cls = Class.forName(className);
}
return new Implementation(cls.newInstance(), prov);
}
catch (ClassNotFoundException e)
{
throw new IllegalStateException(
"algorithm " + algorithm + " in provider " + prov.getName() + " but no class \"" + className + "\" found!");
}
catch (Exception e)
{
throw new IllegalStateException(
"algorithm " + algorithm + " in provider " + prov.getName() + " but class \"" + className + "\" inaccessible!");
}
}
return null;
}
/**
* return an implementation for a given algorithm/provider.
* If the provider is null, we grab the first avalaible who has the required algorithm.
*
* @return null if no algorithm found, an Implementation if it is.
* @exception NoSuchProviderException if a provider is specified and not found.
*/
static Implementation getImplementation(
String baseName,
String algorithm,
String provider)
throws NoSuchProviderException
{
if (provider == null)
{
Provider[] prov = Security.getProviders();
//
// search every provider looking for the algorithm we want.
//
for (int i = 0; i != prov.length; i++)
{
//
// try case insensitive
//
Implementation imp = findImplementation(baseName, algorithm.toUpperCase(Locale.ENGLISH), prov[i]);
if (imp != null)
{
return imp;
}
imp = findImplementation(baseName, algorithm, prov[i]);
if (imp != null)
{
return imp;
}
}
}
else
{
Provider prov = Security.getProvider(provider);
if (prov == null)
{
throw new NoSuchProviderException("Provider " + provider + " not found");
}
//
// try case insensitive
//
Implementation imp = findImplementation(baseName, algorithm.toUpperCase(Locale.ENGLISH), prov);
if (imp != null)
{
return imp;
}
return findImplementation(baseName, algorithm, prov);
}
return null;
}
/**
* return an implementation for a given algorithm/provider.
* If the provider is null, we grab the first avalaible who has the required algorithm.
*
* @return null if no algorithm found, an Implementation if it is.
* @exception NoSuchProviderException if a provider is specified and not found.
*/
static Implementation getImplementation(
String baseName,
String algorithm,
Provider provider)
{
if (provider == null)
{
Provider[] prov = Security.getProviders();
//
// search every provider looking for the algorithm we want.
//
for (int i = 0; i != prov.length; i++)
{
//
// try case insensitive
//
Implementation imp = findImplementation(baseName, algorithm.toUpperCase(Locale.ENGLISH), prov[i]);
if (imp != null)
{
return imp;
}
imp = findImplementation(baseName, algorithm, prov[i]);
if (imp != null)
{
return imp;
}
}
}
else
{
//
// try case insensitive
//
Implementation imp = findImplementation(baseName, algorithm.toUpperCase(Locale.ENGLISH), provider);
if (imp != null)
{
return imp;
}
return findImplementation(baseName, algorithm, provider);
}
return null;
}
}

View File

@@ -0,0 +1,394 @@
package javax.crypto;
import java.security.Key;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.InvalidKeyException;
import java.security.NoSuchProviderException;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class provides the functionality of a key agreement (or key
* exchange) protocol.
* The keys involved in establishing a shared secret are created by one of the
* key generators (<code>KeyPairGenerator</code> or
* <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from
* an intermediate phase of the key agreement protocol
* (see <a href = "#doPhase(java.security.Key, boolean)">doPhase</a>).
*
* For each of the correspondents in the key exchange, <code>doPhase</code>
* needs to be called. For example, if this key exchange is with one other
* party, <code>doPhase</code> needs to be called once, with the
* <code>lastPhase</code> flag set to <code>true</code>.
* If this key exchange is
* with two other parties, <code>doPhase</code> needs to be called twice,
* the first time setting the <code>lastPhase</code> flag to
* <code>false</code>, and the second time setting it to <code>true</code>.
* There may be any number of parties involved in a key exchange.
*
* @see KeyGenerator
* @see SecretKey
*/
public class KeyAgreement
{
KeyAgreementSpi keyAgreeSpi;
Provider provider;
String algorithm;
/**
* Creates a KeyAgreement object.
*
* @param keyAgreeSpi the delegate
* @param provider the provider
* @param algorithm the algorithm
*/
protected KeyAgreement(
KeyAgreementSpi keyAgreeSpi,
Provider provider,
String algorithm)
{
this.keyAgreeSpi = keyAgreeSpi;
this.provider = provider;
this.algorithm = algorithm;
}
/**
* Returns the algorithm name of this <code>KeyAgreement</code> object.
* <p>
* This is the same name that was specified in one of the
* <code>getInstance</code> calls that created this
* <code>KeyAgreement</code> object.
*
* @return the algorithm name of this <code>KeyAgreement</code> object.
*/
public final String getAlgorithm()
{
return algorithm;
}
/**
* Generates a <code>KeyAgreement</code> object that implements the
* specified key agreement algorithm.
* If the default provider package provides an implementation of the
* requested key agreement algorithm, an instance of
* <code>KeyAgreement</code> containing that implementation is returned.
* If the algorithm is not available in the default provider package,
* other provider packages are searched.
*
* @param algorithm the standard name of the requested key agreement algorithm.
* See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
* for information about standard algorithm names.
* @return the new <code>KeyAgreement</code> object
* @exception NoSuchAlgorithmException if the specified algorithm is not
* available in the default provider package or any of the other provider
* packages that were searched.
*/
public static final KeyAgreement getInstance(
String algorithm)
throws NoSuchAlgorithmException
{
try
{
JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, (String) null);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm);
return keyAgree;
}
catch (NoSuchProviderException e)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
}
/**
* Generates a <code>KeyAgreement</code> object for the specified key
* agreement algorithm from the specified provider.
*
* @param algorithm the standard name of the requested key agreement algorithm.
* See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
* for information about standard algorithm names.
* @param provider the provider
* @return the new <code>KeyAgreement</code> object
* @exception NoSuchAlgorithmException if the specified algorithm is not
* available from the specified provider.
*/
public static final KeyAgreement getInstance(
String algorithm,
Provider provider)
throws NoSuchAlgorithmException
{
if (provider == null)
{
throw new IllegalArgumentException("No provider specified to KeyAgreement.getInstance()");
}
JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, provider);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm);
return keyAgree;
}
/**
* Generates a <code>KeyAgreement</code> object for the specified key
* agreement algorithm from the specified provider.
*
* @param algorithm the standard name of the requested key agreement algorithm.
* See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
* for information about standard algorithm names.
* @param provider the name of the provider
* @return the new <code>KeyAgreement</code> object
* @exception NoSuchAlgorithmException if the specified algorithm is not
* available from the specified provider.
* @exception NoSuchProviderException if the specified provider has not
* been configured.
*/
public static final KeyAgreement getInstance(
String algorithm,
String provider)
throws NoSuchAlgorithmException, NoSuchProviderException
{
if (provider == null)
{
throw new IllegalArgumentException("No provider specified to KeyAgreement.getInstance()");
}
JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyAgreement", algorithm, provider);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
KeyAgreement keyAgree = new KeyAgreement((KeyAgreementSpi)imp.getEngine(), imp.getProvider(), algorithm);
return keyAgree;
}
/**
* Returns the provider of this <code>KeyAgreement</code> object.
*
* @return the provider of this <code>KeyAgreement</code> object
*/
public final Provider getProvider()
{
return provider;
}
/**
* Initializes this key agreement with the given key, which is required to
* contain all the algorithm parameters required for this key agreement.
* <p>
* If this key agreement requires any random bytes, it will get
* them using the <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html">
* <code>SecureRandom</code></a> implementation of the highest-priority
* installed provider as the source of randomness.
* (If none of the installed providers supply an implementation of
* SecureRandom, a system-provided source of randomness will be used.)
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
*/
public final void init(
Key key)
throws InvalidKeyException
{
keyAgreeSpi.engineInit(key, null);
}
/**
* Initializes this key agreement with the given key and source of
* randomness. The given key is required to contain all the algorithm
* parameters required for this key agreement.
* <p>
* If the key agreement algorithm requires random bytes, it gets them
* from the given source of randomness, <code>random</code>.
* However, if the underlying
* algorithm implementation does not require any random bytes,
* <code>random</code> is ignored.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param random the source of randomness
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
*/
public final void init(
Key key,
SecureRandom random)
throws InvalidKeyException
{
keyAgreeSpi.engineInit(key, random);
}
/**
* Initializes this key agreement with the given key and set of
* algorithm parameters.
* <p>
* If this key agreement requires any random bytes, it will get
* them using the <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html">
* <code>SecureRandom</code></a> implementation of the highest-priority
* installed provider as the source of randomness.
* (If none of the installed providers supply an implementation of
* SecureRandom, a system-provided source of randomness will be used.)
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param params the key agreement parameters
* @exception InvalidKeyException if the given key is inappropriate for this
* key agreement, e.g., is of the wrong type or has an incompatible algorithm type.
* @exception InvalidAlgorithmParameterException if the given parameters
* are inappropriate for this key agreement.
*/
public final void init(
Key key,
AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
keyAgreeSpi.engineInit(key, params, null);
}
/**
* Initializes this key agreement with the given key, set of
* algorithm parameters, and source of randomness.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param params the key agreement parameters
* @param random the source of randomness
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
* @exception InvalidAlgorithmParameterException if the given parameters
* are inappropriate for this key agreement.
*/
public final void init(
Key key,
AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
keyAgreeSpi.engineInit(key, params, random);
}
/**
* Executes the next phase of this key agreement with the given
* key that was received from one of the other parties involved in this key
* agreement.
*
* @param key the key for this phase. For example, in the case of
* Diffie-Hellman between 2 parties, this would be the other party's
* Diffie-Hellman public key.
* @param lastPhase flag which indicates whether or not this is the last
* phase of this key agreement.
* @return the (intermediate) key resulting from this phase, or null
* if this phase does not yield a key
* @exception InvalidKeyException if the given key is inappropriate for this phase.
* @exception IllegalStateException if this key agreement has not been
* initialized.
*/
public final Key doPhase(
Key key,
boolean lastPhase)
throws InvalidKeyException, IllegalStateException
{
return keyAgreeSpi.engineDoPhase(key, lastPhase);
}
/**
* Generates the shared secret and returns it in a new buffer.
* <p>
* This method resets this <code>KeyAgreement</code> object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>init</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @return the new buffer with the shared secret
* @exception IllegalStateException if this key agreement has not been completed yet
*/
public final byte[] generateSecret()
throws IllegalStateException
{
return keyAgreeSpi.engineGenerateSecret();
}
/**
* Generates the shared secret, and places it into the buffer
* <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
* <p>
* If the <code>sharedSecret</code> buffer is too small to hold the
* result, a <code>ShortBufferException</code> is thrown.
* In this case, this call should be repeated with a larger output buffer.
* <p>
* This method resets this <code>KeyAgreement</code> object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>init</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @param sharedSecret the buffer for the shared secret
* @param offset the offset in <code>sharedSecret</code> where the
* shared secret will be stored
* @return the number of bytes placed into <code>sharedSecret</code>
* @exception IllegalStateException if this key agreement has not been
* completed yet
* @exception ShortBufferException if the given output buffer is too small
* to hold the secret
*/
public final int generateSecret(
byte[] sharedSecret,
int offset)
throws IllegalStateException, ShortBufferException
{
return keyAgreeSpi.engineGenerateSecret(sharedSecret, offset);
}
/**
* Creates the shared secret and returns it as a <code>SecretKey</code>
* object of the specified algorithm.
* <p>
* This method resets this <code>KeyAgreement</code> object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>init</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @param algorithm the requested secret-key algorithm
* @return the shared secret key
* @exception IllegalStateException if this key agreement has not been
* completed yet
* @exception NoSuchAlgorithmException if the specified secret-key
* algorithm is not available
* @exception InvalidKeyException if the shared secret-key material cannot
* be used to generate a secret key of the specified algorithm (e.g.,
* the key material is too short)
*/
public final SecretKey generateSecret(
String algorithm)
throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException
{
return keyAgreeSpi.engineGenerateSecret(algorithm);
}
}

View File

@@ -0,0 +1,159 @@
package javax.crypto;
import java.security.Key;
import java.security.SecureRandom;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>KeyAgreement</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a particular key agreement algorithm.
* <p>
* The keys involved in establishing a shared secret are created by one of the
* key generators (<code>KeyPairGenerator</code> or <code>KeyGenerator</code>),
* a <code>KeyFactory</code>, or as a result from an intermediate phase of the key
* agreement protocol (see <a href = "#engineDoPhase(java.security.Key, boolean)">engineDoPhase</a>).
* <p>
* For each of the correspondents in the key exchange, <code>engineDoPhase</code>
* needs to be called. For example, if the key exchange is with one other
* party, <code>engineDoPhase</code> needs to be called once, with the
* <code>lastPhase</code> flag set to <code>true</code>.
* If the key exchange is with two other parties, <code>engineDoPhase</code> needs to be called twice,
* the first time setting the <code>lastPhase</code> flag to
* <code>false</code>, and the second time setting it to <code>true</code>.
* There may be any number of parties involved in a key exchange.
*
* @see KeyGenerator
* @see SecretKey
*/
public abstract class KeyAgreementSpi
{
public KeyAgreementSpi()
{
}
/**
* Initializes this key agreement with the given key and source of
* randomness. The given key is required to contain all the algorithm
* parameters required for this key agreement.
* <p>
* If the key agreement algorithm requires random bytes, it gets them
* from the given source of randomness, <code>random</code>.
* However, if the underlying
* algorithm implementation does not require any random bytes,
* <code>random</code> is ignored.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own Diffie-Hellman private key.
* @param random the source of randomness
* @exception InvalidKeyException if the given key is inappropriate for this key agreement, e.g., is
* of the wrong type or has an incompatible algorithm type.
*/
protected abstract void engineInit(
Key key,
SecureRandom random)
throws InvalidKeyException;
/**
* Initializes this key agreement with the given key, set of
* algorithm parameters, and source of randomness.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param params the key agreement parameters
* @param random the source of randomness
* @exception InvalidKeyException if the given key is inappropriate for this key agreement, e.g., is of the
* wrong type or has an incompatible algorithm type.
* @exception InvalidAlgorithmParameterException if the given parameters are inappropriate for this key
* agreement.
*/
protected abstract void engineInit(
Key key,
AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Executes the next phase of this key agreement with the given
* key that was received from one of the other parties involved in this key
* agreement.
* @param key the key for this phase. For example, in the case of
* Diffie-Hellman between 2 parties, this would be the other party's
* Diffie-Hellman public key.
* @param lastPhase flag which indicates whether or not this is the last
* phase of this key agreement.
* @return the (intermediate) key resulting from this phase, or null if this phase does not yield a key
* @exception InvalidKeyException if the given key is inappropriate for this phase.
* @exception IllegalStateException if this key agreement has not been initialized.
*/
protected abstract Key engineDoPhase(
Key key,
boolean lastPhase)
throws InvalidKeyException, IllegalStateException;
/**
* Generates the shared secret and returns it in a new buffer.
* <p>
* This method resets this <code>KeyAgreementSpi</code> object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>engineInit</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
* @return the new buffer with the shared secret
* @exception IllegalStateException if this key agreement has not been completed yet
*/
protected abstract byte[] engineGenerateSecret()
throws IllegalStateException;
/**
* Generates the shared secret, and places it into the buffer
* <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
* <p>
* If the <code>sharedSecret</code> buffer is too small to hold the result,
* a <code>ShortBufferException</code> is thrown. In this case, this call should be
* repeated with a larger output buffer.
* <p>
* This method resets this <code>KeyAgreementSpi</code> object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>engineInit</code> methods, the same
* private information and algorithm parameters will be used for subsequent key agreements.
*
* @param sharedSecret the buffer for the shared secret
* @param offset the offset in <code>sharedSecret</code> where the shared secret will be stored
* @return the number of bytes placed into <code>sharedSecret</code>
* @exception IllegalStateException if this key agreement has not been completed yet
* @exception ShortBufferException if the given output buffer is too small to hold the secret
*/
protected abstract int engineGenerateSecret(
byte[] sharedSecret,
int offset)
throws IllegalStateException, ShortBufferException;
/**
* Creates the shared secret and returns it as a secret key object
* of the requested algorithm type.
* <p>
* This method resets this <code>KeyAgreementSpi</code> object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>engineInit</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @param algorithm the requested secret key algorithm
* @return the shared secret key
* @exception IllegalStateException if this key agreement has not been completed yet
* @exception NoSuchAlgorithmException if the requested secret key algorithm is not available
* @exception InvalidKeyException if the shared secret key material cannot be used to generate
* a secret key of the requested algorithm type (e.g., the key material is too short)
*/
protected abstract SecretKey engineGenerateSecret(
String algorithm)
throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException;
}

View File

@@ -0,0 +1,302 @@
package javax.crypto;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class provides the functionality of a (symmetric) key generator.
* <p>
* Key generators are constructed using one of the <code>getInstance</code>
* class methods of this class.
* <p>
* KeyGenerator objects are reusable, i.e., after a key has been
* generated, the same KeyGenerator object can be re-used to generate further
* keys.
* <p>
* There are two ways to generate a key: in an algorithm-independent manner,
* and in an algorithm-specific manner. The only difference between the two is
* the initialization of the object:
*
* <ul>
* <li><b>Algorithm-Independent Initialization</b>
* <p>All key generators share the concepts of a <i>keysize</i> and a
* <i>source of randomness</i>.
* There is an
* <a href = "#init(int, java.security.SecureRandom)">init</a>
* method in this KeyGenerator class that takes these two universally
* shared types of arguments. There is also one that takes just a
* <code>keysize</code> argument, and uses the SecureRandom implementation
* of the highest-priority installed provider as the source of randomness
* (or a system-provided source of randomness if none of the installed
* providers supply a SecureRandom implementation), and one that takes just a
* source of randomness.
* <p>
* Since no other parameters are specified when you call the above
* algorithm-independent <code>init</code> methods, it is up to the
* provider what to do about the algorithm-specific parameters (if any) to be
* associated with each of the keys.
* <p>
* <li><b>Algorithm-Specific Initialization</b>
* <p>For situations where a set of algorithm-specific parameters already
* exists, there are two
* <a href = "#init(java.security.spec.AlgorithmParameterSpec)">init</a>
* methods that have an <code>AlgorithmParameterSpec</code>
* argument. One also has a <code>SecureRandom</code> argument, while the
* other uses the SecureRandom implementation
* of the highest-priority installed provider as the source of randomness
* (or a system-provided source of randomness if none of the installed
* providers supply a SecureRandom implementation).
* </ul>
*
* <p>In case the client does not explicitly initialize the KeyGenerator
* (via a call to an <code>init</code> method), each provider must
* supply (and document) a default initialization.
*
* @see SecretKey
*/
public class KeyGenerator
{
private KeyGeneratorSpi keyGenerator;
private Provider provider;
private String algorithm;
/**
* Creates a KeyGenerator object.
*
* @param keyGenSpi the delegate
* @param provider the provider
* @param algorithm the algorithm
*/
protected KeyGenerator(
KeyGeneratorSpi keyGenSpi,
Provider provider,
String algorithm)
{
this.keyGenerator = keyGenSpi;
this.provider = provider;
this.algorithm = algorithm;
}
/**
* Returns the algorithm name of this <code>KeyGenerator</code> object.
* <p>
* This is the same name that was specified in one of the
* <code>getInstance</code> calls that created this
* <code>KeyGenerator</code> object.
*
* @return the algorithm name of this <code>KeyGenerator</code> object.
*/
public final String getAlgorithm()
{
return algorithm;
}
/**
* Generates a <code>KeyGenerator</code> object for the specified algorithm.
* If the default provider package provides an implementation of the
* requested key generator, an instance of <code>KeyGenerator</code> containing
* that implementation is returned. If the requested key generator is not available
* in the default provider package, other provider packages are searched.
*
* @param algorithm the standard name of the requested key algorithm. See Appendix A in the
* Java Cryptography Extension API Specification &amp; Reference for information about standard
* algorithm names.
* @return the new <code>KeyGenerator</code> object
* @exception NoSuchAlgorithmException if a key generator for the specified algorithm is not
* available in the default provider package or any of the other provider packages that were searched.
*/
public static final KeyGenerator getInstance(
String algorithm)
throws NoSuchAlgorithmException
{
try
{
JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyGenerator", algorithm, (String) null);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
KeyGenerator keyGen = new KeyGenerator((KeyGeneratorSpi)imp.getEngine(), imp.getProvider(), algorithm);
return keyGen;
}
catch (NoSuchProviderException e)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
}
/**
* Generates a <code>KeyGenerator</code> object for the specified key
* algorithm from the specified provider.
*
* @param algorithm the standard name of the requested key algorithm. See Appendix A in the
* Java Cryptography Extension API Specification &amp; Reference for information about standard
* algorithm names.
* @param provider the provider
* @return the new <code>KeyGenerator</code> object
* @exception NoSuchAlgorithmException if a key generator for the specified algorithm is not
* available from the specified provider.
*/
public static final KeyGenerator getInstance(
String algorithm,
Provider provider)
throws NoSuchAlgorithmException
{
if (provider == null)
{
throw new IllegalArgumentException("No provider specified to KeyGenerator.getInstance()");
}
JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyGenerator", algorithm, provider);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
KeyGenerator keyGen = new KeyGenerator((KeyGeneratorSpi)imp.getEngine(), imp.getProvider(), algorithm);
return keyGen;
}
/**
* Generates a <code>KeyGenerator</code> object for the specified key
* algorithm from the specified provider.
*
* @param algorithm the standard name of the requested key algorithm. See Appendix A in the
* Java Cryptography Extension API Specification &amp; Reference for information about standard
* algorithm names.
* @param provider the name of the provider
* @return the new <code>KeyGenerator</code> object
* @exception NoSuchAlgorithmException if a key generator for the specified algorithm is not
* available from the specified provider.
* @exception NoSuchProviderException if the specified provider has not been configured.
*/
public static final KeyGenerator getInstance(
String algorithm,
String provider)
throws NoSuchAlgorithmException, NoSuchProviderException
{
if (provider == null)
{
throw new IllegalArgumentException("No provider specified to KeyGenerator.getInstance()");
}
JCEUtil.Implementation imp = JCEUtil.getImplementation("KeyGenerator", algorithm, provider);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
KeyGenerator keyGen = new KeyGenerator((KeyGeneratorSpi)imp.getEngine(), imp.getProvider(), algorithm);
return keyGen;
}
/**
* Returns the provider of this <code>KeyGenerator</code> object.
*
* @return the provider of this <code>KeyGenerator</code> object
*/
public final Provider getProvider()
{
return provider;
}
/**
* Initializes this key generator.
*
* @param random the source of randomness for this generator
*/
public final void init(
SecureRandom random)
{
keyGenerator.engineInit(random);
}
/**
* Initializes this key generator with the specified parameter set.
* <p>
* If this key generator requires any random bytes, it will get them
* using the * <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html">
* <code>SecureRandom</code></a> implementation of the highest-priority installed
* provider as the source of randomness.
* (If none of the installed providers supply an implementation of
* SecureRandom, a system-provided source of randomness will be used.)
*
* @param params the key generation parameters
* @exception InvalidAlgorithmParameterException if the given parameters are inappropriate
* for this key generator
*/
public final void init(
AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException
{
keyGenerator.engineInit(params, new SecureRandom());
}
/**
* Initializes this key generator with the specified parameter set and a user-provided source of randomness.
*
* @param params the key generation parameters
* @param random the source of randomness for this key generator
* @exception InvalidAlgorithmParameterException if <code>params</code> is inappropriate for this key generator
*/
public final void init(
AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidAlgorithmParameterException
{
keyGenerator.engineInit(params, random);
}
/**
* Initializes this key generator for a certain keysize.
* <p>
* If this key generator requires any random bytes, it will get them using the
* <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.SecureRandom.html">
* <code>SecureRandom</code></a> implementation of the highest-priority installed provider as
* the source of randomness. (If none of the installed providers supply an implementation of
* SecureRandom, a system-provided source of randomness will be used.)
*
* @param keysize the keysize. This is an algorithm-specific metric, specified in number of bits.
* @exception InvalidParameterException if the keysize is wrong or not supported.
*/
public final void init(
int keysize)
{
keyGenerator.engineInit(keysize, new SecureRandom());
}
/**
* Initializes this key generator for a certain keysize, using a user-provided source of randomness.
*
* @param keysize the keysize. This is an algorithm-specific metric, specified in number of bits.
* @param random the source of randomness for this key generator
* @exception InvalidParameterException if the keysize is wrong or not supported.
*/
public final void init(
int keysize,
SecureRandom random)
{
keyGenerator.engineInit(keysize, random);
}
/**
* Generates a secret key.
*
* @return the new key
*/
public final SecretKey generateKey()
{
return keyGenerator.engineGenerateKey();
}
}

View File

@@ -0,0 +1,64 @@
package javax.crypto;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.InvalidParameterException;
import java.security.InvalidAlgorithmParameterException;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>KeyGenerator</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a key generator for a particular algorithm.
*
* @see SecretKey
*/
public abstract class KeyGeneratorSpi
{
public KeyGeneratorSpi()
{
}
/**
* Initializes the key generator.
*
* @param random the source of randomness for this generator
*/
protected abstract void engineInit(
SecureRandom random);
/**
* Initializes the key generator with the specified parameter
* set and a user-provided source of randomness.
*
* @param params the key generation parameters
* @param random the source of randomness for this key generator
* @exception InvalidAlgorithmParameterException if <code>params</code> is
* inappropriate for this key generator
*/
protected abstract void engineInit(
AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidAlgorithmParameterException;
/**
* Initializes this key generator for a certain keysize, using the given
* source of randomness.
*
* @param keysize the keysize. This is an algorithm-specific metric, specified in number of bits.
* @param random the source of randomness for this key generator.
* @exception InvalidParameterException if keysize is wrong or not supported.
*/
protected abstract void engineInit(
int keysize,
SecureRandom random)
throws InvalidParameterException;
/**
* Generates a secret key.
*
* @return the new key.
*/
protected abstract SecretKey engineGenerateKey();
}

View File

@@ -0,0 +1,443 @@
package javax.crypto;
import java.security.Provider;
import java.security.Key;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.InvalidAlgorithmParameterException;
/**
* This class provides the functionality of a "Message Authentication Code"
* (MAC) algorithm.
* <p>
* A MAC provides a way to check the integrity of information transmitted over
* or stored in an unreliable medium, based on a secret key. Typically, message
* authentication codes are used between two parties that share a secret
* key in order to validate information transmitted between these
* parties.
* <p>
* A MAC mechanism that is based on cryptographic hash functions is
* referred to as HMAC. HMAC can be used with any cryptographic hash function,
* e.g., MD5 or SHA-1, in combination with a secret shared key. HMAC is
* specified in RFC 2104.
*/
public class Mac
implements Cloneable
{
MacSpi macSpi;
Provider provider;
String algorithm;
private boolean initialised = false;
/**
* Creates a MAC object.
*
* @param macSpi the delegate
* @param provider the provider
* @param algorithm the algorithm
*/
protected Mac(
MacSpi macSpi,
Provider provider,
String algorithm)
{
this.macSpi = macSpi;
this.provider = provider;
this.algorithm = algorithm;
}
/**
* Returns the algorithm name of this <code>Mac</code> object.
* <p>
* This is the same name that was specified in one of the
* <code>getInstance</code> calls that created this <code>Mac</code> object.
*
* @return the algorithm name of this <code>Mac</code> object.
*/
public final String getAlgorithm()
{
return algorithm;
}
/**
* Generates an <code>Mac</code> object that implements the
* specified MAC algorithm.
* If the default provider package provides an implementation of the
* requested MAC algorithm, an instance of
* <code>Mac</code> containing that implementation is returned.
* If the algorithm is not available in the default provider package,
* other provider packages are searched.
*
* @param algorithm the standard name of the requested MAC algorithm.
* See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
* for information about standard algorithm names.
* @return the new <code>Mac</code> object.
* @exception NoSuchAlgorithmException if the specified algorithm is not
* available in the default provider package or any of the other provider
* packages that were searched.
*/
public static final Mac getInstance(
String algorithm)
throws NoSuchAlgorithmException
{
try
{
JCEUtil.Implementation imp = JCEUtil.getImplementation("Mac", algorithm, (String) null);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
Mac mac = new Mac((MacSpi)imp.getEngine(), imp.getProvider(), algorithm);
return mac;
}
catch (NoSuchProviderException e)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
}
/**
* Generates an <code>Mac</code> object for the specified MAC
* algorithm from the specified provider.
*
* @param algorithm the standard name of the requested MAC algorithm.
* See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
* for information about standard algorithm names.
* @param provider the name of the provider.
* @return the new <code>Mac</code> object.
* @exception NoSuchAlgorithmException if the specified algorithm is not available from the
* specified provider.
* @exception NoSuchProviderException if the specified provider has not been configured.
*/
public static final Mac getInstance(
String algorithm,
String provider)
throws NoSuchAlgorithmException, NoSuchProviderException
{
if (provider == null)
{
throw new IllegalArgumentException("No provider specified to Mac.getInstance()");
}
JCEUtil.Implementation imp = JCEUtil.getImplementation("Mac", algorithm, provider);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
Mac mac = new Mac((MacSpi)imp.getEngine(), imp.getProvider(), algorithm);
return mac;
}
/**
* Generates an <code>Mac</code> object for the specified MAC
* algorithm from the specified provider.
*
* @param algorithm the standard name of the requested MAC algorithm.
* See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
* for information about standard algorithm names.
* @param provider the provider.
* @return the new <code>Mac</code> object.
* @exception NoSuchAlgorithmException if the specified algorithm is not available from the
* specified provider.
*/
public static final Mac getInstance(
String algorithm,
Provider provider)
throws NoSuchAlgorithmException
{
if (provider == null)
{
throw new IllegalArgumentException("No provider specified to Mac.getInstance()");
}
JCEUtil.Implementation imp = JCEUtil.getImplementation("Mac", algorithm, provider);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
Mac mac = new Mac((MacSpi)imp.getEngine(), imp.getProvider(), algorithm);
return mac;
}
/**
* Returns the provider of this <code>Mac</code> object.
*
* @return the provider of this <code>Mac</code> object.
*/
public final Provider getProvider()
{
return provider;
}
/**
* Returns the length of the MAC in bytes.
*
* @return the MAC length in bytes.
*/
public final int getMacLength()
{
return macSpi.engineGetMacLength();
}
/**
* Initializes this <code>Mac</code> object with the given key.
*
* @param key the key.
* @exception InvalidKeyException if the given key is inappropriate for initializing this MAC.
*/
public final void init(
Key key)
throws InvalidKeyException
{
try
{
macSpi.engineInit(key, null);
initialised = true;
}
catch (InvalidAlgorithmParameterException e)
{
throw new IllegalArgumentException("underlying mac waon't work without an AlgorithmParameterSpec");
}
}
/**
* Initializes this <code>Mac</code> object with the given key and
* algorithm parameters.
*
* @param key the key.
* @param params the algorithm parameters.
* @exception InvalidKeyException if the given key is inappropriate for initializing this MAC.
* @exception InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate
* for this MAC.
*/
public final void init(
Key key,
AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
macSpi.engineInit(key, params);
initialised = true;
}
/**
* Processes the given byte.
*
* @param input the input byte to be processed.
* @exception IllegalStateException if this <code>Mac</code> has not been initialized.
*/
public final void update(
byte input)
throws IllegalStateException
{
if (!initialised)
{
throw new IllegalStateException("MAC not initialised");
}
macSpi.engineUpdate(input);
}
/**
* Processes the given array of bytes.
*
* @param input the array of bytes to be processed.
* @exception IllegalStateException if this <code>Mac</code> has not been initialized.
*/
public final void update(
byte[] input)
throws IllegalStateException
{
if (!initialised)
{
throw new IllegalStateException("MAC not initialised");
}
if (input == null)
{
return;
}
macSpi.engineUpdate(input, 0, input.length);
}
/**
* Processes the first <code>len</code> bytes in <code>input</code>,
* starting at <code>offset</code> inclusive.
*
* @param input the input buffer.
* @param offset the offset in <code>input</code> where the input starts.
* @param len the number of bytes to process.
* @exception IllegalStateException if this <code>Mac</code> has not been initialized.
*/
public final void update(
byte[] input,
int offset,
int len)
throws IllegalStateException
{
if (!initialised)
{
throw new IllegalStateException("MAC not initialised");
}
if (input == null)
{
throw new IllegalArgumentException("Null input passed");
}
if (len < 0 || offset < 0 || len > (input.length - offset))
{
throw new IllegalArgumentException("Bad offset/len");
}
if (input.length == 0)
{
return;
}
macSpi.engineUpdate(input, offset, len);
}
/**
* Finishes the MAC operation.
* <p>
* A call to this method resets this <code>Mac</code> object to the
* state it was in when previously initialized via a call to <code>init(Key)</code> or
* <code>init(Key, AlgorithmParameterSpec)</code>.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to <code>update</code> and
* <code>doFinal</code>.
* (In order to reuse this <code>Mac</code> object with a different key,
* it must be reinitialized via a call to <code>init(Key)</code> or
* <code>init(Key, AlgorithmParameterSpec)</code>.
*
* @return the MAC result.
* @exception IllegalStateException if this <code>Mac</code> has not been initialized.
*/
public final byte[] doFinal()
throws IllegalStateException
{
if (!initialised)
{
throw new IllegalStateException("MAC not initialised");
}
return macSpi.engineDoFinal();
}
/**
* Finishes the MAC operation.
*
* <p>A call to this method resets this <code>Mac</code> object to the
* state it was in when previously initialized via a call to
* <code>init(Key)</code> or
* <code>init(Key, AlgorithmParameterSpec)</code>.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to <code>update</code> and
* <code>doFinal</code>.
* (In order to reuse this <code>Mac</code> object with a different key,
* it must be reinitialized via a call to <code>init(Key)</code> or
* <code>init(Key, AlgorithmParameterSpec)</code>.
* <p>
* The MAC result is stored in <code>output</code>, starting at
* <code>outOffset</code> inclusive.
*
* @param output the buffer where the MAC result is stored
* @param outOffset the offset in <code>output</code> where the MAC is stored
* @exception ShortBufferException if the given output buffer is too small to hold the result
* @exception IllegalStateException if this <code>Mac</code> has not been initialized.
*/
public final void doFinal(
byte[] output,
int outOffset)
throws ShortBufferException, IllegalStateException
{
if (!initialised)
{
throw new IllegalStateException("MAC not initialised");
}
if ((output.length - outOffset) < macSpi.engineGetMacLength())
{
throw new ShortBufferException("buffer to short for MAC output");
}
byte[] mac = macSpi.engineDoFinal();
System.arraycopy(mac, 0, output, outOffset, mac.length);
}
/**
* Processes the given array of bytes and finishes the MAC operation.
* <p>
* A call to this method resets this <code>Mac</code> object to the
* state it was in when previously initialized via a call to <code>init(Key)</code> or
* <code>init(Key, AlgorithmParameterSpec)</code>. That is, the object is reset and
* available to generate another MAC from the same key, if desired, via new calls to
* <code>update</code> and <code>doFinal</code>.
* (In order to reuse this <code>Mac</code> object with a different key,
* it must be reinitialized via a call to <code>init(Key)</code> or
* <code>init(Key, AlgorithmParameterSpec)</code>.
*
* @return the MAC result.
* @exception IllegalStateException if this <code>Mac</code> has not been initialized.
*/
public final byte[] doFinal(
byte[] input)
throws IllegalStateException
{
if (!initialised)
{
throw new IllegalStateException("MAC not initialised");
}
macSpi.engineUpdate(input, 0, input.length);
return macSpi.engineDoFinal();
}
/**
* Resets this <code>Mac</code> object.
* <p>
* A call to this method resets this <code>Mac</code> object to the
* state it was in when previously initialized via a call to
* <code>init(Key)</code> or <code>init(Key, AlgorithmParameterSpec)</code>.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to <code>update</code> and
* <code>doFinal</code>.
* (In order to reuse this <code>Mac</code> object with a different key,
* it must be reinitialized via a call to <code>init(Key)</code> or
* <code>init(Key, AlgorithmParameterSpec)</code>.
*/
public final void reset()
{
macSpi.engineReset();
}
/**
* Returns a clone if the provider implementation is cloneable.
*
* @return a clone if the provider implementation is cloneable.
* @exception CloneNotSupportedException if this is called on a delegate that does
* not support <code>Cloneable</code>.
*/
public final Object clone()
throws CloneNotSupportedException
{
Mac result = new Mac((MacSpi)macSpi.clone(), provider, algorithm);
result.initialised = initialised;
return result;
}
}

View File

@@ -0,0 +1,92 @@
package javax.crypto;
import java.security.Key;
import java.security.InvalidKeyException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>Mac</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a particular MAC algorithm.
* <p>
* Implementations are free to implement the Cloneable interface.
*/
public abstract class MacSpi
{
public MacSpi()
{
}
/**
* Returns the length of the MAC in bytes.
*
* @return the MAC length in bytes.
*/
protected abstract int engineGetMacLength();
/**
* Initializes the MAC with the given (secret) key and algorithm
* parameters.
*
* @param key - the (secret) key.
* @param params - the algorithm parameters.
* @exception InvalidKeyException if the given key is inappropriate for initializing this MAC.
* @exception InvalidAlgorithmParameterException - if the given algorithm parameters are inappropriate
* for this MAC.
*/
protected abstract void engineInit(
Key key,
AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Processes the given byte.
*
* @param input - the input byte to be processed.
*/
protected abstract void engineUpdate(
byte input);
/**
* Processes the first <code>len</code> bytes in <code>input</code>,
* starting at <code>offset</code> inclusive.
*
* @param input the input buffer.
* @param offset the offset in <code>input</code> where the input starts.
* @param len the number of bytes to process.
*/
protected abstract void engineUpdate(
byte[] input,
int offset,
int len);
/**
* Completes the MAC computation and resets the MAC for further use,
* maintaining the secret key that the MAC was initialized with.
*
* @return the MAC result.
*/
protected abstract byte[] engineDoFinal();
/**
* Resets the MAC for further use, maintaining the secret key that the
* MAC was initialized with.
*/
protected abstract void engineReset();
/**
* Returns a clone if the implementation is cloneable.
*
* @return a clone if the implementation is cloneable.
* @exception CloneNotSupportedException if this is called on an implementation that does not support
* <code>Cloneable</code>.
*/
public Object clone()
throws CloneNotSupportedException
{
throw new CloneNotSupportedException("Underlying MAC does not support cloning");
}
}

View File

@@ -0,0 +1,36 @@
package javax.crypto;
import java.security.GeneralSecurityException;
/**
* This exception is thrown when a particular padding mechanism is
* requested but is not available in the environment.
*/
public class NoSuchPaddingException
extends GeneralSecurityException
{
private static final long serialVersionUID = -4572885201200175466L;
/**
* Constructs a NoSuchPaddingException with no detail
* message. A detail message is a String that describes this
* particular exception.
*/
public NoSuchPaddingException()
{
}
/**
* Constructs a NoSuchPaddingException with the specified
* detail message. A detail message is a String that describes
* this particular exception, which may, for example, specify which
* algorithm is not available.
*
* @param msg - the detail message.
*/
public NoSuchPaddingException(
String msg)
{
super(msg);
}
}

View File

@@ -0,0 +1,240 @@
package javax.crypto;
import java.security.Key;
import java.security.SecureRandom;
import java.security.InvalidKeyException;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
/**
* The NullCipher class is a class that provides an
* "identity cipher" -- one that does not tranform the plaintext. As
* a consequence, the ciphertext is identical to the plaintext. All
* initialization methods do nothing, while the blocksize is set to 1
* byte.
*
* @since JCE1.2
*/
public class NullCipher
extends Cipher
{
static private class NullCipherSpi
extends CipherSpi
{
/**
* Sets the mode of this cipher - no op.
*/
protected void engineSetMode(
String mode)
throws NoSuchAlgorithmException
{
}
/**
* Sets the padding mechanism of this cipher - no op.
*/
protected void engineSetPadding(
String padding)
throws NoSuchPaddingException
{
}
/**
* Returns the block size (in bytes) - 1
*/
protected int engineGetBlockSize()
{
return 1;
}
/**
* Returns the length in bytes that an output buffer would
* need to be in order to hold the result of the next <code>update</code>
* or <code>doFinal</code> operation, given the input length
* <code>inputLen</code> (in bytes).
*
* @param inputLen the input length (in bytes)
* @return the required output buffer size (in bytes)
*/
protected int engineGetOutputSize(
int inputLen)
{
return inputLen;
}
/**
* Returns the initialization vector (IV) in a new buffer.
*
* @return null
*/
protected byte[] engineGetIV()
{
return null;
}
/**
* Returns the parameters used with this cipher - null
*/
protected AlgorithmParameters engineGetParameters()
{
return null;
}
/**
* Initializes this cipher with a key and a source
* of randomness - no op.
*/
protected void engineInit(
int opmode,
Key key,
SecureRandom random)
throws InvalidKeyException
{
}
/**
* Initializes this cipher with a key, a set of
* algorithm parameters, and a source of randomness - no op.
*/
protected void engineInit(
int opmode,
Key key,
AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
}
/**
* Initializes this cipher with a key, a set of
* algorithm parameters, and a source of randomness - no op.
*/
protected void engineInit(
int opmode,
Key key,
AlgorithmParameters params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
}
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialized), processing another data
* part - in this case just return a copy of the input.
*/
protected byte[] engineUpdate(
byte[] input,
int inputOffset,
int inputLen)
{
if (input == null)
{
return null;
}
byte[] tmp = new byte[inputLen];
System.arraycopy(input, inputOffset, tmp, 0, inputLen);
return tmp;
}
/**
* Continues a multiple-part encryption or decryption operation
* (depending on how this cipher was initialized), processing another data
* part - in this case just copy the input to the output.
*/
protected int engineUpdate(
byte[] input,
int inputOffset,
int inputLen,
byte[] output,
int outputOffset)
throws ShortBufferException
{
if (input == null)
{
return 0;
}
if ((output.length - outputOffset) < inputLen)
{
throw new ShortBufferException("output buffer to short for NullCipher");
}
System.arraycopy(input, inputOffset, output, outputOffset, inputLen);
return inputLen;
}
/**
* Encrypts or decrypts data in a single-part operation, or finishes a multiple-part operation.
* The data is encrypted or decrypted, depending on how this cipher was initialized
* - in this case just return a copy of the input.
*/
protected byte[] engineDoFinal(
byte[] input,
int inputOffset,
int inputLen)
throws IllegalBlockSizeException, BadPaddingException
{
if (input == null)
{
return new byte[0];
}
byte[] tmp = new byte[inputLen];
System.arraycopy(input, inputOffset, tmp, 0, inputLen);
return tmp;
}
/**
* Encrypts or decrypts data in a single-part operation,
* or finishes a multiple-part operation.
* The data is encrypted or decrypted, depending on how this cipher was
* initialized.
*/
protected int engineDoFinal(
byte[] input,
int inputOffset,
int inputLen,
byte[] output,
int outputOffset)
throws ShortBufferException, IllegalBlockSizeException, BadPaddingException
{
if (input == null)
{
return 0;
}
if ((output.length - outputOffset) < inputLen)
{
throw new ShortBufferException("output buffer too short for NullCipher");
}
System.arraycopy(input, inputOffset, output, outputOffset, inputLen);
return inputLen;
}
/**
* Returns the key size of the given key object - 0
*/
protected int engineGetKeySize(
Key key)
throws InvalidKeyException
{
return 0;
}
}
public NullCipher()
{
super(new NullCipherSpi(), null, "NULL");
}
}

View File

@@ -0,0 +1,302 @@
package javax.crypto;
import java.io.*;
import java.security.*;
/**
* This class enables a programmer to create an object and protect its
* confidentiality with a cryptographic algorithm.
*
* <p>
* Given any Serializable object, one can create a SealedObject
* that encapsulates the original object, in serialized
* format (i.e., a "deep copy"), and seals (encrypts) its serialized contents,
* using a cryptographic algorithm such as DES, to protect its
* confidentiality. The encrypted content can later be decrypted (with
* the corresponding algorithm using the correct decryption key) and
* de-serialized, yielding the original object.
*
* <p>
* Note that the Cipher object must be fully initialized with the
* correct algorithm, key, padding scheme, etc., before being applied
* to a SealedObject.
*
* <p>
* The original object that was sealed can be recovered in two different
* ways:
* <p>
*
* <ul>
*
* <li>by using the <a href="#getObject(javax.crypto.Cipher)">getObject</a>
* method that takes a <code>Cipher</code> object.
*
* <p>
* This method requires a fully initialized <code>Cipher</code> object,
* initialized with the
* exact same algorithm, key, padding scheme, etc., that were used to seal the
* object.
*
* <p>
* This approach has the advantage that the party who unseals the
* sealed object does not require knowledge of the decryption key. For example,
* after one party has initialized the cipher object with the required
* decryption key, it could hand over the cipher object to
* another party who then unseals the sealed object.
*
* <p>
*
* <li>by using one of the
* <a href="#getObject(java.security.Key)">getObject</a> methods
* that take a <code>Key</code> object.
*
* <p> In this approach, the <code>getObject</code> method creates a cipher
* object for the appropriate decryption algorithm and initializes it with the
* given decryption key and the algorithm parameters (if any) that were stored
* in the sealed object.
*
* <p> This approach has the advantage that the party who
* unseals the object does not need to keep track of the parameters (e.g., an
* IV) that were used to seal the object.
*
* </ul>
*
* @see Cipher
*/
public class SealedObject
implements Serializable
{
private static final long serialVersionUID = 4482838265551344752L;
private byte[] encodedParams;
private byte[] encryptedContent;
private String paramsAlg;
private String sealAlg;
/**
* Constructs a SealedObject from any Serializable object.
* <p>
* The given object is serialized, and its serialized contents are
* encrypted using the given Cipher, which must be fully initialized.
* <p>
* Any algorithm parameters that may be used in the encryption
* operation are stored inside of the new <code>SealedObject</code>.
*
* @param object the object to be sealed.
* @param c the cipher used to seal the object.
* @exception IOException if an error occurs during serialization
* @exception IllegalBlockSizeException if the given cipher is a block
* cipher, no padding has been requested, and the total input length
* (i.e., the length of the serialized object contents) is not a multiple
* of the cipher's block size
*/
public SealedObject(
Serializable object,
Cipher c)
throws IOException, IllegalBlockSizeException
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ObjectOutputStream oOut = new ObjectOutputStream(bOut);
oOut.writeObject(object);
oOut.close();
byte[] encodedObject = bOut.toByteArray();
if (c == null)
{
throw new IllegalArgumentException("cipher object is null!");
}
try
{
this.encryptedContent = c.doFinal(encodedObject);
}
catch (BadPaddingException e)
{
// should not happen
throw new IOException(e.getMessage());
}
this.sealAlg = c.getAlgorithm();
AlgorithmParameters params = c.getParameters();
if (params != null)
{
this.encodedParams = params.getEncoded();
this.paramsAlg = params.getAlgorithm();
}
}
/**
* Returns the algorithm that was used to seal this object.
*
* @return the algorithm that was used to seal this object.
*/
public final String getAlgorithm()
{
return sealAlg;
}
/**
* Retrieves the original (encapsulated) object.
* <p>
* This method creates a cipher for the algorithm that had been used in
* the sealing operation.
* If the default provider package provides an implementation of that
* algorithm, an instance of Cipher containing that implementation is used.
* If the algorithm is not available in the default package, other
* packages are searched.
* The Cipher object is initialized for decryption, using the given
* <code>key</code> and the parameters (if any) that had been used in the
* sealing operation.
* <p>
* The encapsulated object is unsealed and de-serialized, before it is
* returned.
*
* @param key the key used to unseal the object.
* @return the original object.
* @exception IOException if an error occurs during de-serialiazation.
* @exception ClassNotFoundException if an error occurs during de-serialiazation.
* @exception NoSuchAlgorithmException if the algorithm to unseal the object is not available.
* @exception InvalidKeyException if the given key cannot be used to unseal
* the object (e.g., it has the wrong algorithm).
*/
public final Object getObject(
Key key)
throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeyException
{
if (key == null)
{
throw new IllegalArgumentException("key object is null!");
}
try
{
return getObject(key, null);
}
catch (NoSuchProviderException e)
{
throw new NoSuchAlgorithmException(e.getMessage());
}
}
/**
* Retrieves the original (encapsulated) object.
* <p>
* The encapsulated object is unsealed (using the given Cipher,
* assuming that the Cipher is already properly initialized) and
* de-serialized, before it is returned.
*
* @param c the cipher used to unseal the object
* @return the original object.
* @exception IOException if an error occurs during de-serialiazation
* @exception ClassNotFoundException if an error occurs during de-serialiazation
* @exception IllegalBlockSizeException if the given cipher is a block
* cipher, no padding has been requested, and the total input length is
* not a multiple of the cipher's block size
* @exception BadPaddingException if the given cipher has been
* initialized for decryption, and padding has been specified, but
* the input data does not have proper expected padding bytes
*/
public final Object getObject(
Cipher c)
throws IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException
{
if (c == null)
{
throw new IllegalArgumentException("cipher object is null!");
}
byte[] encodedObject = c.doFinal(encryptedContent);
ObjectInputStream oIn = new ObjectInputStream(
new ByteArrayInputStream(encodedObject));
return oIn.readObject();
}
/**
* Retrieves the original (encapsulated) object.
* <p>
* This method creates a cipher for the algorithm that had been used in
* the sealing operation, using an implementation of that algorithm from
* the given <code>provider</code>.
* The Cipher object is initialized for decryption, using the given
* <code>key</code> and the parameters (if any) that had been used in the
* sealing operation.
* <p>
* The encapsulated object is unsealed and de-serialized, before it is
* returned.
*
* @param key the key used to unseal the object.
* @param provider the name of the provider of the algorithm to unseal
* the object.
* @return the original object.
* @exception IOException if an error occurs during de-serialiazation.
* @exception ClassNotFoundException if an error occurs during
* de-serialization.
* @exception NoSuchAlgorithmException if the algorithm to unseal the
* object is not available.
* @exception NoSuchProviderException if the given provider is not
* configured.
* @exception InvalidKeyException if the given key cannot be used to unseal
* the object (e.g., it has the wrong algorithm).
*/
public final Object getObject(
Key key,
String provider)
throws IOException, ClassNotFoundException,
NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
{
if (key == null)
{
throw new IllegalArgumentException("key object is null!");
}
Cipher cipher = null;
try
{
if (provider != null)
{
cipher = Cipher.getInstance(sealAlg, provider);
}
else
{
cipher = Cipher.getInstance(sealAlg);
}
}
catch (NoSuchPaddingException e)
{
throw new NoSuchAlgorithmException(e.getMessage());
}
if (paramsAlg == null)
{
cipher.init(Cipher.DECRYPT_MODE, key);
}
else
{
AlgorithmParameters algParams =
AlgorithmParameters.getInstance(paramsAlg);
algParams.init(encodedParams);
try
{
cipher.init(Cipher.DECRYPT_MODE, key, algParams);
}
catch (InvalidAlgorithmParameterException e)
{
throw new IOException(e.getMessage());
}
}
try
{
return getObject(cipher);
}
catch (BadPaddingException e)
{
throw new IOException(e.getMessage());
}
catch (IllegalBlockSizeException e2)
{
throw new IOException(e2.getMessage());
}
}
}

View File

@@ -0,0 +1,28 @@
package javax.crypto;
import java.security.Key;
/**
* A secret (symmetric) key.
* <p>
* This interface contains no methods or constants.
* Its only purpose is to group (and provide type safety for) secret keys.
* <p>
* Provider implementations of this interface must overwrite the
* <code>equals</code> and <code>hashCode</code> methods inherited from
* <code>java.lang.Object</code>, so that secret keys are compared based on
* their underlying key material and not based on reference.
* <p>
* Keys that implement this interface return the string <code>RAW</code>
* as their encoding format (see <code>getFormat</code>), and return the
* raw key bytes as the result of a <code>getEncoded</code> method call. (The
* <code>getFormat</code> and <code>getEncoded</code> methods are inherited
* from the <code>java.security.Key</code> parent interface.)
*
* @see SecretKeyFactory
* @see Cipher
*/
public abstract interface SecretKey
extends Key
{
}

View File

@@ -0,0 +1,245 @@
package javax.crypto;
import java.security.Provider;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.KeySpec;
import java.security.spec.InvalidKeySpecException;
/**
* This class represents a factory for secret keys.
*
* <p>
* Key factories are used to convert <I>keys</I> (opaque
* cryptographic keys of type <code>Key</code>) into <I>key specifications</I>
* (transparent representations of the underlying key material), and vice versa.
* Secret key factories operate only on secret (symmetric) keys.
* <p>
* Key factories are bi-directional, i.e., they allow to build an opaque
* key object from a given key specification (key material), or to retrieve
* the underlying key material of a key object in a suitable format.
* <p>
* Application developers should refer to their provider's documentation
* to find out which key specifications are supported by the
* <a href="#generateSecret(java.security.spec.KeySpec)">generateSecret</a> and
* <a href="#getKeySpec(javax.crypto.SecretKey, java.lang.Class)">getKeySpec</a> methods.
* For example, the DES secret-key factory supplied by the "SunJCE" provider
* supports <code>DESKeySpec</code> as a transparent representation of DES
* keys, and that provider's secret-key factory for Triple DES keys supports
* <code>DESedeKeySpec</code> as a transparent representation of Triple DES keys.
*
* @see SecretKey
* @see javax.crypto.spec.DESKeySpec
* @see javax.crypto.spec.DESedeKeySpec
* @see javax.crypto.spec.PBEKeySpec
*/
public class SecretKeyFactory
{
SecretKeyFactorySpi keyFacSpi;
Provider provider;
String algorithm;
/**
* Creates a SecretKeyFactory object.
*
* @param keyFacSpi the delegate
* @param provider the provider
* @param algorithm the secret-key algorithm
*/
protected SecretKeyFactory(
SecretKeyFactorySpi keyFacSpi,
Provider provider,
String algorithm)
{
this.keyFacSpi = keyFacSpi;
this.provider = provider;
this.algorithm = algorithm;
}
/**
* Generates a <code>SecretKeyFactory</code> object for the specified secret-key algorithm.
* If the default provider package provides an implementation of the
* requested factory, an instance of <code>SecretKeyFactory</code>
* containing that implementation is returned.
* If the requested factory is not available in the default provider
* package, other provider packages are searched.
*
* @param algorithm the standard name of the requested secret-key algorithm.
* See Appendix A in the Java Cryptography Extension API Specification &amp; Reference </a>
* for information about standard algorithm names.
* @return a <code>SecretKeyFactory</code> object for the specified secret-key algorithm.
* @exception NoSuchAlgorithmException if a secret-key factory for the specified algorithm
* is not available in the default provider package or any of the other provider packages
* that were searched.
*/
public static final SecretKeyFactory getInstance(
String algorithm)
throws NoSuchAlgorithmException
{
try
{
JCEUtil.Implementation imp = JCEUtil.getImplementation("SecretKeyFactory", algorithm, (String) null);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
SecretKeyFactory keyFact = new SecretKeyFactory(
(SecretKeyFactorySpi)imp.getEngine(), imp.getProvider(), algorithm);
return keyFact;
}
catch (NoSuchProviderException e)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
}
/**
* Generates a <code>SecretKeyFactory</code> object for the specified
* secret-key algorithm from the specified provider.
*
* @param algorithm the standard name of the requested secret-key algorithm.
* See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
* for information about standard algorithm names.
* @param provider the name of the provider.
* @return a <code>SecretKeyFactory</code> object for the specified secret-key algorithm.
* @exception NoSuchAlgorithmException if a secret-key factory for the specified algorithm is not
* available from the specified provider.
* @exception NoSuchProviderException if the specified provider has not been configured.
*/
public static final SecretKeyFactory getInstance(
String algorithm,
String provider)
throws NoSuchAlgorithmException, NoSuchProviderException
{
if (provider == null)
{
throw new IllegalArgumentException("No provider specified to SecretKeyFactory.getInstance()");
}
JCEUtil.Implementation imp = JCEUtil.getImplementation("SecretKeyFactory", algorithm, provider);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
SecretKeyFactory keyFact = new SecretKeyFactory(
(SecretKeyFactorySpi)imp.getEngine(), imp.getProvider(), algorithm);
return keyFact;
}
/**
* Generates a <code>SecretKeyFactory</code> object for the specified
* secret-key algorithm from the specified provider.
*
* @param algorithm the standard name of the requested secret-key algorithm.
* See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
* for information about standard algorithm names.
* @param provider the provider.
* @return a <code>SecretKeyFactory</code> object for the specified secret-key algorithm.
* @exception NoSuchAlgorithmException if a secret-key factory for the specified algorithm is not
* available from the specified provider.
*/
public static final SecretKeyFactory getInstance(
String algorithm,
Provider provider)
throws NoSuchAlgorithmException
{
if (provider == null)
{
throw new IllegalArgumentException("No provider specified to SecretKeyFactory.getInstance()");
}
JCEUtil.Implementation imp = JCEUtil.getImplementation("SecretKeyFactory", algorithm, provider);
if (imp == null)
{
throw new NoSuchAlgorithmException(algorithm + " not found");
}
SecretKeyFactory keyFact = new SecretKeyFactory(
(SecretKeyFactorySpi)imp.getEngine(), imp.getProvider(), algorithm);
return keyFact;
}
/**
* Returns the provider of this <code>SecretKeyFactory</code> object.
*
* @return the provider of this <code>SecretKeyFactory</code> object
*/
public final Provider getProvider()
{
return provider;
}
/**
* Returns the algorithm name of this <code>SecretKeyFactory</code> object.
* <p>
* This is the same name that was specified in one of the <code>getInstance</code> calls
* that created this <code>SecretKeyFactory</code> object.
*
* @return the algorithm name of this <code>SecretKeyFactory</code> object.
*/
public final String getAlgorithm()
{
return algorithm;
}
/**
* Generates a <code>SecretKey</code> object from the provided key specification (key material).
*
* @param keySpec the specification (key material) of the secret key
* @return the secret key
* @exception InvalidKeySpecException if the given key specification
* is inappropriate for this secret-key factory to produce a secret key.
*/
public final SecretKey generateSecret(
KeySpec keySpec)
throws InvalidKeySpecException
{
return keyFacSpi.engineGenerateSecret(keySpec);
}
/**
* Returns a specification (key material) of the given key object
* in the requested format.
*
* @param key the key
* @param keySpec the requested format in which the key material shall be
* returned
* @return the underlying key specification (key material) in the requested format
* @exception InvalidKeySpecException if the requested key specification is inappropriate for
* the given key (e.g., the algorithms associated with <code>key</code> and <code>keySpec</code> do
* not match, or <code>key</code> references a key on a cryptographic hardware device whereas
* <code>keySpec</code> is the specification of a software-based key), or the given key cannot be dealt with
* (e.g., the given key has an algorithm or format not supported by this secret-key factory).
*/
public final KeySpec getKeySpec(
SecretKey key,
Class keySpec)
throws InvalidKeySpecException
{
return keyFacSpi.engineGetKeySpec(key, keySpec);
}
/**
* Translates a key object, whose provider may be unknown or potentially
* untrusted, into a corresponding key object of this secret-key factory.
*
* @param key the key whose provider is unknown or untrusted
* @return the translated key
* @exception InvalidKeyException if the given key cannot be processed by this secret-key factory.
*/
public final SecretKey translateKey(
SecretKey key)
throws InvalidKeyException
{
return keyFacSpi.engineTranslateKey(key);
}
}

View File

@@ -0,0 +1,72 @@
package javax.crypto;
import java.security.InvalidKeyException;
import java.security.spec.KeySpec;
import java.security.spec.InvalidKeySpecException;
/**
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
* for the <code>SecretKeyFactory</code> class.
* All the abstract methods in this class must be implemented by each
* cryptographic service provider who wishes to supply the implementation
* of a secret-key factory for a particular algorithm.
* <p>
* A provider should document all the key specifications supported by its
* secret key factory.
* For example, the DES secret-key factory supplied by the "SunJCE" provider
* supports <code>DESKeySpec</code> as a transparent representation of DES
* keys, and that provider's secret-key factory for Triple DES keys supports
* <code>DESedeKeySpec</code> as a transparent representation of Triple DES
* keys.
*
* @see SecretKey
* @see javax.crypto.spec.DESKeySpec
* @see javax.crypto.spec.DESedeKeySpec
*/
public abstract class SecretKeyFactorySpi
{
public SecretKeyFactorySpi()
{
}
/**
* Generates a <code>SecretKey</code> object from the
* provided key specification (key material).
*
* @param keySpec the specification (key material) of the secret key
* @return the secret key
* @exception InvalidKeySpecException if the given key specification
* is inappropriate for this secret-key factory to produce a secret key.
*/
protected abstract SecretKey engineGenerateSecret(
KeySpec keySpec)
throws InvalidKeySpecException;
/**
* Returns a specification (key material) of the given key object in the requested format.
*
* @param key the key
* @param keySpec the requested format in which the key material shall be returned
* @return the underlying key specification (key material) in the requested format
* @exception InvalidKeySpecException if the requested key specification is inappropriate for
* the given key (e.g., the algorithms associated with <code>key</code> and <code>keySpec</code> do
* not match, or <code>key</code> references a key on a cryptographic hardware device whereas
* <code>keySpec</code> is the specification of a software-based key), or the given key cannot be
* dealt with (e.g., the given key has an algorithm or format not supported by this secret-key factory).
*/
protected abstract KeySpec engineGetKeySpec(
SecretKey key,
Class keySpec)
throws InvalidKeySpecException;
/**
* Translates a key object, whose provider may be unknown or potentially untrusted, into a
* corresponding key object of this secret-key factory.
*
* @param key the key whose provider is unknown or untrusted
* @return InvalidKeyException if the given key cannot be processed by this secret-key factory.
*/
protected abstract SecretKey engineTranslateKey(
SecretKey key)
throws InvalidKeyException;
}

View File

@@ -0,0 +1,36 @@
package javax.crypto;
import java.security.GeneralSecurityException;
/**
* This exception is thrown when an output buffer provided by the user
* is too short to hold the operation result.
*/
public class ShortBufferException
extends GeneralSecurityException
{
private static final long serialVersionUID = 8427718640832943747L;
/**
* Constructs a ShortBufferException with no detail
* message. A detail message is a String that describes this
* particular exception.
*/
public ShortBufferException()
{
}
/**
* Constructs a ShortBufferException with the specified
* detail message. A detail message is a String that describes
* this particular exception, which may, for example, specify which
* algorithm is not available.
*
* @param msg the detail message.
*/
public ShortBufferException(
String msg)
{
super(msg);
}
}

View File

@@ -0,0 +1,20 @@
package javax.crypto.interfaces;
import javax.crypto.spec.DHParameterSpec;
/**
* The interface to a Diffie-Hellman key.
*
* @see DHParameterSpec
* @see DHPublicKey
* @see DHPrivateKey
*/
public abstract interface DHKey
{
/**
* Returns the key parameters.
*
* @return the key parameters
*/
public DHParameterSpec getParams();
}

View File

@@ -0,0 +1,21 @@
package javax.crypto.interfaces;
import java.math.BigInteger;
import java.security.PrivateKey;
/**
* The interface to a Diffie-Hellman private key.
*
* @see DHKey
* @see DHPublicKey
*/
public abstract interface DHPrivateKey
extends DHKey, PrivateKey
{
/**
* Returns the private value, <code>x</code>.
*
* @return the private value, <code>x</code>
*/
public BigInteger getX();
}

View File

@@ -0,0 +1,21 @@
package javax.crypto.interfaces;
import java.math.BigInteger;
import java.security.PublicKey;
/**
* The interface to a Diffie-Hellman public key.
*
* @see DHKey
* @see DHPrivateKey
*/
public abstract interface DHPublicKey
extends DHKey, PublicKey
{
/**
* Returns the public value, <code>y</code>.
*
* @return the public value, <code>y</code>
*/
public BigInteger getY();
}

View File

@@ -0,0 +1,41 @@
package javax.crypto.interfaces;
import javax.crypto.SecretKey;
/**
* The interface to a PBE key.
*
* @see PBEKeySpec, SecretKey
*/
public interface PBEKey
extends SecretKey
{
/**
* Returns the password.
*
* Note: this method should return a copy of the password. It is the
* caller's responsibility to zero out the password information after it is
* no longer needed.
*
* @return the password.
*/
public char[] getPassword();
/**
* Returns the salt or null if not specified.
*
* Note: this method should return a copy of the salt. It is the caller's
* responsibility to zero out the salt information after it is no longer
* needed.
*
* @return the salt.
*/
public byte[] getSalt();
/**
* Returns the iteration count or 0 if not specified.
*
* @return the iteration count.
*/
public int getIterationCount();
}

View File

@@ -0,0 +1,194 @@
package javax.crypto.spec;
import java.security.InvalidKeyException;
import java.security.spec.KeySpec;
/**
* This class specifies a DES key.
*/
public class DESKeySpec
implements KeySpec
{
public static final int DES_KEY_LEN = 8;
private byte[] keyBytes = new byte[DES_KEY_LEN];
/**
* Uses the first 8 bytes in <code>key</code> as the key material for the DES key.
* <p>
* The bytes that constitute the DES key are those between
* <code>key[0]</code> and <code>key[7]</code> inclusive.
*
* @param key - the buffer with the DES key material.
* @exception InvalidKeyException - if the given key material is shorter than 8 bytes.
*/
public DESKeySpec(
byte[] key)
throws InvalidKeyException
{
if (key.length < DES_KEY_LEN)
{
throw new InvalidKeyException("DES key material too short in construction");
}
System.arraycopy(key, 0, keyBytes, 0, keyBytes.length);
}
/**
* Uses the first 8 bytes in <code>key</code>, beginning at
* <code>offset</code> inclusive, as the key material for the DES key.
* <p>
* The bytes that constitute the DES key are those between
* <code>key[offset]</code> and <code>key[offset+7]</code> inclusive.
*
* @param key the buffer with the DES key material.
* @param offset the offset in <code>key</code>, where the DES key material starts.
* @exception InvalidKeyException if the given key material, starting at
* <code>offset</code> inclusive, is shorter than 8 bytes.
*/
public DESKeySpec(
byte[] key,
int offset)
throws InvalidKeyException
{
if ((key.length - offset) < DES_KEY_LEN)
{
throw new InvalidKeyException("DES key material too short in construction");
}
System.arraycopy(key, offset, keyBytes, 0, keyBytes.length);
}
/**
* Returns the DES key material.
*
* @return the DES key material.
*/
public byte[] getKey()
{
byte[] tmp = new byte[DES_KEY_LEN];
System.arraycopy(keyBytes, 0, tmp, 0, tmp.length);
return tmp;
}
/**
* Checks if the given DES key material, starting at <code>offset</code>
* inclusive, is parity-adjusted.
*
* @param key the buffer with the DES key material.
* @param offset the offset in <code>key</code>, where the DES key material starts.
* @returns true if the given DES key material is parity-adjusted, false otherwise.
* @exception InvalidKeyException if the given key material, starting at <code>offset</code>
* inclusive, is shorter than 8 bytes.
*/
public static boolean isParityAdjusted(
byte[] key,
int offset)
throws InvalidKeyException
{
if ((key.length - offset) < DES_KEY_LEN)
{
throw new InvalidKeyException("key material too short in DESKeySpec.isParityAdjusted");
}
for (int i = 0; i < DES_KEY_LEN; i++)
{
byte keyByte = key[i + offset];
int count = 0;
keyByte = (byte)((keyByte & 0xff) >> 1);
while (keyByte != 0)
{
/*
* we increment for every "on" bit
*/
if ((keyByte & 0x01) != 0)
{
count++;
}
keyByte = (byte)((keyByte & 0xff) >> 1);
}
if ((count & 1) == 1)
{
if ((key[i + offset] & 1) == 1)
{
return false;
}
}
else if ((key[i + offset] & 1) != 1)
{
return false;
}
}
return true;
}
/*
* Table of weak and semi-weak keys taken from Schneier pp281
*/
static private final int N_DES_WEAK_KEYS = 16;
static private byte[] DES_weak_keys =
{
/* weak keys */
(byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
(byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
(byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
(byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
/* semi-weak keys */
(byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
(byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
(byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
(byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
(byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
(byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
(byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
(byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
(byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
(byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
(byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
(byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
};
/**
* Checks if the given DES key material is weak or semi-weak.
*
* @param key the buffer with the DES key material.
* @param offset the offset in <code>key</code>, where the DES key
* material starts.
* @return true if the given DES key material is weak or semi-weak, false otherwise.
* @exception InvalidKeyException if the given key material, starting at <code>offset</code>
* inclusive, is shorter than 8 bytes.
*/
public static boolean isWeak(
byte[] key,
int offset)
throws InvalidKeyException
{
if (key.length - offset < DES_KEY_LEN)
{
throw new InvalidKeyException("key material too short in DESKeySpec.isWeak");
}
nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++)
{
for (int j = 0; j < DES_KEY_LEN; j++)
{
if (key[j + offset] != DES_weak_keys[i * DES_KEY_LEN + j])
{
continue nextkey;
}
}
return true;
}
return false;
}
}

View File

@@ -0,0 +1,100 @@
package javax.crypto.spec;
import java.security.InvalidKeyException;
import java.security.spec.KeySpec;
/**
* This class specifies a DES-EDE ("triple-DES") key.
*/
public class DESedeKeySpec
implements KeySpec
{
public static final int DES_EDE_KEY_LEN = 24;
private byte[] keyBytes = new byte[DES_EDE_KEY_LEN];
/**
* Uses the first 24 bytes in <code>key</code> as the DES-EDE key.
* <p>
* The bytes that constitute the DES-EDE key are those between
* <code>key[0]</code> and <code>key[23]</code> inclusive
*
* @param key the buffer with the DES-EDE key material.
* @exception InvalidKeyException if the given key material is shorter
* than 24 bytes.
*/
public DESedeKeySpec(
byte[] key)
throws InvalidKeyException
{
if (key.length < DES_EDE_KEY_LEN)
{
throw new InvalidKeyException("DESede key material too short in construction");
}
System.arraycopy(key, 0, keyBytes, 0, keyBytes.length);
}
/**
* Uses the first 24 bytes in <code>key</code>, beginning at
* <code>offset</code> inclusive, as the DES-EDE key.
* <p>
* The bytes that constitute the DES-EDE key are those between
* <code>key[offset]</code> and <code>key[offset+23]</code> inclusive.
* @param key the buffer with the DES-EDE key material.
* @param offset the offset in <code>key</code>, where the DES-EDE key
* material starts.
* @exception InvalidKeyException if the given key material, starting at
* <code>offset</code> inclusive, is shorter than 24 bytes
*/
public DESedeKeySpec(
byte[] key,
int offset)
throws InvalidKeyException
{
if ((key.length - offset) < DES_EDE_KEY_LEN)
{
throw new InvalidKeyException("DESede key material too short in construction");
}
System.arraycopy(key, 0, keyBytes, 0, keyBytes.length);
}
/**
* Returns the DES-EDE key.
*
* @return the DES-EDE key
*/
public byte[] getKey()
{
byte[] tmp = new byte[DES_EDE_KEY_LEN];
System.arraycopy(keyBytes, 0, tmp, 0, tmp.length);
return tmp;
}
/**
* Checks if the given DES-EDE key, starting at <code>offset</code>
* inclusive, is parity-adjusted.
*
* @return true if the given DES-EDE key is parity-adjusted, false
* otherwise
* @exception InvalidKeyException if the given key material, starting at
* <code>offset</code> inclusive, is shorter than 24 bytes
*/
public static boolean isParityAdjusted(
byte[] key,
int offset)
throws InvalidKeyException
{
if ((key.length - offset) < DES_EDE_KEY_LEN)
{
throw new InvalidKeyException("key material too short in DESedeKeySpec.isParityAdjusted");
}
return (DESKeySpec.isParityAdjusted(key, offset)
&& DESKeySpec.isParityAdjusted(key, offset + 8)
&& DESKeySpec.isParityAdjusted(key, offset + 16));
}
}

View File

@@ -0,0 +1,56 @@
package javax.crypto.spec;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class specifies the set of parameters used for generating
* Diffie-Hellman (system) parameters for use in Diffie-Hellman key
* agreement. This is typically done by a central
* authority.
* <p>
* The central authority, after computing the parameters, must send this
* information to the parties looking to agree on a secret key.
*/
public class DHGenParameterSpec
implements AlgorithmParameterSpec
{
private int primeSize;
private int exponentSize;
/**
* Constructs a parameter set for the generation of Diffie-Hellman
* (system) parameters. The constructed parameter set can be used to
* initialize an <a href="http://java.sun.com/products/jdk/1.2/docs/api/java.security.AlgorithmParameterGenerator.html"><code>AlgorithmParameterGenerator</code></a>
* object for the generation of Diffie-Hellman parameters.
*
* @param primeSize the size (in bits) of the prime modulus.
* @param exponentSize the size (in bits) of the random exponent.
*/
public DHGenParameterSpec(
int primeSize,
int exponentSize)
{
this.primeSize = primeSize;
this.exponentSize = exponentSize;
}
/**
* Returns the size in bits of the prime modulus.
*
* @return the size in bits of the prime modulus
*/
public int getPrimeSize()
{
return primeSize;
}
/**
* Returns the size in bits of the random exponent (private value).
*
* @return the size in bits of the random exponent (private value)
*/
public int getExponentSize()
{
return exponentSize;
}
}

View File

@@ -0,0 +1,95 @@
package javax.crypto.spec;
import java.math.BigInteger;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class specifies the set of parameters used with the Diffie-Hellman
* algorithm, as specified in PKCS #3: <i>Diffie-Hellman Key-Agreement
* Standard</i>.
* <p>
* A central authority generates parameters and gives them to the two
* entities seeking to generate a secret key. The parameters are a prime
* <code>p</code>, a base <code>g</code>, and optionally the length
* in bits of the private value, <code>l</code>.
* <p>
* It is possible that more than one instance of parameters may be
* generated by a given central authority, and that there may be more than
* one central authority. Indeed, each individual may be its own central
* authority, with different entities having different parameters.
*
* @see javax.crypto.KeyAgreement
*/
public class DHParameterSpec
implements AlgorithmParameterSpec
{
private BigInteger p;
private BigInteger g;
private int l;
/**
* Constructs a parameter set for Diffie-Hellman, using a prime modulus
* <code>p</code> and a base generator <code>g</code>.
*
* @param p the prime modulus
* @param g the base generator
*/
public DHParameterSpec(
BigInteger p,
BigInteger g)
{
this.p = p;
this.g = g;
}
/**
* Constructs a parameter set for Diffie-Hellman, using a prime modulus
* <code>p</code>, a base generator <code>g</code>, and the size in bits,
* <code>l</code>, of the random exponent (private value).
*
* @param p the prime modulus
* @param g the base generator
* @param l the size in bits of the random exponent (private value)
*/
public DHParameterSpec(
BigInteger p,
BigInteger g,
int l)
{
this.p = p;
this.g = g;
this.l = l;
}
/**
* Returns the prime modulus <code>p</code>.
*
* @return the prime modulus <code>p</code>
*/
public BigInteger getP()
{
return p;
}
/**
* Returns the base generator <code>g</code>.
*
* @return the base generator <code>g</code>
*/
public BigInteger getG()
{
return g;
}
/**
* Returns the size in bits, <code>l</code>, of the random exponent
* (private value).
*
* @return the size in bits, <code>l</code>, of the random exponent
* (private value), or 0 if this size has not been set
*/
public int getL()
{
return l;
}
}

View File

@@ -0,0 +1,61 @@
package javax.crypto.spec;
import java.math.BigInteger;
import java.security.spec.KeySpec;
/**
* This class specifies a Diffie-Hellman private key with its associated parameters.
*
* @see DHPublicKeySpec
*/
public class DHPrivateKeySpec
implements KeySpec
{
private BigInteger x;
private BigInteger p;
private BigInteger g;
/**
* Constructor that takes a private value <code>x</code>, a prime
* modulus <code>p</code>, and a base generator <code>g</code>.
*/
public DHPrivateKeySpec(
BigInteger x,
BigInteger p,
BigInteger g)
{
this.x = x;
this.p = p;
this.g = g;
}
/**
* Returns the private value <code>x</code>.
*
* @return the private value <code>x</code>
*/
public BigInteger getX()
{
return x;
}
/**
* Returns the prime modulus <code>p</code>.
*
* @return the prime modulus <code>p</code>
*/
public BigInteger getP()
{
return p;
}
/**
* Returns the base generator <code>g</code>.
*
* @return the base generator <code>g</code>
*/
public BigInteger getG()
{
return g;
}
}

View File

@@ -0,0 +1,61 @@
package javax.crypto.spec;
import java.math.BigInteger;
import java.security.spec.KeySpec;
/**
* This class specifies a Diffie-Hellman public key with its associated parameters.
*
* @see DHPrivateKeySpec
*/
public class DHPublicKeySpec
implements KeySpec
{
private BigInteger y;
private BigInteger p;
private BigInteger g;
/**
* Constructor that takes a public value <code>y</code>, a prime
* modulus <code>p</code>, and a base generator <code>g</code>.
*/
public DHPublicKeySpec(
BigInteger y,
BigInteger p,
BigInteger g)
{
this.y = y;
this.p = p;
this.g = g;
}
/**
* Returns the public value <code>y</code>.
*
* @return the public value <code>y</code>
*/
public BigInteger getY()
{
return y;
}
/**
* Returns the prime modulus <code>p</code>.
*
* @return the prime modulus <code>p</code>
*/
public BigInteger getP()
{
return p;
}
/**
* Returns the base generator <code>g</code>.
*
* @return the base generator <code>g</code>
*/
public BigInteger getG()
{
return g;
}
}

View File

@@ -0,0 +1,75 @@
package javax.crypto.spec;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class specifies an <i>initialization vector</i> (IV). IVs are used
* by ciphers in feedback mode, e.g., DES in CBC mode.
*/
public class IvParameterSpec
implements AlgorithmParameterSpec
{
private byte[] iv;
/**
* Uses the bytes in <code>iv</code> as the IV.
*
* @param iv the buffer with the IV
*/
public IvParameterSpec(
byte[] iv)
{
if (iv == null)
{
throw new IllegalArgumentException("null iv passed");
}
this.iv = new byte[iv.length];
System.arraycopy(iv, 0, this.iv, 0, iv.length);
}
/**
* Uses the first <code>len</code> bytes in <code>iv</code>,
* beginning at <code>offset</code> inclusive, as the IV.
* <p>
* The bytes that constitute the IV are those between
* <code>iv[offset]</code> and <code>iv[offset+len-1]</code> inclusive.
*
* @param iv the buffer with the IV
* @param offset the offset in <code>iv</code> where the IV starts
* @param len the number of IV bytes
*/
public IvParameterSpec(
byte[] iv,
int offset,
int len)
{
if (iv == null)
{
throw new IllegalArgumentException("Null iv passed");
}
if (offset < 0 || len < 0 || (iv.length - offset) < len)
{
throw new IllegalArgumentException("Bad offset/len");
}
this.iv = new byte[len];
System.arraycopy(iv, offset, this.iv, 0, len);
}
/**
* Returns the initialization vector (IV).
*
* @return the initialization vector (IV)
*/
public byte[] getIV()
{
byte[] tmp = new byte[iv.length];
System.arraycopy(iv, 0, tmp, 0, iv.length);
return tmp;
}
}

View File

@@ -0,0 +1,103 @@
package javax.crypto.spec;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class specifies the set of parameters used with OAEP Padding, as defined
* in the PKCS #1 standard. Its ASN.1 definition in PKCS#1 standard is described
* below:
*
* </pre>
*
* RSAES-OAEP-params ::= SEQUENCE { hashAlgorithm [0] OAEP-PSSDigestAlgorithms
* DEFAULT sha1, maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
* pSourceAlgorithm [2] PKCS1PSourceAlgorithms DEFAULT pSpecifiedEmpty }
*
* </pre>
*
* where
*
* <pre>
*
* OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= { { OID id-sha1 PARAMETERS
* NULL }| { OID id-sha256 PARAMETERS NULL }| { OID id-sha384 PARAMETERS NULL } | {
* OID id-sha512 PARAMETERS NULL }, ... -- Allows for future expansion -- }
* PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= { { OID id-mgf1 PARAMETERS
* OAEP-PSSDigestAlgorithms }, ... -- Allows for future expansion -- }
* PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= { { OID id-pSpecified
* PARAMETERS OCTET STRING }, ... -- Allows for future expansion -- }
*
* </pre>
*
* @see PSource
*/
public class OAEPParameterSpec
implements AlgorithmParameterSpec
{
private String mdName;
private String mgfName;
private AlgorithmParameterSpec mgfSpec;
private PSource pSrc;
/**
* Constructs a parameter set for OAEP padding as defined in the PKCS #1
* standard using the specified message digest algorithm mdName, mask
* generation function algorithm mgfName, parameters for the mask generation
* function mgfSpec, and source of the encoding input P pSrc.
*
* @param mdName the algorithm name for the message digest.
* @param mgfName the algorithm name for the mask generation function.
* @param mgfSpec the parameters for the mask generation function. If null is
* specified, null will be returned by getMGFParameters().
* @param pSrc the source of the encoding input P.
* @throws NullPointerException if mdName, mgfName, or pSrc is null.
*/
public OAEPParameterSpec(String mdName, String mgfName,
AlgorithmParameterSpec mgfSpec, PSource pSrc)
{
this.mdName = mdName;
this.mgfName = mgfName;
this.mgfSpec = mgfSpec;
this.pSrc = pSrc;
}
/**
* Returns the message digest algorithm name.
*
* @return the message digest algorithm name.
*/
public String getDigestAlgorithm()
{
return mdName;
}
/**
* Returns the mask generation function algorithm name.
*
* @return the mask generation function algorithm name.
*/
public String getMGFAlgorithm()
{
return mgfName;
}
/**
* Returns the parameters for the mask generation function.
*
* @return the parameters for the mask generation function.
*/
public AlgorithmParameterSpec getMGFParameters()
{
return mgfSpec;
}
/**
* Returns the source of encoding input P.
*
* @return the source of encoding input P.
*/
public PSource getPSource()
{
return pSrc;
}
}

View File

@@ -0,0 +1,222 @@
package javax.crypto.spec;
import java.security.spec.KeySpec;
import javax.crypto.SecretKeyFactory;
/**
* A user-chosen password that can be used with password-based encryption (PBE).
* <p>
* The password can be viewed as some kind of raw key material, from which the
* encryption mechanism that uses it derives a cryptographic key.
* <p>
* Different PBE mechanisms may consume different bits of each password
* character. For example, the PBE mechanism defined in PKCS #5 looks at only
* the low order 8 bits of each character, whereas PKCS #12 looks at all 16 bits
* of each character.
* <p>
* You convert the password characters to a PBE key by creating an instance of
* the appropriate secret-key factory. For example, a secret-key factory for
* PKCS #5 will construct a PBE key from only the low order 8 bits of each
* password character, whereas a secret-key factory for PKCS #12 will take all
* 16 bits of each character.
* <p>
* Also note that this class stores passwords as char arrays instead of String
* objects (which would seem more logical), because the String class is
* immutable and there is no way to overwrite its internal value when the
* password stored in it is no longer needed. Hence, this class requests the
* password as a char array, so it can be overwritten when done.
*
* @see SecretKeyFactory
* @see PBEParameterSpec
*/
public class PBEKeySpec
implements KeySpec
{
private char[] password;
private byte[] salt;
private int iterationCount;
private int keyLength;
private boolean isPasswordCleared;
/**
* Constructor that takes a password. An empty char[] is used if null is
* specified.
* <p>
* Note: password is cloned before it is stored in the new PBEKeySpec
* object.
*
* @param password -
* the password.
*/
public PBEKeySpec(char[] password)
{
if (password == null)
{
this.password = new char[0];
}
else
{
this.password = new char[password.length];
System.arraycopy(password, 0, this.password, 0, password.length);
}
}
/**
* Returns a copy of the password.
* <p>
* Note: this method returns a copy of the password. It is the caller's
* responsibility to zero out the password information after it is no longer
* needed.
*
* @return the password
* @throws IllegalStateException -
* if password has been cleared by calling clearPassword method.
*/
public final char[] getPassword()
{
if (isPasswordCleared)
{
throw new IllegalStateException("Password has been cleared");
}
return password;
}
/**
* Constructor that takes a password, salt, iteration count, and
* to-be-derived key length for generating PBEKey of variable-key-size PBE
* ciphers. An empty char[] is used if null is specified for password.
* <p>
* Note: the password and salt are cloned before they are stored in the new
* PBEKeySpec object.
*
*
* @param password
* password - the password.
* @param salt
* salt - the salt.
* @param iterationCount
* iterationCount - the iteration count.
* @param keyLength
* keyLength - the to-be-derived key length.
* @throws NullPointerException -
* if salt is null.
* @throws IllegalArgumentException -
* if salt is empty, i.e. 0-length, iterationCount or keyLength
* is not positive.
*/
public PBEKeySpec(char[] password, byte[] salt, int iterationCount, int keyLength)
{
this(password);
if (salt == null)
{
throw new NullPointerException("salt is null");
}
if (salt.length == 0)
{
throw new IllegalArgumentException("salt is empty");
}
if (iterationCount < 0)
{
throw new IllegalArgumentException("iterationCount is not positive");
}
if (keyLength < 0)
{
throw new IllegalArgumentException("keyLength is not positive");
}
this.keyLength = keyLength;
this.iterationCount = iterationCount;
this.salt = (byte[]) salt.clone();
}
/**
* Constructor that takes a password, salt, iteration count for generating
* PBEKey of fixed-key-size PBE ciphers. An empty char[] is used if null is
* specified for password.
* <p>
* Note: the password and salt are cloned before they are stored in the new
* PBEKeySpec object.
*
* @param password -
* the password.
* @param salt -
* the salt.
* @param iterationCount -
* the iteration count.
* @throws NullPointerException -
* if salt is null.
* @throws IllegalArgumentException -
* if salt is empty, i.e. 0-length, or iterationCount is not
* positive.
*/
public PBEKeySpec(char[] password, byte[] salt, int iterationCount)
{
this(password, salt, iterationCount, 0);
}
/**
* Clears the internal copy of the password.
*/
public final void clearPassword()
{
for (int i = 0; i < password.length; i++)
{
password[i] = 0;
}
password = null;
isPasswordCleared = true;
}
/**
* Returns a copy of the salt or null if not specified.
*
* Note: this method should return a copy of the salt. It is the caller's
* responsibility to zero out the salt information after it is no longer
* needed.
*
* @return the salt.
*/
public final byte[] getSalt()
{
if (salt != null)
{
byte[] tmp = new byte[salt.length];
System.arraycopy(salt, 0, tmp, 0, salt.length);
return tmp;
}
return null;
}
/**
* Returns the iteration count or 0 if not specified.
*
* @return the iteration count.
*/
public final int getIterationCount()
{
return iterationCount;
}
/**
* Returns the to-be-derived key length or 0 if not specified.
* <p>
* Note: this is used to indicate the preference on key length for
* variable-key-size ciphers. The actual key size depends on each provider's
* implementation.
*
* @return the to-be-derived key length.
*/
public final int getKeyLength()
{
return keyLength;
}
}

View File

@@ -0,0 +1,55 @@
package javax.crypto.spec;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class specifies the set of parameters used with password-based encryption (PBE), as defined in the
* <a href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-5.html">PKCS #5</a> standard.
*/
public class PBEParameterSpec
implements AlgorithmParameterSpec
{
private byte[] salt;
private int iterationCount;
/**
* Constructs a parameter set for password-based encryption as defined in
* the PKCS #5 standard.
*
* @param salt the salt.
* @param iterationCount the iteration count.
*/
public PBEParameterSpec(
byte[] salt,
int iterationCount)
{
this.salt = new byte[salt.length];
System.arraycopy(salt, 0, this.salt, 0, salt.length);
this.iterationCount = iterationCount;
}
/**
* Returns the salt.
*
* @return the salt
*/
public byte[] getSalt()
{
byte[] tmp = new byte[salt.length];
System.arraycopy(salt, 0, tmp, 0, salt.length);
return tmp;
}
/**
* Returns the iteration count.
*
* @return the iteration count
*/
public int getIterationCount()
{
return iterationCount;
}
}

View File

@@ -0,0 +1,98 @@
package javax.crypto.spec;
/**
* This class specifies the source for encoding input P in OAEP Padding, as
* defined in the {@link http://www.ietf.org/rfc/rfc3447.txt PKCS #1} standard.
*
* <pre>
*
* PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= {
* { OID id-pSpecified PARAMETERS OCTET STRING },
* ... -- Allows for future expansion --
* }
* </pre>
*/
public class PSource
{
/**
* This class is used to explicitly specify the value for encoding input P
* in OAEP Padding.
*
*/
public final static class PSpecified
extends PSource
{
private byte[] p;
/**
* The encoding input P whose value equals byte[0].
*/
public static final PSpecified DEFAULT = new PSpecified(new byte[0]);
/**
* Constructs the source explicitly with the specified value p as the
* encoding input P.
*
* @param p the value of the encoding input. The contents of the array
* are copied to protect against subsequent modification.
* @throws NullPointerException if p is null.
*/
public PSpecified(byte[] p)
{
super("PSpecified");
if (p == null)
{
throw new NullPointerException("The encoding input is null");
}
this.p = copyOf(p);
}
/**
* Returns the value of encoding input P.
*
* @return the value of encoding input P. A new array is returned each
* time this method is called.
*/
public byte[] getValue()
{
return copyOf(p);
}
private byte[] copyOf(byte[] b)
{
byte[] tmp = new byte[b.length];
System.arraycopy(b, 0, tmp, 0, b.length);
return tmp;
}
}
private String pSrcName;
/**
* Constructs a source of the encoding input P for OAEP padding as defined
* in the PKCS #1 standard using the specified PSource algorithm.
*
* @param pSrcName the algorithm for the source of the encoding input P.
* @throws NullPointerException if pSrcName is null.
*/
protected PSource(String pSrcName)
{
if (pSrcName == null)
{
throw new NullPointerException("pSrcName is null");
}
this.pSrcName = pSrcName;
}
/**
* Returns the PSource algorithm name.
*
* @return the PSource algorithm name.
*/
public String getAlgorithm()
{
return pSrcName;
}
}

View File

@@ -0,0 +1,162 @@
package javax.crypto.spec;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class specifies the parameters used with the
* <a href="http://www.rsa.com/rsalabs/newfaq/q75.html"><i>RC2</i></a>
* algorithm.
* <p>
* The parameters consist of an effective key size and optionally
* an 8-byte initialization vector (IV) (only in feedback mode).
* <p>
* This class can be used to initialize a <code>Cipher</code> object that
* implements the <i>RC2</i> algorithm.
*/
public class RC2ParameterSpec
implements AlgorithmParameterSpec
{
private int effectiveKeyBits;
private byte[] iv = new byte[8];
/**
* Constructs a parameter set for RC2 from the given effective key size
* (in bits).
*
* @param effectiveKeyBits the effective key size in bits.
*/
public RC2ParameterSpec(
int effectiveKeyBits)
{
this.effectiveKeyBits = effectiveKeyBits;
}
/**
* Constructs a parameter set for RC2 from the given effective key size
* (in bits) and an 8-byte IV.
* <p>
* The bytes that constitute the IV are those between
* <code>iv[0]</code> and <code>iv[7]</code> inclusive.
*
* @param effectiveKeyBits the effective key size in bits.
* @param iv the buffer with the 8-byte IV.
*/
public RC2ParameterSpec(
int effectiveKeyBits,
byte[] iv)
{
this(effectiveKeyBits, iv, 0);
}
/**
* Constructs a parameter set for RC2 from the given effective key size
* (in bits) and IV.
* <p>
* The IV is taken from <code>iv</code>, starting at
* <code>offset</code> inclusive.
* The bytes that constitute the IV are those between
* <code>iv[offset]</code> and <code>iv[offset+7]</code> inclusive.
*
* @param effectiveKeyBits the effective key size in bits.
* @param iv the buffer with the IV.
* @param offset the offset in <code>iv</code> where the 8-byte IV starts.
*/
public RC2ParameterSpec(
int effectiveKeyBits,
byte[] iv,
int offset)
{
this.effectiveKeyBits = effectiveKeyBits;
this.iv = new byte[8];
System.arraycopy(iv, offset, this.iv, 0, this.iv.length);
}
/**
* Returns the effective key size in bits.
*
* @return the effective key size in bits.
*/
public int getEffectiveKeyBits()
{
return effectiveKeyBits;
}
/**
* Returns the IV or null if this parameter set does not contain an IV.
*
* @return the IV or null if this parameter set does not contain an IV.
*/
public byte[] getIV()
{
if (iv == null)
{
return null;
}
byte[] tmp = new byte[iv.length];
System.arraycopy(iv, 0, tmp, 0, tmp.length);
return tmp;
}
/**
* Tests for equality between the specified object and this
* object. Two RC2ParameterSpec objects are considered equal if their
* effective key sizes and IVs are equal.
* (Two IV references are considered equal if both are <tt>null</tt>.)
*
* @param obj the object to test for equality with this object.
* @return true if the objects are considered equal, false otherwise.
* @override equals in class java.lang.Object
*/
public boolean equals(
Object obj)
{
if ((obj == null) || !(obj instanceof RC2ParameterSpec))
{
return false;
}
RC2ParameterSpec spec = (RC2ParameterSpec)obj;
if (this.effectiveKeyBits != spec.effectiveKeyBits)
{
return false;
}
if (iv != null)
{
if (spec.iv == null)
{
return false;
}
for (int i = 0; i != iv.length; i++)
{
if (iv[i] != spec.iv[i])
{
return false;
}
}
}
else if (spec.iv != null)
{
return false;
}
return true;
}
/**
* Calculates a hash code value for the object.
* Objects that are equal will also have the same hashcode.
*
* @override hashCode in class java.lang.Object
*/
public int hashCode()
{
throw new RuntimeException("Not yet implemented");
}
}

View File

@@ -0,0 +1,224 @@
package javax.crypto.spec;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class specifies the parameters used with the
* <a href="http://www.rsa.com/rsalabs/newfaq/q76.html"><i>RC5</i></a>
* algorithm.
* <p>
* The parameters consist of a version number, a rounds count, a word
* size, and optionally an initialization vector (IV) (only in feedback mode).
* <p>
* This class can be used to initialize a <code>Cipher</code> object that
* implements the <i>RC5</i> algorithm as supplied by
* <a href="http://www.rsa.com">RSA Data Security, Inc.</a> (RSA DSI),
* or any parties authorized by RSA DSI.
*/
public class RC5ParameterSpec
implements AlgorithmParameterSpec
{
private int version;
private int rounds;
private int wordSize;
private byte[] iv;
/**
* Constructs a parameter set for RC5 from the given version, number of
* rounds and word size (in bits).
*
* @param version the version.
* @param rounds the number of rounds.
* @param wordSize the word size in bits.
*/
public RC5ParameterSpec(
int version,
int rounds,
int wordSize)
{
this.version = version;
this.rounds = rounds;
this.wordSize = wordSize;
this.iv = null;
}
/**
* Constructs a parameter set for RC5 from the given version, number of
* rounds, word size (in bits), and IV.
* <p>
* Note that the size of the IV (block size) must be twice the word
* size. The bytes that constitute the IV are those between
* <code>iv[0]</code> and <code>iv[2*(wordSize/8)-1]</code> inclusive.
*
* @param version the version.
* @param rounds the number of rounds.
* @param wordSize the word size in bits.
* @param iv the buffer with the IV.
*/
public RC5ParameterSpec(
int version,
int rounds,
int wordSize,
byte[] iv)
{
this(version, rounds, wordSize, iv, 0);
}
/**
* Constructs a parameter set for RC5 from the given version, number of
* rounds, word size (in bits), and IV.
* <p>
* The IV is taken from <code>iv</code>, starting at <code>offset</code> inclusive.
* Note that the size of the IV (block size), starting at
* <code>offset</code> inclusive, must be twice the word size.
* The bytes that constitute the IV are those between
* <code>iv[offset]</code> and <code>iv[offset+2*(wordSize/8)-1]</code>
* inclusive.
*
* @param version the version.
* @param rounds the number of rounds.
* @param wordSize the word size in bits.
* @param iv the buffer with the IV.
* @param offset the offset in <code>iv</code> where the IV starts.
*/
public RC5ParameterSpec(
int version,
int rounds,
int wordSize,
byte[] iv,
int offset)
{
this.version = version;
this.rounds = rounds;
this.wordSize = wordSize;
this.iv = new byte[2 * (wordSize / 8)];
System.arraycopy(iv, offset, this.iv, 0, this.iv.length);
}
/**
* Returns the version.
*
* @return the version.
*/
public int getVersion()
{
return version;
}
/**
* Returns the number of rounds.
*
* @return the number of rounds.
*/
public int getRounds()
{
return rounds;
}
/**
* Returns the word size in bits
*
* @return the word size in bits.
*/
public int getWordSize()
{
return wordSize;
}
/**
* Returns the IV or null if this parameter set does not contain an IV.
*
* @return the IV or null if this parameter set does not contain an IV.
*/
public byte[] getIV()
{
if (iv == null)
{
return null;
}
byte[] tmp = new byte[iv.length];
System.arraycopy(iv, 0, tmp, 0, iv.length);
return tmp;
}
/**
* Tests for equality between the specified object and this
* object. Two RC5ParameterSpec objects are considered equal if their
* version numbers, number of rounds, word sizes, and IVs are equal.
* (Two IV references are considered equal if both are <tt>null</tt>.)
*
* @param obj the object to test for equality with this object.
* @return true if the objects are considered equal, false otherwise.
*/
public boolean equals(
Object obj)
{
if ((obj == null) || !(obj instanceof RC5ParameterSpec))
{
return false;
}
RC5ParameterSpec spec = (RC5ParameterSpec)obj;
if (this.version != spec.version)
{
return false;
}
if (this.rounds != spec.rounds)
{
return false;
}
if (this.wordSize != spec.wordSize)
{
return false;
}
if (iv != null)
{
if (spec.iv == null || spec.iv.length != iv.length)
{
return false;
}
for (int i = 0; i != iv.length; i++)
{
if (iv[i] != spec.iv[i])
{
return false;
}
}
}
else if (spec.iv != null)
{
return false;
}
return true;
}
/**
* Calculates a hash code value for the object.
* Objects that are equal will also have the same hashcode.
*/
public int hashCode()
{
int code = version ^ rounds ^ wordSize;
if (iv != null)
{
for (int i = 0; i != iv.length; i++)
{
code ^= iv[i] << (8 * (i % 4));
}
}
return code;
}
}

View File

@@ -0,0 +1,193 @@
package javax.crypto.spec;
import javax.crypto.SecretKey;
import java.security.spec.KeySpec;
/**
* This class specifies a secret key in a provider-independent fashion.
* <p>
* It can be used to construct a <code>SecretKey</code> from a byte array,
* without having to go through a (provider-based)
* <code>SecretKeyFactory</code>.
* <p>
* This class is only useful for raw secret keys that can be represented as
* a byte array and have no key parameters associated with them, e.g., DES or
* Triple DES keys.
*
* @see SecretKey
* @see javax.crypto.SecretKeyFactory
*/
public class SecretKeySpec
implements KeySpec, SecretKey
{
private static final long serialVersionUID = 6577238317307289933L;
private String algorithm;
private byte[] key;
/**
* Constructs a secret key from the given byte array.
* <p>
* This constructor does not check if the given bytes indeed specify a
* secret key of the specified algorithm. For example, if the algorithm is
* DES, this constructor does not check if <code>key</code> is 8 bytes
* long, and also does not check for weak or semi-weak keys.
* In order for those checks to be performed, an algorithm-specific
* <i>key specification</i> class (in this case:
* <a href = "DESKeySpec.html"><code>DESKeySpec</code></a>)
* should be used.
*
* @param key the key material of the secret key.
* @param algorithm the name of the secret-key algorithm to be associated
* See Appendix A in the Java Cryptography Extension API Specification &amp; Reference
* for information about standard algorithm names.
*/
public SecretKeySpec(
byte[] key,
String algorithm)
{
if (key == null)
{
throw new IllegalArgumentException("null key passed");
}
if (algorithm == null)
{
throw new IllegalArgumentException("null algorithm passed");
}
this.key = new byte[key.length];
System.arraycopy(key, 0, this.key, 0, key.length);
this.algorithm = algorithm;
}
/**
* Constructs a secret key from the given byte array, using the first
* <code>len</code> bytes of <code>key</code>, starting at
* <code>offset</code> inclusive.
* <p>
* The bytes that constitute the secret key are those between <code>key[offset]</code> and
* <code>key[offset+len-1]</code> inclusive.
* <p>
* This constructor does not check if the given bytes indeed specify a
* secret key of the specified algorithm. For example, if the algorithm is
* DES, this constructor does not check if <code>key</code> is 8 bytes
* long, and also does not check for weak or semi-weak keys.
* In order for those checks to be performed, an algorithm-specific key
* specification class (in this case: <a href = "DESKeySpec.html"><code>DESKeySpec</code></a>)
* must be used.
*
* @param key the key material of the secret key.
* @param offset the offset in <code>key</code> where the key material starts.
* @param len the length of the key material.
* @param algorithm the name of the secret-key algorithm to be associated
* with the given key material. See Appendix A in the Java Cryptography Extension API
* Specification &amp; Reference for information about standard algorithm names.
*/
public SecretKeySpec(
byte[] key,
int offset,
int len,
String algorithm)
{
if (key == null)
{
throw new IllegalArgumentException("Null key passed");
}
if ((key.length - offset) < len)
{
throw new IllegalArgumentException("Bad offset/len");
}
if (algorithm == null)
{
throw new IllegalArgumentException("Null algorithm string passed");
}
this.key = new byte[len];
System.arraycopy(key, offset, this.key, 0, len);
this.algorithm = algorithm;
}
/**
* Returns the name of the algorithm associated with this secret key.
*
* @return the secret key algorithm.
*/
public String getAlgorithm()
{
return algorithm;
}
/**
* Returns the name of the encoding format for this secret key.
*
* @return the string "RAW".
*/
public java.lang.String getFormat()
{
return "RAW";
}
/**
* Returns the key material of this secret key.
*
* @return the key material
*/
public byte[] getEncoded()
{
byte[] tmp = new byte[key.length];
System.arraycopy(key, 0, tmp, 0, tmp.length);
return tmp;
}
/**
* Calculates a hash code value for the object.
* Objects that are equal will also have the same hashcode.
*/
public int hashCode()
{
int code = algorithm.toUpperCase().hashCode();
for (int i = 0; i != this.key.length; i++)
{
code ^= this.key[i] << (8 * (i % 4));
}
return code;
}
public boolean equals(
Object obj)
{
if ((obj == null) || !(obj instanceof SecretKeySpec))
{
return false;
}
SecretKeySpec spec = (SecretKeySpec)obj;
if (!this.algorithm.equalsIgnoreCase(spec.algorithm))
{
return false;
}
if (this.key.length != spec.key.length)
{
return false;
}
for (int i = 0; i != this.key.length; i++)
{
if (this.key[i] != spec.key[i])
{
return false;
}
}
return true;
}
}