Add spongy castle sources to libraries folder
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
1509
libraries/spongycastle/jce/src/main/java/javax/crypto/Cipher.java
Normal file
1509
libraries/spongycastle/jce/src/main/java/javax/crypto/Cipher.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 & 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 & 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 & 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 & 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 & 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 & 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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
443
libraries/spongycastle/jce/src/main/java/javax/crypto/Mac.java
Normal file
443
libraries/spongycastle/jce/src/main/java/javax/crypto/Mac.java
Normal 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 & 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 & 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 & 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;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
@@ -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 & 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 & 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 & 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 & 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 & 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user