8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
/**
* This exception is thrown when a {@link Cipher} operating in
* an AEAD mode (such as GCM/CCM) is unable to verify the supplied
* authentication tag.
*
* @since 1.7
*/
public class AEADBadTagException extends BadPaddingException {
private static final long serialVersionUID = -488059093241685509L;
/**
* Constructs a AEADBadTagException with no detail message.
*/
public AEADBadTagException() {
super();
}
/**
* Constructs a AEADBadTagException with the specified
* detail message.
*
* @param msg the detail message.
*/
public AEADBadTagException(String msg) {
super(msg);
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
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.
*
* @author Gigi Ankney
* @since 1.4
*/
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() {
super();
}
/**
* Constructs a BadPaddingException with the specified
* detail message.
*
* @param msg the detail message.
*/
public BadPaddingException(String msg) {
super(msg);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,338 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.io.InputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
/**
* 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.
*
* @author Li Gong
* @see java.io.InputStream
* @see java.io.FilterInputStream
* @see javax.crypto.Cipher
* @see javax.crypto.CipherOutputStream
*
* @since 1.4
*/
public class CipherInputStream extends FilterInputStream {
// the cipher engine to use to process stream data
private Cipher cipher;
// the underlying input stream
private InputStream input;
/* the buffer holding data that have been read in from the
underlying stream, but have not been processed by the cipher
engine. the size 512 bytes is somewhat randomly chosen */
private byte[] ibuffer = new byte[512];
// having reached the end of the underlying input stream
private boolean done = false;
/* the buffer holding data that have been processed by the cipher
engine, but have not been read out */
private byte[] obuffer;
// the offset pointing to the next "new" byte
private int ostart = 0;
// the offset pointing to the last "new" byte
private int ofinish = 0;
// stream status
private boolean closed = false;
/*
* private convenience function.
*
* Entry condition: ostart = ofinish
*
* Exit condition: ostart <= ofinish
*
* return (ofinish-ostart) (we have this many bytes for you)
* return 0 (no data now, but could have more later)
* return -1 (absolutely no more data)
*
* Note: Exceptions are only thrown after the stream is completely read.
* For AEAD ciphers a read() of any length will internally cause the
* whole stream to be read fully and verify the authentication tag before
* returning decrypted data or exceptions.
*/
private int getMoreData() throws IOException {
if (done) return -1;
int readin = input.read(ibuffer);
if (readin == -1) {
done = true;
try {
obuffer = cipher.doFinal();
} catch (IllegalBlockSizeException | BadPaddingException e) {
obuffer = null;
throw new IOException(e);
}
if (obuffer == null)
return -1;
else {
ostart = 0;
ofinish = obuffer.length;
return ofinish;
}
}
try {
obuffer = cipher.update(ibuffer, 0, readin);
} catch (IllegalStateException e) {
obuffer = null;
throw e;
}
ostart = 0;
if (obuffer == null)
ofinish = 0;
else ofinish = obuffer.length;
return ofinish;
}
/**
* Constructs a CipherInputStream from an InputStream and a
* Cipher.
* <br>Note: if the specified input stream or cipher is
* null, a NullPointerException may be thrown later when
* they are used.
* @param is the to-be-processed input stream
* @param c an initialized Cipher object
*/
public CipherInputStream(InputStream is, Cipher c) {
super(is);
input = is;
cipher = c;
}
/**
* Constructs a CipherInputStream from an InputStream without
* specifying a Cipher. This has the effect of constructing a
* CipherInputStream using a NullCipher.
* <br>Note: if the specified input stream is null, a
* NullPointerException may be thrown later when it is used.
* @param is the to-be-processed input stream
*/
protected CipherInputStream(InputStream is) {
super(is);
input = is;
cipher = new NullCipher();
}
/**
* 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.
*/
public int read() throws IOException {
if (ostart >= ofinish) {
// we loop for new data as the spec says we are blocking
int i = 0;
while (i == 0) i = getMoreData();
if (i == -1) return -1;
}
return ((int) obuffer[ostart++] & 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.
* @see java.io.InputStream#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 in the destination array
* <code>buf</code>
* @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.
* @see java.io.InputStream#read()
*/
public int read(byte b[], int off, int len) throws IOException {
if (ostart >= ofinish) {
// we loop for new data as the spec says we are blocking
int i = 0;
while (i == 0) i = getMoreData();
if (i == -1) return -1;
}
if (len <= 0) {
return 0;
}
int available = ofinish - ostart;
if (len < available) available = len;
if (b != null) {
System.arraycopy(obuffer, ostart, b, off, available);
}
ostart = ostart + available;
return available;
}
/**
* 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
* {@link #available() available},
* 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.
*/
public long skip(long n) throws IOException {
int available = ofinish - ostart;
if (n > available) {
n = available;
}
if (n < 0) {
return 0;
}
ostart += n;
return 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.
*/
public int available() throws IOException {
return (ofinish - ostart);
}
/**
* 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.
*/
public void close() throws IOException {
if (closed) {
return;
}
closed = true;
input.close();
// Throw away the unprocessed data and throw no crypto exceptions.
// AEAD ciphers are fully readed before closing. Any authentication
// exceptions would occur while reading.
if (!done) {
try {
cipher.doFinal();
}
catch (BadPaddingException | IllegalBlockSizeException ex) {
// Catch exceptions as the rest of the stream is unused.
}
}
ostart = 0;
ofinish = 0;
}
/**
* 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.
* @see java.io.InputStream#mark(int)
* @see java.io.InputStream#reset()
*/
public boolean markSupported() {
return false;
}
}

View file

@ -0,0 +1,214 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.io.*;
/**
* 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.
*
* @author Li Gong
* @see java.io.OutputStream
* @see java.io.FilterOutputStream
* @see javax.crypto.Cipher
* @see javax.crypto.CipherInputStream
*
* @since 1.4
*/
public class CipherOutputStream extends FilterOutputStream {
// the cipher engine to use to process stream data
private Cipher cipher;
// the underlying output stream
private OutputStream output;
/* the buffer holding one byte of incoming data */
private byte[] ibuffer = new byte[1];
// the buffer holding data ready to be written out
private byte[] obuffer;
// stream status
private boolean closed = false;
/**
*
* Constructs a CipherOutputStream from an OutputStream and a
* Cipher.
* <br>Note: if the specified output stream or cipher is
* null, a NullPointerException may be thrown later when
* they are used.
*
* @param os the OutputStream object
* @param c an initialized Cipher object
*/
public CipherOutputStream(OutputStream os, Cipher c) {
super(os);
output = os;
cipher = c;
};
/**
* Constructs a CipherOutputStream from an OutputStream without
* specifying a Cipher. This has the effect of constructing a
* CipherOutputStream using a NullCipher.
* <br>Note: if the specified output stream is null, a
* NullPointerException may be thrown later when it is used.
*
* @param os the OutputStream object
*/
protected CipherOutputStream(OutputStream os) {
super(os);
output = os;
cipher = new NullCipher();
}
/**
* Writes the specified byte to this output stream.
*
* @param b the <code>byte</code>.
* @exception IOException if an I/O error occurs.
*/
public void write(int b) throws IOException {
ibuffer[0] = (byte) b;
obuffer = cipher.update(ibuffer, 0, 1);
if (obuffer != null) {
output.write(obuffer);
obuffer = null;
}
};
/**
* 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 NullPointerException if <code>b</code> is null.
* @exception IOException if an I/O error occurs.
* @see javax.crypto.CipherOutputStream#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.
*/
public void write(byte b[], int off, int len) throws IOException {
obuffer = cipher.update(b, off, len);
if (obuffer != null) {
output.write(obuffer);
obuffer = null;
}
}
/**
* 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.
*/
public void flush() throws IOException {
if (obuffer != null) {
output.write(obuffer);
obuffer = null;
}
output.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.
*/
public void close() throws IOException {
if (closed) {
return;
}
closed = true;
try {
obuffer = cipher.doFinal();
} catch (IllegalBlockSizeException | BadPaddingException e) {
obuffer = null;
}
try {
flush();
} catch (IOException ignored) {}
out.close();
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,177 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.util.Enumeration;
import java.util.Vector;
/**
* The CryptoAllPermission is a permission that implies
* any other crypto permissions.
* <p>
*
* @see java.security.Permission
* @see java.security.AllPermission
*
* @author Sharon Liu
* @since 1.4
*/
final class CryptoAllPermission extends CryptoPermission {
private static final long serialVersionUID = -5066513634293192112L;
// This class is similar to java.security.AllPermission.
static final String ALG_NAME = "CryptoAllPermission";
static final CryptoAllPermission INSTANCE =
new CryptoAllPermission();
private CryptoAllPermission() {
super(ALG_NAME);
}
/**
* Checks if the specified permission is implied by
* this object.
*
* @param p the permission to check against.
*
* @return true if the specified permission is an
* instance of CryptoPermission.
*/
public boolean implies(Permission p) {
return (p instanceof CryptoPermission);
}
/**
* Checks two CryptoAllPermission objects for equality.
* Two CryptoAllPermission objects are always equal.
*
* @param obj the object to test for equality with this object.
*
* @return true if <i>obj</i> is a CryptoAllPermission object.
*/
public boolean equals(Object obj) {
return (obj == INSTANCE);
}
/**
*
* Returns the hash code value for this object.
*
* @return a hash code value for this object.
*/
public int hashCode() {
return 1;
}
/**
* Returns a new PermissionCollection object for storing
* CryptoAllPermission objects.
* <p>
*
* @return a new PermissionCollection object suitable for
* storing CryptoAllPermissions.
*/
public PermissionCollection newPermissionCollection() {
return new CryptoAllPermissionCollection();
}
}
/**
* A CryptoAllPermissionCollection stores a collection
* of CryptoAllPermission permissions.
*
* @see java.security.Permission
* @see java.security.Permissions
* @see javax.crypto.CryptoPermission
*
* @author Sharon Liu
*/
final class CryptoAllPermissionCollection extends PermissionCollection
implements java.io.Serializable
{
private static final long serialVersionUID = 7450076868380144072L;
// true if a CryptoAllPermission has been added
private boolean all_allowed;
/**
* Create an empty CryptoAllPermissions object.
*/
CryptoAllPermissionCollection() {
all_allowed = false;
}
/**
* Adds a permission to the CryptoAllPermissions.
*
* @param permission the Permission object to add.
*
* @exception SecurityException - if this CryptoAllPermissionCollection
* object has been marked readonly
*/
public void add(Permission permission) {
if (isReadOnly())
throw new SecurityException("attempt to add a Permission to " +
"a readonly PermissionCollection");
if (permission != CryptoAllPermission.INSTANCE)
return;
all_allowed = true;
}
/**
* Check and see if this set of permissions implies the permissions
* expressed in "permission".
*
* @param permission the Permission object to compare
*
* @return true if the given permission is implied by this
* CryptoAllPermissionCollection.
*/
public boolean implies(Permission permission) {
if (!(permission instanceof CryptoPermission)) {
return false;
}
return all_allowed;
}
/**
* Returns an enumeration of all the CryptoAllPermission
* objects in the container.
*
* @return an enumeration of all the CryptoAllPermission objects.
*/
public Enumeration<Permission> elements() {
Vector<Permission> v = new Vector<>(1);
if (all_allowed) v.add(CryptoAllPermission.INSTANCE);
return v.elements();
}
}

View file

@ -0,0 +1,543 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
import javax.crypto.spec.*;
/**
* The CryptoPermission class extends the
* java.security.Permission class. A
* CryptoPermission object is used to represent
* the ability of an application/applet to use certain
* algorithms with certain key sizes and other
* restrictions in certain environments. <p>
*
* @see java.security.Permission
*
* @author Jan Luehe
* @author Sharon Liu
* @since 1.4
*/
class CryptoPermission extends java.security.Permission {
private static final long serialVersionUID = 8987399626114087514L;
private String alg;
private int maxKeySize = Integer.MAX_VALUE; // no restriction on maxKeySize
private String exemptionMechanism = null;
private AlgorithmParameterSpec algParamSpec = null;
private boolean checkParam = false; // no restriction on param
static final String ALG_NAME_WILDCARD = "*";
/**
* Constructor that takes an algorithm name.
*
* This constructor implies that the given algorithm can be
* used without any restrictions.
*
* @param alg the algorithm name.
*/
CryptoPermission(String alg) {
super(null);
this.alg = alg;
}
/**
* Constructor that takes an algorithm name and a maximum
* key size.
*
* This constructor implies that the given algorithm can be
* used with a key size up to <code>maxKeySize</code>.
*
* @param alg the algorithm name.
*
* @param maxKeySize the maximum allowable key size,
* specified in number of bits.
*/
CryptoPermission(String alg, int maxKeySize) {
super(null);
this.alg = alg;
this.maxKeySize = maxKeySize;
}
/**
* Constructor that takes an algorithm name, a maximum
* key size, and an AlgorithmParameterSpec object.
*
* This constructor implies that the given algorithm can be
* used with a key size up to <code>maxKeySize</code>, and
* algorithm
* parameters up to the limits set in <code>algParamSpec</code>.
*
* @param alg the algorithm name.
*
* @param maxKeySize the maximum allowable key size,
* specified in number of bits.
*
* @param algParamSpec the limits for allowable algorithm
* parameters.
*/
CryptoPermission(String alg,
int maxKeySize,
AlgorithmParameterSpec algParamSpec) {
super(null);
this.alg = alg;
this.maxKeySize = maxKeySize;
this.checkParam = true;
this.algParamSpec = algParamSpec;
}
/**
* Constructor that takes an algorithm name and the name of
* an exemption mechanism.
*
* This constructor implies that the given algorithm can be
* used without any key size or algorithm parameter restrictions
* provided that the specified exemption mechanism is enforced.
*
* @param alg the algorithm name.
*
* @param exemptionMechanism the name of the exemption mechanism.
*/
CryptoPermission(String alg,
String exemptionMechanism) {
super(null);
this.alg = alg;
this.exemptionMechanism = exemptionMechanism;
}
/**
* Constructor that takes an algorithm name, a maximum key
* size, and the name of an exemption mechanism.
*
* This constructor implies that the given algorithm can be
* used with a key size up to <code>maxKeySize</code>
* provided that the
* specified exemption mechanism is enforced.
*
* @param alg the algorithm name.
* @param maxKeySize the maximum allowable key size,
* specified in number of bits.
* @param exemptionMechanism the name of the exemption
* mechanism.
*/
CryptoPermission(String alg,
int maxKeySize,
String exemptionMechanism) {
super(null);
this.alg = alg;
this.exemptionMechanism = exemptionMechanism;
this.maxKeySize = maxKeySize;
}
/**
* Constructor that takes an algorithm name, a maximum key
* size, the name of an exemption mechanism, and an
* AlgorithmParameterSpec object.
*
* This constructor implies that the given algorithm can be
* used with a key size up to <code>maxKeySize</code>
* and algorithm
* parameters up to the limits set in <code>algParamSpec</code>
* provided that
* the specified exemption mechanism is enforced.
*
* @param alg the algorithm name.
* @param maxKeySize the maximum allowable key size,
* specified in number of bits.
* @param algParamSpec the limit for allowable algorithm
* parameter spec.
* @param exemptionMechanism the name of the exemption
* mechanism.
*/
CryptoPermission(String alg,
int maxKeySize,
AlgorithmParameterSpec algParamSpec,
String exemptionMechanism) {
super(null);
this.alg = alg;
this.exemptionMechanism = exemptionMechanism;
this.maxKeySize = maxKeySize;
this.checkParam = true;
this.algParamSpec = algParamSpec;
}
/**
* Checks if the specified permission is "implied" by
* this object.
* <p>
* More specifically, this method returns true if:
* <ul>
* <li> <i>p</i> is an instance of CryptoPermission, and</li>
* <li> <i>p</i>'s algorithm name equals or (in the case of wildcards)
* is implied by this permission's algorithm name, and</li>
* <li> <i>p</i>'s maximum allowable key size is less or
* equal to this permission's maximum allowable key size, and</li>
* <li> <i>p</i>'s algorithm parameter spec equals or is
* implied by this permission's algorithm parameter spec, and</li>
* <li> <i>p</i>'s exemptionMechanism equals or
* is implied by this permission's
* exemptionMechanism (a <code>null</code> exemption mechanism
* implies any other exemption mechanism).</li>
* </ul>
*
* @param p the permission to check against.
*
* @return true if the specified permission is equal to or
* implied by this permission, false otherwise.
*/
public boolean implies(Permission p) {
if (!(p instanceof CryptoPermission))
return false;
CryptoPermission cp = (CryptoPermission)p;
if ((!alg.equalsIgnoreCase(cp.alg)) &&
(!alg.equalsIgnoreCase(ALG_NAME_WILDCARD))) {
return false;
}
// alg is the same as cp's alg or
// alg is a wildcard.
if (cp.maxKeySize <= this.maxKeySize) {
// check algParamSpec.
if (!impliesParameterSpec(cp.checkParam, cp.algParamSpec)) {
return false;
}
// check exemptionMechanism.
if (impliesExemptionMechanism(cp.exemptionMechanism)) {
return true;
}
}
return false;
}
/**
* Checks two CryptoPermission objects for equality. Checks that
* <code>obj</code> is a CryptoPermission, and has the same
* algorithm name,
* exemption mechanism name, maximum allowable key size and
* algorithm parameter spec
* as this object.
* <P>
* @param obj the object to test for equality with this object.
* @return true if <code>obj</code> is equal to this object.
*/
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof CryptoPermission))
return false;
CryptoPermission that = (CryptoPermission) obj;
if (!(alg.equalsIgnoreCase(that.alg)) ||
(maxKeySize != that.maxKeySize)) {
return false;
}
if (this.checkParam != that.checkParam) {
return false;
}
return (equalObjects(this.exemptionMechanism,
that.exemptionMechanism) &&
equalObjects(this.algParamSpec,
that.algParamSpec));
}
/**
* Returns the hash code value for this object.
*
* @return a hash code value for this object.
*/
public int hashCode() {
int retval = alg.hashCode();
retval ^= maxKeySize;
if (exemptionMechanism != null) {
retval ^= exemptionMechanism.hashCode();
}
if (checkParam) retval ^= 100;
if (algParamSpec != null) {
retval ^= algParamSpec.hashCode();
}
return retval;
}
/**
* There is no action defined for a CryptoPermission
* onject.
*/
public String getActions()
{
return null;
}
/**
* Returns a new PermissionCollection object for storing
* CryptoPermission objects.
*
* @return a new PermissionCollection object suitable for storing
* CryptoPermissions.
*/
public PermissionCollection newPermissionCollection() {
return new CryptoPermissionCollection();
}
/**
* Returns the algorithm name associated with
* this CryptoPermission object.
*/
final String getAlgorithm() {
return alg;
}
/**
* Returns the exemption mechanism name
* associated with this CryptoPermission
* object.
*/
final String getExemptionMechanism() {
return exemptionMechanism;
}
/**
* Returns the maximum allowable key size associated
* with this CryptoPermission object.
*/
final int getMaxKeySize() {
return maxKeySize;
}
/**
* Returns true if there is a limitation on the
* AlgorithmParameterSpec associated with this
* CryptoPermission object and false if otherwise.
*/
final boolean getCheckParam() {
return checkParam;
}
/**
* Returns the AlgorithmParameterSpec
* associated with this CryptoPermission
* object.
*/
final AlgorithmParameterSpec getAlgorithmParameterSpec() {
return algParamSpec;
}
/**
* Returns a string describing this CryptoPermission. The convention is to
* specify the class name, the algorithm name, the maximum allowable
* key size, and the name of the exemption mechanism, in the following
* format: '("ClassName" "algorithm" "keysize" "exemption_mechanism")'.
*
* @return information about this CryptoPermission.
*/
public String toString() {
StringBuilder buf = new StringBuilder(100);
buf.append("(CryptoPermission " + alg + " " + maxKeySize);
if (algParamSpec != null) {
if (algParamSpec instanceof RC2ParameterSpec) {
buf.append(" , effective " +
((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits());
} else if (algParamSpec instanceof RC5ParameterSpec) {
buf.append(" , rounds " +
((RC5ParameterSpec)algParamSpec).getRounds());
}
}
if (exemptionMechanism != null) { // OPTIONAL
buf.append(" " + exemptionMechanism);
}
buf.append(")");
return buf.toString();
}
private boolean impliesExemptionMechanism(String exemptionMechanism) {
if (this.exemptionMechanism == null) {
return true;
}
if (exemptionMechanism == null) {
return false;
}
if (this.exemptionMechanism.equals(exemptionMechanism)) {
return true;
}
return false;
}
private boolean impliesParameterSpec(boolean checkParam,
AlgorithmParameterSpec algParamSpec) {
if ((this.checkParam) && checkParam) {
if (algParamSpec == null) {
return true;
} else if (this.algParamSpec == null) {
return false;
}
if (this.algParamSpec.getClass() != algParamSpec.getClass()) {
return false;
}
if (algParamSpec instanceof RC2ParameterSpec) {
if (((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits() <=
((RC2ParameterSpec)
(this.algParamSpec)).getEffectiveKeyBits()) {
return true;
}
}
if (algParamSpec instanceof RC5ParameterSpec) {
if (((RC5ParameterSpec)algParamSpec).getRounds() <=
((RC5ParameterSpec)this.algParamSpec).getRounds()) {
return true;
}
}
if (algParamSpec instanceof PBEParameterSpec) {
if (((PBEParameterSpec)algParamSpec).getIterationCount() <=
((PBEParameterSpec)this.algParamSpec).getIterationCount()) {
return true;
}
}
// For classes we don't know, the following
// may be the best try.
if (this.algParamSpec.equals(algParamSpec)) {
return true;
}
return false;
} else if (this.checkParam) {
return false;
} else {
return true;
}
}
private boolean equalObjects(Object obj1, Object obj2) {
if (obj1 == null) {
return (obj2 == null ? true : false);
}
return obj1.equals(obj2);
}
}
/**
* A CryptoPermissionCollection stores a set of CryptoPermission
* permissions.
*
* @see java.security.Permission
* @see java.security.Permissions
* @see java.security.PermissionCollection
*
* @author Sharon Liu
*/
final class CryptoPermissionCollection extends PermissionCollection
implements Serializable
{
private static final long serialVersionUID = -511215555898802763L;
private Vector<Permission> permissions;
/**
* Creates an empty CryptoPermissionCollection
* object.
*/
CryptoPermissionCollection() {
permissions = new Vector<Permission>(3);
}
/**
* Adds a permission to the CryptoPermissionCollection.
*
* @param permission the Permission object to add.
*
* @exception SecurityException - if this CryptoPermissionCollection
* object has been marked <i>readOnly</i>.
*/
public void add(Permission permission) {
if (isReadOnly())
throw new SecurityException("attempt to add a Permission " +
"to a readonly PermissionCollection");
if (!(permission instanceof CryptoPermission))
return;
permissions.addElement(permission);
}
/**
* Check and see if this CryptoPermission object implies
* the given Permission object.
*
* @param permission the Permission object to compare
*
* @return true if the given permission is implied by this
* CryptoPermissionCollection, false if not.
*/
public boolean implies(Permission permission) {
if (!(permission instanceof CryptoPermission))
return false;
CryptoPermission cp = (CryptoPermission)permission;
Enumeration<Permission> e = permissions.elements();
while (e.hasMoreElements()) {
CryptoPermission x = (CryptoPermission) e.nextElement();
if (x.implies(cp)) {
return true;
}
}
return false;
}
/**
* Returns an enumeration of all the CryptoPermission objects
* in the container.
*
* @return an enumeration of all the CryptoPermission objects.
*/
public Enumeration<Permission> elements() {
return permissions.elements();
}
}

View file

@ -0,0 +1,518 @@
/*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
import java.io.Serializable;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.ObjectStreamField;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
/**
* This class contains CryptoPermission objects, organized into
* PermissionCollections according to algorithm names.
*
* <p>When the <code>add</code> method is called to add a
* CryptoPermission, the CryptoPermission is stored in the
* appropriate PermissionCollection. If no such
* collection exists yet, the algorithm name associated with
* the CryptoPermission object is
* determined and the <code>newPermissionCollection</code> method
* is called on the CryptoPermission or CryptoAllPermission class to
* create the PermissionCollection and add it to the Permissions object.
*
* @see javax.crypto.CryptoPermission
* @see java.security.PermissionCollection
* @see java.security.Permissions
*
* @author Sharon Liu
* @since 1.4
*/
final class CryptoPermissions extends PermissionCollection
implements Serializable {
private static final long serialVersionUID = 4946547168093391015L;
/**
* @serialField perms java.util.Hashtable
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("perms", Hashtable.class),
};
// Switched from Hashtable to ConcurrentHashMap to improve scalability.
// To maintain serialization compatibility, this field is made transient
// and custom readObject/writeObject methods are used.
private transient ConcurrentHashMap<String,PermissionCollection> perms;
/**
* Creates a new CryptoPermissions object containing
* no CryptoPermissionCollections.
*/
CryptoPermissions() {
perms = new ConcurrentHashMap<>(7);
}
/**
* Populates the crypto policy from the specified
* InputStream into this CryptoPermissions object.
*
* @param in the InputStream to load from.
*
* @exception SecurityException if cannot load
* successfully.
*/
void load(InputStream in)
throws IOException, CryptoPolicyParser.ParsingException {
CryptoPolicyParser parser = new CryptoPolicyParser();
parser.read(new BufferedReader(new InputStreamReader(in, "UTF-8")));
CryptoPermission[] parsingResult = parser.getPermissions();
for (int i = 0; i < parsingResult.length; i++) {
this.add(parsingResult[i]);
}
}
/**
* Returns true if this CryptoPermissions object doesn't
* contain any CryptoPermission objects; otherwise, returns
* false.
*/
boolean isEmpty() {
return perms.isEmpty();
}
/**
* Adds a permission object to the PermissionCollection for the
* algorithm returned by
* <code>(CryptoPermission)permission.getAlgorithm()</code>.
*
* This method creates
* a new PermissionCollection object (and adds the permission to it)
* if an appropriate collection does not yet exist. <p>
*
* @param permission the Permission object to add.
*
* @exception SecurityException if this CryptoPermissions object is
* marked as readonly.
*
* @see isReadOnly
*/
@Override
public void add(Permission permission) {
if (isReadOnly()) {
throw new SecurityException("Attempt to add a Permission " +
"to a readonly CryptoPermissions " +
"object");
}
if (!(permission instanceof CryptoPermission)) {
return;
}
CryptoPermission cryptoPerm = (CryptoPermission)permission;
PermissionCollection pc =
getPermissionCollection(cryptoPerm);
pc.add(cryptoPerm);
String alg = cryptoPerm.getAlgorithm();
perms.putIfAbsent(alg, pc);
}
/**
* Checks if this object's PermissionCollection for permissons
* of the specified permission's algorithm implies the specified
* permission. Returns true if the checking succeeded.
*
* @param permission the Permission object to check.
*
* @return true if "permission" is implied by the permissions
* in the PermissionCollection it belongs to, false if not.
*
*/
@Override
public boolean implies(Permission permission) {
if (!(permission instanceof CryptoPermission)) {
return false;
}
CryptoPermission cryptoPerm = (CryptoPermission)permission;
PermissionCollection pc =
getPermissionCollection(cryptoPerm.getAlgorithm());
if (pc != null) {
return pc.implies(cryptoPerm);
} else {
// none found
return false;
}
}
/**
* Returns an enumeration of all the Permission objects in all the
* PermissionCollections in this CryptoPermissions object.
*
* @return an enumeration of all the Permissions.
*/
@Override
public Enumeration<Permission> elements() {
// go through each Permissions in the hash table
// and call their elements() function.
return new PermissionsEnumerator(perms.elements());
}
/**
* Returns a CryptoPermissions object which
* represents the minimum of the specified
* CryptoPermissions object and this
* CryptoPermissions object.
*
* @param other the CryptoPermission
* object to compare with this object.
*/
CryptoPermissions getMinimum(CryptoPermissions other) {
if (other == null) {
return null;
}
if (this.perms.containsKey(CryptoAllPermission.ALG_NAME)) {
return other;
}
if (other.perms.containsKey(CryptoAllPermission.ALG_NAME)) {
return this;
}
CryptoPermissions ret = new CryptoPermissions();
PermissionCollection thatWildcard =
other.perms.get(CryptoPermission.ALG_NAME_WILDCARD);
int maxKeySize = 0;
if (thatWildcard != null) {
maxKeySize = ((CryptoPermission)
thatWildcard.elements().nextElement()).getMaxKeySize();
}
// For each algorithm in this CryptoPermissions,
// find out if there is anything we should add into
// ret.
Enumeration<String> thisKeys = this.perms.keys();
while (thisKeys.hasMoreElements()) {
String alg = thisKeys.nextElement();
PermissionCollection thisPc = this.perms.get(alg);
PermissionCollection thatPc = other.perms.get(alg);
CryptoPermission[] partialResult;
if (thatPc == null) {
if (thatWildcard == null) {
// The other CryptoPermissions
// doesn't allow this given
// algorithm at all. Just skip this
// algorithm.
continue;
}
partialResult = getMinimum(maxKeySize, thisPc);
} else {
partialResult = getMinimum(thisPc, thatPc);
}
for (int i = 0; i < partialResult.length; i++) {
ret.add(partialResult[i]);
}
}
PermissionCollection thisWildcard =
this.perms.get(CryptoPermission.ALG_NAME_WILDCARD);
// If this CryptoPermissions doesn't
// have a wildcard, we are done.
if (thisWildcard == null) {
return ret;
}
// Deal with the algorithms only appear
// in the other CryptoPermissions.
maxKeySize =
((CryptoPermission)
thisWildcard.elements().nextElement()).getMaxKeySize();
Enumeration<String> thatKeys = other.perms.keys();
while (thatKeys.hasMoreElements()) {
String alg = thatKeys.nextElement();
if (this.perms.containsKey(alg)) {
continue;
}
PermissionCollection thatPc = other.perms.get(alg);
CryptoPermission[] partialResult;
partialResult = getMinimum(maxKeySize, thatPc);
for (int i = 0; i < partialResult.length; i++) {
ret.add(partialResult[i]);
}
}
return ret;
}
/**
* Get the minimum of the two given PermissionCollection
* <code>thisPc</code> and <code>thatPc</code>.
*
* @param thisPc the first given PermissionColloection
* object.
*
* @param thatPc the second given PermissionCollection
* object.
*/
private CryptoPermission[] getMinimum(PermissionCollection thisPc,
PermissionCollection thatPc) {
Vector<CryptoPermission> permVector = new Vector<>(2);
Enumeration<Permission> thisPcPermissions = thisPc.elements();
// For each CryptoPermission in
// thisPc object, do the following:
// 1) if this CryptoPermission is implied
// by thatPc, this CryptoPermission
// should be returned, and we can
// move on to check the next
// CryptoPermission in thisPc.
// 2) otherwise, we should return
// all CryptoPermissions in thatPc
// which
// are implied by this CryptoPermission.
// Then we can move on to the
// next CryptoPermission in thisPc.
while (thisPcPermissions.hasMoreElements()) {
CryptoPermission thisCp =
(CryptoPermission)thisPcPermissions.nextElement();
Enumeration<Permission> thatPcPermissions = thatPc.elements();
while (thatPcPermissions.hasMoreElements()) {
CryptoPermission thatCp =
(CryptoPermission)thatPcPermissions.nextElement();
if (thatCp.implies(thisCp)) {
permVector.addElement(thisCp);
break;
}
if (thisCp.implies(thatCp)) {
permVector.addElement(thatCp);
}
}
}
CryptoPermission[] ret = new CryptoPermission[permVector.size()];
permVector.copyInto(ret);
return ret;
}
/**
* Returns all the CryptoPermission objects in the given
* PermissionCollection object
* whose maximum keysize no greater than <code>maxKeySize</code>.
* For all CryptoPermission objects with a maximum keysize greater
* than <code>maxKeySize</code>, this method constructs a
* corresponding CryptoPermission object whose maximum keysize is
* set to <code>maxKeySize</code>, and includes that in the result.
*
* @param maxKeySize the given maximum key size.
*
* @param pc the given PermissionCollection object.
*/
private CryptoPermission[] getMinimum(int maxKeySize,
PermissionCollection pc) {
Vector<CryptoPermission> permVector = new Vector<>(1);
Enumeration<Permission> enum_ = pc.elements();
while (enum_.hasMoreElements()) {
CryptoPermission cp =
(CryptoPermission)enum_.nextElement();
if (cp.getMaxKeySize() <= maxKeySize) {
permVector.addElement(cp);
} else {
if (cp.getCheckParam()) {
permVector.addElement(
new CryptoPermission(cp.getAlgorithm(),
maxKeySize,
cp.getAlgorithmParameterSpec(),
cp.getExemptionMechanism()));
} else {
permVector.addElement(
new CryptoPermission(cp.getAlgorithm(),
maxKeySize,
cp.getExemptionMechanism()));
}
}
}
CryptoPermission[] ret = new CryptoPermission[permVector.size()];
permVector.copyInto(ret);
return ret;
}
/**
* Returns the PermissionCollection for the
* specified algorithm. Returns null if there
* isn't such a PermissionCollection.
*
* @param alg the algorithm name.
*/
PermissionCollection getPermissionCollection(String alg) {
// If this CryptoPermissions includes CryptoAllPermission,
// we should return CryptoAllPermission.
PermissionCollection pc = perms.get(CryptoAllPermission.ALG_NAME);
if (pc == null) {
pc = perms.get(alg);
// If there isn't a PermissionCollection for
// the given algorithm,we should return the
// PermissionCollection for the wildcard
// if there is one.
if (pc == null) {
pc = perms.get(CryptoPermission.ALG_NAME_WILDCARD);
}
}
return pc;
}
/**
* Returns the PermissionCollection for the algorithm
* associated with the specified CryptoPermission
* object. Creates such a PermissionCollection
* if such a PermissionCollection does not
* exist yet.
*
* @param cryptoPerm the CryptoPermission object.
*/
private PermissionCollection getPermissionCollection(
CryptoPermission cryptoPerm) {
String alg = cryptoPerm.getAlgorithm();
PermissionCollection pc = perms.get(alg);
if (pc == null) {
pc = cryptoPerm.newPermissionCollection();
}
return pc;
}
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
@SuppressWarnings("unchecked")
Hashtable<String,PermissionCollection> permTable =
(Hashtable<String,PermissionCollection>)
(fields.get("perms", null));
if (permTable != null) {
perms = new ConcurrentHashMap<>(permTable);
} else {
perms = new ConcurrentHashMap<>();
}
}
private void writeObject(ObjectOutputStream s) throws IOException {
Hashtable<String,PermissionCollection> permTable =
new Hashtable<>(perms);
ObjectOutputStream.PutField fields = s.putFields();
fields.put("perms", permTable);
s.writeFields();
}
}
final class PermissionsEnumerator implements Enumeration<Permission> {
// all the perms
private final Enumeration<PermissionCollection> perms;
// the current set
private Enumeration<Permission> permset;
PermissionsEnumerator(Enumeration<PermissionCollection> e) {
perms = e;
permset = getNextEnumWithMore();
}
@Override
public synchronized boolean hasMoreElements() {
// if we enter with permissionimpl null, we know
// there are no more left.
if (permset == null) {
return false;
}
// try to see if there are any left in the current one
if (permset.hasMoreElements()) {
return true;
}
// get the next one that has something in it...
permset = getNextEnumWithMore();
// if it is null, we are done!
return (permset != null);
}
@Override
public synchronized Permission nextElement() {
// hasMoreElements will update permset to the next permset
// with something in it...
if (hasMoreElements()) {
return permset.nextElement();
} else {
throw new NoSuchElementException("PermissionsEnumerator");
}
}
private Enumeration<Permission> getNextEnumWithMore() {
while (perms.hasMoreElements()) {
PermissionCollection pc = perms.nextElement();
Enumeration<Permission> next = pc.elements();
if (next.hasMoreElements()) {
return next;
}
}
return null;
}
}

View file

@ -0,0 +1,706 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.io.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import static java.util.Locale.ENGLISH;
import java.security.GeneralSecurityException;
import java.security.spec.AlgorithmParameterSpec;
import java.lang.reflect.*;
/**
* JCE has two pairs of jurisdiction policy files: one represents U.S. export
* laws, and the other represents the local laws of the country where the
* JCE will be used.
*
* The jurisdiction policy file has the same syntax as JDK policy files except
* that JCE has new permission classes called javax.crypto.CryptoPermission
* and javax.crypto.CryptoAllPermission.
*
* The format of a permission entry in the jurisdiction policy file is:
*
* <pre>{@code
* permission <crypto permission class name>[, <algorithm name>
* [[, <exemption mechanism name>][, <maxKeySize>
* [, <AlgrithomParameterSpec class name>, <parameters
* for constructing an AlgrithomParameterSpec object>]]]];
* }</pre>
*
* @author Sharon Liu
*
* @see java.security.Permissions
* @see java.security.spec.AlgorithmParameterSpec
* @see javax.crypto.CryptoPermission
* @see javax.crypto.CryptoAllPermission
* @see javax.crypto.CryptoPermissions
* @since 1.4
*/
final class CryptoPolicyParser {
private Vector<GrantEntry> grantEntries;
// Convenience variables for parsing
private StreamTokenizer st;
private int lookahead;
/**
* Creates a CryptoPolicyParser object.
*/
CryptoPolicyParser() {
grantEntries = new Vector<GrantEntry>();
}
/**
* Reads a policy configuration using a Reader object. <p>
*
* @param policy the policy Reader object.
*
* @exception ParsingException if the policy configuration
* contains a syntax error.
*
* @exception IOException if an error occurs while reading
* the policy configuration.
*/
void read(Reader policy)
throws ParsingException, IOException
{
if (!(policy instanceof BufferedReader)) {
policy = new BufferedReader(policy);
}
/*
* Configure the stream tokenizer:
* Recognize strings between "..."
* Don't convert words to lowercase
* Recognize both C-style and C++-style comments
* Treat end-of-line as white space, not as a token
*/
st = new StreamTokenizer(policy);
st.resetSyntax();
st.wordChars('a', 'z');
st.wordChars('A', 'Z');
st.wordChars('.', '.');
st.wordChars('0', '9');
st.wordChars('_', '_');
st.wordChars('$', '$');
st.wordChars(128 + 32, 255);
st.whitespaceChars(0, ' ');
st.commentChar('/');
st.quoteChar('\'');
st.quoteChar('"');
st.lowerCaseMode(false);
st.ordinaryChar('/');
st.slashSlashComments(true);
st.slashStarComments(true);
st.parseNumbers();
/*
* The crypto jurisdiction policy must be consistent. The
* following hashtable is used for checking consistency.
*/
Hashtable<String, Vector<String>> processedPermissions = null;
/*
* The main parsing loop. The loop is executed once for each entry
* in the policy file. The entries are delimited by semicolons. Once
* we've read in the information for an entry, go ahead and try to
* add it to the grantEntries.
*/
lookahead = st.nextToken();
while (lookahead != StreamTokenizer.TT_EOF) {
if (peek("grant")) {
GrantEntry ge = parseGrantEntry(processedPermissions);
if (ge != null)
grantEntries.addElement(ge);
} else {
throw new ParsingException(st.lineno(), "expected grant " +
"statement");
}
match(";");
}
}
/**
* parse a Grant entry
*/
private GrantEntry parseGrantEntry(
Hashtable<String, Vector<String>> processedPermissions)
throws ParsingException, IOException
{
GrantEntry e = new GrantEntry();
match("grant");
match("{");
while(!peek("}")) {
if (peek("Permission")) {
CryptoPermissionEntry pe =
parsePermissionEntry(processedPermissions);
e.add(pe);
match(";");
} else {
throw new
ParsingException(st.lineno(), "expected permission entry");
}
}
match("}");
return e;
}
/**
* parse a CryptoPermission entry
*/
private CryptoPermissionEntry parsePermissionEntry(
Hashtable<String, Vector<String>> processedPermissions)
throws ParsingException, IOException
{
CryptoPermissionEntry e = new CryptoPermissionEntry();
match("Permission");
e.cryptoPermission = match("permission type");
if (e.cryptoPermission.equals("javax.crypto.CryptoAllPermission")) {
// Done with the CryptoAllPermission entry.
e.alg = CryptoAllPermission.ALG_NAME;
e.maxKeySize = Integer.MAX_VALUE;
return e;
}
// Should see the algorithm name.
if (peek("\"")) {
// Algorithm name - always convert to upper case after parsing.
e.alg = match("quoted string").toUpperCase(ENGLISH);
} else {
// The algorithm name can be a wildcard.
if (peek("*")) {
match("*");
e.alg = CryptoPermission.ALG_NAME_WILDCARD;
} else {
throw new ParsingException(st.lineno(),
"Missing the algorithm name");
}
}
peekAndMatch(",");
// May see the exemption mechanism name.
if (peek("\"")) {
// Exemption mechanism name - convert to upper case too.
e.exemptionMechanism = match("quoted string").toUpperCase(ENGLISH);
}
peekAndMatch(",");
// Check whether this entry is consistent with other permission entries
// that have been read.
if (!isConsistent(e.alg, e.exemptionMechanism, processedPermissions)) {
throw new ParsingException(st.lineno(), "Inconsistent policy");
}
// Should see the maxKeySize if not at the end of this entry yet.
if (peek("number")) {
e.maxKeySize = match();
} else {
if (peek("*")) {
match("*");
e.maxKeySize = Integer.MAX_VALUE;
} else {
if (!peek(";")) {
throw new ParsingException(st.lineno(),
"Missing the maximum " +
"allowable key size");
} else {
// At the end of this permission entry
e.maxKeySize = Integer.MAX_VALUE;
}
}
}
peekAndMatch(",");
// May see an AlgorithmParameterSpec class name.
if (peek("\"")) {
// AlgorithmParameterSpec class name.
String algParamSpecClassName = match("quoted string");
Vector<Integer> paramsV = new Vector<>(1);
while (peek(",")) {
match(",");
if (peek("number")) {
paramsV.addElement(match());
} else {
if (peek("*")) {
match("*");
paramsV.addElement(Integer.MAX_VALUE);
} else {
throw new ParsingException(st.lineno(),
"Expecting an integer");
}
}
}
Integer[] params = new Integer[paramsV.size()];
paramsV.copyInto(params);
e.checkParam = true;
e.algParamSpec = getInstance(algParamSpecClassName, params);
}
return e;
}
private static final AlgorithmParameterSpec getInstance(String type,
Integer[] params)
throws ParsingException
{
AlgorithmParameterSpec ret = null;
try {
Class<?> apsClass = Class.forName(type);
Class<?>[] paramClasses = new Class<?>[params.length];
for (int i = 0; i < params.length; i++) {
paramClasses[i] = int.class;
}
Constructor<?> c = apsClass.getConstructor(paramClasses);
ret = (AlgorithmParameterSpec) c.newInstance((Object[]) params);
} catch (Exception e) {
throw new ParsingException("Cannot call the constructor of " +
type + e);
}
return ret;
}
private boolean peekAndMatch(String expect)
throws ParsingException, IOException
{
if (peek(expect)) {
match(expect);
return true;
}
return false;
}
private boolean peek(String expect) {
boolean found = false;
switch (lookahead) {
case StreamTokenizer.TT_WORD:
if (expect.equalsIgnoreCase(st.sval))
found = true;
break;
case StreamTokenizer.TT_NUMBER:
if (expect.equalsIgnoreCase("number")) {
found = true;
}
break;
case ',':
if (expect.equals(","))
found = true;
break;
case '{':
if (expect.equals("{"))
found = true;
break;
case '}':
if (expect.equals("}"))
found = true;
break;
case '"':
if (expect.equals("\""))
found = true;
break;
case '*':
if (expect.equals("*"))
found = true;
break;
case ';':
if (expect.equals(";"))
found = true;
break;
default:
break;
}
return found;
}
/**
* Excepts to match a non-negative number.
*/
private int match()
throws ParsingException, IOException
{
int value = -1;
int lineno = st.lineno();
String sValue = null;
switch (lookahead) {
case StreamTokenizer.TT_NUMBER:
value = (int)st.nval;
if (value < 0) {
sValue = String.valueOf(st.nval);
}
lookahead = st.nextToken();
break;
default:
sValue = st.sval;
break;
}
if (value <= 0) {
throw new ParsingException(lineno, "a non-negative number",
sValue);
}
return value;
}
private String match(String expect)
throws ParsingException, IOException
{
String value = null;
switch (lookahead) {
case StreamTokenizer.TT_NUMBER:
throw new ParsingException(st.lineno(), expect,
"number "+String.valueOf(st.nval));
case StreamTokenizer.TT_EOF:
throw new ParsingException("expected "+expect+", read end of file");
case StreamTokenizer.TT_WORD:
if (expect.equalsIgnoreCase(st.sval)) {
lookahead = st.nextToken();
}
else if (expect.equalsIgnoreCase("permission type")) {
value = st.sval;
lookahead = st.nextToken();
}
else
throw new ParsingException(st.lineno(), expect, st.sval);
break;
case '"':
if (expect.equalsIgnoreCase("quoted string")) {
value = st.sval;
lookahead = st.nextToken();
} else if (expect.equalsIgnoreCase("permission type")) {
value = st.sval;
lookahead = st.nextToken();
}
else
throw new ParsingException(st.lineno(), expect, st.sval);
break;
case ',':
if (expect.equals(","))
lookahead = st.nextToken();
else
throw new ParsingException(st.lineno(), expect, ",");
break;
case '{':
if (expect.equals("{"))
lookahead = st.nextToken();
else
throw new ParsingException(st.lineno(), expect, "{");
break;
case '}':
if (expect.equals("}"))
lookahead = st.nextToken();
else
throw new ParsingException(st.lineno(), expect, "}");
break;
case ';':
if (expect.equals(";"))
lookahead = st.nextToken();
else
throw new ParsingException(st.lineno(), expect, ";");
break;
case '*':
if (expect.equals("*"))
lookahead = st.nextToken();
else
throw new ParsingException(st.lineno(), expect, "*");
break;
default:
throw new ParsingException(st.lineno(), expect,
new String(new char[] {(char)lookahead}));
}
return value;
}
CryptoPermission[] getPermissions() {
Vector<CryptoPermission> result = new Vector<>();
Enumeration<GrantEntry> grantEnum = grantEntries.elements();
while (grantEnum.hasMoreElements()) {
GrantEntry ge = grantEnum.nextElement();
Enumeration<CryptoPermissionEntry> permEnum =
ge.permissionElements();
while (permEnum.hasMoreElements()) {
CryptoPermissionEntry pe = permEnum.nextElement();
if (pe.cryptoPermission.equals(
"javax.crypto.CryptoAllPermission")) {
result.addElement(CryptoAllPermission.INSTANCE);
} else {
if (pe.checkParam) {
result.addElement(new CryptoPermission(
pe.alg,
pe.maxKeySize,
pe.algParamSpec,
pe.exemptionMechanism));
} else {
result.addElement(new CryptoPermission(
pe.alg,
pe.maxKeySize,
pe.exemptionMechanism));
}
}
}
}
CryptoPermission[] ret = new CryptoPermission[result.size()];
result.copyInto(ret);
return ret;
}
private boolean isConsistent(String alg, String exemptionMechanism,
Hashtable<String, Vector<String>> processedPermissions) {
String thisExemptionMechanism =
exemptionMechanism == null ? "none" : exemptionMechanism;
if (processedPermissions == null) {
processedPermissions = new Hashtable<String, Vector<String>>();
Vector<String> exemptionMechanisms = new Vector<>(1);
exemptionMechanisms.addElement(thisExemptionMechanism);
processedPermissions.put(alg, exemptionMechanisms);
return true;
}
if (processedPermissions.containsKey(CryptoAllPermission.ALG_NAME)) {
return false;
}
Vector<String> exemptionMechanisms;
if (processedPermissions.containsKey(alg)) {
exemptionMechanisms = processedPermissions.get(alg);
if (exemptionMechanisms.contains(thisExemptionMechanism)) {
return false;
}
} else {
exemptionMechanisms = new Vector<String>(1);
}
exemptionMechanisms.addElement(thisExemptionMechanism);
processedPermissions.put(alg, exemptionMechanisms);
return true;
}
/**
* Each grant entry in the policy configuration file is represented by a
* GrantEntry object.
* <p>
* For example, the entry
* <pre>
* grant {
* permission javax.crypto.CryptoPermission "DES", 56;
* };
*
* </pre>
* is represented internally
* <pre>
*
* pe = new CryptoPermissionEntry("javax.crypto.CryptoPermission",
* "DES", 56);
*
* ge = new GrantEntry();
*
* ge.add(pe);
*
* </pre>
*
* @see java.security.Permission
* @see javax.crypto.CryptoPermission
* @see javax.crypto.CryptoPermissions
*/
private static class GrantEntry {
private Vector<CryptoPermissionEntry> permissionEntries;
GrantEntry() {
permissionEntries = new Vector<CryptoPermissionEntry>();
}
void add(CryptoPermissionEntry pe)
{
permissionEntries.addElement(pe);
}
boolean remove(CryptoPermissionEntry pe)
{
return permissionEntries.removeElement(pe);
}
boolean contains(CryptoPermissionEntry pe)
{
return permissionEntries.contains(pe);
}
/**
* Enumerate all the permission entries in this GrantEntry.
*/
Enumeration<CryptoPermissionEntry> permissionElements(){
return permissionEntries.elements();
}
}
/**
* Each crypto permission entry in the policy configuration file is
* represented by a CryptoPermissionEntry object.
* <p>
* For example, the entry
* <pre>
* permission javax.crypto.CryptoPermission "DES", 56;
* </pre>
* is represented internally
* <pre>
*
* pe = new CryptoPermissionEntry("javax.crypto.cryptoPermission",
* "DES", 56);
* </pre>
*
* @see java.security.Permissions
* @see javax.crypto.CryptoPermission
* @see javax.crypto.CryptoAllPermission
*/
private static class CryptoPermissionEntry {
String cryptoPermission;
String alg;
String exemptionMechanism;
int maxKeySize;
boolean checkParam;
AlgorithmParameterSpec algParamSpec;
CryptoPermissionEntry() {
// Set default values.
maxKeySize = 0;
alg = null;
exemptionMechanism = null;
checkParam = false;
algParamSpec = null;
}
/**
* Calculates a hash code value for the object. Objects
* which are equal will also have the same hashcode.
*/
public int hashCode() {
int retval = cryptoPermission.hashCode();
if (alg != null) retval ^= alg.hashCode();
if (exemptionMechanism != null) {
retval ^= exemptionMechanism.hashCode();
}
retval ^= maxKeySize;
if (checkParam) retval ^= 100;
if (algParamSpec != null) {
retval ^= algParamSpec.hashCode();
}
return retval;
}
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof CryptoPermissionEntry))
return false;
CryptoPermissionEntry that = (CryptoPermissionEntry) obj;
if (this.cryptoPermission == null) {
if (that.cryptoPermission != null) return false;
} else {
if (!this.cryptoPermission.equals(
that.cryptoPermission))
return false;
}
if (this.alg == null) {
if (that.alg != null) return false;
} else {
if (!this.alg.equalsIgnoreCase(that.alg))
return false;
}
if (!(this.maxKeySize == that.maxKeySize)) return false;
if (this.checkParam != that.checkParam) return false;
if (this.algParamSpec == null) {
if (that.algParamSpec != null) return false;
} else {
if (!this.algParamSpec.equals(that.algParamSpec))
return false;
}
// everything matched -- the 2 objects are equal
return true;
}
}
static final class ParsingException extends GeneralSecurityException {
private static final long serialVersionUID = 7147241245566588374L;
/**
* Constructs a ParsingException with the specified
* detail message.
* @param msg the detail message.
*/
ParsingException(String msg) {
super(msg);
}
ParsingException(int line, String msg) {
super("line " + line + ": " + msg);
}
ParsingException(int line, String expect, String actual) {
super("line "+line+": expected '"+expect+"', found '"+actual+"'");
}
}
}

View file

@ -0,0 +1,426 @@
/*
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.io.*;
import java.security.*;
import java.security.spec.*;
import sun.security.x509.AlgorithmId;
import sun.security.util.DerValue;
import sun.security.util.DerInputStream;
import sun.security.util.DerOutputStream;
/**
* 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>
*
* @author Valerie Peng
*
* @see java.security.spec.PKCS8EncodedKeySpec
*
* @since 1.4
*/
public class EncryptedPrivateKeyInfo {
// the "encryptionAlgorithm" field
private AlgorithmId algid;
// the algorithm name of the encrypted private key
private String keyAlg;
// the "encryptedData" field
private byte[] encryptedData;
// the ASN.1 encoded contents of this class
private byte[] encoded = null;
/**
* Constructs (i.e., parses) an <code>EncryptedPrivateKeyInfo</code> from
* its ASN.1 encoding.
* @param encoded the ASN.1 encoding of this object. The contents of
* the array are copied to protect against subsequent modification.
* @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 IOException {
if (encoded == null) {
throw new NullPointerException("the encoded parameter " +
"must be non-null");
}
this.encoded = encoded.clone();
DerValue val = new DerValue(this.encoded);
DerValue[] seq = new DerValue[2];
seq[0] = val.data.getDerValue();
seq[1] = val.data.getDerValue();
if (val.data.available() != 0) {
throw new IOException("overrun, bytes = " + val.data.available());
}
this.algid = AlgorithmId.parse(seq[0]);
if (seq[0].data.available() != 0) {
throw new IOException("encryptionAlgorithm field overrun");
}
this.encryptedData = seq[1].getOctetString();
if (seq[1].data.available() != 0) {
throw new IOException("encryptedData field overrun");
}
}
/**
* Constructs an <code>EncryptedPrivateKeyInfo</code> from the
* encryption algorithm name and the encrypted data.
*
* <p>Note: This constructor will use null as the value of the
* algorithm parameters. If the encryption algorithm has
* parameters whose value is not null, a different constructor,
* e.g. EncryptedPrivateKeyInfo(AlgorithmParameters, byte[]),
* should be used.
*
* @param algName encryption algorithm name. See the
* <a href="{@docRoot}/../specs/security/standard-names.html">
* Java Security Standard Algorithm Names</a> document
* for information about standard Cipher algorithm names.
* @param encryptedData encrypted data. The contents of
* <code>encrypedData</code> are copied to protect against subsequent
* modification when constructing this object.
* @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 NoSuchAlgorithmException {
if (algName == null)
throw new NullPointerException("the algName parameter " +
"must be non-null");
this.algid = AlgorithmId.get(algName);
if (encryptedData == null) {
throw new NullPointerException("the encryptedData " +
"parameter must be non-null");
} else if (encryptedData.length == 0) {
throw new IllegalArgumentException("the encryptedData " +
"parameter must not be empty");
} else {
this.encryptedData = encryptedData.clone();
}
// delay the generation of ASN.1 encoding until
// getEncoded() is called
this.encoded = null;
}
/**
* Constructs an <code>EncryptedPrivateKeyInfo</code> from the
* encryption algorithm parameters and the encrypted data.
*
* @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. The contents of
* <code>encrypedData</code> are copied to protect against
* subsequent modification when constructing this object.
* @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 NoSuchAlgorithmException {
if (algParams == null) {
throw new NullPointerException("algParams must be non-null");
}
this.algid = AlgorithmId.get(algParams);
if (encryptedData == null) {
throw new NullPointerException("encryptedData must be non-null");
} else if (encryptedData.length == 0) {
throw new IllegalArgumentException("the encryptedData " +
"parameter must not be empty");
} else {
this.encryptedData = encryptedData.clone();
}
// delay the generation of ASN.1 encoding until
// getEncoded() is called
this.encoded = null;
}
/**
* Returns the encryption algorithm.
* <p>Note: Standard name is returned instead of the specified one
* in the constructor when such mapping is available.
* See the <a href="{@docRoot}/../specs/security/standard-names.html">
* Java Security Standard Algorithm Names</a> document
* for information about standard Cipher algorithm names.
*
* @return the encryption algorithm name.
*/
public String getAlgName() {
return this.algid.getName();
}
/**
* Returns the algorithm parameters used by the encryption algorithm.
* @return the algorithm parameters.
*/
public AlgorithmParameters getAlgParameters() {
return this.algid.getParameters();
}
/**
* Returns the encrypted data.
* @return the encrypted data. Returns a new array
* each time this method is called.
*/
public byte[] getEncryptedData() {
return this.encryptedData.clone();
}
/**
* Extract the enclosed PKCS8EncodedKeySpec object from the
* encrypted data and return it.
* <br>Note: In order to successfully retrieve the enclosed
* PKCS8EncodedKeySpec object, <code>cipher</code> needs
* to be initialized to either Cipher.DECRYPT_MODE or
* Cipher.UNWRAP_MODE, with the same key and parameters used
* for generating the encrypted data.
*
* @param cipher the initialized cipher object which will be
* used for decrypting the encrypted data.
* @return the PKCS8EncodedKeySpec object.
* @exception NullPointerException if <code>cipher</code>
* is null.
* @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 cipher)
throws InvalidKeySpecException {
byte[] encoded = null;
try {
encoded = cipher.doFinal(encryptedData);
checkPKCS8Encoding(encoded);
} catch (GeneralSecurityException |
IOException |
IllegalStateException ex) {
throw new InvalidKeySpecException(
"Cannot retrieve the PKCS8EncodedKeySpec", ex);
}
return new PKCS8EncodedKeySpec(encoded, keyAlg);
}
private PKCS8EncodedKeySpec getKeySpecImpl(Key decryptKey,
Provider provider) throws NoSuchAlgorithmException,
InvalidKeyException {
byte[] encoded = null;
Cipher c;
try {
if (provider == null) {
// use the most preferred one
c = Cipher.getInstance(algid.getName());
} else {
c = Cipher.getInstance(algid.getName(), provider);
}
c.init(Cipher.DECRYPT_MODE, decryptKey, algid.getParameters());
encoded = c.doFinal(encryptedData);
checkPKCS8Encoding(encoded);
} catch (NoSuchAlgorithmException nsae) {
// rethrow
throw nsae;
} catch (GeneralSecurityException | IOException ex) {
throw new InvalidKeyException(
"Cannot retrieve the PKCS8EncodedKeySpec", ex);
}
return new PKCS8EncodedKeySpec(encoded, keyAlg);
}
/**
* Extract the enclosed PKCS8EncodedKeySpec object from the
* encrypted data and return it.
* @param decryptKey key used for decrypting the encrypted data.
* @return the PKCS8EncodedKeySpec object.
* @exception NullPointerException if <code>decryptKey</code>
* is null.
* @exception NoSuchAlgorithmException if cannot find appropriate
* cipher to decrypt the encrypted data.
* @exception InvalidKeyException if <code>decryptKey</code>
* cannot be used to decrypt the encrypted data or the decryption
* result is not a valid PKCS8KeySpec.
*
* @since 1.5
*/
public PKCS8EncodedKeySpec getKeySpec(Key decryptKey)
throws NoSuchAlgorithmException, InvalidKeyException {
if (decryptKey == null) {
throw new NullPointerException("decryptKey is null");
}
return getKeySpecImpl(decryptKey, null);
}
/**
* Extract the enclosed PKCS8EncodedKeySpec object from the
* encrypted data and return it.
* @param decryptKey key used for decrypting the encrypted data.
* @param providerName the name of provider whose Cipher
* implementation will be used.
* @return the PKCS8EncodedKeySpec object.
* @exception NullPointerException if <code>decryptKey</code>
* or <code>providerName</code> is null.
* @exception NoSuchProviderException if no provider
* <code>providerName</code> is registered.
* @exception NoSuchAlgorithmException if cannot find appropriate
* cipher to decrypt the encrypted data.
* @exception InvalidKeyException if <code>decryptKey</code>
* cannot be used to decrypt the encrypted data or the decryption
* result is not a valid PKCS8KeySpec.
*
* @since 1.5
*/
public PKCS8EncodedKeySpec getKeySpec(Key decryptKey,
String providerName) throws NoSuchProviderException,
NoSuchAlgorithmException, InvalidKeyException {
if (decryptKey == null) {
throw new NullPointerException("decryptKey is null");
}
if (providerName == null) {
throw new NullPointerException("provider is null");
}
Provider provider = Security.getProvider(providerName);
if (provider == null) {
throw new NoSuchProviderException("provider " +
providerName + " not found");
}
return getKeySpecImpl(decryptKey, provider);
}
/**
* Extract the enclosed PKCS8EncodedKeySpec object from the
* encrypted data and return it.
* @param decryptKey key used for decrypting the encrypted data.
* @param provider the name of provider whose Cipher implementation
* will be used.
* @return the PKCS8EncodedKeySpec object.
* @exception NullPointerException if <code>decryptKey</code>
* or <code>provider</code> is null.
* @exception NoSuchAlgorithmException if cannot find appropriate
* cipher to decrypt the encrypted data in <code>provider</code>.
* @exception InvalidKeyException if <code>decryptKey</code>
* cannot be used to decrypt the encrypted data or the decryption
* result is not a valid PKCS8KeySpec.
*
* @since 1.5
*/
public PKCS8EncodedKeySpec getKeySpec(Key decryptKey,
Provider provider) throws NoSuchAlgorithmException,
InvalidKeyException {
if (decryptKey == null) {
throw new NullPointerException("decryptKey is null");
}
if (provider == null) {
throw new NullPointerException("provider is null");
}
return getKeySpecImpl(decryptKey, provider);
}
/**
* Returns the ASN.1 encoding of this object.
* @return the ASN.1 encoding. Returns a new array
* each time this method is called.
* @exception IOException if error occurs when constructing its
* ASN.1 encoding.
*/
public byte[] getEncoded() throws IOException {
if (this.encoded == null) {
DerOutputStream out = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream();
// encode encryption algorithm
algid.encode(tmp);
// encode encrypted data
tmp.putOctetString(encryptedData);
// wrap everything into a SEQUENCE
out.write(DerValue.tag_Sequence, tmp);
this.encoded = out.toByteArray();
}
return this.encoded.clone();
}
private static void checkTag(DerValue val, byte tag, String valName)
throws IOException {
if (val.getTag() != tag) {
throw new IOException("invalid key encoding - wrong tag for " +
valName);
}
}
@SuppressWarnings("fallthrough")
private void checkPKCS8Encoding(byte[] encodedKey)
throws IOException {
DerInputStream in = new DerInputStream(encodedKey);
DerValue[] values = in.getSequence(3);
switch (values.length) {
case 4:
checkTag(values[3], DerValue.TAG_CONTEXT, "attributes");
/* fall through */
case 3:
checkTag(values[0], DerValue.tag_Integer, "version");
keyAlg = AlgorithmId.parse(values[1]).getName();
checkTag(values[2], DerValue.tag_OctetString, "privateKey");
break;
default:
throw new IOException("invalid key encoding");
}
}
}

View file

@ -0,0 +1,486 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.AlgorithmParameters;
import java.security.Provider;
import java.security.Key;
import java.security.Security;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.InvalidKeyException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Objects;
import sun.security.jca.GetInstance.Instance;
/**
* This class provides the functionality of an exemption mechanism, examples
* of which are <i>key recovery</i>, <i>key weakening</i>, and
* <i>key escrow</i>.
*
* <p>Applications or applets that use an exemption mechanism may be granted
* stronger encryption capabilities than those which don't.
*
* @since 1.4
*/
public class ExemptionMechanism {
// The provider
private Provider provider;
// The provider implementation (delegate)
private ExemptionMechanismSpi exmechSpi;
// The name of the exemption mechanism.
private String mechanism;
// Flag which indicates whether this ExemptionMechanism
// result is generated successfully.
private boolean done = false;
// State information
private boolean initialized = false;
// Store away the key at init() time for later comparison.
private Key keyStored = null;
/**
* Creates a ExemptionMechanism object.
*
* @param exmechSpi the delegate
* @param provider the provider
* @param mechanism the exemption mechanism
*/
protected ExemptionMechanism(ExemptionMechanismSpi exmechSpi,
Provider provider,
String mechanism) {
this.exmechSpi = exmechSpi;
this.provider = provider;
this.mechanism = mechanism;
}
/**
* Returns the exemption mechanism name of this
* <code>ExemptionMechanism</code> object.
*
* <p>This is the same name that was specified in one of the
* <code>getInstance</code> calls that created this
* <code>ExemptionMechanism</code> object.
*
* @return the exemption mechanism name of this
* <code>ExemptionMechanism</code> object.
*/
public final String getName() {
return this.mechanism;
}
/**
* Returns an <code>ExemptionMechanism</code> object that implements the
* specified exemption mechanism algorithm.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new ExemptionMechanism object encapsulating the
* ExemptionMechanismSpi implementation from the first
* Provider that supports the specified algorithm is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @implNote
* The JDK Reference Implementation additionally uses the
* {@code jdk.security.provider.preferred}
* {@link Security#getProperty(String) Security} property to determine
* the preferred provider order for the specified algorithm. This
* may be different than the order of providers returned by
* {@link Security#getProviders() Security.getProviders()}.
*
* @param algorithm the standard name of the requested exemption
* mechanism.
* See the ExemptionMechanism section in the
* <a href=
* "{@docRoot}/../specs/security/standard-names.html#exemption-mechanisms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard exemption mechanism names.
*
* @return the new {@code ExemptionMechanism} object
*
* @throws NoSuchAlgorithmException if no {@code Provider} supports an
* {@code ExemptionMechanismSpi} implementation for the
* specified algorithm
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final ExemptionMechanism getInstance(String algorithm)
throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance("ExemptionMechanism",
ExemptionMechanismSpi.class, algorithm);
return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns an <code>ExemptionMechanism</code> object that implements the
* specified exemption mechanism algorithm.
*
* <p> A new ExemptionMechanism object encapsulating the
* ExemptionMechanismSpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the security provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
* @param algorithm the standard name of the requested exemption mechanism.
* See the ExemptionMechanism section in the
* <a href=
* "{@docRoot}/../specs/security/standard-names.html#exemption-mechanisms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard exemption mechanism names.
*
* @param provider the name of the provider.
*
* @return the new {@code ExemptionMechanism} object
*
* @throws IllegalArgumentException if the {@code provider}
* is {@code null} or empty
*
* @throws NoSuchAlgorithmException if an {@code ExemptionMechanismSpi}
* implementation for the specified algorithm is not
* available from the specified provider
*
* @throws NoSuchProviderException if the specified provider is not
* registered in the security provider list
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final ExemptionMechanism getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance("ExemptionMechanism",
ExemptionMechanismSpi.class, algorithm, provider);
return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns an <code>ExemptionMechanism</code> object that implements the
* specified exemption mechanism algorithm.
*
* <p> A new ExemptionMechanism object encapsulating the
* ExemptionMechanismSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the standard name of the requested exemption mechanism.
* See the ExemptionMechanism section in the
* <a href=
* "{@docRoot}/../specs/security/standard-names.html#exemption-mechanisms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard exemption mechanism names.
*
* @param provider the provider.
*
* @return the new {@code ExemptionMechanism} object
*
* @throws IllegalArgumentException if the {@code provider}
* is null
*
* @throws NoSuchAlgorithmException if an {@code ExemptionMechanismSpi}
* implementation for the specified algorithm is not available
* from the specified {@code Provider object}
*
* @exception NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final ExemptionMechanism getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance("ExemptionMechanism",
ExemptionMechanismSpi.class, algorithm, provider);
return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns the provider of this <code>ExemptionMechanism</code> object.
*
* @return the provider of this <code>ExemptionMechanism</code> object.
*/
public final Provider getProvider() {
return this.provider;
}
/**
* Returns whether the result blob has been generated successfully by this
* exemption mechanism.
*
* <p>The method also makes sure that the key passed in is the same as
* the one this exemption mechanism used in initializing and generating
* phases.
*
* @param key the key the crypto is going to use.
*
* @return whether the result blob of the same key has been generated
* successfully by this exemption mechanism; false if <code>key</code>
* is null.
*
* @exception ExemptionMechanismException if problem(s) encountered
* while determining whether the result blob has been generated successfully
* by this exemption mechanism object.
*/
public final boolean isCryptoAllowed(Key key)
throws ExemptionMechanismException {
boolean ret = false;
if (done && (key != null)) {
// Check if the key passed in is the same as the one
// this exemption mechanism used.
ret = keyStored.equals(key);
}
return ret;
}
/**
* Returns the length in bytes that an output buffer would need to be in
* order to hold the result of the next
* {@link #genExemptionBlob(byte[]) genExemptionBlob}
* operation, given the input length <code>inputLen</code> (in bytes).
*
* <p>The actual output length of the next
* {@link #genExemptionBlob(byte[]) genExemptionBlob}
* 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)
*
* @exception IllegalStateException if this exemption mechanism is in a
* wrong state (e.g., has not yet been initialized)
*/
public final int getOutputSize(int inputLen) throws IllegalStateException {
if (!initialized) {
throw new IllegalStateException(
"ExemptionMechanism not initialized");
}
if (inputLen < 0) {
throw new IllegalArgumentException(
"Input size must be equal to " + "or greater than zero");
}
return exmechSpi.engineGetOutputSize(inputLen);
}
/**
* Initializes this exemption mechanism with a key.
*
* <p>If this exemption mechanism requires any algorithm parameters
* that cannot be derived from the given <code>key</code>, the
* underlying exemption mechanism implementation is supposed to
* generate the required parameters itself (using provider-specific
* default values); in the case that algorithm parameters must be
* specified by the caller, an <code>InvalidKeyException</code> is raised.
*
* @param key the key for this exemption mechanism
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
public final void init(Key key)
throws InvalidKeyException, ExemptionMechanismException {
done = false;
initialized = false;
keyStored = key;
exmechSpi.engineInit(key);
initialized = true;
}
/**
* Initializes this exemption mechanism with a key and a set of algorithm
* parameters.
*
* <p>If this exemption mechanism requires any algorithm parameters
* and <code>params</code> is null, the underlying exemption
* mechanism implementation is supposed to generate the required
* parameters itself (using provider-specific default values); in the case
* that algorithm parameters must be specified by the caller, an
* <code>InvalidAlgorithmParameterException</code> is raised.
*
* @param key the key for this exemption mechanism
* @param params the algorithm parameters
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
public final void init(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException,
ExemptionMechanismException {
done = false;
initialized = false;
keyStored = key;
exmechSpi.engineInit(key, params);
initialized = true;
}
/**
* Initializes this exemption mechanism with a key and a set of algorithm
* parameters.
*
* <p>If this exemption mechanism requires any algorithm parameters
* and <code>params</code> is null, the underlying exemption mechanism
* implementation is supposed to generate the required parameters itself
* (using provider-specific default values); in the case that algorithm
* parameters must be specified by the caller, an
* <code>InvalidAlgorithmParameterException</code> is raised.
*
* @param key the key for this exemption mechanism
* @param params the algorithm parameters
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
public final void init(Key key, AlgorithmParameters params)
throws InvalidKeyException, InvalidAlgorithmParameterException,
ExemptionMechanismException {
done = false;
initialized = false;
keyStored = key;
exmechSpi.engineInit(key, params);
initialized = true;
}
/**
* Generates the exemption mechanism key blob.
*
* @return the new buffer with the result key blob.
*
* @exception IllegalStateException if this exemption mechanism is in
* a wrong state (e.g., has not been initialized).
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of generating.
*/
public final byte[] genExemptionBlob() throws IllegalStateException,
ExemptionMechanismException {
if (!initialized) {
throw new IllegalStateException(
"ExemptionMechanism not initialized");
}
byte[] blob = exmechSpi.engineGenExemptionBlob();
done = true;
return blob;
}
/**
* Generates the exemption mechanism key blob, and stores the result in
* the <code>output</code> buffer.
*
* <p>If the <code>output</code> buffer is too small to hold the result,
* a <code>ShortBufferException</code> is thrown. In this case, repeat this
* call with a larger output buffer. Use
* {@link #getOutputSize(int) getOutputSize} to determine how big
* the output buffer should be.
*
* @param output the buffer for the result
*
* @return the number of bytes stored in <code>output</code>
*
* @exception IllegalStateException if this exemption mechanism is in
* a wrong state (e.g., has not been initialized).
* @exception ShortBufferException if the given output buffer is too small
* to hold the result.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of generating.
*/
public final int genExemptionBlob(byte[] output)
throws IllegalStateException, ShortBufferException,
ExemptionMechanismException {
if (!initialized) {
throw new IllegalStateException
("ExemptionMechanism not initialized");
}
int n = exmechSpi.engineGenExemptionBlob(output, 0);
done = true;
return n;
}
/**
* Generates the exemption mechanism key blob, and stores the result 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. In this case, repeat this
* call with a larger output buffer. Use
* {@link #getOutputSize(int) getOutputSize} to determine how big
* the output buffer should be.
*
* @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 IllegalStateException if this exemption mechanism is in
* a wrong state (e.g., has not been initialized).
* @exception ShortBufferException if the given output buffer is too small
* to hold the result.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of generating.
*/
public final int genExemptionBlob(byte[] output, int outputOffset)
throws IllegalStateException, ShortBufferException,
ExemptionMechanismException {
if (!initialized) {
throw new IllegalStateException
("ExemptionMechanism not initialized");
}
int n = exmechSpi.engineGenExemptionBlob(output, outputOffset);
done = true;
return n;
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.GeneralSecurityException;
/**
* This is the generic ExemptionMechanism exception.
*
* @since 1.4
*/
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() {
super();
}
/**
* Constructs a ExemptionMechanismException with the specified
* detailed message. (A detailed message is a String that describes
* this particular exception.)
*
* @param msg the detailed message.
*/
public ExemptionMechanismException(String msg) {
super(msg);
}
}

View file

@ -0,0 +1,170 @@
/*
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.Key;
import java.security.AlgorithmParameters;
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>ExemptionMechanism</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 exemption mechanism.
*
* @author Sharon Liu
*
* @since 1.4
*/
public abstract class ExemptionMechanismSpi {
/**
* Returns the length in bytes that an output buffer would need to be in
* order to hold the result of the next
* {@link #engineGenExemptionBlob(byte[], int) engineGenExemptionBlob}
* operation, given the input length <code>inputLen</code> (in bytes).
*
* <p>The actual output length of the next
* {@link #engineGenExemptionBlob(byte[], int) engineGenExemptionBlob}
* 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);
/**
* Initializes this exemption mechanism with a key.
*
* <p>If this exemption mechanism requires any algorithm parameters
* that cannot be derived from the given <code>key</code>, the underlying
* exemption mechanism implementation is supposed to generate the required
* parameters itself (using provider-specific default values); in the case
* that algorithm parameters must be specified by the caller, an
* <code>InvalidKeyException</code> is raised.
*
* @param key the key for this exemption mechanism
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
protected abstract void engineInit(Key key)
throws InvalidKeyException, ExemptionMechanismException;
/**
* Initializes this exemption mechanism with a key and a set of algorithm
* parameters.
*
* <p>If this exemption mechanism requires any algorithm parameters and
* <code>params</code> is null, the underlying exemption mechanism
* implementation is supposed to generate the required parameters
* itself (using provider-specific default values); in the case that
* algorithm parameters must be specified by the caller, an
* <code>InvalidAlgorithmParameterException</code> is raised.
*
* @param key the key for this exemption mechanism
* @param params the algorithm parameters
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
protected abstract void engineInit(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException,
ExemptionMechanismException;
/**
* Initializes this exemption mechanism with a key and a set of algorithm
* parameters.
*
* <p>If this exemption mechanism requires any algorithm parameters
* and <code>params</code> is null, the underlying exemption mechanism
* implementation is supposed to generate the required parameters
* itself (using provider-specific default values); in the case that
* algorithm parameters must be specified by the caller, an
* <code>InvalidAlgorithmParameterException</code> is raised.
*
* @param key the key for this exemption mechanism
* @param params the algorithm parameters
*
* @exception InvalidKeyException if the given key is inappropriate for
* this exemption mechanism.
* @exception InvalidAlgorithmParameterException if the given algorithm
* parameters are inappropriate for this exemption mechanism.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of initializing.
*/
protected abstract void engineInit(Key key, AlgorithmParameters params)
throws InvalidKeyException, InvalidAlgorithmParameterException,
ExemptionMechanismException;
/**
* Generates the exemption mechanism key blob.
*
* @return the new buffer with the result key blob.
*
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of generating.
*/
protected abstract byte[] engineGenExemptionBlob()
throws ExemptionMechanismException;
/**
* Generates the exemption mechanism key blob, and stores the result 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. In this case, repeat this
* call with a larger output buffer. Use
* {@link #engineGetOutputSize(int) engineGetOutputSize} to determine
* how big the output buffer should be.
*
* @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.
* @exception ExemptionMechanismException if problem(s) encountered in the
* process of generating.
*/
protected abstract int engineGenExemptionBlob
(byte[] output, int outputOffset)
throws ShortBufferException, ExemptionMechanismException;
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
/**
* 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.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class IllegalBlockSizeException
extends java.security.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() {
super();
}
/**
* Constructs an IllegalBlockSizeException with the specified
* detail message.
*
* @param msg the detail message.
*/
public IllegalBlockSizeException(String msg) {
super(msg);
}
}

View file

@ -0,0 +1,392 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* README README README README README README README README README
*
* This file is the template for generating the JceSecurity.java source
* file.
*
* In the current jdk builds, this file is first preprocessed to replace
* @@JCE_DEFAULT_POLICY@ [sic] with "limited" or "unlimited" which is
* determined by the $(UNLIMTED_CRYPTO) make variable. This variable is
* set by top-level configure script, using either
* --disable-unlimited-crypto or --enable-unlimited-crypto [default].
*
* Since this file is a generated source, incremental changes to
* this file require regenerating the source. Compilation options:
*
* (fewer dependencies/"faster" ones first)
*
* 1. make JDK_FILTER=javax/crypto java.base-gensrc-only java.base-java-only
* 2. make java.base-gensrc-only java.base-java-only
* 3. make java.base-gensrc-only java.base-only
* 4. make java.base-only
* 5. make
*/
package javax.crypto;
import java.util.*;
import java.io.*;
import java.net.URL;
import java.nio.file.*;
import java.security.*;
import java.security.Provider.Service;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
import sun.security.util.Debug;
/**
* This class instantiates implementations of JCE engine classes from
* providers registered with the java.security.Security object.
*
* @author Jan Luehe
* @author Sharon Liu
* @since 1.4
*/
final class JceSecurity {
private static final Debug debug = Debug.getInstance("jca");
static final SecureRandom RANDOM = new SecureRandom();
// The defaultPolicy and exemptPolicy will be set up
// in the static initializer.
private static CryptoPermissions defaultPolicy = null;
private static CryptoPermissions exemptPolicy = null;
// Map<Provider,?> of the providers we already have verified
// value == PROVIDER_VERIFIED is successfully verified
// value is failure cause Exception in error case
private static final Map<Provider, Object> verificationResults =
new IdentityHashMap<>();
// Map<Provider,?> of the providers currently being verified
private static final Map<Provider, Object> verifyingProviders =
new IdentityHashMap<>();
private static final boolean isRestricted;
/*
* Don't let anyone instantiate this.
*/
private JceSecurity() {
}
static {
try {
AccessController.doPrivileged(
new PrivilegedExceptionAction<> () {
@Override
public Void run() throws Exception {
setupJurisdictionPolicies();
return null;
}
}
);
isRestricted = defaultPolicy.implies(
CryptoAllPermission.INSTANCE) ? false : true;
} catch (Exception e) {
throw new SecurityException(
"Can not initialize cryptographic mechanism", e);
}
}
static Instance getInstance(String type, Class<?> clazz, String algorithm,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException {
Service s = GetInstance.getService(type, algorithm, provider);
Exception ve = getVerificationResult(s.getProvider());
if (ve != null) {
String msg = "JCE cannot authenticate the provider " + provider;
throw (NoSuchProviderException)
new NoSuchProviderException(msg).initCause(ve);
}
return GetInstance.getInstance(s, clazz);
}
static Instance getInstance(String type, Class<?> clazz, String algorithm,
Provider provider) throws NoSuchAlgorithmException {
Service s = GetInstance.getService(type, algorithm, provider);
Exception ve = JceSecurity.getVerificationResult(provider);
if (ve != null) {
String msg = "JCE cannot authenticate the provider "
+ provider.getName();
throw new SecurityException(msg, ve);
}
return GetInstance.getInstance(s, clazz);
}
static Instance getInstance(String type, Class<?> clazz, String algorithm)
throws NoSuchAlgorithmException {
List<Service> services = GetInstance.getServices(type, algorithm);
NoSuchAlgorithmException failure = null;
for (Service s : services) {
if (canUseProvider(s.getProvider()) == false) {
// allow only signed providers
continue;
}
try {
Instance instance = GetInstance.getInstance(s, clazz);
return instance;
} catch (NoSuchAlgorithmException e) {
failure = e;
}
}
throw new NoSuchAlgorithmException("Algorithm " + algorithm
+ " not available", failure);
}
/**
* Verify if the JAR at URL codeBase is a signed exempt application
* JAR file and returns the permissions bundled with the JAR.
*
* @throws Exception on error
*/
static CryptoPermissions verifyExemptJar(URL codeBase) throws Exception {
ProviderVerifier pv = new ProviderVerifier(codeBase, true);
pv.verify();
return pv.getPermissions();
}
/**
* Verify if the JAR at URL codeBase is a signed provider JAR file.
*
* @throws Exception on error
*/
static void verifyProvider(URL codeBase, Provider p) throws Exception {
// Verify the provider JAR file and all
// supporting JAR files if there are any.
ProviderVerifier pv = new ProviderVerifier(codeBase, p, false);
pv.verify();
}
private static final Object PROVIDER_VERIFIED = Boolean.TRUE;
/*
* Verify that the provider JAR files are signed properly, which
* means the signer's certificate can be traced back to a
* JCE trusted CA.
* Return null if ok, failure Exception if verification failed.
*/
static synchronized Exception getVerificationResult(Provider p) {
Object o = verificationResults.get(p);
if (o == PROVIDER_VERIFIED) {
return null;
} else if (o != null) {
return (Exception)o;
}
if (verifyingProviders.get(p) != null) {
// this method is static synchronized, must be recursion
// return failure now but do not save the result
return new NoSuchProviderException("Recursion during verification");
}
try {
verifyingProviders.put(p, Boolean.FALSE);
URL providerURL = getCodeBase(p.getClass());
verifyProvider(providerURL, p);
// Verified ok, cache result
verificationResults.put(p, PROVIDER_VERIFIED);
return null;
} catch (Exception e) {
verificationResults.put(p, e);
return e;
} finally {
verifyingProviders.remove(p);
}
}
// return whether this provider is properly signed and can be used by JCE
static boolean canUseProvider(Provider p) {
return getVerificationResult(p) == null;
}
// dummy object to represent null
private static final URL NULL_URL;
static {
try {
NULL_URL = new URL("http://null.oracle.com/");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// reference to a Map we use as a cache for codebases
private static final Map<Class<?>, URL> codeBaseCacheRef =
new WeakHashMap<>();
/*
* Returns the CodeBase for the given class.
*/
static URL getCodeBase(final Class<?> clazz) {
synchronized (codeBaseCacheRef) {
URL url = codeBaseCacheRef.get(clazz);
if (url == null) {
url = AccessController.doPrivileged(
new PrivilegedAction<>() {
@Override
public URL run() {
ProtectionDomain pd = clazz.getProtectionDomain();
if (pd != null) {
CodeSource cs = pd.getCodeSource();
if (cs != null) {
return cs.getLocation();
}
}
return NULL_URL;
}
});
codeBaseCacheRef.put(clazz, url);
}
return (url == NULL_URL) ? null : url;
}
}
// This is called from within an doPrivileged block.
private static void setupJurisdictionPolicies() throws Exception {
// Sanity check the crypto.policy Security property. Single
// directory entry, no pseudo-directories (".", "..", leading/trailing
// path separators). normalize()/getParent() will help later.
String cryptoPolicyProperty = Security.getProperty("crypto.policy");
/*
* In case no property is present, rather than fail catastrophically,
* we at least try for a "sane" value, which is what we were
* built with. We first preprocess this file to plug in that
* value, then compile the result gensrc.
*
* Log the warning first.
*/
if (cryptoPolicyProperty == null) {
cryptoPolicyProperty = "@@JCE_DEFAULT_POLICY@@";
if (debug != null) {
debug.println(
"Security Property 'crypto.policy' not found: "
+ "using '" + cryptoPolicyProperty + "' as fallback");
}
}
Path cpPath = Paths.get(cryptoPolicyProperty);
if ((cpPath.getNameCount() != 1) ||
(cpPath.compareTo(cpPath.getFileName()) != 0)) {
throw new SecurityException(
"Invalid policy directory name format: " +
cryptoPolicyProperty);
}
// Prepend java.home to get the full path. normalize() in
// case an extra "." or ".." snuck in somehow.
String javaHomeProperty = System.getProperty("java.home");
Path javaHomePolicyPath = Paths.get(javaHomeProperty, "conf",
"security", "policy").normalize();
Path cryptoPolicyPath = Paths.get(javaHomeProperty, "conf", "security",
"policy", cryptoPolicyProperty).normalize();
if (cryptoPolicyPath.getParent().compareTo(javaHomePolicyPath) != 0) {
throw new SecurityException(
"Invalid cryptographic jurisdiction policy directory path: " +
cryptoPolicyProperty);
}
if (!Files.isDirectory(cryptoPolicyPath)
|| !Files.isReadable(cryptoPolicyPath)) {
throw new SecurityException(
"Can't read cryptographic policy directory: " +
cryptoPolicyProperty);
}
try (DirectoryStream<Path> stream = Files.newDirectoryStream(
cryptoPolicyPath, "{default,exempt}_*.policy")) {
for (Path entry : stream) {
try (InputStream is = new BufferedInputStream(
Files.newInputStream(entry))) {
String filename = entry.getFileName().toString();
CryptoPermissions tmpPerms = new CryptoPermissions();
tmpPerms.load(is);
if (filename.startsWith("default_")) {
// Did we find a default perms?
defaultPolicy = ((defaultPolicy == null) ? tmpPerms :
defaultPolicy.getMinimum(tmpPerms));
} else if (filename.startsWith("exempt_")) {
// Did we find a exempt perms?
exemptPolicy = ((exemptPolicy == null) ? tmpPerms :
exemptPolicy.getMinimum(tmpPerms));
} else {
// This should never happen. newDirectoryStream
// should only throw return "{default,exempt}_*.policy"
throw new SecurityException(
"Unexpected jurisdiction policy files in : " +
cryptoPolicyProperty);
}
} catch (Exception e) {
throw new SecurityException(
"Couldn't parse jurisdiction policy files in: " +
cryptoPolicyProperty);
}
}
} catch (DirectoryIteratorException ex) {
// I/O error encountered during the iteration,
// the cause is an IOException
throw new SecurityException(
"Couldn't iterate through the jurisdiction policy files: " +
cryptoPolicyProperty);
}
// Must have a default policy
if ((defaultPolicy == null) || defaultPolicy.isEmpty()) {
throw new SecurityException(
"Missing mandatory jurisdiction policy files: " +
cryptoPolicyProperty);
}
// If there was an empty exempt policy file, ignore it.
if ((exemptPolicy != null) && exemptPolicy.isEmpty()) {
exemptPolicy = null;
}
}
static CryptoPermissions getDefaultPolicy() {
return defaultPolicy;
}
static CryptoPermissions getExemptPolicy() {
return exemptPolicy;
}
static boolean isRestricted() {
return isRestricted;
}
}

View file

@ -0,0 +1,281 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* The JCE security manager.
*
* <p>The JCE security manager is responsible for determining the maximum
* allowable cryptographic strength for a given applet/application, for a given
* algorithm, by consulting the configured jurisdiction policy files and
* the cryptographic permissions bundled with the applet/application.
*
* <p>Note that this security manager is never installed, only instantiated.
*
* @author Jan Luehe
*
* @since 1.4
*/
final class JceSecurityManager extends SecurityManager {
private static final CryptoPermissions defaultPolicy;
private static final CryptoPermissions exemptPolicy;
private static final CryptoAllPermission allPerm;
private static final Vector<Class<?>> TrustedCallersCache =
new Vector<>(2);
private static final ConcurrentMap<URL,CryptoPermissions> exemptCache =
new ConcurrentHashMap<>();
private static final CryptoPermissions CACHE_NULL_MARK =
new CryptoPermissions();
// singleton instance
static final JceSecurityManager INSTANCE;
static {
defaultPolicy = JceSecurity.getDefaultPolicy();
exemptPolicy = JceSecurity.getExemptPolicy();
allPerm = CryptoAllPermission.INSTANCE;
INSTANCE = AccessController.doPrivileged(
new PrivilegedAction<>() {
public JceSecurityManager run() {
return new JceSecurityManager();
}
});
}
private JceSecurityManager() {
// empty
}
/**
* Returns the maximum allowable crypto strength for the given
* applet/application, for the given algorithm.
*/
CryptoPermission getCryptoPermission(String alg) {
// Need to convert to uppercase since the crypto perm
// lookup is case sensitive.
alg = alg.toUpperCase(Locale.ENGLISH);
// If CryptoAllPermission is granted by default, we return that.
// Otherwise, this will be the permission we return if anything goes
// wrong.
CryptoPermission defaultPerm = getDefaultPermission(alg);
if (defaultPerm == CryptoAllPermission.INSTANCE) {
return defaultPerm;
}
// Determine the codebase of the caller of the JCE API.
// This is the codebase of the first class which is not in
// javax.crypto.* packages.
// NOTE: javax.crypto.* package maybe subject to package
// insertion, so need to check its classloader as well.
Class<?>[] context = getClassContext();
URL callerCodeBase = null;
int i;
for (i=0; i<context.length; i++) {
Class<?> cls = context[i];
callerCodeBase = JceSecurity.getCodeBase(cls);
if (callerCodeBase != null) {
break;
} else {
if (cls.getName().startsWith("javax.crypto.")) {
// skip jce classes since they aren't the callers
continue;
}
// use default permission when the caller is system classes
return defaultPerm;
}
}
if (i == context.length) {
return defaultPerm;
}
CryptoPermissions appPerms = exemptCache.get(callerCodeBase);
if (appPerms == null) {
// no match found in cache
synchronized (this.getClass()) {
appPerms = exemptCache.get(callerCodeBase);
if (appPerms == null) {
appPerms = getAppPermissions(callerCodeBase);
exemptCache.putIfAbsent(callerCodeBase,
(appPerms == null? CACHE_NULL_MARK:appPerms));
}
}
}
if (appPerms == null || appPerms == CACHE_NULL_MARK) {
return defaultPerm;
}
// If the app was granted the special CryptoAllPermission, return that.
if (appPerms.implies(allPerm)) {
return allPerm;
}
// Check if the crypto permissions granted to the app contain a
// crypto permission for the requested algorithm that does not require
// any exemption mechanism to be enforced.
// Return that permission, if present.
PermissionCollection appPc = appPerms.getPermissionCollection(alg);
if (appPc == null) {
return defaultPerm;
}
Enumeration<Permission> enum_ = appPc.elements();
while (enum_.hasMoreElements()) {
CryptoPermission cp = (CryptoPermission)enum_.nextElement();
if (cp.getExemptionMechanism() == null) {
return cp;
}
}
// Check if the jurisdiction file for exempt applications contains
// any entries for the requested algorithm.
// If not, return the default permission.
PermissionCollection exemptPc =
exemptPolicy.getPermissionCollection(alg);
if (exemptPc == null) {
return defaultPerm;
}
// In the jurisdiction file for exempt applications, go through the
// list of CryptoPermission entries for the requested algorithm, and
// stop at the first entry:
// - that is implied by the collection of crypto permissions granted
// to the app, and
// - whose exemption mechanism is available from one of the
// registered CSPs
enum_ = exemptPc.elements();
while (enum_.hasMoreElements()) {
CryptoPermission cp = (CryptoPermission)enum_.nextElement();
try {
ExemptionMechanism.getInstance(cp.getExemptionMechanism());
if (cp.getAlgorithm().equals(
CryptoPermission.ALG_NAME_WILDCARD)) {
CryptoPermission newCp;
if (cp.getCheckParam()) {
newCp = new CryptoPermission(
alg, cp.getMaxKeySize(),
cp.getAlgorithmParameterSpec(),
cp.getExemptionMechanism());
} else {
newCp = new CryptoPermission(
alg, cp.getMaxKeySize(),
cp.getExemptionMechanism());
}
if (appPerms.implies(newCp)) {
return newCp;
}
}
if (appPerms.implies(cp)) {
return cp;
}
} catch (Exception e) {
continue;
}
}
return defaultPerm;
}
private static CryptoPermissions getAppPermissions(URL callerCodeBase) {
// Check if app is exempt, and retrieve the permissions bundled with it
try {
return JceSecurity.verifyExemptJar(callerCodeBase);
} catch (Exception e) {
// Jar verification fails
return null;
}
}
/**
* Returns the default permission for the given algorithm.
*/
private CryptoPermission getDefaultPermission(String alg) {
Enumeration<Permission> enum_ =
defaultPolicy.getPermissionCollection(alg).elements();
return (CryptoPermission)enum_.nextElement();
}
// Only used by javax.crypto.Cipher constructor to disallow Cipher
// objects being constructed by untrusted code (See bug 4341369 &
// 4334690 for more info).
boolean isCallerTrusted(Provider provider) {
// Get the caller and its codebase.
Class<?>[] context = getClassContext();
if (context.length >= 3) {
// context[0]: class javax.crypto.JceSecurityManager
// context[1]: class javax.crypto.Cipher (or other JCE API class)
// context[2]: this is what we are gonna check
Class<?> caller = context[2];
URL callerCodeBase = JceSecurity.getCodeBase(caller);
if (callerCodeBase == null) {
return true;
}
// The caller has been verified.
if (TrustedCallersCache.contains(caller)) {
return true;
}
// Check the association between caller and provider
Class<?> pCls = provider.getClass();
Module pMod = pCls.getModule();
// If they are in the same named module or share
// the same codebase, then they are associated
boolean sameOrigin = (pMod.isNamed()?
caller.getModule().equals(pMod) :
callerCodeBase.equals(JceSecurity.getCodeBase(pCls)));
if (sameOrigin) {
// The caller is from trusted provider
if (ProviderVerifier.isTrustedCryptoProvider(provider)) {
TrustedCallersCache.addElement(caller);
return true;
}
} else {
// Don't include the provider in the subsequent
// JceSecurity.verifyProvider(...) call
provider = null;
}
// Check whether the caller is a trusted provider.
try {
JceSecurity.verifyProvider(callerCodeBase, provider);
} catch (Exception e2) {
return false;
}
TrustedCallersCache.addElement(caller);
return true;
}
return false;
}
}

View file

@ -0,0 +1,662 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.util.*;
import java.security.*;
import java.security.Provider.Service;
import java.security.spec.*;
import sun.security.util.Debug;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
/**
* This class provides the functionality of a key agreement (or key
* exchange) protocol.
* <p>
* The keys involved in establishing a shared secret are created by one of the
* key generators ({@code KeyPairGenerator} or
* {@code KeyGenerator}), a {@code KeyFactory}, or as a result from
* an intermediate phase of the key agreement protocol.
*
* <p> For each of the correspondents in the key exchange, {@code doPhase}
* needs to be called. For example, if this key exchange is with one other
* party, {@code doPhase} needs to be called once, with the
* {@code lastPhase} flag set to {@code true}.
* If this key exchange is
* with two other parties, {@code doPhase} needs to be called twice,
* the first time setting the {@code lastPhase} flag to
* {@code false}, and the second time setting it to {@code true}.
* There may be any number of parties involved in a key exchange.
*
* <p> Every implementation of the Java platform is required to support the
* following standard {@code KeyAgreement} algorithm:
* <ul>
* <li>{@code DiffieHellman}</li>
* </ul>
* This algorithm is described in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
* KeyAgreement section</a> of the
* Java Security Standard Algorithm Names Specification.
* Consult the release documentation for your implementation to see if any
* other algorithms are supported.
*
* @author Jan Luehe
*
* @see KeyGenerator
* @see SecretKey
* @since 1.4
*/
public class KeyAgreement {
private static final Debug debug =
Debug.getInstance("jca", "KeyAgreement");
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
Debug.isOn("engine=") && !Debug.isOn("keyagreement");
// The provider
private Provider provider;
// The provider implementation (delegate)
private KeyAgreementSpi spi;
// The name of the key agreement algorithm.
private final String algorithm;
// next service to try in provider selection
// null once provider is selected
private Service firstService;
// remaining services to try in provider selection
// null once provider is selected
private Iterator<Service> serviceIterator;
private final Object lock;
/**
* 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.spi = keyAgreeSpi;
this.provider = provider;
this.algorithm = algorithm;
lock = null;
}
private KeyAgreement(Service s, Iterator<Service> t, String algorithm) {
firstService = s;
serviceIterator = t;
this.algorithm = algorithm;
lock = new Object();
}
/**
* Returns the algorithm name of this {@code KeyAgreement} object.
*
* <p>This is the same name that was specified in one of the
* {@code getInstance} calls that created this
* {@code KeyAgreement} object.
*
* @return the algorithm name of this {@code KeyAgreement} object.
*/
public final String getAlgorithm() {
return this.algorithm;
}
/**
* Returns a {@code KeyAgreement} object that implements the
* specified key agreement algorithm.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new KeyAgreement object encapsulating the
* KeyAgreementSpi implementation from the first
* Provider that supports the specified algorithm is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @implNote
* The JDK Reference Implementation additionally uses the
* {@code jdk.security.provider.preferred}
* {@link Security#getProperty(String) Security} property to determine
* the preferred provider order for the specified algorithm. This
* may be different than the order of providers returned by
* {@link Security#getProviders() Security.getProviders()}.
*
* @param algorithm the standard name of the requested key agreement
* algorithm.
* See the KeyAgreement section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @return the new {@code KeyAgreement} object
*
* @throws NoSuchAlgorithmException if no {@code Provider} supports a
* {@code KeyAgreementSpi} implementation for the
* specified algorithm
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final KeyAgreement getInstance(String algorithm)
throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
List<Service> services =
GetInstance.getServices("KeyAgreement", algorithm);
// make sure there is at least one service from a signed provider
Iterator<Service> t = services.iterator();
while (t.hasNext()) {
Service s = t.next();
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
return new KeyAgreement(s, t, algorithm);
}
throw new NoSuchAlgorithmException
("Algorithm " + algorithm + " not available");
}
/**
* Returns a {@code KeyAgreement} object that implements the
* specified key agreement algorithm.
*
* <p> A new KeyAgreement object encapsulating the
* KeyAgreementSpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the security provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested key agreement
* algorithm.
* See the KeyAgreement section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @param provider the name of the provider.
*
* @return the new {@code KeyAgreement} object
*
* @throws IllegalArgumentException if the {@code provider}
* is {@code null} or empty
*
* @throws NoSuchAlgorithmException if a {@code KeyAgreementSpi}
* implementation for the specified algorithm is not
* available from the specified provider
*
* @throws NoSuchProviderException if the specified provider is not
* registered in the security provider list
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final KeyAgreement getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance
("KeyAgreement", KeyAgreementSpi.class, algorithm, provider);
return new KeyAgreement((KeyAgreementSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns a {@code KeyAgreement} object that implements the
* specified key agreement algorithm.
*
* <p> A new KeyAgreement object encapsulating the
* KeyAgreementSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the standard name of the requested key agreement
* algorithm.
* See the KeyAgreement section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @param provider the provider.
*
* @return the new {@code KeyAgreement} object
*
* @throws IllegalArgumentException if the {@code provider}
* is {@code null}
*
* @throws NoSuchAlgorithmException if a {@code KeyAgreementSpi}
* implementation for the specified algorithm is not available
* from the specified Provider object
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final KeyAgreement getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance
("KeyAgreement", KeyAgreementSpi.class, algorithm, provider);
return new KeyAgreement((KeyAgreementSpi)instance.impl,
instance.provider, algorithm);
}
// max number of debug warnings to print from chooseFirstProvider()
private static int warnCount = 10;
/**
* Choose the Spi from the first provider available. Used if
* delayed provider selection is not possible because init()
* is not the first method called.
*/
void chooseFirstProvider() {
if (spi != null) {
return;
}
synchronized (lock) {
if (spi != null) {
return;
}
if (debug != null) {
int w = --warnCount;
if (w >= 0) {
debug.println("KeyAgreement.init() not first method "
+ "called, disabling delayed provider selection");
if (w == 0) {
debug.println("Further warnings of this type will "
+ "be suppressed");
}
new Exception("Call trace").printStackTrace();
}
}
Exception lastException = null;
while ((firstService != null) || serviceIterator.hasNext()) {
Service s;
if (firstService != null) {
s = firstService;
firstService = null;
} else {
s = serviceIterator.next();
}
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
Object obj = s.newInstance(null);
if (obj instanceof KeyAgreementSpi == false) {
continue;
}
spi = (KeyAgreementSpi)obj;
provider = s.getProvider();
// not needed any more
firstService = null;
serviceIterator = null;
return;
} catch (Exception e) {
lastException = e;
}
}
ProviderException e = new ProviderException
("Could not construct KeyAgreementSpi instance");
if (lastException != null) {
e.initCause(lastException);
}
throw e;
}
}
private static final int I_NO_PARAMS = 1;
private static final int I_PARAMS = 2;
private void implInit(KeyAgreementSpi spi, int type, Key key,
AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
if (type == I_NO_PARAMS) {
spi.engineInit(key, random);
} else { // I_PARAMS
spi.engineInit(key, params, random);
}
}
private void chooseProvider(int initType, Key key,
AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
synchronized (lock) {
if (spi != null) {
implInit(spi, initType, key, params, random);
return;
}
Exception lastException = null;
while ((firstService != null) || serviceIterator.hasNext()) {
Service s;
if (firstService != null) {
s = firstService;
firstService = null;
} else {
s = serviceIterator.next();
}
// if provider says it does not support this key, ignore it
if (s.supportsParameter(key) == false) {
continue;
}
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
KeyAgreementSpi spi = (KeyAgreementSpi)s.newInstance(null);
implInit(spi, initType, key, params, random);
provider = s.getProvider();
this.spi = spi;
firstService = null;
serviceIterator = null;
return;
} catch (Exception e) {
// NoSuchAlgorithmException from newInstance()
// InvalidKeyException from init()
// RuntimeException (ProviderException) from init()
if (lastException == null) {
lastException = e;
}
}
}
// no working provider found, fail
if (lastException instanceof InvalidKeyException) {
throw (InvalidKeyException)lastException;
}
if (lastException instanceof InvalidAlgorithmParameterException) {
throw (InvalidAlgorithmParameterException)lastException;
}
if (lastException instanceof RuntimeException) {
throw (RuntimeException)lastException;
}
String kName = (key != null) ? key.getClass().getName() : "(null)";
throw new InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
/**
* Returns the provider of this {@code KeyAgreement} object.
*
* @return the provider of this {@code KeyAgreement} object
*/
public final Provider getProvider() {
chooseFirstProvider();
return this.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
* {@link java.security.SecureRandom}
* 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 {
init(key, JceSecurity.RANDOM);
}
/**
* 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}.
* However, if the underlying
* algorithm implementation does not require any random bytes,
* {@code random} 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 {
if (spi != null) {
spi.engineInit(key, random);
} else {
try {
chooseProvider(I_NO_PARAMS, key, null, random);
} catch (InvalidAlgorithmParameterException e) {
// should never occur
throw new InvalidKeyException(e);
}
}
if (!skipDebug && pdebug != null) {
pdebug.println("KeyAgreement." + algorithm + " algorithm from: " +
getProviderName());
}
}
/**
* 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
* {@link java.security.SecureRandom}
* 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
{
init(key, params, JceSecurity.RANDOM);
}
private String getProviderName() {
return (provider == null) ? "(no provider)" : provider.getName();
}
/**
* 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
{
if (spi != null) {
spi.engineInit(key, params, random);
} else {
chooseProvider(I_PARAMS, key, params, random);
}
if (!skipDebug && pdebug != null) {
pdebug.println("KeyAgreement." + algorithm + " algorithm from: " +
getProviderName());
}
}
/**
* 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
{
chooseFirstProvider();
return spi.engineDoPhase(key, lastPhase);
}
/**
* Generates the shared secret and returns it in a new buffer.
*
* <p>This method resets this {@code KeyAgreement} object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the {@code init} 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 {
chooseFirstProvider();
return spi.engineGenerateSecret();
}
/**
* Generates the shared secret, and places it into the buffer
* {@code sharedSecret}, beginning at {@code offset} inclusive.
*
* <p>If the {@code sharedSecret} buffer is too small to hold the
* result, a {@code ShortBufferException} is thrown.
* In this case, this call should be repeated with a larger output buffer.
*
* <p>This method resets this {@code KeyAgreement} object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the {@code init} 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} where the
* shared secret will be stored
*
* @return the number of bytes placed into {@code sharedSecret}
*
* @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
{
chooseFirstProvider();
return spi.engineGenerateSecret(sharedSecret, offset);
}
/**
* Creates the shared secret and returns it as a {@code SecretKey}
* object of the specified algorithm.
*
* <p>This method resets this {@code KeyAgreement} object, so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the {@code init} 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
{
chooseFirstProvider();
return spi.engineGenerateSecret(algorithm);
}
}

View file

@ -0,0 +1,204 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.*;
/**
* 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
* ({@link #engineDoPhase(java.security.Key, boolean) engineDoPhase}).
*
* <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.
*
* @author Jan Luehe
*
* @see KeyGenerator
* @see SecretKey
* @since 1.4
*/
public abstract class KeyAgreementSpi {
/**
* Initializes this key agreement with the given key and source of
* randomness. The given key is required to contain all the algorithm
* parameters required for this key agreement.
*
* <p> If the key agreement algorithm requires random bytes, it gets them
* from the given source of randomness, <code>random</code>.
* However, if the underlying
* algorithm implementation does not require any random bytes,
* <code>random</code> is ignored.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param random the source of randomness
*
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
*/
protected abstract void engineInit(Key key, SecureRandom random)
throws InvalidKeyException;
/**
* Initializes this key agreement with the given key, set of
* algorithm parameters, and source of randomness.
*
* @param key the party's private information. For example, in the case
* of the Diffie-Hellman key agreement, this would be the party's own
* Diffie-Hellman private key.
* @param params the key agreement parameters
* @param random the source of randomness
*
* @exception InvalidKeyException if the given key is
* inappropriate for this key agreement, e.g., is of the wrong type or
* has an incompatible algorithm type.
* @exception InvalidAlgorithmParameterException if the given parameters
* are inappropriate for this key agreement.
*/
protected abstract void engineInit(Key key, AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* Executes the next phase of this key agreement with the given
* key that was received from one of the other parties involved in this key
* agreement.
*
* @param key the key for this phase. For example, in the case of
* Diffie-Hellman between 2 parties, this would be the other party's
* Diffie-Hellman public key.
* @param lastPhase flag which indicates whether or not this is the last
* phase of this key agreement.
*
* @return the (intermediate) key resulting from this phase, or null if
* this phase does not yield a key
*
* @exception InvalidKeyException if the given key is inappropriate for
* this phase.
* @exception IllegalStateException if this key agreement has not been
* initialized.
*/
protected abstract Key engineDoPhase(Key key, boolean lastPhase)
throws InvalidKeyException, IllegalStateException;
/**
* Generates the shared secret and returns it in a new buffer.
*
* <p>This method resets this <code>KeyAgreementSpi</code> object,
* so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>engineInit</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @return the new buffer with the shared secret
*
* @exception IllegalStateException if this key agreement has not been
* completed yet
*/
protected abstract byte[] engineGenerateSecret()
throws IllegalStateException;
/**
* Generates the shared secret, and places it into the buffer
* <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
*
* <p>If the <code>sharedSecret</code> buffer is too small to hold the
* result, a <code>ShortBufferException</code> is thrown.
* In this case, this call should be repeated with a larger output buffer.
*
* <p>This method resets this <code>KeyAgreementSpi</code> object,
* so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>engineInit</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @param sharedSecret the buffer for the shared secret
* @param offset the offset in <code>sharedSecret</code> where the
* shared secret will be stored
*
* @return the number of bytes placed into <code>sharedSecret</code>
*
* @exception IllegalStateException if this key agreement has not been
* completed yet
* @exception ShortBufferException if the given output buffer is too small
* to hold the secret
*/
protected abstract int engineGenerateSecret(byte[] sharedSecret,
int offset)
throws IllegalStateException, ShortBufferException;
/**
* Creates the shared secret and returns it as a secret key object
* of the requested algorithm type.
*
* <p>This method resets this <code>KeyAgreementSpi</code> object,
* so that it
* can be reused for further key agreements. Unless this key agreement is
* reinitialized with one of the <code>engineInit</code> methods, the same
* private information and algorithm parameters will be used for
* subsequent key agreements.
*
* @param algorithm the requested secret key algorithm
*
* @return the shared secret key
*
* @exception IllegalStateException if this key agreement has not been
* completed yet
* @exception NoSuchAlgorithmException if the requested secret key
* algorithm is not available
* @exception InvalidKeyException if the shared secret key material cannot
* be used to generate a secret key of the requested algorithm type (e.g.,
* the key material is too short)
*/
protected abstract SecretKey engineGenerateSecret(String algorithm)
throws IllegalStateException, NoSuchAlgorithmException,
InvalidKeyException;
}

View file

@ -0,0 +1,579 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.util.*;
import java.security.*;
import java.security.Provider.Service;
import java.security.spec.*;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
import sun.security.util.Debug;
/**
* This class provides the functionality of a secret (symmetric) key generator.
*
* <p>Key generators are constructed using one of the {@code getInstance}
* 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
* {@link #init(int, java.security.SecureRandom) init}
* method in this KeyGenerator class that takes these two universally
* shared types of arguments. There is also one that takes just a
* {@code keysize} 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} 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.
*
* <li><b>Algorithm-Specific Initialization</b>
* <p>For situations where a set of algorithm-specific parameters already
* exists, there are two
* {@link #init(java.security.spec.AlgorithmParameterSpec) init}
* methods that have an {@code AlgorithmParameterSpec}
* argument. One also has a {@code SecureRandom} 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} method), each provider must
* supply (and document) a default initialization.
* See the Keysize Restriction sections of the
* {@extLink security_guide_jdk_providers JDK Providers}
* document for information on the KeyGenerator defaults used by
* JDK providers.
* However, note that defaults may vary across different providers.
* Additionally, the default value for a provider may change in a future
* version. Therefore, it is recommended to explicitly initialize the
* KeyGenerator instead of relying on provider-specific defaults.
*
* <p> Every implementation of the Java platform is required to support the
* following standard {@code KeyGenerator} algorithms with the keysizes in
* parentheses:
* <ul>
* <li>{@code AES} (128)</li>
* <li>{@code DES} (56)</li>
* <li>{@code DESede} (168)</li>
* <li>{@code HmacSHA1}</li>
* <li>{@code HmacSHA256}</li>
* </ul>
* These algorithms are described in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
* KeyGenerator section</a> of the
* Java Security Standard Algorithm Names Specification.
* Consult the release documentation for your implementation to see if any
* other algorithms are supported.
*
* @author Jan Luehe
*
* @see SecretKey
* @since 1.4
*/
public class KeyGenerator {
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
Debug.isOn("engine=") && !Debug.isOn("keygenerator");
// see java.security.KeyPairGenerator for failover notes
private static final int I_NONE = 1;
private static final int I_RANDOM = 2;
private static final int I_PARAMS = 3;
private static final int I_SIZE = 4;
// The provider
private Provider provider;
// The provider implementation (delegate)
private volatile KeyGeneratorSpi spi;
// The algorithm
private final String algorithm;
private final Object lock = new Object();
private Iterator<Service> serviceIterator;
private int initType;
private int initKeySize;
private AlgorithmParameterSpec initParams;
private SecureRandom initRandom;
/**
* 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.spi = keyGenSpi;
this.provider = provider;
this.algorithm = algorithm;
if (!skipDebug && pdebug != null) {
pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
getProviderName());
}
}
private KeyGenerator(String algorithm) throws NoSuchAlgorithmException {
this.algorithm = algorithm;
List<Service> list =
GetInstance.getServices("KeyGenerator", algorithm);
serviceIterator = list.iterator();
initType = I_NONE;
// fetch and instantiate initial spi
if (nextSpi(null, false) == null) {
throw new NoSuchAlgorithmException
(algorithm + " KeyGenerator not available");
}
if (!skipDebug && pdebug != null) {
pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
getProviderName());
}
}
private String getProviderName() {
return (provider == null) ? "(no provider)" : provider.getName();
}
/**
* Returns the algorithm name of this {@code KeyGenerator} object.
*
* <p>This is the same name that was specified in one of the
* {@code getInstance} calls that created this
* {@code KeyGenerator} object.
*
* @return the algorithm name of this {@code KeyGenerator} object.
*/
public final String getAlgorithm() {
return this.algorithm;
}
/**
* Returns a {@code KeyGenerator} object that generates secret keys
* for the specified algorithm.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new KeyGenerator object encapsulating the
* KeyGeneratorSpi implementation from the first
* Provider that supports the specified algorithm is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @implNote
* The JDK Reference Implementation additionally uses the
* {@code jdk.security.provider.preferred}
* {@link Security#getProperty(String) Security} property to determine
* the preferred provider order for the specified algorithm. This
* may be different than the order of providers returned by
* {@link Security#getProviders() Security.getProviders()}.
*
* @param algorithm the standard name of the requested key algorithm.
* See the KeyGenerator section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @return the new {@code KeyGenerator} object
*
* @throws NoSuchAlgorithmException if no {@code Provider} supports a
* {@code KeyGeneratorSpi} implementation for the
* specified algorithm
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final KeyGenerator getInstance(String algorithm)
throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
return new KeyGenerator(algorithm);
}
/**
* Returns a {@code KeyGenerator} object that generates secret keys
* for the specified algorithm.
*
* <p> A new KeyGenerator object encapsulating the
* KeyGeneratorSpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the security provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested key algorithm.
* See the KeyGenerator section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @param provider the name of the provider.
*
* @return the new {@code KeyGenerator} object
*
* @throws IllegalArgumentException if the {@code provider}
* is {@code null} or empty
*
* @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi}
* implementation for the specified algorithm is not
* available from the specified provider
*
* @throws NoSuchProviderException if the specified provider is not
* registered in the security provider list
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final KeyGenerator getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance("KeyGenerator",
KeyGeneratorSpi.class, algorithm, provider);
return new KeyGenerator((KeyGeneratorSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns a {@code KeyGenerator} object that generates secret keys
* for the specified algorithm.
*
* <p> A new KeyGenerator object encapsulating the
* KeyGeneratorSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the standard name of the requested key algorithm.
* See the KeyGenerator section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#keygenerator-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @param provider the provider.
*
* @return the new {@code KeyGenerator} object
*
* @throws IllegalArgumentException if the {@code provider}
* is {@code null}
*
* @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi}
* implementation for the specified algorithm is not available
* from the specified {@code Provider} object
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final KeyGenerator getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance("KeyGenerator",
KeyGeneratorSpi.class, algorithm, provider);
return new KeyGenerator((KeyGeneratorSpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns the provider of this {@code KeyGenerator} object.
*
* @return the provider of this {@code KeyGenerator} object
*/
public final Provider getProvider() {
synchronized (lock) {
disableFailover();
return provider;
}
}
/**
* Update the active spi of this class and return the next
* implementation for failover. If no more implementations are
* available, this method returns null. However, the active spi of
* this class is never set to null.
*/
private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi,
boolean reinit) {
synchronized (lock) {
// somebody else did a failover concurrently
// try that spi now
if ((oldSpi != null) && (oldSpi != spi)) {
return spi;
}
if (serviceIterator == null) {
return null;
}
while (serviceIterator.hasNext()) {
Service s = serviceIterator.next();
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
Object inst = s.newInstance(null);
// ignore non-spis
if (inst instanceof KeyGeneratorSpi == false) {
continue;
}
KeyGeneratorSpi spi = (KeyGeneratorSpi)inst;
if (reinit) {
if (initType == I_SIZE) {
spi.engineInit(initKeySize, initRandom);
} else if (initType == I_PARAMS) {
spi.engineInit(initParams, initRandom);
} else if (initType == I_RANDOM) {
spi.engineInit(initRandom);
} else if (initType != I_NONE) {
throw new AssertionError
("KeyGenerator initType: " + initType);
}
}
provider = s.getProvider();
this.spi = spi;
return spi;
} catch (Exception e) {
// ignore
}
}
disableFailover();
return null;
}
}
void disableFailover() {
serviceIterator = null;
initType = 0;
initParams = null;
initRandom = null;
}
/**
* Initializes this key generator.
*
* @param random the source of randomness for this generator
*/
public final void init(SecureRandom random) {
if (serviceIterator == null) {
spi.engineInit(random);
return;
}
RuntimeException failure = null;
KeyGeneratorSpi mySpi = spi;
do {
try {
mySpi.engineInit(random);
initType = I_RANDOM;
initKeySize = 0;
initParams = null;
initRandom = random;
return;
} catch (RuntimeException e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi, false);
}
} while (mySpi != null);
throw failure;
}
/**
* Initializes this key generator with the specified parameter set.
*
* <p> If this key generator requires any random bytes, it will get them
* using the
* {@link java.security.SecureRandom}
* 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
{
init(params, JceSecurity.RANDOM);
}
/**
* 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} is
* inappropriate for this key generator
*/
public final void init(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException
{
if (serviceIterator == null) {
spi.engineInit(params, random);
return;
}
Exception failure = null;
KeyGeneratorSpi mySpi = spi;
do {
try {
mySpi.engineInit(params, random);
initType = I_PARAMS;
initKeySize = 0;
initParams = params;
initRandom = random;
return;
} catch (Exception e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi, false);
}
} while (mySpi != null);
if (failure instanceof InvalidAlgorithmParameterException) {
throw (InvalidAlgorithmParameterException)failure;
}
if (failure instanceof RuntimeException) {
throw (RuntimeException)failure;
}
throw new InvalidAlgorithmParameterException("init() failed", failure);
}
/**
* Initializes this key generator for a certain keysize.
*
* <p> If this key generator requires any random bytes, it will get them
* using the
* {@link java.security.SecureRandom}
* 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) {
init(keysize, JceSecurity.RANDOM);
}
/**
* 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) {
if (serviceIterator == null) {
spi.engineInit(keysize, random);
return;
}
RuntimeException failure = null;
KeyGeneratorSpi mySpi = spi;
do {
try {
mySpi.engineInit(keysize, random);
initType = I_SIZE;
initKeySize = keysize;
initParams = null;
initRandom = random;
return;
} catch (RuntimeException e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi, false);
}
} while (mySpi != null);
throw failure;
}
/**
* Generates a secret key.
*
* @return the new key
*/
public final SecretKey generateKey() {
if (serviceIterator == null) {
return spi.engineGenerateKey();
}
RuntimeException failure = null;
KeyGeneratorSpi mySpi = spi;
do {
try {
return mySpi.engineGenerateKey();
} catch (RuntimeException e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi, true);
}
} while (mySpi != null);
throw failure;
}
}

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.*;
/**
* 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.
*
* <p>In case the client does not explicitly initialize the KeyGenerator
* (via a call to an {@code init} method), each provider must
* supply (and document) a default initialization.
* See the Keysize Restriction sections of the
* {@extLink security_guide_jdk_providers JDK Providers}
* document for information on the KeyGenerator defaults used by
* JDK providers.
* However, note that defaults may vary across different providers.
* Additionally, the default value for a provider may change in a future
* version. Therefore, it is recommended to explicitly initialize the
* KeyGenerator instead of relying on provider-specific defaults.
*
* @author Jan Luehe
*
* @see SecretKey
* @since 1.4
*/
public abstract class 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 the keysize is wrong or not
* supported.
*/
protected abstract void engineInit(int keysize, SecureRandom random);
/**
* Generates a secret key.
*
* @return the new key
*/
protected abstract SecretKey engineGenerateKey();
}

View file

@ -0,0 +1,692 @@
/*
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.util.*;
import java.security.*;
import java.security.Provider.Service;
import java.security.spec.AlgorithmParameterSpec;
import java.nio.ByteBuffer;
import sun.security.util.Debug;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
/**
* 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., SHA256 or SHA384, in combination with a secret shared key. HMAC is
* specified in RFC 2104.
*
* <p> Every implementation of the Java platform is required to support
* the following standard {@code Mac} algorithms:
* <ul>
* <li>{@code HmacMD5}</li>
* <li>{@code HmacSHA1}</li>
* <li>{@code HmacSHA256}</li>
* </ul>
* These algorithms are described in the
* <a href="{@docRoot}/../specs/security/standard-names.html#mac-algorithms">
* Mac section</a> of the
* Java Security Standard Algorithm Names Specification.
* Consult the release documentation for your implementation to see if any
* other algorithms are supported.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class Mac implements Cloneable {
private static final Debug debug =
Debug.getInstance("jca", "Mac");
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
Debug.isOn("engine=") && !Debug.isOn("mac");
// The provider
private Provider provider;
// The provider implementation (delegate)
private MacSpi spi;
// The name of the MAC algorithm.
private final String algorithm;
// Has this object been initialized?
private boolean initialized = false;
// next service to try in provider selection
// null once provider is selected
private Service firstService;
// remaining services to try in provider selection
// null once provider is selected
private Iterator<Service> serviceIterator;
private final Object lock;
/**
* 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.spi = macSpi;
this.provider = provider;
this.algorithm = algorithm;
serviceIterator = null;
lock = null;
}
private Mac(Service s, Iterator<Service> t, String algorithm) {
firstService = s;
serviceIterator = t;
this.algorithm = algorithm;
lock = new Object();
}
/**
* Returns the algorithm name of this {@code Mac} object.
*
* <p>This is the same name that was specified in one of the
* {@code getInstance} calls that created this
* {@code Mac} object.
*
* @return the algorithm name of this {@code Mac} object.
*/
public final String getAlgorithm() {
return this.algorithm;
}
/**
* Returns a {@code Mac} object that implements the
* specified MAC algorithm.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new Mac object encapsulating the
* MacSpi implementation from the first
* Provider that supports the specified algorithm is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @implNote
* The JDK Reference Implementation additionally uses the
* {@code jdk.security.provider.preferred}
* {@link Security#getProperty(String) Security} property to determine
* the preferred provider order for the specified algorithm. This
* may be different than the order of providers returned by
* {@link Security#getProviders() Security.getProviders()}.
*
* @param algorithm the standard name of the requested MAC algorithm.
* See the Mac section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#mac-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @return the new {@code Mac} object
*
* @throws NoSuchAlgorithmException if no {@code Provider} supports a
* {@code MacSpi} implementation for the specified algorithm
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final Mac getInstance(String algorithm)
throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
List<Service> services = GetInstance.getServices("Mac", algorithm);
// make sure there is at least one service from a signed provider
Iterator<Service> t = services.iterator();
while (t.hasNext()) {
Service s = t.next();
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
return new Mac(s, t, algorithm);
}
throw new NoSuchAlgorithmException
("Algorithm " + algorithm + " not available");
}
/**
* Returns a {@code Mac} object that implements the
* specified MAC algorithm.
*
* <p> A new Mac object encapsulating the
* MacSpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the security provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested MAC algorithm.
* See the Mac section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#mac-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @param provider the name of the provider.
*
* @return the new {@code Mac} object
*
* @throws IllegalArgumentException if the {@code provider}
* is {@code null} or empty
*
* @throws NoSuchAlgorithmException if a {@code MacSpi}
* implementation for the specified algorithm is not
* available from the specified provider
*
* @throws NoSuchProviderException if the specified provider is not
* registered in the security provider list
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final Mac getInstance(String algorithm, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance
("Mac", MacSpi.class, algorithm, provider);
return new Mac((MacSpi)instance.impl, instance.provider, algorithm);
}
/**
* Returns a {@code Mac} object that implements the
* specified MAC algorithm.
*
* <p> A new Mac object encapsulating the
* MacSpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the standard name of the requested MAC algorithm.
* See the Mac section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#mac-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @param provider the provider.
*
* @return the new {@code Mac} object
*
* @throws IllegalArgumentException if the {@code provider} is
* {@code null}
*
* @throws NoSuchAlgorithmException if a {@code MacSpi}
* implementation for the specified algorithm is not available
* from the specified {@code Provider} object
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final Mac getInstance(String algorithm, Provider provider)
throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance
("Mac", MacSpi.class, algorithm, provider);
return new Mac((MacSpi)instance.impl, instance.provider, algorithm);
}
// max number of debug warnings to print from chooseFirstProvider()
private static int warnCount = 10;
/**
* Choose the Spi from the first provider available. Used if
* delayed provider selection is not possible because init()
* is not the first method called.
*/
void chooseFirstProvider() {
if ((spi != null) || (serviceIterator == null)) {
return;
}
synchronized (lock) {
if (spi != null) {
return;
}
if (debug != null) {
int w = --warnCount;
if (w >= 0) {
debug.println("Mac.init() not first method "
+ "called, disabling delayed provider selection");
if (w == 0) {
debug.println("Further warnings of this type will "
+ "be suppressed");
}
new Exception("Call trace").printStackTrace();
}
}
Exception lastException = null;
while ((firstService != null) || serviceIterator.hasNext()) {
Service s;
if (firstService != null) {
s = firstService;
firstService = null;
} else {
s = serviceIterator.next();
}
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
Object obj = s.newInstance(null);
if (obj instanceof MacSpi == false) {
continue;
}
spi = (MacSpi)obj;
provider = s.getProvider();
// not needed any more
firstService = null;
serviceIterator = null;
return;
} catch (NoSuchAlgorithmException e) {
lastException = e;
}
}
ProviderException e = new ProviderException
("Could not construct MacSpi instance");
if (lastException != null) {
e.initCause(lastException);
}
throw e;
}
}
private void chooseProvider(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
synchronized (lock) {
if (spi != null) {
spi.engineInit(key, params);
return;
}
Exception lastException = null;
while ((firstService != null) || serviceIterator.hasNext()) {
Service s;
if (firstService != null) {
s = firstService;
firstService = null;
} else {
s = serviceIterator.next();
}
// if provider says it does not support this key, ignore it
if (s.supportsParameter(key) == false) {
continue;
}
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
MacSpi spi = (MacSpi)s.newInstance(null);
spi.engineInit(key, params);
provider = s.getProvider();
this.spi = spi;
firstService = null;
serviceIterator = null;
return;
} catch (Exception e) {
// NoSuchAlgorithmException from newInstance()
// InvalidKeyException from init()
// RuntimeException (ProviderException) from init()
if (lastException == null) {
lastException = e;
}
}
}
// no working provider found, fail
if (lastException instanceof InvalidKeyException) {
throw (InvalidKeyException)lastException;
}
if (lastException instanceof InvalidAlgorithmParameterException) {
throw (InvalidAlgorithmParameterException)lastException;
}
if (lastException instanceof RuntimeException) {
throw (RuntimeException)lastException;
}
String kName = (key != null) ? key.getClass().getName() : "(null)";
throw new InvalidKeyException
("No installed provider supports this key: "
+ kName, lastException);
}
}
/**
* Returns the provider of this {@code Mac} object.
*
* @return the provider of this {@code Mac} object.
*/
public final Provider getProvider() {
chooseFirstProvider();
return this.provider;
}
/**
* Returns the length of the MAC in bytes.
*
* @return the MAC length in bytes.
*/
public final int getMacLength() {
chooseFirstProvider();
return spi.engineGetMacLength();
}
private String getProviderName() {
return (provider == null) ? "(no provider)" : provider.getName();
}
/**
* Initializes this {@code Mac} 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 {
if (spi != null) {
spi.engineInit(key, null);
} else {
chooseProvider(key, null);
}
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidKeyException("init() failed", e);
}
initialized = true;
if (!skipDebug && pdebug != null) {
pdebug.println("Mac." + algorithm + " algorithm from: " +
getProviderName());
}
}
/**
* Initializes this {@code Mac} 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 {
if (spi != null) {
spi.engineInit(key, params);
} else {
chooseProvider(key, params);
}
initialized = true;
if (!skipDebug && pdebug != null) {
pdebug.println("Mac." + algorithm + " algorithm from: " +
getProviderName());
}
}
/**
* Processes the given byte.
*
* @param input the input byte to be processed.
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final void update(byte input) throws IllegalStateException {
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
spi.engineUpdate(input);
}
/**
* Processes the given array of bytes.
*
* @param input the array of bytes to be processed.
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final void update(byte[] input) throws IllegalStateException {
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
if (input != null) {
spi.engineUpdate(input, 0, input.length);
}
}
/**
* Processes the first {@code len} bytes in {@code input},
* starting at {@code offset} inclusive.
*
* @param input the input buffer.
* @param offset the offset in {@code input} where the input starts.
* @param len the number of bytes to process.
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final void update(byte[] input, int offset, int len)
throws IllegalStateException {
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
if (input != null) {
if ((offset < 0) || (len > (input.length - offset)) || (len < 0))
throw new IllegalArgumentException("Bad arguments");
spi.engineUpdate(input, offset, len);
}
}
/**
* Processes {@code input.remaining()} bytes in the ByteBuffer
* {@code input}, starting at {@code input.position()}.
* Upon return, the buffer's position will be equal to its limit;
* its limit will not have changed.
*
* @param input the ByteBuffer
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
* @since 1.5
*/
public final void update(ByteBuffer input) {
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
if (input == null) {
throw new IllegalArgumentException("Buffer must not be null");
}
spi.engineUpdate(input);
}
/**
* Finishes the MAC operation.
*
* <p>A call to this method resets this {@code Mac} object to the
* state it was in when previously initialized via a call to
* {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to {@code update} and
* {@code doFinal}.
* (In order to reuse this {@code Mac} object with a different key,
* it must be reinitialized via a call to {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
*
* @return the MAC result.
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final byte[] doFinal() throws IllegalStateException {
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
byte[] mac = spi.engineDoFinal();
spi.engineReset();
return mac;
}
/**
* Finishes the MAC operation.
*
* <p>A call to this method resets this {@code Mac} object to the
* state it was in when previously initialized via a call to
* {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to {@code update} and
* {@code doFinal}.
* (In order to reuse this {@code Mac} object with a different key,
* it must be reinitialized via a call to {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
*
* <p>The MAC result is stored in {@code output}, starting at
* {@code outOffset} inclusive.
*
* @param output the buffer where the MAC result is stored
* @param outOffset the offset in {@code output} 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} has not been
* initialized.
*/
public final void doFinal(byte[] output, int outOffset)
throws ShortBufferException, IllegalStateException
{
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
int macLen = getMacLength();
if (output == null || output.length-outOffset < macLen) {
throw new ShortBufferException
("Cannot store MAC in output buffer");
}
byte[] mac = doFinal();
System.arraycopy(mac, 0, output, outOffset, macLen);
return;
}
/**
* Processes the given array of bytes and finishes the MAC operation.
*
* <p>A call to this method resets this {@code Mac} object to the
* state it was in when previously initialized via a call to
* {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to {@code update} and
* {@code doFinal}.
* (In order to reuse this {@code Mac} object with a different key,
* it must be reinitialized via a call to {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
*
* @param input data in bytes
* @return the MAC result.
*
* @exception IllegalStateException if this {@code Mac} has not been
* initialized.
*/
public final byte[] doFinal(byte[] input) throws IllegalStateException
{
chooseFirstProvider();
if (initialized == false) {
throw new IllegalStateException("MAC not initialized");
}
update(input);
return doFinal();
}
/**
* Resets this {@code Mac} object.
*
* <p>A call to this method resets this {@code Mac} object to the
* state it was in when previously initialized via a call to
* {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
* That is, the object is reset and available to generate another MAC from
* the same key, if desired, via new calls to {@code update} and
* {@code doFinal}.
* (In order to reuse this {@code Mac} object with a different key,
* it must be reinitialized via a call to {@code init(Key)} or
* {@code init(Key, AlgorithmParameterSpec)}.
*/
public final void reset() {
chooseFirstProvider();
spi.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}.
*/
public final Object clone() throws CloneNotSupportedException {
chooseFirstProvider();
Mac that = (Mac)super.clone();
that.spi = (MacSpi)this.spi.clone();
return that;
}
}

View file

@ -0,0 +1,153 @@
/*
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.*;
import java.nio.ByteBuffer;
/**
* 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.
*
* @author Jan Luehe
*
* @since 1.4
*/
public abstract class 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);
/**
* Processes <code>input.remaining()</code> bytes in the ByteBuffer
* <code>input</code>, starting at <code>input.position()</code>.
* Upon return, the buffer's position will be equal to its limit;
* its limit will not have changed.
*
* <p>Subclasses should consider overriding this method if they can
* process ByteBuffers more efficiently than byte arrays.
*
* @param input the ByteBuffer
* @since 1.5
*/
protected void engineUpdate(ByteBuffer input) {
if (input.hasRemaining() == false) {
return;
}
if (input.hasArray()) {
byte[] b = input.array();
int ofs = input.arrayOffset();
int pos = input.position();
int lim = input.limit();
engineUpdate(b, ofs + pos, lim - pos);
input.position(lim);
} else {
int len = input.remaining();
byte[] b = new byte[CipherSpi.getTempArraySize(len)];
while (len > 0) {
int chunk = Math.min(len, b.length);
input.get(b, 0, chunk);
engineUpdate(b, 0, chunk);
len -= chunk;
}
}
}
/**
* 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 {
if (this instanceof Cloneable) {
return super.clone();
} else {
throw new CloneNotSupportedException();
}
}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
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.
*
* @author Jan Luehe
*
* @since 1.4
*/
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() {
super();
}
/**
* Constructs a NoSuchPaddingException with the specified
* detail message.
*
* @param msg the detail message.
*/
public NoSuchPaddingException(String msg) {
super(msg);
}
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
/**
* The NullCipher class is a class that provides an
* "identity cipher" -- one that does not transform the plain text. As
* a consequence, the ciphertext is identical to the plaintext. All
* initialization methods do nothing, while the blocksize is set to 1
* byte.
*
* @author Li Gong
* @since 1.4
*/
public class NullCipher extends Cipher {
/**
* Creates a NullCipher object.
*/
public NullCipher() {
super(new NullCipherSpi(), null);
}
}

View file

@ -0,0 +1,113 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.*;
/**
* This class provides a delegate for the identity cipher - one that does not
* transform the plain text.
*
* @author Li Gong
* @see NullCipher
*
* @since 1.4
*/
final class NullCipherSpi extends CipherSpi {
/*
* Do not let anybody instantiate this directly (protected).
*/
protected NullCipherSpi() {}
public void engineSetMode(String mode) {}
public void engineSetPadding(String padding) {}
protected int engineGetBlockSize() {
return 1;
}
protected int engineGetOutputSize(int inputLen) {
return inputLen;
}
protected byte[] engineGetIV() {
byte[] x = new byte[8];
return x;
}
protected AlgorithmParameters engineGetParameters() {
return null;
}
protected void engineInit(int mode, Key key, SecureRandom random) {}
protected void engineInit(int mode, Key key,
AlgorithmParameterSpec params,
SecureRandom random) {}
protected void engineInit(int mode, Key key,
AlgorithmParameters params,
SecureRandom random) {}
protected byte[] engineUpdate(byte[] input, int inputOffset,
int inputLen) {
if (input == null) return null;
byte[] x = new byte[inputLen];
System.arraycopy(input, inputOffset, x, 0, inputLen);
return x;
}
protected int engineUpdate(byte[] input, int inputOffset,
int inputLen, byte[] output,
int outputOffset) {
if (input == null) return 0;
System.arraycopy(input, inputOffset, output, outputOffset, inputLen);
return inputLen;
}
protected byte[] engineDoFinal(byte[] input, int inputOffset,
int inputLen)
{
return engineUpdate(input, inputOffset, inputLen);
}
protected int engineDoFinal(byte[] input, int inputOffset,
int inputLen, byte[] output,
int outputOffset)
{
return engineUpdate(input, inputOffset, inputLen,
output, outputOffset);
}
protected int engineGetKeySize(Key key)
{
return 0;
}
}

View file

@ -0,0 +1,177 @@
/*
* Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.io.*;
import java.net.*;
import java.security.*;
import java.util.jar.*;
/**
* This class verifies Provider/Policy resources found at a URL
* (currently only JAR files and any supporting JAR files), and
* determines whether they may be used in this implementation.
*
* The JCE in OpenJDK has an open cryptographic interface, meaning it
* does not restrict which providers can be used. Compliance with
* United States export controls and with local law governing the
* import/export of products incorporating the JCE in the OpenJDK is
* the responsibility of the licensee.
*
* @since 1.7
*/
final class ProviderVerifier {
// The URL for the JAR file we want to verify.
private URL jarURL;
private Provider provider;
private boolean savePerms;
private CryptoPermissions appPerms = null;
/**
* Creates a ProviderVerifier object to verify the given URL.
*
* @param jarURL the JAR file to be verified.
* @param savePerms if true, save the permissions allowed by the
* exemption mechanism
*/
ProviderVerifier(URL jarURL, boolean savePerms) {
this(jarURL, null, savePerms);
}
/**
* Creates a ProviderVerifier object to verify the given URL.
*
* @param jarURL the JAR file to be verified
* @param provider the corresponding provider.
* @param savePerms if true, save the permissions allowed by the
* exemption mechanism
*/
ProviderVerifier(URL jarURL, Provider provider, boolean savePerms) {
this.jarURL = jarURL;
this.provider = provider;
this.savePerms = savePerms;
}
/**
* Verify the JAR file is signed by an entity which has a certificate
* issued by a trusted CA.
*
* In OpenJDK, we just need to examine the "cryptoperms" file to see
* if any permissions were bundled together with this jar file.
*/
void verify() throws IOException {
// Short-circuit. If we weren't asked to save any, we're done.
if (!savePerms) {
return;
}
// If the protocol of jarURL isn't "jar", we should
// construct a JAR URL so we can open a JarURLConnection
// for verifying this provider.
final URL url = jarURL.getProtocol().equalsIgnoreCase("jar")?
jarURL : new URL("jar:" + jarURL.toString() + "!/");
JarFile jf = null;
try {
// Get a link to the Jarfile to search.
try {
jf = AccessController.doPrivileged(
new PrivilegedExceptionAction<JarFile>() {
public JarFile run() throws Exception {
JarURLConnection conn =
(JarURLConnection) url.openConnection();
// You could do some caching here as
// an optimization.
conn.setUseCaches(false);
return conn.getJarFile();
}
});
} catch (java.security.PrivilegedActionException pae) {
throw new SecurityException("Cannot load " + url.toString(),
pae.getCause());
}
if (jf != null) {
JarEntry je = jf.getJarEntry("cryptoPerms");
if (je == null) {
throw new JarException(
"Can not find cryptoPerms");
}
try {
appPerms = new CryptoPermissions();
appPerms.load(jf.getInputStream(je));
} catch (Exception ex) {
JarException jex =
new JarException("Cannot load/parse" +
jarURL.toString());
jex.initCause(ex);
throw jex;
}
}
} finally {
// Only call close() when caching is not enabled.
// Otherwise, exceptions will be thrown for all
// subsequent accesses of this cached jar.
if (jf != null) {
jf.close();
}
}
}
/**
* Verify that the provided certs include the
* framework signing certificate.
*
* @param certs the list of certs to be checked.
* @throws Exception if the list of certs did not contain
* the framework signing certificate
*/
static void verifyPolicySigned(java.security.cert.Certificate[] certs)
throws Exception {
}
/**
* Returns true if the given provider is JDK trusted crypto provider
* if the implementation supports fast-path verification.
*/
static boolean isTrustedCryptoProvider(Provider provider) {
return false;
}
/**
* Returns the permissions which are bundled with the JAR file,
* aka the "cryptoperms" file.
*
* NOTE: if this ProviderVerifier instance is constructed with "savePerms"
* equal to false, then this method would always return null.
*/
CryptoPermissions getPermissions() {
return appPerms;
}
}

View file

@ -0,0 +1,487 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.io.*;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.InvalidKeyException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
/**
* 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 AES, 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:
*
* <ul>
*
* <li>by using the {@link #getObject(javax.crypto.Cipher) getObject}
* 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.
*
* <li>by using one of the
* {@link #getObject(java.security.Key) getObject} 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>
*
* @author Li Gong
* @author Jan Luehe
* @see Cipher
* @since 1.4
*/
public class SealedObject implements Serializable {
static final long serialVersionUID = 4482838265551344752L;
/**
* The serialized object contents in encrypted format.
*
* @serial
*/
private byte[] encryptedContent = null;
/**
* The algorithm that was used to seal this object.
*
* @serial
*/
private String sealAlg = null;
/**
* The algorithm of the parameters used.
*
* @serial
*/
private String paramsAlg = null;
/**
* The cryptographic parameters used by the sealing Cipher,
* encoded in the default format.
* <p>
* That is, <code>cipher.getParameters().getEncoded()</code>.
*
* @serial
*/
protected byte[] encodedParams = null;
/**
* 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; can be null.
* @param c the cipher used to seal the object.
*
* @exception NullPointerException if the given cipher is null.
* @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
{
/*
* Serialize the object
*/
// creating a stream pipe-line, from a to b
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutput a = new ObjectOutputStream(b);
byte[] content;
try {
// write and flush the object content to byte array
a.writeObject(object);
a.flush();
content = b.toByteArray();
} finally {
a.close();
}
/*
* Seal the object
*/
try {
this.encryptedContent = c.doFinal(content);
}
catch (BadPaddingException ex) {
// if sealing is encryption only
// Should never happen??
}
// Save the parameters
if (c.getParameters() != null) {
this.encodedParams = c.getParameters().getEncoded();
this.paramsAlg = c.getParameters().getAlgorithm();
}
// Save the encryption algorithm
this.sealAlg = c.getAlgorithm();
}
/**
* Constructs a SealedObject object from the passed-in SealedObject.
*
* @param so a SealedObject object
* @exception NullPointerException if the given sealed object is null.
*/
protected SealedObject(SealedObject so) {
this.encryptedContent = so.encryptedContent.clone();
this.sealAlg = so.sealAlg;
this.paramsAlg = so.paramsAlg;
if (so.encodedParams != null) {
this.encodedParams = so.encodedParams.clone();
} else {
this.encodedParams = null;
}
}
/**
* 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 this.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).
* @exception NullPointerException if <code>key</code> is null.
*/
public final Object getObject(Key key)
throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
InvalidKeyException
{
if (key == null) {
throw new NullPointerException("key is null");
}
try {
return unseal(key, null);
} catch (NoSuchProviderException nspe) {
// we've already caught NoSuchProviderException's and converted
// them into NoSuchAlgorithmException's with details about
// the failing algorithm
throw new NoSuchAlgorithmException("algorithm not found");
} catch (IllegalBlockSizeException ibse) {
throw new InvalidKeyException(ibse.getMessage());
} catch (BadPaddingException bpe) {
throw new InvalidKeyException(bpe.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 NullPointerException if the given cipher is null.
* @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
{
/*
* Unseal the object
*/
byte[] content = c.doFinal(this.encryptedContent);
/*
* De-serialize it
*/
// creating a stream pipe-line, from b to a
ByteArrayInputStream b = new ByteArrayInputStream(content);
ObjectInput a = new extObjectInputStream(b);
try {
Object obj = a.readObject();
return obj;
} finally {
a.close();
}
}
/**
* 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 IllegalArgumentException if the given provider is null
* or empty.
* @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 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).
* @exception NullPointerException if <code>key</code> is null.
*/
public final Object getObject(Key key, String provider)
throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException
{
if (key == null) {
throw new NullPointerException("key is null");
}
if (provider == null || provider.length() == 0) {
throw new IllegalArgumentException("missing provider");
}
try {
return unseal(key, provider);
} catch (IllegalBlockSizeException | BadPaddingException ex) {
throw new InvalidKeyException(ex.getMessage());
}
}
private Object unseal(Key key, String provider)
throws IOException, ClassNotFoundException, NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException
{
/*
* Create the parameter object.
*/
AlgorithmParameters params = null;
if (this.encodedParams != null) {
try {
if (provider != null)
params = AlgorithmParameters.getInstance(this.paramsAlg,
provider);
else
params = AlgorithmParameters.getInstance(this.paramsAlg);
} catch (NoSuchProviderException nspe) {
if (provider == null) {
throw new NoSuchAlgorithmException(this.paramsAlg
+ " not found");
} else {
throw new NoSuchProviderException(nspe.getMessage());
}
}
params.init(this.encodedParams);
}
/*
* Create and initialize the cipher.
*/
Cipher c;
try {
if (provider != null)
c = Cipher.getInstance(this.sealAlg, provider);
else
c = Cipher.getInstance(this.sealAlg);
} catch (NoSuchPaddingException nspe) {
throw new NoSuchAlgorithmException("Padding that was used in "
+ "sealing operation not "
+ "available");
} catch (NoSuchProviderException nspe) {
if (provider == null) {
throw new NoSuchAlgorithmException(this.sealAlg+" not found");
} else {
throw new NoSuchProviderException(nspe.getMessage());
}
}
try {
if (params != null)
c.init(Cipher.DECRYPT_MODE, key, params);
else
c.init(Cipher.DECRYPT_MODE, key);
} catch (InvalidAlgorithmParameterException iape) {
// this should never happen, because we use the exact same
// parameters that were used in the sealing operation
throw new RuntimeException(iape.getMessage());
}
/*
* Unseal the object
*/
byte[] content = c.doFinal(this.encryptedContent);
/*
* De-serialize it
*/
// creating a stream pipe-line, from b to a
ByteArrayInputStream b = new ByteArrayInputStream(content);
ObjectInput a = new extObjectInputStream(b);
try {
Object obj = a.readObject();
return obj;
} finally {
a.close();
}
}
/**
* Restores the state of the SealedObject from a stream.
* @param s the object input stream.
* @exception NullPointerException if s is null.
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException
{
s.defaultReadObject();
if (encryptedContent != null)
encryptedContent = encryptedContent.clone();
if (encodedParams != null)
encodedParams = encodedParams.clone();
}
}
final class extObjectInputStream extends ObjectInputStream {
extObjectInputStream(InputStream in)
throws IOException, StreamCorruptedException {
super(in);
}
protected Class<?> resolveClass(ObjectStreamClass v)
throws IOException, ClassNotFoundException
{
try {
/*
* Calling the super.resolveClass() first
* will let us pick up bug fixes in the super
* class (e.g., 4171142).
*/
return super.resolveClass(v);
} catch (ClassNotFoundException cnfe) {
/*
* This is a workaround for bug 4224921.
*/
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
loader = ClassLoader.getSystemClassLoader();
if (loader == null) {
throw new ClassNotFoundException(v.getName());
}
}
return Class.forName(v.getName(), false, loader);
}
}
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
/**
* A secret (symmetric) key.
* The purpose of this interface is to group (and provide type safety
* for) all secret key interfaces.
* <p>
* Provider implementations of this interface must overwrite the
* {@code equals} and {@code hashCode} methods inherited from
* {@link java.lang.Object}, so that secret keys are compared based on
* their underlying key material and not based on reference.
* Implementations should override the default {@code destroy} and
* {@code isDestroyed} methods from the
* {@link javax.security.auth.Destroyable} interface to enable
* sensitive key information to be destroyed, cleared, or in the case
* where such information is immutable, unreferenced.
* Finally, since {@code SecretKey} is {@code Serializable}, implementations
* should also override
* {@link java.io.ObjectOutputStream#writeObject(java.lang.Object)}
* to prevent keys that have been destroyed from being serialized.
*
* <p>Keys that implement this interface return the string {@code RAW}
* as their encoding format (see {@code getFormat}), and return the
* raw key bytes as the result of a {@code getEncoded} method call. (The
* {@code getFormat} and {@code getEncoded} methods are inherited
* from the {@link java.security.Key} parent interface.)
*
* @author Jan Luehe
*
* @see SecretKeyFactory
* @see Cipher
* @since 1.4
*/
public interface SecretKey extends
java.security.Key, javax.security.auth.Destroyable {
/**
* The class fingerprint that is set to indicate serialization
* compatibility since J2SE 1.4.
*/
static final long serialVersionUID = -4795878709595146952L;
}

View file

@ -0,0 +1,437 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.util.*;
import java.security.*;
import java.security.Provider.Service;
import java.security.spec.*;
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
/**
* 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}) 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
* {@link #generateSecret(java.security.spec.KeySpec) generateSecret} and
* {@link #getKeySpec(javax.crypto.SecretKey, java.lang.Class) getKeySpec}
* methods.
* For example, the DES secret-key factory supplied by the "SunJCE" provider
* supports {@code DESKeySpec} as a transparent representation of DES
* keys, and that provider's secret-key factory for Triple DES keys supports
* {@code DESedeKeySpec} as a transparent representation of Triple DES
* keys.
*
* <p> Every implementation of the Java platform is required to support the
* following standard {@code SecretKeyFactory} algorithms:
* <ul>
* <li>{@code DES}</li>
* <li>{@code DESede}</li>
* </ul>
* These algorithms are described in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#secretkeyfactory-algorithms">
* SecretKeyFactory section</a> of the
* Java Security Standard Algorithm Names Specification.
* Consult the release documentation for your implementation to see if any
* other algorithms are supported.
*
* @author Jan Luehe
*
* @see SecretKey
* @see javax.crypto.spec.DESKeySpec
* @see javax.crypto.spec.DESedeKeySpec
* @see javax.crypto.spec.PBEKeySpec
* @since 1.4
*/
public class SecretKeyFactory {
// The provider
private Provider provider;
// The algorithm associated with this factory
private final String algorithm;
// The provider implementation (delegate)
private volatile SecretKeyFactorySpi spi;
// lock for mutex during provider selection
private final Object lock = new Object();
// remaining services to try in provider selection
// null once provider is selected
private Iterator<Service> serviceIterator;
/**
* 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.spi = keyFacSpi;
this.provider = provider;
this.algorithm = algorithm;
}
private SecretKeyFactory(String algorithm) throws NoSuchAlgorithmException {
this.algorithm = algorithm;
List<Service> list =
GetInstance.getServices("SecretKeyFactory", algorithm);
serviceIterator = list.iterator();
// fetch and instantiate initial spi
if (nextSpi(null) == null) {
throw new NoSuchAlgorithmException
(algorithm + " SecretKeyFactory not available");
}
}
/**
* Returns a {@code SecretKeyFactory} object that converts
* secret keys of the specified algorithm.
*
* <p> This method traverses the list of registered security Providers,
* starting with the most preferred Provider.
* A new SecretKeyFactory object encapsulating the
* SecretKeyFactorySpi implementation from the first
* Provider that supports the specified algorithm is returned.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @implNote
* The JDK Reference Implementation additionally uses the
* {@code jdk.security.provider.preferred}
* {@link Security#getProperty(String) Security} property to determine
* the preferred provider order for the specified algorithm. This
* may be different than the order of providers returned by
* {@link Security#getProviders() Security.getProviders()}.
*
* @param algorithm the standard name of the requested secret-key
* algorithm.
* See the SecretKeyFactory section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#secretkeyfactory-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @return the new {@code SecretKeyFactory} object
*
* @throws NoSuchAlgorithmException if no {@code Provider} supports a
* {@code SecretKeyFactorySpi} implementation for the
* specified algorithm
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final SecretKeyFactory getInstance(String algorithm)
throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
return new SecretKeyFactory(algorithm);
}
/**
* Returns a {@code SecretKeyFactory} object that converts
* secret keys of the specified algorithm.
*
* <p> A new SecretKeyFactory object encapsulating the
* SecretKeyFactorySpi implementation from the specified provider
* is returned. The specified provider must be registered
* in the security provider list.
*
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
* @param algorithm the standard name of the requested secret-key
* algorithm.
* See the SecretKeyFactory section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#secretkeyfactory-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @param provider the name of the provider.
*
* @return the new {@code SecretKeyFactory} object
*
* @throws IllegalArgumentException if the {@code provider}
* is {@code null} or empty
*
* @throws NoSuchAlgorithmException if a {@code SecretKeyFactorySpi}
* implementation for the specified algorithm is not
* available from the specified provider
*
* @throws NoSuchProviderException if the specified provider is not
* registered in the security provider list
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final SecretKeyFactory getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
NoSuchProviderException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance("SecretKeyFactory",
SecretKeyFactorySpi.class, algorithm, provider);
return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns a {@code SecretKeyFactory} object that converts
* secret keys of the specified algorithm.
*
* <p> A new SecretKeyFactory object encapsulating the
* SecretKeyFactorySpi implementation from the specified Provider
* object is returned. Note that the specified Provider object
* does not have to be registered in the provider list.
*
* @param algorithm the standard name of the requested secret-key
* algorithm.
* See the SecretKeyFactory section in the <a href=
* "{@docRoot}/../specs/security/standard-names.html#secretkeyfactory-algorithms">
* Java Security Standard Algorithm Names Specification</a>
* for information about standard algorithm names.
*
* @param provider the provider.
*
* @return the new {@code SecretKeyFactory} object
*
* @throws IllegalArgumentException if the {@code provider}
* is {@code null}
*
* @throws NoSuchAlgorithmException if a {@code SecretKeyFactorySpi}
* implementation for the specified algorithm is not available
* from the specified {@code Provider} object
*
* @throws NullPointerException if {@code algorithm} is {@code null}
*
* @see java.security.Provider
*/
public static final SecretKeyFactory getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
Instance instance = JceSecurity.getInstance("SecretKeyFactory",
SecretKeyFactorySpi.class, algorithm, provider);
return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
instance.provider, algorithm);
}
/**
* Returns the provider of this {@code SecretKeyFactory} object.
*
* @return the provider of this {@code SecretKeyFactory} object
*/
public final Provider getProvider() {
synchronized (lock) {
// disable further failover after this call
serviceIterator = null;
return provider;
}
}
/**
* Returns the algorithm name of this {@code SecretKeyFactory} object.
*
* <p>This is the same name that was specified in one of the
* {@code getInstance} calls that created this
* {@code SecretKeyFactory} object.
*
* @return the algorithm name of this {@code SecretKeyFactory}
* object.
*/
public final String getAlgorithm() {
return this.algorithm;
}
/**
* Update the active spi of this class and return the next
* implementation for failover. If no more implemenations are
* available, this method returns null. However, the active spi of
* this class is never set to null.
*/
private SecretKeyFactorySpi nextSpi(SecretKeyFactorySpi oldSpi) {
synchronized (lock) {
// somebody else did a failover concurrently
// try that spi now
if ((oldSpi != null) && (oldSpi != spi)) {
return spi;
}
if (serviceIterator == null) {
return null;
}
while (serviceIterator.hasNext()) {
Service s = serviceIterator.next();
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
try {
Object obj = s.newInstance(null);
if (obj instanceof SecretKeyFactorySpi == false) {
continue;
}
SecretKeyFactorySpi spi = (SecretKeyFactorySpi)obj;
provider = s.getProvider();
this.spi = spi;
return spi;
} catch (NoSuchAlgorithmException e) {
// ignore
}
}
serviceIterator = null;
return null;
}
}
/**
* Generates a {@code SecretKey} 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 {
if (serviceIterator == null) {
return spi.engineGenerateSecret(keySpec);
}
Exception failure = null;
SecretKeyFactorySpi mySpi = spi;
do {
try {
return mySpi.engineGenerateSecret(keySpec);
} catch (Exception e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi);
}
} while (mySpi != null);
if (failure instanceof InvalidKeySpecException) {
throw (InvalidKeySpecException)failure;
}
throw new InvalidKeySpecException
("Could not generate secret key", failure);
}
/**
* 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} and {@code keySpec} do not match, or
* {@code key} references a key on a cryptographic hardware device
* whereas {@code keySpec} 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 {
if (serviceIterator == null) {
return spi.engineGetKeySpec(key, keySpec);
}
Exception failure = null;
SecretKeyFactorySpi mySpi = spi;
do {
try {
return mySpi.engineGetKeySpec(key, keySpec);
} catch (Exception e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi);
}
} while (mySpi != null);
if (failure instanceof InvalidKeySpecException) {
throw (InvalidKeySpecException)failure;
}
throw new InvalidKeySpecException
("Could not get key spec", failure);
}
/**
* 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 {
if (serviceIterator == null) {
return spi.engineTranslateKey(key);
}
Exception failure = null;
SecretKeyFactorySpi mySpi = spi;
do {
try {
return mySpi.engineTranslateKey(key);
} catch (Exception e) {
if (failure == null) {
failure = e;
}
mySpi = nextSpi(mySpi);
}
} while (mySpi != null);
if (failure instanceof InvalidKeyException) {
throw (InvalidKeyException)failure;
}
throw new InvalidKeyException
("Could not translate key", failure);
}
}

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto;
import java.security.*;
import java.security.spec.*;
/**
* 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.
*
* @author Jan Luehe
*
* @see SecretKey
* @see javax.crypto.spec.DESKeySpec
* @see javax.crypto.spec.DESedeKeySpec
* @since 1.4
*/
public abstract class 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 the translated key
*
* @exception InvalidKeyException if the given key cannot be processed
* by this secret-key factory.
*/
protected abstract SecretKey engineTranslateKey(SecretKey key)
throws InvalidKeyException;
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
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.
*
* @author Jan Luehe
*
* @since 1.4
*/
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() {
super();
}
/**
* Constructs a ShortBufferException with the specified
* detail message.
*
* @param msg the detail message.
*/
public ShortBufferException(String msg) {
super(msg);
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.interfaces;
import javax.crypto.spec.DHParameterSpec;
/**
* The interface to a Diffie-Hellman key.
*
* @author Jan Luehe
*
* @see javax.crypto.spec.DHParameterSpec
* @see DHPublicKey
* @see DHPrivateKey
* @since 1.4
*/
public interface DHKey {
/**
* Returns the key parameters.
*
* @return the key parameters
*/
DHParameterSpec getParams();
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.interfaces;
import java.math.BigInteger;
/**
* The interface to a Diffie-Hellman private key.
*
* @author Jan Luehe
*
* @see DHKey
* @see DHPublicKey
* @since 1.4
*/
public interface DHPrivateKey extends DHKey, java.security.PrivateKey {
/**
* The class fingerprint that is set to indicate serialization
* compatibility since J2SE 1.4.
*/
static final long serialVersionUID = 2211791113380396553L;
/**
* Returns the private value, <code>x</code>.
*
* @return the private value, <code>x</code>
*/
BigInteger getX();
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.interfaces;
import java.math.BigInteger;
/**
* The interface to a Diffie-Hellman public key.
*
* @author Jan Luehe
*
* @see DHKey
* @see DHPrivateKey
* @since 1.4
*/
public interface DHPublicKey extends DHKey, java.security.PublicKey {
/**
* The class fingerprint that is set to indicate serialization
* compatibility since J2SE 1.4.
*/
static final long serialVersionUID = -6628103563352519193L;
/**
* Returns the public value, <code>y</code>.
*
* @return the public value, <code>y</code>
*/
BigInteger getY();
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.interfaces;
import java.math.BigInteger;
/**
* The interface to a PBE key.
*
* @author Valerie Peng
*
* @see javax.crypto.spec.PBEKeySpec
* @see javax.crypto.SecretKey
* @since 1.4
*/
public interface PBEKey extends javax.crypto.SecretKey {
/**
* The class fingerprint that is set to indicate serialization
* compatibility since J2SE 1.4.
*/
static final long serialVersionUID = -1430015993304333921L;
/**
* Returns the password.
*
* <p> 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.
*/
char[] getPassword();
/**
* Returns the salt or null if not specified.
*
* <p> 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.
*/
byte[] getSalt();
/**
* Returns the iteration count or 0 if not specified.
*
* @return the iteration count.
*/
int getIterationCount();
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Provides interfaces for Diffie-Hellman keys as defined in RSA
* Laboratories' PKCS #3.
*
* <P>Note that these interfaces are intended only for key
* implementations whose key material is accessible and
* available. These interfaces are not intended for key implementations
* whose key material resides in inaccessible, protected storage (such
* as in a hardware device).
*
* <P>For more developer information on how to use these interfaces,
* including information on how to design <code>Key</code> classes for
* hardware devices, please refer to the cryptographic provider
* developer guide:
*
* <ul>
* <li> {@extLink security_guide_impl_provider
* How to Implement a Provider in the Java Cryptography Architecture}</li>
* </ul>
*
* <h2>Package Specification</h2>
*
* <ul>
* <li>PKCS #3: Diffie-Hellman Key-Agreement Standard, Version 1.4,
* November 1993.</li>
* </ul>
*
* <h2>Related Documentation</h2>
*
* For further documentation, please see:
* <ul>
* <li>
* {@extLink security_guide_jca
* Java Cryptography Architecture (JCA) Reference Guide}</li>
* </ul>
*
* @since 1.4
*/
package javax.crypto.interfaces;

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Provides the classes and interfaces for cryptographic
* operations. The cryptographic operations defined in this package
* include encryption, key generation and key agreement, and Message
* Authentication Code (MAC) generation.
*
* <p>Support for encryption includes symmetric, asymmetric, block,
* and stream ciphers. This package also supports secure streams and
* sealed objects.
*
* <p>Many of the classes provided in this package are provider-based.
* The class itself defines a programming interface to which
* applications may write. The implementations themselves may then be
* written by independent third-party vendors and plugged in
* seamlessly as needed. Therefore application developers may take
* advantage of any number of provider-based implementations without
* having to add or rewrite code.
*
* <ul>
* <li><a href="{@docRoot}/../specs/security/standard-names.html">
* <b>Java Security Standard Algorithm Names Specification
* </b></a></li>
* </ul>
*
* <h2>Related Documentation</h2>
*
* For further documentation, please see:
* <ul>
* <li>
* {@extLink security_guide_jca
* Java Cryptography Architecture (JCA) Reference Guide}</li>
* <li>
* {@extLink security_guide_impl_provider
* How to Implement a Provider in the Java Cryptography Architecture}</li>
* </ul>
*
* @since 1.4
*/
package javax.crypto;

View file

@ -0,0 +1,240 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.security.InvalidKeyException;
/**
* This class specifies a DES key.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class DESKeySpec implements java.security.spec.KeySpec {
/**
* The constant which defines the length of a DES key in bytes.
*/
public static final int DES_KEY_LEN = 8;
private byte[] key;
/*
* Weak/semi-weak keys copied from FIPS 74.
*
* "...The first 6 keys have duals different than themselves, hence
* each is both a key and a dual giving 12 keys with duals. The last
* four keys equal their duals, and are called self-dual keys..."
*
* 1. E001E001F101F101 01E001E001F101F1
* 2. FE1FFE1FFEOEFEOE 1FFE1FFEOEFEOEFE
* 3. E01FE01FF10EF10E 1FE01FEOOEF10EF1
* 4. 01FE01FE01FE01FE FE01FE01FE01FE01
* 5. 011F011F010E010E 1F011F010E010E01
* 6. E0FEE0FEF1FEF1FE FEE0FEE0FEF1FEF1
* 7. 0101010101010101 0101010101010101
* 8. FEFEFEFEFEFEFEFE FEFEFEFEFEFEFEFE
* 9. E0E0E0E0F1F1F1F1 E0E0E0E0F1F1F1F1
* 10. 1F1F1F1F0E0E0E0E 1F1F1F1F0E0E0E0E
*/
private static final byte[][] WEAK_KEYS = {
{ (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,
(byte)0x01, (byte)0x01, (byte)0x01 },
{ (byte)0xFE, (byte)0xFE, (byte)0xFE, (byte)0xFE, (byte)0xFE,
(byte)0xFE, (byte)0xFE, (byte)0xFE },
{ (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)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 }
};
/**
* Creates a DESKeySpec object using 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. The first 8 bytes
* of the buffer are copied to protect against subsequent modification.
*
* @exception NullPointerException if the given key material is
* <code>null</code>
* @exception InvalidKeyException if the given key material is shorter
* than 8 bytes.
*/
public DESKeySpec(byte[] key) throws InvalidKeyException {
this(key, 0);
}
/**
* Creates a DESKeySpec object using 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. The first 8 bytes
* of the buffer beginning at <code>offset</code> inclusive are copied
* to protect against subsequent modification.
* @param offset the offset in <code>key</code>, where the DES key
* material starts.
*
* @exception NullPointerException if the given key material is
* <code>null</code>
* @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("Wrong key size");
}
this.key = new byte[DES_KEY_LEN];
System.arraycopy(key, offset, this.key, 0, DES_KEY_LEN);
}
/**
* Returns the DES key material.
*
* @return the DES key material. Returns a new array
* each time this method is called.
*/
public byte[] getKey() {
return this.key.clone();
}
/**
* 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.
*
* @return true if the given DES key material is parity-adjusted, false
* otherwise.
*
* @exception InvalidKeyException if the given key material is
* <code>null</code>, or starting at <code>offset</code> inclusive, is
* shorter than 8 bytes.
*/
public static boolean isParityAdjusted(byte[] key, int offset)
throws InvalidKeyException {
if (key == null) {
throw new InvalidKeyException("null key");
}
if (key.length - offset < DES_KEY_LEN) {
throw new InvalidKeyException("Wrong key size");
}
for (int i = 0; i < DES_KEY_LEN; i++) {
int k = Integer.bitCount(key[offset++] & 0xff);
if ((k & 1) == 0) {
return false;
}
}
return true;
}
/**
* 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 is
* <code>null</code>, or starting at <code>offset</code> inclusive, is
* shorter than 8 bytes.
*/
public static boolean isWeak(byte[] key, int offset)
throws InvalidKeyException {
if (key == null) {
throw new InvalidKeyException("null key");
}
if (key.length - offset < DES_KEY_LEN) {
throw new InvalidKeyException("Wrong key size");
}
for (int i = 0; i < WEAK_KEYS.length; i++) {
boolean found = true;
for (int j = 0; j < DES_KEY_LEN && found == true; j++) {
if (WEAK_KEYS[i][j] != key[j+offset]) {
found = false;
}
}
if (found == true) {
return found;
}
}
return false;
}
}

View file

@ -0,0 +1,126 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.security.InvalidKeyException;
/**
* This class specifies a DES-EDE ("triple-DES") key.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class DESedeKeySpec implements java.security.spec.KeySpec {
/**
* The constant which defines the length of a DESede key in bytes.
*/
public static final int DES_EDE_KEY_LEN = 24;
private byte[] key;
/**
* Creates a DESedeKeySpec object using the first 24 bytes in
* <code>key</code> as the key material for 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. The first
* 24 bytes of the buffer are copied to protect against subsequent
* modification.
*
* @exception NullPointerException if <code>key</code> is null.
* @exception InvalidKeyException if the given key material is shorter
* than 24 bytes.
*/
public DESedeKeySpec(byte[] key) throws InvalidKeyException {
this(key, 0);
}
/**
* Creates a DESedeKeySpec object using the first 24 bytes in
* <code>key</code>, beginning at <code>offset</code> inclusive,
* as the key material for 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. The first
* 24 bytes of the buffer beginning at <code>offset</code> inclusive
* are copied to protect against subsequent modification.
* @param offset the offset in <code>key</code>, where the DES-EDE key
* material starts.
*
* @exception NullPointerException if <code>key</code> is null.
* @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 < 24) {
throw new InvalidKeyException("Wrong key size");
}
this.key = new byte[24];
System.arraycopy(key, offset, this.key, 0, 24);
}
/**
* Returns the DES-EDE key.
*
* @return the DES-EDE key. Returns a new array
* each time this method is called.
*/
public byte[] getKey() {
return this.key.clone();
}
/**
* Checks if the given DES-EDE key, starting at <code>offset</code>
* inclusive, is parity-adjusted.
*
* @param key a byte array which holds the key value
* @param offset the offset into the byte array
* @return true if the given DES-EDE key is parity-adjusted, false
* otherwise
*
* @exception NullPointerException if <code>key</code> is null.
* @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 < 24) {
throw new InvalidKeyException("Wrong key size");
}
if (DESKeySpec.isParityAdjusted(key, offset) == false
|| DESKeySpec.isParityAdjusted(key, offset + 8) == false
|| DESKeySpec.isParityAdjusted(key, offset + 16) == false) {
return false;
}
return true;
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.math.BigInteger;
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.
*
* @author Jan Luehe
*
* @see DHParameterSpec
* @since 1.4
*/
public class DHGenParameterSpec implements AlgorithmParameterSpec {
// The size in bits of the prime modulus
private int primeSize;
// The size in bits of the random exponent (private value)
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
* {@link java.security.AlgorithmParameterGenerator AlgorithmParameterGenerator}
* 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 this.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 this.exponentSize;
}
}

View file

@ -0,0 +1,123 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
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.
*
* <p>Note that this class does not perform any validation on specified
* parameters. Thus, the specified values are returned directly even
* if they are null.
*
* @author Jan Luehe
*
* @see javax.crypto.KeyAgreement
* @since 1.4
*/
public class DHParameterSpec implements AlgorithmParameterSpec {
// The prime modulus
private BigInteger p;
// The base generator
private BigInteger g;
// The size in bits of the random exponent (private value) (optional)
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;
this.l = 0;
}
/**
* 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 this.p;
}
/**
* Returns the base generator <code>g</code>.
*
* @return the base generator <code>g</code>
*/
public BigInteger getG() {
return this.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 this.l;
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.math.BigInteger;
/**
* This class specifies a Diffie-Hellman private key with its associated
* parameters.
*
* <p>Note that this class does not perform any validation on specified
* parameters. Thus, the specified values are returned directly even
* if they are null.
*
* @author Jan Luehe
*
* @see DHPublicKeySpec
* @since 1.4
*/
public class DHPrivateKeySpec implements java.security.spec.KeySpec {
// The private value
private BigInteger x;
// The prime modulus
private BigInteger p;
// The base generator
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>.
* @param x private value x
* @param p prime modulus p
* @param g base generator g
*/
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 this.x;
}
/**
* Returns the prime modulus <code>p</code>.
*
* @return the prime modulus <code>p</code>
*/
public BigInteger getP() {
return this.p;
}
/**
* Returns the base generator <code>g</code>.
*
* @return the base generator <code>g</code>
*/
public BigInteger getG() {
return this.g;
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.math.BigInteger;
/**
* This class specifies a Diffie-Hellman public key with its associated
* parameters.
*
* <p>Note that this class does not perform any validation on specified
* parameters. Thus, the specified values are returned directly even
* if they are null.
*
* @author Jan Luehe
*
* @see DHPrivateKeySpec
* @since 1.4
*/
public class DHPublicKeySpec implements java.security.spec.KeySpec {
// The public value
private BigInteger y;
// The prime modulus
private BigInteger p;
// The base generator
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>.
* @param y public value y
* @param p prime modulus p
* @param g base generator g
*/
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 this.y;
}
/**
* Returns the prime modulus <code>p</code>.
*
* @return the prime modulus <code>p</code>
*/
public BigInteger getP() {
return this.p;
}
/**
* Returns the base generator <code>g</code>.
*
* @return the base generator <code>g</code>
*/
public BigInteger getG() {
return this.g;
}
}

View file

@ -0,0 +1,149 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.security.spec.AlgorithmParameterSpec;
/**
* Specifies the set of parameters required by a {@link
* javax.crypto.Cipher} using the Galois/Counter Mode (GCM) mode.
* <p>
* Simple block cipher modes (such as CBC) generally require only an
* initialization vector (such as {@code IvParameterSpec}),
* but GCM needs these parameters:
* <ul>
* <li>{@code IV}: Initialization Vector (IV) </li>
* <li>{@code tLen}: length (in bits) of authentication tag T</li>
* </ul>
* <p>
* In addition to the parameters described here, other GCM inputs/output
* (Additional Authenticated Data (AAD), Keys, block ciphers,
* plain/ciphertext and authentication tags) are handled in the {@code
* Cipher} class.
* <p>
* Please see <a href="http://www.ietf.org/rfc/rfc5116.txt"> RFC 5116
* </a> for more information on the Authenticated Encryption with
* Associated Data (AEAD) algorithm, and <a href=
* "http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf">
* NIST Special Publication 800-38D</a>, "NIST Recommendation for Block
* Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC."
* <p>
* The GCM specification states that {@code tLen} may only have the
* values {128, 120, 112, 104, 96}, or {64, 32} for certain
* applications. Other values can be specified for this class, but not
* all CSP implementations will support them.
*
* @see javax.crypto.Cipher
*
* @since 1.7
*/
public class GCMParameterSpec implements AlgorithmParameterSpec {
// Initialization Vector. Could use IvParameterSpec, but that
// would add extra copies.
private byte[] iv;
// Required Tag length (in bits).
private int tLen;
/**
* Constructs a GCMParameterSpec using the specified authentication
* tag bit-length and IV buffer.
*
* @param tLen the authentication tag length (in bits)
* @param src the IV source buffer. The contents of the buffer are
* copied to protect against subsequent modification.
*
* @throws IllegalArgumentException if {@code tLen} is negative,
* or {@code src} is null.
*/
public GCMParameterSpec(int tLen, byte[] src) {
if (src == null) {
throw new IllegalArgumentException("src array is null");
}
init(tLen, src, 0, src.length);
}
/**
* Constructs a GCMParameterSpec object using the specified
* authentication tag bit-length and a subset of the specified
* buffer as the IV.
*
* @param tLen the authentication tag length (in bits)
* @param src the IV source buffer. The contents of the
* buffer are copied to protect against subsequent modification.
* @param offset the offset in {@code src} where the IV starts
* @param len the number of IV bytes
*
* @throws IllegalArgumentException if {@code tLen} is negative,
* {@code src} is null, {@code len} or {@code offset} is negative,
* or the sum of {@code offset} and {@code len} is greater than the
* length of the {@code src} byte array.
*/
public GCMParameterSpec(int tLen, byte[] src, int offset, int len) {
init(tLen, src, offset, len);
}
/*
* Check input parameters.
*/
private void init(int tLen, byte[] src, int offset, int len) {
if (tLen < 0) {
throw new IllegalArgumentException(
"Length argument is negative");
}
this.tLen = tLen;
// Input sanity check
if ((src == null) ||(len < 0) || (offset < 0)
|| ((len + offset) > src.length)) {
throw new IllegalArgumentException("Invalid buffer arguments");
}
iv = new byte[len];
System.arraycopy(src, offset, iv, 0, len);
}
/**
* Returns the authentication tag length.
*
* @return the authentication tag length (in bits)
*/
public int getTLen() {
return tLen;
}
/**
* Returns the Initialization Vector (IV).
*
* @return the IV. Creates a new array each time this method
* is called.
*/
public byte[] getIV() {
return iv.clone();
}
}

View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class specifies an <i>initialization vector</i> (IV).
* Examples which use IVs are ciphers in feedback mode,
* e.g., DES in CBC mode and RSA ciphers with OAEP encoding
* operation.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class IvParameterSpec implements AlgorithmParameterSpec {
private byte[] iv;
/**
* Creates an IvParameterSpec object using the bytes in <code>iv</code>
* as the IV.
*
* @param iv the buffer with the IV. The contents of the
* buffer are copied to protect against subsequent modification.
* @throws NullPointerException if <code>iv</code> is <code>null</code>
*/
public IvParameterSpec(byte[] iv) {
this(iv, 0, iv.length);
}
/**
* Creates an IvParameterSpec object using 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. The first <code>len</code>
* bytes of the buffer beginning at <code>offset</code> inclusive
* are copied to protect against subsequent modification.
* @param offset the offset in <code>iv</code> where the IV
* starts.
* @param len the number of IV bytes.
* @throws IllegalArgumentException if <code>iv</code> is <code>null</code>
* or {@code (iv.length - offset < len)}
* @throws ArrayIndexOutOfBoundsException is thrown if <code>offset</code>
* or <code>len</code> index bytes outside the <code>iv</code>.
*/
public IvParameterSpec(byte[] iv, int offset, int len) {
if (iv == null) {
throw new IllegalArgumentException("IV missing");
}
if (iv.length - offset < len) {
throw new IllegalArgumentException
("IV buffer too short for given offset/length combination");
}
if (len < 0) {
throw new ArrayIndexOutOfBoundsException("len is negative");
}
this.iv = new byte[len];
System.arraycopy(iv, offset, this.iv, 0, len);
}
/**
* Returns the initialization vector (IV).
*
* @return the initialization vector (IV). Returns a new array
* each time this method is called.
*/
public byte[] getIV() {
return this.iv.clone();
}
}

View file

@ -0,0 +1,168 @@
/*
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.math.BigInteger;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.MGF1ParameterSpec;
/**
* This class specifies the set of parameters used with OAEP Padding,
* as defined in the
* <a href="http://www.ietf.org/rfc/rfc3447.txt">PKCS #1</a>
* 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>
* <p>Note: the OAEPParameterSpec.DEFAULT uses the following:
* message digest -- "SHA-1"
* mask generation function (mgf) -- "MGF1"
* parameters for mgf -- MGF1ParameterSpec.SHA1
* source of encoding input -- PSource.PSpecified.DEFAULT
*
* @see java.security.spec.MGF1ParameterSpec
* @see PSource
*
* @author Valerie Peng
*
* @since 1.5
*/
public class OAEPParameterSpec implements AlgorithmParameterSpec {
private String mdName = "SHA-1";
private String mgfName = "MGF1";
private AlgorithmParameterSpec mgfSpec = MGF1ParameterSpec.SHA1;
private PSource pSrc = PSource.PSpecified.DEFAULT;
/**
* The OAEP parameter set with all default values.
*/
public static final OAEPParameterSpec DEFAULT = new OAEPParameterSpec();
/**
* Constructs a parameter set for OAEP padding as defined in
* the PKCS #1 standard using the default values.
*/
private OAEPParameterSpec() {
}
/**
* Constructs a parameter set for OAEP padding as defined in
* the PKCS #1 standard using the specified message digest
* algorithm <code>mdName</code>, mask generation function
* algorithm <code>mgfName</code>, parameters for the mask
* generation function <code>mgfSpec</code>, and source of
* the encoding input P <code>pSrc</code>.
*
* @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.
* @exception NullPointerException if <code>mdName</code>,
* <code>mgfName</code>, or <code>pSrc</code> is null.
*/
public OAEPParameterSpec(String mdName, String mgfName,
AlgorithmParameterSpec mgfSpec,
PSource pSrc) {
if (mdName == null) {
throw new NullPointerException("digest algorithm is null");
}
if (mgfName == null) {
throw new NullPointerException("mask generation function " +
"algorithm is null");
}
if (pSrc == null) {
throw new NullPointerException("source of the encoding input " +
"is null");
}
this.mdName = mdName;
this.mgfName = mgfName;
this.mgfSpec = mgfSpec;
this.pSrc = pSrc;
}
/**
* Returns the message digest algorithm name.
*
* @return the message digest algorithm name.
*/
public String getDigestAlgorithm() {
return mdName;
}
/**
* Returns the mask generation function algorithm name.
*
* @return the mask generation function algorithm name.
*/
public String getMGFAlgorithm() {
return mgfName;
}
/**
* Returns the parameters for the mask generation function.
*
* @return the parameters for the mask generation function.
*/
public AlgorithmParameterSpec getMGFParameters() {
return mgfSpec;
}
/**
* Returns the source of encoding input P.
*
* @return the source of encoding input P.
*/
public PSource getPSource() {
return pSrc;
}
}

View file

@ -0,0 +1,240 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.security.spec.KeySpec;
/**
* A user-chosen password that can be used with password-based encryption
* (<i>PBE</i>).
*
* <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
* <a href="http://www.ietf.org/rfc/rfc2898.txt">
* PKCS #5</a> 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
* <code>String</code> 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.
*
* @author Jan Luehe
* @author Valerie Peng
*
* @see javax.crypto.SecretKeyFactory
* @see PBEParameterSpec
* @since 1.4
*/
public class PBEKeySpec implements KeySpec {
private char[] password;
private byte[] salt = null;
private int iterationCount = 0;
private int keyLength = 0;
/**
* Constructor that takes a password. An empty char[] is used if
* null is specified.
*
* <p> Note: <code>password</code> is cloned before it is stored in
* the new <code>PBEKeySpec</code> object.
*
* @param password the password.
*/
public PBEKeySpec(char[] password) {
if ((password == null) || (password.length == 0)) {
this.password = new char[0];
} else {
this.password = password.clone();
}
}
/**
* 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
* <code>password</code>.
*
* <p> Note: the <code>password</code> and <code>salt</code>
* are cloned before they are stored in
* the new <code>PBEKeySpec</code> object.
*
* @param password the password.
* @param salt the salt.
* @param iterationCount the iteration count.
* @param keyLength the to-be-derived key length.
* @exception NullPointerException if <code>salt</code> is null.
* @exception IllegalArgumentException if <code>salt</code> is empty,
* i.e. 0-length, <code>iterationCount</code> or
* <code>keyLength</code> is not positive.
*/
public PBEKeySpec(char[] password, byte[] salt, int iterationCount,
int keyLength) {
if ((password == null) || (password.length == 0)) {
this.password = new char[0];
} else {
this.password = password.clone();
}
if (salt == null) {
throw new NullPointerException("the salt parameter " +
"must be non-null");
} else if (salt.length == 0) {
throw new IllegalArgumentException("the salt parameter " +
"must not be empty");
} else {
this.salt = salt.clone();
}
if (iterationCount<=0) {
throw new IllegalArgumentException("invalid iterationCount value");
}
if (keyLength<=0) {
throw new IllegalArgumentException("invalid keyLength value");
}
this.iterationCount = iterationCount;
this.keyLength = keyLength;
}
/**
* 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 <code>password</code>.
*
* <p> Note: the <code>password</code> and <code>salt</code>
* are cloned before they are stored in the new
* <code>PBEKeySpec</code> object.
*
* @param password the password.
* @param salt the salt.
* @param iterationCount the iteration count.
* @exception NullPointerException if <code>salt</code> is null.
* @exception IllegalArgumentException if <code>salt</code> is empty,
* i.e. 0-length, or <code>iterationCount</code> is not positive.
*/
public PBEKeySpec(char[] password, byte[] salt, int iterationCount) {
if ((password == null) || (password.length == 0)) {
this.password = new char[0];
} else {
this.password = password.clone();
}
if (salt == null) {
throw new NullPointerException("the salt parameter " +
"must be non-null");
} else if (salt.length == 0) {
throw new IllegalArgumentException("the salt parameter " +
"must not be empty");
} else {
this.salt = salt.clone();
}
if (iterationCount<=0) {
throw new IllegalArgumentException("invalid iterationCount value");
}
this.iterationCount = iterationCount;
}
/**
* Clears the internal copy of the password.
*
*/
public final void clearPassword() {
if (password != null) {
for (int i = 0; i < password.length; i++) {
password[i] = ' ';
}
password = null;
}
}
/**
* 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.
*
* @exception IllegalStateException if password has been cleared by
* calling <code>clearPassword</code> method.
* @return the password.
*/
public final char[] getPassword() {
if (password == null) {
throw new IllegalStateException("password has been cleared");
}
return password.clone();
}
/**
* Returns a copy of the salt or null if not specified.
*
* <p> 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) {
return salt.clone();
} else {
return null;
}
}
/**
* Returns the iteration count or 0 if not specified.
*
* @return the iteration count.
*/
public final int getIterationCount() {
return iterationCount;
}
/**
* Returns the to-be-derived key length or 0 if not specified.
*
* <p> Note: this is used to indicate the preference on key length
* for variable-key-size ciphers. The actual key size depends on
* each provider's implementation.
*
* @return the to-be-derived key length.
*/
public final int getKeyLength() {
return keyLength;
}
}

View file

@ -0,0 +1,109 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
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.ietf.org/rfc/rfc2898.txt">PKCS #5</a>
* standard.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class PBEParameterSpec implements AlgorithmParameterSpec {
private byte[] salt;
private int iterationCount;
private AlgorithmParameterSpec paramSpec = null;
/**
* Constructs a parameter set for password-based encryption as defined in
* the PKCS #5 standard.
*
* @param salt the salt. The contents of <code>salt</code> are copied
* to protect against subsequent modification.
* @param iterationCount the iteration count.
* @exception NullPointerException if <code>salt</code> is null.
*/
public PBEParameterSpec(byte[] salt, int iterationCount) {
this.salt = salt.clone();
this.iterationCount = iterationCount;
}
/**
* Constructs a parameter set for password-based encryption as defined in
* the PKCS #5 standard.
*
* @param salt the salt. The contents of <code>salt</code> are copied
* to protect against subsequent modification.
* @param iterationCount the iteration count.
* @param paramSpec the cipher algorithm parameter specification, which
* may be null.
* @exception NullPointerException if <code>salt</code> is null.
*
* @since 1.8
*/
public PBEParameterSpec(byte[] salt, int iterationCount,
AlgorithmParameterSpec paramSpec) {
this.salt = salt.clone();
this.iterationCount = iterationCount;
this.paramSpec = paramSpec;
}
/**
* Returns the salt.
*
* @return the salt. Returns a new array
* each time this method is called.
*/
public byte[] getSalt() {
return this.salt.clone();
}
/**
* Returns the iteration count.
*
* @return the iteration count
*/
public int getIterationCount() {
return this.iterationCount;
}
/**
* Returns the cipher algorithm parameter specification.
*
* @return the parameter specification, or null if none was set.
*
* @since 1.8
*/
public AlgorithmParameterSpec getParameterSpec() {
return this.paramSpec;
}
}

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
/**
* This class specifies the source for encoding input P in OAEP Padding,
* as defined in the
* <a href="http://www.ietf.org/rfc/rfc3447.txt">PKCS #1</a>
* standard.
* <pre>
* PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= {
* { OID id-pSpecified PARAMETERS OCTET STRING },
* ... -- Allows for future expansion --
* }
* </pre>
* @author Valerie Peng
*
* @since 1.5
*/
public class PSource {
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.
* @exception NullPointerException if <code>pSrcName</code>
* is null.
*/
protected PSource(String pSrcName) {
if (pSrcName == null) {
throw new NullPointerException("pSource algorithm is null");
}
this.pSrcName = pSrcName;
}
/**
* Returns the PSource algorithm name.
*
* @return the PSource algorithm name.
*/
public String getAlgorithm() {
return pSrcName;
}
/**
* This class is used to explicitly specify the value for
* encoding input P in OAEP Padding.
*
* @since 1.5
*/
public static final class PSpecified extends PSource {
private byte[] p = new byte[0];
/**
* 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 <code>p</code> as the encoding input P.
* Note:
* @param p the value of the encoding input. The contents
* of the array are copied to protect against subsequent
* modification.
* @exception NullPointerException if <code>p</code> is null.
*/
public PSpecified(byte[] p) {
super("PSpecified");
this.p = p.clone();
}
/**
* 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 (p.length==0? p: p.clone());
}
}
}

View file

@ -0,0 +1,160 @@
/*
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class specifies the parameters used with the
* <a href="http://www.ietf.org/rfc/rfc2268.txt"><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} object that
* implements the <i>RC2</i> algorithm.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class RC2ParameterSpec implements AlgorithmParameterSpec {
private byte[] iv = null;
private int effectiveKeyBits;
/**
* 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]} and {@code iv[7]} inclusive.
*
* @param effectiveKeyBits the effective key size in bits.
* @param iv the buffer with the 8-byte IV. The first 8 bytes of
* the buffer are copied to protect against subsequent modification.
* @exception IllegalArgumentException if {@code iv} is null.
*/
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}, starting at
* {@code offset} inclusive.
* The bytes that constitute the IV are those between
* {@code iv[offset]} and {@code iv[offset+7]} inclusive.
*
* @param effectiveKeyBits the effective key size in bits.
* @param iv the buffer with the IV. The first 8 bytes
* of the buffer beginning at {@code offset} inclusive
* are copied to protect against subsequent modification.
* @param offset the offset in {@code iv} where the 8-byte IV
* starts.
* @exception IllegalArgumentException if {@code iv} is null.
*/
public RC2ParameterSpec(int effectiveKeyBits, byte[] iv, int offset) {
this.effectiveKeyBits = effectiveKeyBits;
if (iv == null) throw new IllegalArgumentException("IV missing");
int blockSize = 8;
if (iv.length - offset < blockSize) {
throw new IllegalArgumentException("IV too short");
}
this.iv = new byte[blockSize];
System.arraycopy(iv, offset, this.iv, 0, blockSize);
}
/**
* Returns the effective key size in bits.
*
* @return the effective key size in bits.
*/
public int getEffectiveKeyBits() {
return this.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.
* Returns a new array each time this method is called.
*/
public byte[] getIV() {
return (iv == null? null:iv.clone());
}
/**
* 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 {@code null}.)
*
* @param obj the object to test for equality with this object.
*
* @return true if the objects are considered equal, false if
* {@code obj} is null or otherwise.
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof RC2ParameterSpec)) {
return false;
}
RC2ParameterSpec other = (RC2ParameterSpec) obj;
return ((effectiveKeyBits == other.effectiveKeyBits) &&
java.util.Arrays.equals(iv, other.iv));
}
/**
* Calculates a hash code value for the object.
* Objects that are equal will also have the same hashcode.
*/
public int hashCode() {
int retval = 0;
if (iv != null) {
for (int i = 1; i < iv.length; i++) {
retval += iv[i] * i;
}
}
return (retval += effectiveKeyBits);
}
}

View file

@ -0,0 +1,203 @@
/*
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.security.spec.AlgorithmParameterSpec;
/**
* This class specifies the parameters used with the
* <a href="http://tools.ietf.org/html/rfc2040"><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} object that
* implements the <i>RC5</i> algorithm as supplied by
* <a href="http://www.rsa.com">RSA Security LLC</a>,
* or any parties authorized by RSA Security.
*
* @author Jan Luehe
*
* @since 1.4
*/
public class RC5ParameterSpec implements AlgorithmParameterSpec {
private byte[] iv = null;
private int version;
private int rounds;
private int wordSize; // the word size in bits
/**
* 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;
}
/**
* 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]} and {@code iv[2*(wordSize/8)-1]} 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. The first {@code 2*(wordSize/8)}
* bytes of the buffer are copied to protect against subsequent
* modification.
* @exception IllegalArgumentException if {@code iv} is
* {@code null} or {@code (iv.length < 2 * (wordSize / 8))}
*/
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}, starting at
* {@code offset} inclusive.
* Note that the size of the IV (block size), starting at
* {@code offset} inclusive, must be twice the word size.
* The bytes that constitute the IV are those between
* {@code iv[offset]} and {@code iv[offset+2*(wordSize/8)-1]}
* 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. The first {@code 2*(wordSize/8)}
* bytes of the buffer beginning at {@code offset}
* inclusive are copied to protect against subsequent modification.
* @param offset the offset in {@code iv} where the IV starts.
* @exception IllegalArgumentException if {@code iv} is
* {@code null} or
* {@code (iv.length - offset < 2 * (wordSize / 8))}
*/
public RC5ParameterSpec(int version, int rounds, int wordSize,
byte[] iv, int offset) {
this.version = version;
this.rounds = rounds;
this.wordSize = wordSize;
if (iv == null) throw new IllegalArgumentException("IV missing");
int blockSize = (wordSize / 8) * 2;
if (iv.length - offset < blockSize) {
throw new IllegalArgumentException("IV too short");
}
this.iv = new byte[blockSize];
System.arraycopy(iv, offset, this.iv, 0, blockSize);
}
/**
* Returns the version.
*
* @return the version.
*/
public int getVersion() {
return this.version;
}
/**
* Returns the number of rounds.
*
* @return the number of rounds.
*/
public int getRounds() {
return this.rounds;
}
/**
* Returns the word size in bits.
*
* @return the word size in bits.
*/
public int getWordSize() {
return this.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.
* Returns a new array each time this method is called.
*/
public byte[] getIV() {
return (iv == null? null:iv.clone());
}
/**
* 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 {@code null}.)
*
* @param obj the object to test for equality with this object.
*
* @return true if the objects are considered equal, false if
* {@code obj} is null or otherwise.
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof RC5ParameterSpec)) {
return false;
}
RC5ParameterSpec other = (RC5ParameterSpec) obj;
return ((version == other.version) &&
(rounds == other.rounds) &&
(wordSize == other.wordSize) &&
java.util.Arrays.equals(iv, other.iv));
}
/**
* Calculates a hash code value for the object.
* Objects that are equal will also have the same hashcode.
*/
public int hashCode() {
int retval = 0;
if (iv != null) {
for (int i = 1; i < iv.length; i++) {
retval += iv[i] * i;
}
}
retval += (version + rounds + wordSize);
return retval;
}
}

View file

@ -0,0 +1,232 @@
/*
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.crypto.spec;
import java.security.MessageDigest;
import java.security.spec.KeySpec;
import java.util.Locale;
import javax.crypto.SecretKey;
/**
* 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.
*
* @author Jan Luehe
*
* @see javax.crypto.SecretKey
* @see javax.crypto.SecretKeyFactory
* @since 1.4
*/
public class SecretKeySpec implements KeySpec, SecretKey {
private static final long serialVersionUID = 6577238317307289933L;
/**
* The secret key.
*
* @serial
*/
private byte[] key;
/**
* The name of the algorithm associated with this key.
*
* @serial
*/
private String algorithm;
/**
* 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:
* {@link DESKeySpec DESKeySpec})
* should be used.
*
* @param key the key material of the secret key. The contents of
* the array are copied to protect against subsequent modification.
* @param algorithm the name of the secret-key algorithm to be associated
* with the given key material.
* See the <a href="{@docRoot}/../specs/security/standard-names.html">
* Java Security Standard Algorithm Names</a> document
* for information about standard algorithm names.
* @exception IllegalArgumentException if <code>algorithm</code>
* is null or <code>key</code> is null or empty.
*/
public SecretKeySpec(byte[] key, String algorithm) {
if (key == null || algorithm == null) {
throw new IllegalArgumentException("Missing argument");
}
if (key.length == 0) {
throw new IllegalArgumentException("Empty key");
}
this.key = key.clone();
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:
* {@link DESKeySpec DESKeySpec})
* must be used.
*
* @param key the key material of the secret key. The first
* <code>len</code> bytes of the array beginning at
* <code>offset</code> inclusive are copied to protect
* against subsequent modification.
* @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 the <a href="{@docRoot}/../specs/security/standard-names.html">
* Java Security Standard Algorithm Names</a> document
* for information about standard algorithm names.
* @exception IllegalArgumentException if <code>algorithm</code>
* is null or <code>key</code> is null, empty, or too short,
* i.e. {@code key.length-offset<len}.
* @exception ArrayIndexOutOfBoundsException is thrown if
* <code>offset</code> or <code>len</code> index bytes outside the
* <code>key</code>.
*/
public SecretKeySpec(byte[] key, int offset, int len, String algorithm) {
if (key == null || algorithm == null) {
throw new IllegalArgumentException("Missing argument");
}
if (key.length == 0) {
throw new IllegalArgumentException("Empty key");
}
if (key.length-offset < len) {
throw new IllegalArgumentException
("Invalid offset/length combination");
}
if (len < 0) {
throw new ArrayIndexOutOfBoundsException("len is negative");
}
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 this.algorithm;
}
/**
* Returns the name of the encoding format for this secret key.
*
* @return the string "RAW".
*/
public String getFormat() {
return "RAW";
}
/**
* Returns the key material of this secret key.
*
* @return the key material. Returns a new array
* each time this method is called.
*/
public byte[] getEncoded() {
return this.key.clone();
}
/**
* Calculates a hash code value for the object.
* Objects that are equal will also have the same hashcode.
*/
public int hashCode() {
int retval = 0;
for (int i = 1; i < this.key.length; i++) {
retval += this.key[i] * i;
}
if (this.algorithm.equalsIgnoreCase("TripleDES"))
return (retval ^= "desede".hashCode());
else
return (retval ^=
this.algorithm.toLowerCase(Locale.ENGLISH).hashCode());
}
/**
* Tests for equality between the specified object and this
* object. Two SecretKeySpec objects are considered equal if
* they are both SecretKey instances which have the
* same case-insensitive algorithm name and key encoding.
*
* @param obj the object to test for equality with this object.
*
* @return true if the objects are considered equal, false if
* <code>obj</code> is null or otherwise.
*/
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof SecretKey))
return false;
String thatAlg = ((SecretKey)obj).getAlgorithm();
if (!(thatAlg.equalsIgnoreCase(this.algorithm))) {
if ((!(thatAlg.equalsIgnoreCase("DESede"))
|| !(this.algorithm.equalsIgnoreCase("TripleDES")))
&& (!(thatAlg.equalsIgnoreCase("TripleDES"))
|| !(this.algorithm.equalsIgnoreCase("DESede"))))
return false;
}
byte[] thatKey = ((SecretKey)obj).getEncoded();
return MessageDigest.isEqual(this.key, thatKey);
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Provides classes and interfaces for key specifications and
* algorithm parameter specifications.
*
* <p>A key specification is a transparent representation of the key
* material that constitutes a key. A key may be specified in an
* algorithm-specific way, or in an algorithm-independent encoding
* format (such as ASN.1). This package contains key specifications
* for Diffie-Hellman public and private keys, as well as key
* specifications for DES, Triple DES, and PBE secret keys.
*
* <p>An algorithm parameter specification is a transparent
* representation of the sets of parameters used with an
* algorithm. This package contains algorithm parameter specifications
* for parameters used with the Diffie-Hellman, DES, Triple DES, PBE,
* RC2 and RC5 algorithms.
*
*
* <ul>
* <li>PKCS #3: Diffie-Hellman Key-Agreement Standard, Version 1.4,
* November 1993.</li>
* <li>PKCS #5: Password-Based Encryption Standard, Version 1.5,
* November 1993.</li>
* <li>Federal Information Processing Standards Publication (FIPS PUB) 46-2:
* Data Encryption Standard (DES) </li>
* </ul>
*
* <h2>Related Documentation</h2>
*
* For documentation that includes information about algorithm
* parameter and key specifications, please see:
*
* <ul>
* <li>
* {@extLink security_guide_jca
* Java Cryptography Architecture (JCA) Reference Guide} </li>
* <li>
* {@extLink security_guide_impl_provider
* How to Implement a Provider in the Java Cryptography Architecture}</li>
* </ul>
*
* @since 1.4
*/
package javax.crypto.spec;