From 0b85fb3e6530e91e62c332e987c3283f50a3e2b1 Mon Sep 17 00:00:00 2001
From: david_page <david_page@localhost>
Date: Sun, 14 Oct 2007 01:32:43 +0000
Subject: [PATCH] No issue. CryptoManager Step 3. Factor interface from CryptoManager implementation.
---
opends/src/server/org/opends/server/crypto/CryptoManagerImpl.java | 1697 ++++++++++++++++++++++++----------------------------------
1 files changed, 703 insertions(+), 994 deletions(-)
diff --git a/opends/src/server/org/opends/server/crypto/CryptoManager.java b/opends/src/server/org/opends/server/crypto/CryptoManagerImpl.java
similarity index 88%
rename from opends/src/server/org/opends/server/crypto/CryptoManager.java
rename to opends/src/server/org/opends/server/crypto/CryptoManagerImpl.java
index 8ec0244..d1a7a3c 100644
--- a/opends/src/server/org/opends/server/crypto/CryptoManager.java
+++ b/opends/src/server/org/opends/server/crypto/CryptoManagerImpl.java
@@ -103,19 +103,15 @@
are a lot of similarities and it is conceivable at some point that
accelerated compression may be available just as it is for
cryptographic operations.
-
+ <p>
+ Other components of CryptoManager:
@see "src/admin/defn/org/opends/server/admin/std\
/CryptoManagerConfiguration.xml"
@see org.opends.server.crypto.CryptoManagerSync
@see org.opends.server.crypto.GetSymmetricKeyExtendedOperation
*/
-@org.opends.server.types.PublicAPI(
- stability=org.opends.server.types.StabilityLevel.VOLATILE,
- mayInstantiate=false,
- mayExtend=false,
- mayInvoke=true)
-public class CryptoManager
- implements ConfigurationChangeListener<CryptoManagerCfg>
+public class CryptoManagerImpl
+ implements ConfigurationChangeListener<CryptoManagerCfg>, CryptoManager
{
/**
* The tracer object for the debug logger.
@@ -131,7 +127,7 @@
private static AttributeType attrInitVectorLength;
private static AttributeType attrKeyLength;
private static AttributeType attrCompromisedTime;
- private static ObjectClass ocCertRequest;
+ private static ObjectClass ocCertRequest;
private static ObjectClass ocInstanceKey;
private static ObjectClass ocCipherKey;
private static ObjectClass ocMacKey;
@@ -215,7 +211,7 @@
occurs while creating this {@code CryptoManager} that is not the result of a
problem in the configuration.
*/
- public CryptoManager(CryptoManagerCfg cfg)
+ public CryptoManagerImpl(CryptoManagerCfg cfg)
throws ConfigException, InitializationException {
if (!schemaInitDone) {
// Initialize various schema references.
@@ -464,6 +460,35 @@
/**
+ * Retrieve the ADS trust store backend.
+ * @return The ADS trust store backend.
+ * @throws ConfigException If the ADS trust store backend is
+ * not configured.
+ */
+ private TrustStoreBackend getTrustStoreBackend()
+ throws ConfigException
+ {
+ Backend b = DirectoryServer.getBackend(
+ ConfigConstants.ID_ADS_TRUST_STORE_BACKEND);
+ if (b == null)
+ {
+ Message msg =
+ ERR_CRYPTOMGR_ADS_TRUST_STORE_BACKEND_NOT_ENABLED.get(
+ ConfigConstants.ID_ADS_TRUST_STORE_BACKEND);
+ throw new ConfigException(msg);
+ }
+ if (!(b instanceof TrustStoreBackend))
+ {
+ Message msg =
+ ERR_CRYPTOMGR_ADS_TRUST_STORE_BACKEND_WRONG_CLASS.get(
+ ConfigConstants.ID_ADS_TRUST_STORE_BACKEND);
+ throw new ConfigException(msg);
+ }
+ return (TrustStoreBackend)b;
+ }
+
+
+ /**
* Returns this instance's instance-key public-key certificate from
* the local keystore (i.e., from the truststore-backend and not
* from the ADS backed keystore). If the certificate entry does not
@@ -1014,878 +1039,120 @@
/**
- * Retrieves the name of the preferred message digest algorithm.
+ * Given a set of other servers' symmetric key values for
+ * a given secret key, use the Get Symmetric Key extended
+ * operation to request this server's symmetric key value.
*
- * @return The name of the preferred message digest algorithm
+ * @param symmetricKeys The known symmetric key values for
+ * a given secret key.
+ *
+ * @return The symmetric key value for this server, or null if
+ * none could be obtained.
*/
- public String getPreferredMessageDigestAlgorithm()
+ private String getSymmetricKey(List<String> symmetricKeys)
{
- return preferredDigestAlgorithm;
- }
-
-
- /**
- * Retrieves a <CODE>MessageDigest</CODE> object that may be used to
- * generate digests using the preferred digest algorithm.
- *
- * @return A <CODE>MessageDigest</CODE> object that may be used to
- * generate digests using the preferred digest algorithm.
- *
- * @throws NoSuchAlgorithmException If the requested algorithm is
- * not supported or is
- * unavailable.
- */
- public MessageDigest getPreferredMessageDigest()
- throws NoSuchAlgorithmException
- {
- return MessageDigest.getInstance(preferredDigestAlgorithm);
- }
-
-
-
- /**
- * Retrieves a <CODE>MessageDigest</CODE> object that may be used to
- * generate digests using the specified algorithm.
- *
- * @param digestAlgorithm The algorithm to use to generate the
- * message digest.
- *
- * @return A <CODE>MessageDigest</CODE> object that may be used to
- * generate digests using the specified algorithm.
- *
- * @throws NoSuchAlgorithmException If the requested algorithm is
- * not supported or is
- * unavailable.
- */
- public MessageDigest getMessageDigest(String digestAlgorithm)
- throws NoSuchAlgorithmException
- {
- return MessageDigest.getInstance(digestAlgorithm);
- }
-
-
-
- /**
- * Retrieves a byte array containing a message digest based on the
- * provided data, using the preferred digest algorithm.
- *
- * @param data The data to be digested.
- *
- * @return A byte array containing the generated message digest.
- *
- * @throws NoSuchAlgorithmException If the requested algorithm is
- * not supported or is
- * unavailable.
- */
- public byte[] digest(byte[] data)
- throws NoSuchAlgorithmException
- {
- return MessageDigest.getInstance(preferredDigestAlgorithm).
- digest(data);
- }
-
-
-
- /**
- * Retrieves a byte array containing a message digest based on the
- * provided data, using the requested digest algorithm.
- *
- * @param digestAlgorithm The algorithm to use to generate the
- * message digest.
- * @param data The data to be digested.
- *
- * @return A byte array containing the generated message digest.
- *
- * @throws NoSuchAlgorithmException If the requested algorithm is
- * not supported or is
- * unavailable.
- */
- public byte[] digest(String digestAlgorithm, byte[] data)
- throws NoSuchAlgorithmException
- {
- return MessageDigest.getInstance(digestAlgorithm).digest(data);
- }
-
-
-
- /**
- * Retrieves a byte array containing a message digest based on the
- * data read from the provided input stream, using the preferred
- * digest algorithm. Data will be read until the end of the stream
- * is reached.
- *
- * @param inputStream The input stream from which the data is to
- * be read.
- *
- * @return A byte array containing the generated message digest.
- *
- * @throws IOException If a problem occurs while reading data from
- * the provided stream.
- *
- * @throws NoSuchAlgorithmException If the requested algorithm is
- * not supported or is
- * unavailable.
- */
- public byte[] digest(InputStream inputStream)
- throws IOException, NoSuchAlgorithmException
- {
- MessageDigest digest =
- MessageDigest.getInstance(preferredDigestAlgorithm);
-
- byte[] buffer = new byte[8192];
- while (true)
+ InternalClientConnection internalConnection =
+ InternalClientConnection.getRootConnection();
+ for (String symmetricKey : symmetricKeys)
{
- int bytesRead = inputStream.read(buffer);
- if (bytesRead < 0)
+ try
{
- break;
- }
+ // Get the server instance key ID from the symmetric key.
+ String[] elements = symmetricKey.split(":", 0);
+ String instanceKeyID = elements[0];
- digest.update(buffer, 0, bytesRead);
- }
+ // Find the server entry from the instance key ID.
+ String filter = "(" +
+ ConfigConstants.ATTR_CRYPTO_KEY_ID + "=" +
+ instanceKeyID + ")";
+ InternalSearchOperation internalSearch =
+ internalConnection.processSearch(
+ serversDN, SearchScope.SUBORDINATE_SUBTREE,
+ SearchFilter.createFilterFromString(filter));
+ if (internalSearch.getResultCode() != ResultCode.SUCCESS)
+ continue;
- return digest.digest();
- }
-
-
-
- /**
- * Retrieves a byte array containing a message digest based on the
- * data read from the provided input stream, using the requested
- * digest algorithm. Data will be read until the end of the stream
- * is reached.
- *
- * @param digestAlgorithm The algorithm to use to generate the
- * message digest.
- * @param inputStream The input stream from which the data is
- * to be read.
- *
- * @return A byte array containing the generated message digest.
- *
- * @throws IOException If a problem occurs while reading data from
- * the provided stream.
- *
- * @throws NoSuchAlgorithmException If the requested algorithm is
- * not supported or is
- * unavailable.
- */
- public byte[] digest(String digestAlgorithm,
- InputStream inputStream)
- throws IOException, NoSuchAlgorithmException
- {
- MessageDigest digest = MessageDigest.getInstance(digestAlgorithm);
-
- byte[] buffer = new byte[8192];
- while (true)
- {
- int bytesRead = inputStream.read(buffer);
- if (bytesRead < 0)
- {
- break;
- }
-
- digest.update(buffer, 0, bytesRead);
- }
-
- return digest.digest();
- }
-
-
-
- /**
- * For the current preferred MAC algorithm and key length, return
- * the identifier of the corresponding key entry. Note: the result
- * (key identifier) might change across invocations, due to either
- * of the perferred parameters changing, or because the original
- * key was marked compromised and a replacement key generated.
- *
- * @return A String representation of the identifier of a key entry
- * corresponding to the preferred MAC algorithm and key length.
- *
- * @throws CryptoManagerException In case one or more of the key
- * parameters is invalid, or there is a problem instantiating the
- * key entry in case it does not already exist.
- */
- public String getMacEngineKeyEntryID()
- throws CryptoManagerException
- {
- return getMacEngineKeyEntryID(preferredMACAlgorithm,
- preferredMACAlgorithmKeyLengthBits);
- }
-
-
- /**
- * For the specified MAC algorithm and key length, return
- * the identifier of the corresponding key entry. Note: the result
- * (key identifier) might change across invocations, due to either
- * of the perferred parameters changing, or because the original
- * key was marked compromised and a replacement key generated.
- *
- * @param macAlgorithm The algorithm to use for the MAC engine.
- *
- * @param keyLengthBits The key length in bits to use with the
- * specified algorithm.
- *
- * @return A String representation of the identifier of a key entry
- * corresponding to the specified MAC algorithm and key length.
- *
- * @throws CryptoManagerException In case one or more of the key
- * parameters is invalid, or there is a problem instantiating the
- * key entry in case it does not already exist.
- */
- public String getMacEngineKeyEntryID(final String macAlgorithm,
- final int keyLengthBits)
- throws CryptoManagerException {
- Validator.ensureNotNull(macAlgorithm);
-
- MacKeyEntry keyEntry = MacKeyEntry.getKeyEntry(this, macAlgorithm,
- keyLengthBits);
- if (null == keyEntry) {
- keyEntry = MacKeyEntry.generateKeyEntry(this, macAlgorithm,
- keyLengthBits);
- }
-
- return keyEntry.getKeyID().getStringValue();
- }
-
-
- /**
- * For the specified key entry identifier, instantiate a MAC engine.
- *
- * @param keyEntryID The identifier of the key entry containing the
- * desired MAC algorithm name and key length.
- *
- * @return The MAC engine instantiated with the parameters from the
- * referenced key entry, or null if no such entry exists.
- *
- * @throws CryptoManagerException In case the key entry identifier
- * is invalid or there is a problem instatiating the MAC engine from
- * the parameters in the referenced key entry.
- */
- public Mac getMacEngine(String keyEntryID)
- throws CryptoManagerException
- {
- final MacKeyEntry keyEntry = MacKeyEntry.getKeyEntry(this,
- new KeyEntryID(keyEntryID));
- return (null == keyEntry) ? null : getMacEngine(keyEntry);
- }
-
-
- /**
- * This method produces an initialized MAC engine based on the
- * supplied MacKeyEntry's state.
- *
- * @param keyEntry The MacKeyEntry specifying the Mac properties.
- *
- * @return An initialized Mac object.
- *
- * @throws CryptoManagerException In case there was a error
- * instantiating the Mac object.
- */
- private static Mac getMacEngine(MacKeyEntry keyEntry)
- throws CryptoManagerException
- {
- Mac mac;
- try {
- mac = Mac.getInstance(keyEntry.getType());
- }
- catch (NoSuchAlgorithmException ex){
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, ex);
- }
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_GET_MAC_ENGINE_INVALID_MAC_ALGORITHM.get(
- keyEntry.getType(), getExceptionMessage(ex)),
- ex);
- }
-
- try {
- mac.init(keyEntry.getSecretKey());
- }
- catch (InvalidKeyException ex) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, ex);
- }
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_GET_MAC_ENGINE_CANNOT_INITIALIZE.get(
- getExceptionMessage(ex)), ex);
- }
-
- return mac;
- }
-
-
- /**
- * This method produces an initialized Cipher based on the supplied
- * CipherKeyEntry's state.
- *
- * @param keyEntry The secret key entry containing the cipher
- * transformation and secret key for which to instantiate
- * the cipher.
- *
- * @param mode Either Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE.
- *
- * @param initializationVector For Cipher.DECRYPT_MODE, supply
- * any initialzation vector used in the corresponding encryption
- * cipher. May be null.
- *
- * @return The initialized cipher object.
- *
- * @throws CryptoManagerException In case of a problem creating
- * or initializing the requested cipher object. Possible causes
- * include NoSuchAlgorithmException, NoSuchPaddingException,
- * InvalidKeyException, and InvalidAlgorithmParameterException.
- */
- private static Cipher getCipher(final CipherKeyEntry keyEntry,
- final int mode,
- final byte[] initializationVector)
- throws CryptoManagerException {
- Validator.ensureTrue(Cipher.ENCRYPT_MODE == mode
- || Cipher.DECRYPT_MODE == mode);
- Validator.ensureTrue(Cipher.ENCRYPT_MODE != mode
- || null == initializationVector);
- Validator.ensureTrue(-1 != keyEntry.getIVLengthBits()
- || Cipher.ENCRYPT_MODE == mode);
- Validator.ensureTrue(null == initializationVector
- || initializationVector.length * Byte.SIZE
- == keyEntry.getIVLengthBits());
-
- Cipher cipher;
- try {
- cipher = Cipher.getInstance(keyEntry.getType());
- }
- catch (GeneralSecurityException ex) {
- // NoSuchAlgorithmException, NoSuchPaddingException
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, ex);
- }
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_GET_CIPHER_INVALID_CIPHER_TRANSFORMATION.get(
- keyEntry.getType(), getExceptionMessage(ex)), ex);
- }
-
- try {
- if (0 < keyEntry.getIVLengthBits()) {
- byte[] iv;
- if (Cipher.ENCRYPT_MODE == mode
- && null == initializationVector) {
- iv = new byte[keyEntry.getIVLengthBits() / Byte.SIZE];
- pseudoRandom.nextBytes(iv);
- }
- else {
- iv = initializationVector;
- }
- cipher.init(mode, keyEntry.getSecretKey(),
- new IvParameterSpec(iv));
- }
- else {
- cipher.init(mode, keyEntry.getSecretKey());
- }
- }
- catch (GeneralSecurityException ex) {
- // InvalidKeyException, InvalidAlgorithmParameterException
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, ex);
- }
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_GET_CIPHER_CANNOT_INITIALIZE.get(
- getExceptionMessage(ex)), ex);
- }
-
- return cipher;
- }
-
-
- /**
- * Encrypts the data in the provided byte array using the preferred
- * cipher transformation.
- *
- * @param data The plain-text data to be encrypted.
- *
- * @return A byte array containing the encrypted representation of
- * the provided data.
- *
- * @throws GeneralSecurityException If a problem occurs while
- * encrypting the data.
- *
- * @throws CryptoManagerException If a problem occurs managing the
- * encryption key or producing the cipher.
- */
- public byte[] encrypt(byte[] data)
- throws GeneralSecurityException, CryptoManagerException
- {
- return encrypt(preferredCipherTransformation,
- preferredCipherTransformationKeyLengthBits, data);
- }
-
-
- /**
- * Encrypts the data in the provided byte array using the requested
- * cipher algorithm.
- *
- * @param cipherTransformation The algorithm/mode/padding to use
- * for the cipher.
- *
- * @param keyLengthBits The length in bits of the encryption key
- * this method is to use. Note the specified key length and
- * transformation must be compatible.
- *
- * @param data The plain-text data to be encrypted.
- *
- * @return A byte array containing the encrypted representation of
- * the provided data.
- *
- * @throws GeneralSecurityException If a problem occurs while
- * encrypting the data.
- *
- * @throws CryptoManagerException If a problem occurs managing the
- * encryption key or producing the cipher.
- */
- public byte[] encrypt(String cipherTransformation,
- int keyLengthBits,
- byte[] data)
- throws GeneralSecurityException, CryptoManagerException
- {
- Validator.ensureNotNull(cipherTransformation, data);
-
- CipherKeyEntry keyEntry = CipherKeyEntry.getKeyEntry(
- this, cipherTransformation, keyLengthBits);
- if (null == keyEntry) {
- keyEntry = CipherKeyEntry.generateKeyEntry(this,
- cipherTransformation, keyLengthBits);
- }
-
- final Cipher cipher
- = getCipher(keyEntry, Cipher.ENCRYPT_MODE, null);
-
- final byte[] keyID = keyEntry.getKeyID().getByteValue();
- final byte[] iv = cipher.getIV();
- final int prologueLength
- = keyID.length + ((null == iv) ? 0 : iv.length);
- final int dataLength = cipher.getOutputSize(data.length);
- final byte[] cipherText = new byte[prologueLength + dataLength];
- System.arraycopy(keyID, 0, cipherText, 0, keyID.length);
- if (null != iv) {
- System.arraycopy(iv, 0, cipherText, keyID.length, iv.length);
- }
- System.arraycopy(cipher.doFinal(data), 0, cipherText,
- prologueLength, dataLength);
- return cipherText;
- }
-
-
- /**
- * Writes encrypted data to the provided output stream using the
- * preferred cipher transformation.
- *
- * @param outputStream The output stream to be wrapped by the
- * returned cipher output stream.
- *
- * @return The output stream wrapped with a CipherOutputStream.
- *
- * @throws CryptoManagerException If a problem occurs managing the
- * encryption key or producing the cipher.
- */
- public CipherOutputStream getCipherOutputStream(
- OutputStream outputStream) throws CryptoManagerException
- {
- return getCipherOutputStream(preferredCipherTransformation,
- preferredCipherTransformationKeyLengthBits, outputStream);
- }
-
-
- /**
- * Writes encrypted data to the provided output stream using the
- * requested cipher transformation.
- *
- * @param cipherTransformation The algorithm/mode/padding to use
- * for the cipher.
- *
- * @param keyLengthBits The length in bits of the encryption key
- * this method will generate. Note the specified key length
- * must be compatible with the transformation.
- *
- * @param outputStream The output stream to be wrapped by the
- * returned cipher output stream.
- *
- * @return The output stream wrapped with a CipherOutputStream.
- *
- * @throws CryptoManagerException If a problem occurs managing the
- * encryption key or producing the cipher.
- */
- public CipherOutputStream getCipherOutputStream(
- String cipherTransformation, int keyLengthBits,
- OutputStream outputStream)
- throws CryptoManagerException
- {
- Validator.ensureNotNull(cipherTransformation, outputStream);
-
- CipherKeyEntry keyEntry = CipherKeyEntry.getKeyEntry(
- this, cipherTransformation, keyLengthBits);
- if (null == keyEntry) {
- keyEntry = CipherKeyEntry.generateKeyEntry(this,
- cipherTransformation, keyLengthBits);
- }
-
- final Cipher cipher
- = getCipher(keyEntry, Cipher.ENCRYPT_MODE, null);
- final byte[] keyID = keyEntry.getKeyID().getByteValue();
- try {
- outputStream.write(keyID);
- if (null != cipher.getIV()) {
- outputStream.write(cipher.getIV());
- }
- }
- catch (IOException ex) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, ex);
- }
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_GET_CIPHER_STREAM_PROLOGUE_WRITE_ERROR.get(
- getExceptionMessage(ex)), ex);
- }
-
- return new CipherOutputStream(outputStream, cipher);
- }
-
-
- /**
- * Decrypts the data in the provided byte array using cipher
- * specified by the key identifier prologue to the data.
- * cipher.
- *
- * @param data The cipher-text data to be decrypted.
- *
- * @return A byte array containing the clear-text representation of
- * the provided data.
- *
- * @throws GeneralSecurityException If a problem occurs while
- * encrypting the data.
- *
- * @throws CryptoManagerException If a problem occurs reading the
- * key identifier or initialization vector from the data
- * prologue, or using these values to initialize a Cipher.
- */
- public byte[] decrypt(byte[] data)
- throws GeneralSecurityException,
- CryptoManagerException
- {
- KeyEntryID keyID;
- try {
- final byte[] keyIDBytes
- = new byte[KeyEntryID.getByteValueLength()];
- System.arraycopy(data, 0, keyIDBytes, 0, keyIDBytes.length);
- keyID = new KeyEntryID(keyIDBytes);
- }
- catch (Exception ex) {
- // IndexOutOfBoundsException, ArrayStoreException, ...
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, ex);
- }
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_DECRYPT_FAILED_TO_READ_KEY_IDENTIFIER.get(),
- ex);
- }
-
- CipherKeyEntry keyEntry = CipherKeyEntry.getKeyEntry(this, keyID);
- if (null == keyEntry) {
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_DECRYPT_UNKNOWN_KEY_IDENTIFIER.get());
- }
-
- byte[] iv = null;
- if (0 < keyEntry.getIVLengthBits()) {
- iv = new byte[keyEntry.getIVLengthBits()/Byte.SIZE];
- try {
- System.arraycopy(data, KeyEntryID.getByteValueLength(), iv, 0,
- iv.length);
- }
- catch (Exception ex) {
- // IndexOutOfBoundsException, ArrayStoreException, ...
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, ex);
- }
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_DECRYPT_FAILED_TO_READ_IV.get(), ex);
- }
- }
-
- final Cipher cipher = getCipher(keyEntry, Cipher.DECRYPT_MODE,
- iv);
- final int prologueLength = KeyEntryID.getByteValueLength()
- + ((null == iv) ? 0 : iv.length);
- return cipher.doFinal(data, prologueLength,
- data.length - prologueLength);
- }
-
-
-
- /**
- * Returns a CipherInputStream instantiated with a cipher
- * corresponding to the key identifier prologue to the data.
- *
- * @param inputStream The input stream be wrapped with the
- * CipherInputStream.
- *
- * @return The CiperInputStream instantiated as specified.
- *
- * @throws CryptoManagerException If there is a problem reading the
- * key ID or initialization vector from the input stream,
- * or using these values to inititalize a Cipher.
- */
- public CipherInputStream getCipherInputStream(
- InputStream inputStream) throws CryptoManagerException
- {
- CipherKeyEntry keyEntry;
- byte[] iv = null;
- try {
- final byte[] keyID = new byte[KeyEntryID.getByteValueLength()];
- if (keyID.length != inputStream.read(keyID)){
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_DECRYPT_FAILED_TO_READ_KEY_IDENTIFIER.get());
- }
- keyEntry = CipherKeyEntry.getKeyEntry(this,
- new KeyEntryID(keyID));
- if (null == keyEntry) {
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_DECRYPT_UNKNOWN_KEY_IDENTIFIER.get());
- }
-
- if (0 < keyEntry.getIVLengthBits()) {
- iv = new byte[keyEntry.getIVLengthBits() / Byte.SIZE];
- if (iv.length != inputStream.read(iv)) {
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_DECRYPT_FAILED_TO_READ_IV.get());
- }
- }
- }
- catch (IOException ex) {
- throw new CryptoManagerException(
- ERR_CRYPTOMGR_DECRYPT_CIPHER_INPUT_STREAM_ERROR.get(
- getExceptionMessage(ex)), ex);
- }
-
- return new CipherInputStream(inputStream,
- getCipher(keyEntry, Cipher.DECRYPT_MODE, iv));
- }
-
-
- /**
- * Attempts to compress the data in the provided source array into
- * the given destination array. If the compressed data will fit
- * into the destination array, then this method will return the
- * number of bytes of compressed data in the array. Otherwise, it
- * will return -1 to indicate that the compression was not
- * successful. Note that if -1 is returned, then the data in the
- * destination array should be considered invalid.
- *
- * @param src The array containing the raw data to compress.
- * @param dst The array into which the compressed data should be
- * written.
- *
- * @return The number of bytes of compressed data, or -1 if it was
- * not possible to actually compress the data.
- */
- public int compress(byte[] src, byte[] dst)
- {
- Deflater deflater = new Deflater();
- try
- {
- deflater.setInput(src);
- deflater.finish();
-
- int compressedLength = deflater.deflate(dst);
- if (deflater.finished())
- {
- return compressedLength;
- }
- else
- {
- return -1;
- }
- }
- finally
- {
- deflater.end();
- }
- }
-
-
-
- /**
- * Attempts to uncompress the data in the provided source array into
- * the given destination array. If the uncompressed data will fit
- * into the given destination array, then this method will return
- * the number of bytes of uncompressed data written into the
- * destination buffer. Otherwise, it will return a negative value
- * to indicate that the destination buffer was not large enough.
- * The absolute value of that negative return value will indicate
- * the buffer size required to fully decompress the data. Note that
- * if a negative value is returned, then the data in the destination
- * array should be considered invalid.
- *
- * @param src The array containing the compressed data.
- * @param dst The array into which the uncompressed data should be
- * written.
- *
- * @return A positive value containing the number of bytes of
- * uncompressed data written into the destination buffer,
- * or a negative value whose absolute value is the size of
- * the destination buffer required to fully decompress the
- * provided data.
- *
- * @throws DataFormatException If a problem occurs while
- * attempting to uncompress the data.
- */
- public int uncompress(byte[] src, byte[] dst)
- throws DataFormatException
- {
- Inflater inflater = new Inflater();
- try
- {
- inflater.setInput(src);
-
- int decompressedLength = inflater.inflate(dst);
- if (inflater.finished())
- {
- return decompressedLength;
- }
- else
- {
- int totalLength = decompressedLength;
-
- while (! inflater.finished())
+ LinkedList<SearchResultEntry> resultEntries =
+ internalSearch.getSearchEntries();
+ for (SearchResultEntry resultEntry : resultEntries)
{
- totalLength += inflater.inflate(dst);
+ AttributeType hostnameAttr =
+ DirectoryServer.getAttributeType("hostname", true);
+ String hostname = resultEntry.getAttributeValue(
+ hostnameAttr, DirectoryStringSyntax.DECODER);
+ AttributeType ldapPortAttr =
+ DirectoryServer.getAttributeType("ldapport", true);
+ Integer ldapPort = resultEntry.getAttributeValue(
+ ldapPortAttr, IntegerSyntax.DECODER);
+
+ // Connect to the server.
+ AtomicInteger nextMessageID = new AtomicInteger(1);
+ LDAPConnectionOptions connectionOptions =
+ new LDAPConnectionOptions();
+ PrintStream nullPrintStream =
+ new PrintStream(new OutputStream() {
+ public void write ( int b ) { }
+ });
+ LDAPConnection connection =
+ new LDAPConnection(hostname, ldapPort,
+ connectionOptions,
+ nullPrintStream,
+ nullPrintStream);
+
+ connection.connectToHost(null, null, nextMessageID);
+
+ try
+ {
+ LDAPReader reader = connection.getLDAPReader();
+ LDAPWriter writer = connection.getLDAPWriter();
+
+ // Send the Get Symmetric Key extended request.
+
+ ASN1OctetString requestValue =
+ GetSymmetricKeyExtendedOperation.encodeRequestValue(
+ symmetricKey, getInstanceKeyID());
+
+ ExtendedRequestProtocolOp extendedRequest =
+ new ExtendedRequestProtocolOp(
+ ServerConstants.
+ OID_GET_SYMMETRIC_KEY_EXTENDED_OP,
+ requestValue);
+
+ ArrayList<LDAPControl> controls =
+ new ArrayList<LDAPControl>();
+ LDAPMessage requestMessage =
+ new LDAPMessage(nextMessageID.getAndIncrement(),
+ extendedRequest, controls);
+ writer.writeMessage(requestMessage);
+ LDAPMessage responseMessage = reader.readMessage();
+
+ ExtendedResponseProtocolOp extendedResponse =
+ responseMessage.getExtendedResponseProtocolOp();
+ if (extendedResponse.getResultCode() ==
+ LDAPResultCode.SUCCESS)
+ {
+ // Got our symmetric key value.
+ return extendedResponse.getValue().stringValue();
+ }
+ }
+ finally
+ {
+ connection.close(nextMessageID);
+ }
}
-
- return -totalLength;
}
- }
- finally
- {
- inflater.end();
- }
- }
-
-
- /**
- * Retrieve the ADS trust store backend.
- * @return The ADS trust store backend.
- * @throws ConfigException If the ADS trust store backend is
- * not configured.
- */
- private TrustStoreBackend getTrustStoreBackend()
- throws ConfigException
- {
- Backend b = DirectoryServer.getBackend(
- ConfigConstants.ID_ADS_TRUST_STORE_BACKEND);
- if (b == null)
- {
- Message msg =
- ERR_CRYPTOMGR_ADS_TRUST_STORE_BACKEND_NOT_ENABLED.get(
- ConfigConstants.ID_ADS_TRUST_STORE_BACKEND);
- throw new ConfigException(msg);
- }
- if (!(b instanceof TrustStoreBackend))
- {
- Message msg =
- ERR_CRYPTOMGR_ADS_TRUST_STORE_BACKEND_WRONG_CLASS.get(
- ConfigConstants.ID_ADS_TRUST_STORE_BACKEND);
- throw new ConfigException(msg);
- }
- return (TrustStoreBackend)b;
- }
-
- /**
- * Create an SSL context that may be used for communication to
- * another ADS component.
- *
- * @param sslCertNickname The name of the local certificate to use,
- * or null if none is specified.
- * @return A new SSL Context.
- * @throws ConfigException If the context could not be created.
- */
- public SSLContext getSslContext(String sslCertNickname)
- throws ConfigException
- {
- SSLContext sslContext;
- try
- {
- TrustStoreBackend trustStoreBackend = getTrustStoreBackend();
- KeyManager[] keyManagers = trustStoreBackend.getKeyManagers();
- TrustManager[] trustManagers =
- trustStoreBackend.getTrustManagers();
-
- sslContext = SSLContext.getInstance("TLS");
-
- if (sslCertNickname == null)
+ catch (Exception e)
{
- sslContext.init(keyManagers, trustManagers, null);
- }
- else
- {
- X509ExtendedKeyManager[] extendedKeyManagers =
- SelectableCertificateKeyManager.wrap(
- keyManagers,
- sslCertNickname);
- sslContext.init(extendedKeyManagers, trustManagers, null);
+ // Just try another server.
}
}
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- Message message =
- ERR_CRYPTOMGR_SSL_CONTEXT_CANNOT_INITIALIZE.get(
- getExceptionMessage(e));
- throw new ConfigException(message, e);
- }
-
- return sslContext;
+ // Give up.
+ return null;
}
/**
- * Get the name of the local certificate to use for SSL.
- * @return The name of the local certificate to use for SSL.
- */
- public String getSslCertNickname()
- {
- return sslCertNickname;
- }
-
- /**
- * Determine whether SSL encryption is enabled.
- * @return true if SSL encryption is enabled.
- */
- public boolean isSslEncryption()
- {
- return sslEncryption;
- }
-
- /**
- * Get the set of enabled SSL protocols.
- * @return The set of enabled SSL protocols.
- */
- public SortedSet<String> getSslProtocols()
- {
- return sslProtocols;
- }
-
- /**
- * Get the set of enabled SSL cipher suites.
- * @return The set of enabled SSL cipher suites.
- */
- public SortedSet<String> getSslCipherSuites()
- {
- return sslCipherSuites;
- }
-
- /**
* Imports a cipher key entry from an entry in ADS.
*
* @param entry The ADS cipher key entry to be imported.
@@ -1999,119 +1266,6 @@
}
}
- /**
- * Given a set of other servers' symmetric key values for
- * a given secret key, use the Get Symmetric Key extended
- * operation to request this server's symmetric key value.
- *
- * @param symmetricKeys The known symmetric key values for
- * a given secret key.
- *
- * @return The symmetric key value for this server, or null if
- * none could be obtained.
- */
- private String getSymmetricKey(List<String> symmetricKeys)
- {
- InternalClientConnection internalConnection =
- InternalClientConnection.getRootConnection();
- for (String symmetricKey : symmetricKeys)
- {
- try
- {
- // Get the server instance key ID from the symmetric key.
- String[] elements = symmetricKey.split(":", 0);
- String instanceKeyID = elements[0];
-
- // Find the server entry from the instance key ID.
- String filter = "(" +
- ConfigConstants.ATTR_CRYPTO_KEY_ID + "=" +
- instanceKeyID + ")";
- InternalSearchOperation internalSearch =
- internalConnection.processSearch(
- serversDN, SearchScope.SUBORDINATE_SUBTREE,
- SearchFilter.createFilterFromString(filter));
- if (internalSearch.getResultCode() != ResultCode.SUCCESS)
- continue;
-
- LinkedList<SearchResultEntry> resultEntries =
- internalSearch.getSearchEntries();
- for (SearchResultEntry resultEntry : resultEntries)
- {
- AttributeType hostnameAttr =
- DirectoryServer.getAttributeType("hostname", true);
- String hostname = resultEntry.getAttributeValue(
- hostnameAttr, DirectoryStringSyntax.DECODER);
- AttributeType ldapPortAttr =
- DirectoryServer.getAttributeType("ldapport", true);
- Integer ldapPort = resultEntry.getAttributeValue(
- ldapPortAttr, IntegerSyntax.DECODER);
-
- // Connect to the server.
- AtomicInteger nextMessageID = new AtomicInteger(1);
- LDAPConnectionOptions connectionOptions =
- new LDAPConnectionOptions();
- PrintStream nullPrintStream =
- new PrintStream(new OutputStream() {
- public void write ( int b ) { }
- });
- LDAPConnection connection =
- new LDAPConnection(hostname, ldapPort,
- connectionOptions,
- nullPrintStream,
- nullPrintStream);
-
- connection.connectToHost(null, null, nextMessageID);
-
- try
- {
- LDAPReader reader = connection.getLDAPReader();
- LDAPWriter writer = connection.getLDAPWriter();
-
- // Send the Get Symmetric Key extended request.
-
- ASN1OctetString requestValue =
- GetSymmetricKeyExtendedOperation.encodeRequestValue(
- symmetricKey, getInstanceKeyID());
-
- ExtendedRequestProtocolOp extendedRequest =
- new ExtendedRequestProtocolOp(
- ServerConstants.
- OID_GET_SYMMETRIC_KEY_EXTENDED_OP,
- requestValue);
-
- ArrayList<LDAPControl> controls =
- new ArrayList<LDAPControl>();
- LDAPMessage requestMessage =
- new LDAPMessage(nextMessageID.getAndIncrement(),
- extendedRequest, controls);
- writer.writeMessage(requestMessage);
- LDAPMessage responseMessage = reader.readMessage();
-
- ExtendedResponseProtocolOp extendedResponse =
- responseMessage.getExtendedResponseProtocolOp();
- if (extendedResponse.getResultCode() ==
- LDAPResultCode.SUCCESS)
- {
- // Got our symmetric key value.
- return extendedResponse.getValue().stringValue();
- }
- }
- finally
- {
- connection.close(nextMessageID);
- }
- }
- }
- catch (Exception e)
- {
- // Just try another server.
- }
- }
-
- // Give up.
- return null;
- }
-
/**
* Imports a mac key entry from an entry in ADS.
@@ -2219,6 +1373,7 @@
}
}
+
/**
* This class implements a utility interface to the unique
* identifier corresponding to a cryptographic key. For each key
@@ -2517,10 +1672,10 @@
* instantiating a Cipher object in order to validate the supplied
* parameters when creating a new entry.
*
- * @see CipherKeyEntry#getKeyEntry(CryptoManager, String, int)
+ * @see CipherKeyEntry#getKeyEntry(CryptoManagerImpl, String, int)
*/
public static CipherKeyEntry generateKeyEntry(
- final CryptoManager cryptoManager,
+ final CryptoManagerImpl cryptoManager,
final String transformation,
final int keyLengthBits)
throws CryptoManagerException {
@@ -2563,7 +1718,7 @@
* If the key entry could not be added to
* ADS.
*/
- private static void publishKeyEntry(CryptoManager cryptoManager,
+ private static void publishKeyEntry(CryptoManagerImpl cryptoManager,
CipherKeyEntry keyEntry)
throws CryptoManagerException
{
@@ -2644,7 +1799,7 @@
// Need to add our own instance certificate.
byte[] instanceKeyCertificate =
- CryptoManager.getInstanceKeyCertificateFromLocalTruststore();
+ CryptoManagerImpl.getInstanceKeyCertificateFromLocalTruststore();
trustedCerts.put(getInstanceKeyID(instanceKeyCertificate),
instanceKeyCertificate);
@@ -2720,7 +1875,7 @@
* parameters used to initialize or validate the key entry.
*/
public static CipherKeyEntry importCipherKeyEntry(
- final CryptoManager cryptoManager,
+ final CryptoManagerImpl cryptoManager,
final String keyIDString,
final String transformation,
final SecretKey secretKey,
@@ -2791,7 +1946,7 @@
* {@code null} if no such entry exists.
*/
public static CipherKeyEntry getKeyEntry(
- final CryptoManager cryptoManager,
+ final CryptoManagerImpl cryptoManager,
final String transformation,
final int keyLengthBits) {
Validator.ensureNotNull(cryptoManager, transformation);
@@ -2838,12 +1993,12 @@
* @return The key entry associated with the key identifier, or
* {@code null} if no such entry exists.
*
- * @see org.opends.server.crypto.CryptoManager.MacKeyEntry
+ * @see CryptoManagerImpl.MacKeyEntry
* #getKeyEntry(org.opends.server.types.CryptoManager,
* java.lang.String, int)
*/
public static CipherKeyEntry getKeyEntry(
- CryptoManager cryptoManager,
+ CryptoManagerImpl cryptoManager,
final KeyEntryID keyID) {
return cryptoManager.cipherKeyEntryCache.get(keyID);
}
@@ -2983,6 +2138,86 @@
}
+ /**
+ * This method produces an initialized Cipher based on the supplied
+ * CipherKeyEntry's state.
+ *
+ * @param keyEntry The secret key entry containing the cipher
+ * transformation and secret key for which to instantiate
+ * the cipher.
+ *
+ * @param mode Either Cipher.ENCRYPT_MODE or Cipher.DECRYPT_MODE.
+ *
+ * @param initializationVector For Cipher.DECRYPT_MODE, supply
+ * any initialzation vector used in the corresponding encryption
+ * cipher. May be null.
+ *
+ * @return The initialized cipher object.
+ *
+ * @throws CryptoManagerException In case of a problem creating
+ * or initializing the requested cipher object. Possible causes
+ * include NoSuchAlgorithmException, NoSuchPaddingException,
+ * InvalidKeyException, and InvalidAlgorithmParameterException.
+ */
+ private static Cipher getCipher(final CipherKeyEntry keyEntry,
+ final int mode,
+ final byte[] initializationVector)
+ throws CryptoManagerException {
+ Validator.ensureTrue(Cipher.ENCRYPT_MODE == mode
+ || Cipher.DECRYPT_MODE == mode);
+ Validator.ensureTrue(Cipher.ENCRYPT_MODE != mode
+ || null == initializationVector);
+ Validator.ensureTrue(-1 != keyEntry.getIVLengthBits()
+ || Cipher.ENCRYPT_MODE == mode);
+ Validator.ensureTrue(null == initializationVector
+ || initializationVector.length * Byte.SIZE
+ == keyEntry.getIVLengthBits());
+
+ Cipher cipher;
+ try {
+ cipher = Cipher.getInstance(keyEntry.getType());
+ }
+ catch (GeneralSecurityException ex) {
+ // NoSuchAlgorithmException, NoSuchPaddingException
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_GET_CIPHER_INVALID_CIPHER_TRANSFORMATION.get(
+ keyEntry.getType(), getExceptionMessage(ex)), ex);
+ }
+
+ try {
+ if (0 < keyEntry.getIVLengthBits()) {
+ byte[] iv;
+ if (Cipher.ENCRYPT_MODE == mode
+ && null == initializationVector) {
+ iv = new byte[keyEntry.getIVLengthBits() / Byte.SIZE];
+ pseudoRandom.nextBytes(iv);
+ }
+ else {
+ iv = initializationVector;
+ }
+ cipher.init(mode, keyEntry.getSecretKey(),
+ new IvParameterSpec(iv));
+ }
+ else {
+ cipher.init(mode, keyEntry.getSecretKey());
+ }
+ }
+ catch (GeneralSecurityException ex) {
+ // InvalidKeyException, InvalidAlgorithmParameterException
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_GET_CIPHER_CANNOT_INITIALIZE.get(
+ getExceptionMessage(ex)), ex);
+ }
+
+ return cipher;
+ }
+
/**
* This class corresponds to the MAC key entry in ADS. It is
@@ -3014,10 +2249,10 @@
* instantiating a Mac object in order to validate the supplied
* parameters when creating a new entry.
*
- * @see MacKeyEntry#getKeyEntry(CryptoManager, String, int)
+ * @see MacKeyEntry#getKeyEntry(CryptoManagerImpl, String, int)
*/
public static MacKeyEntry generateKeyEntry(
- final CryptoManager cryptoManager,
+ final CryptoManagerImpl cryptoManager,
final String algorithm,
final int keyLengthBits)
throws CryptoManagerException {
@@ -3056,7 +2291,7 @@
* If the key entry could not be added to
* ADS.
*/
- private static void publishKeyEntry(CryptoManager cryptoManager,
+ private static void publishKeyEntry(CryptoManagerImpl cryptoManager,
MacKeyEntry keyEntry)
throws CryptoManagerException
{
@@ -3123,7 +2358,7 @@
// Need to add our own instance certificate.
byte[] instanceKeyCertificate =
- CryptoManager.getInstanceKeyCertificateFromLocalTruststore();
+ CryptoManagerImpl.getInstanceKeyCertificateFromLocalTruststore();
trustedCerts.put(getInstanceKeyID(instanceKeyCertificate),
instanceKeyCertificate);
@@ -3193,7 +2428,7 @@
* parameters used to initialize or validate the key entry.
*/
public static MacKeyEntry importMacKeyEntry(
- final CryptoManager cryptoManager,
+ final CryptoManagerImpl cryptoManager,
final String keyIDString,
final String algorithm,
final SecretKey secretKey,
@@ -3257,7 +2492,7 @@
* {@code null} if no such entry exists.
*/
public static MacKeyEntry getKeyEntry(
- final CryptoManager cryptoManager,
+ final CryptoManagerImpl cryptoManager,
final String algorithm,
final int keyLengthBits) {
Validator.ensureNotNull(cryptoManager, algorithm);
@@ -3304,12 +2539,12 @@
* @return The key entry associated with the key identifier, or
* {@code null} if no such entry exists.
*
- * @see org.opends.server.crypto.CryptoManager.CipherKeyEntry
+ * @see CryptoManagerImpl.CipherKeyEntry
* #getKeyEntry(org.opends.server.types.CryptoManager,
* java.lang.String, int)
*/
public static MacKeyEntry getKeyEntry(
- final CryptoManager cryptoManager,
+ final CryptoManagerImpl cryptoManager,
final KeyEntryID keyID) {
return cryptoManager.macKeyEntryCache.get(keyID);
}
@@ -3379,8 +2614,482 @@
return fType;
}
-
// state
private final String fType;
}
+
+
+ /**
+ * This method produces an initialized MAC engine based on the
+ * supplied MacKeyEntry's state.
+ *
+ * @param keyEntry The MacKeyEntry specifying the Mac properties.
+ *
+ * @return An initialized Mac object.
+ *
+ * @throws CryptoManagerException In case there was a error
+ * instantiating the Mac object.
+ */
+ private static Mac getMacEngine(MacKeyEntry keyEntry)
+ throws CryptoManagerException
+ {
+ Mac mac;
+ try {
+ mac = Mac.getInstance(keyEntry.getType());
+ }
+ catch (NoSuchAlgorithmException ex){
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_GET_MAC_ENGINE_INVALID_MAC_ALGORITHM.get(
+ keyEntry.getType(), getExceptionMessage(ex)),
+ ex);
+ }
+
+ try {
+ mac.init(keyEntry.getSecretKey());
+ }
+ catch (InvalidKeyException ex) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_GET_MAC_ENGINE_CANNOT_INITIALIZE.get(
+ getExceptionMessage(ex)), ex);
+ }
+
+ return mac;
+ }
+
+
+ /** {@inheritDoc} */
+ public String getPreferredMessageDigestAlgorithm()
+ {
+ return preferredDigestAlgorithm;
+ }
+
+
+ /** {@inheritDoc} */
+ public MessageDigest getPreferredMessageDigest()
+ throws NoSuchAlgorithmException
+ {
+ return MessageDigest.getInstance(preferredDigestAlgorithm);
+ }
+
+
+ /** {@inheritDoc} */
+ public MessageDigest getMessageDigest(String digestAlgorithm)
+ throws NoSuchAlgorithmException
+ {
+ return MessageDigest.getInstance(digestAlgorithm);
+ }
+
+
+ /** {@inheritDoc} */
+ public byte[] digest(byte[] data)
+ throws NoSuchAlgorithmException
+ {
+ return MessageDigest.getInstance(preferredDigestAlgorithm).
+ digest(data);
+ }
+
+
+ /** {@inheritDoc} */
+ public byte[] digest(String digestAlgorithm, byte[] data)
+ throws NoSuchAlgorithmException
+ {
+ return MessageDigest.getInstance(digestAlgorithm).digest(data);
+ }
+
+
+ /** {@inheritDoc} */
+ public byte[] digest(InputStream inputStream)
+ throws IOException, NoSuchAlgorithmException
+ {
+ MessageDigest digest =
+ MessageDigest.getInstance(preferredDigestAlgorithm);
+
+ byte[] buffer = new byte[8192];
+ while (true)
+ {
+ int bytesRead = inputStream.read(buffer);
+ if (bytesRead < 0)
+ {
+ break;
+ }
+
+ digest.update(buffer, 0, bytesRead);
+ }
+
+ return digest.digest();
+ }
+
+
+ /** {@inheritDoc} */
+ public byte[] digest(String digestAlgorithm,
+ InputStream inputStream)
+ throws IOException, NoSuchAlgorithmException
+ {
+ MessageDigest digest = MessageDigest.getInstance(digestAlgorithm);
+
+ byte[] buffer = new byte[8192];
+ while (true)
+ {
+ int bytesRead = inputStream.read(buffer);
+ if (bytesRead < 0)
+ {
+ break;
+ }
+
+ digest.update(buffer, 0, bytesRead);
+ }
+
+ return digest.digest();
+ }
+
+
+ /** {@inheritDoc} */
+ public String getMacEngineKeyEntryID()
+ throws CryptoManagerException
+ {
+ return getMacEngineKeyEntryID(preferredMACAlgorithm,
+ preferredMACAlgorithmKeyLengthBits);
+ }
+
+
+ /** {@inheritDoc} */
+ public String getMacEngineKeyEntryID(final String macAlgorithm,
+ final int keyLengthBits)
+ throws CryptoManagerException {
+ Validator.ensureNotNull(macAlgorithm);
+
+ MacKeyEntry keyEntry = MacKeyEntry.getKeyEntry(this, macAlgorithm,
+ keyLengthBits);
+ if (null == keyEntry) {
+ keyEntry = MacKeyEntry.generateKeyEntry(this, macAlgorithm,
+ keyLengthBits);
+ }
+
+ return keyEntry.getKeyID().getStringValue();
+ }
+
+
+ /** {@inheritDoc} */
+ public Mac getMacEngine(String keyEntryID)
+ throws CryptoManagerException
+ {
+ final MacKeyEntry keyEntry = MacKeyEntry.getKeyEntry(this,
+ new KeyEntryID(keyEntryID));
+ return (null == keyEntry) ? null : getMacEngine(keyEntry);
+ }
+
+
+ /** {@inheritDoc} */
+ public byte[] encrypt(byte[] data)
+ throws GeneralSecurityException, CryptoManagerException
+ {
+ return encrypt(preferredCipherTransformation,
+ preferredCipherTransformationKeyLengthBits, data);
+ }
+
+
+ /** {@inheritDoc} */
+ public byte[] encrypt(String cipherTransformation,
+ int keyLengthBits,
+ byte[] data)
+ throws GeneralSecurityException, CryptoManagerException
+ {
+ Validator.ensureNotNull(cipherTransformation, data);
+
+ CipherKeyEntry keyEntry = CipherKeyEntry.getKeyEntry(
+ this, cipherTransformation, keyLengthBits);
+ if (null == keyEntry) {
+ keyEntry = CipherKeyEntry.generateKeyEntry(this,
+ cipherTransformation, keyLengthBits);
+ }
+
+ final Cipher cipher
+ = getCipher(keyEntry, Cipher.ENCRYPT_MODE, null);
+
+ final byte[] keyID = keyEntry.getKeyID().getByteValue();
+ final byte[] iv = cipher.getIV();
+ final int prologueLength
+ = keyID.length + ((null == iv) ? 0 : iv.length);
+ final int dataLength = cipher.getOutputSize(data.length);
+ final byte[] cipherText = new byte[prologueLength + dataLength];
+ System.arraycopy(keyID, 0, cipherText, 0, keyID.length);
+ if (null != iv) {
+ System.arraycopy(iv, 0, cipherText, keyID.length, iv.length);
+ }
+ System.arraycopy(cipher.doFinal(data), 0, cipherText,
+ prologueLength, dataLength);
+ return cipherText;
+ }
+
+
+ /** {@inheritDoc} */
+ public CipherOutputStream getCipherOutputStream(
+ OutputStream outputStream) throws CryptoManagerException
+ {
+ return getCipherOutputStream(preferredCipherTransformation,
+ preferredCipherTransformationKeyLengthBits, outputStream);
+ }
+
+
+ /** {@inheritDoc} */
+ public CipherOutputStream getCipherOutputStream(
+ String cipherTransformation, int keyLengthBits,
+ OutputStream outputStream)
+ throws CryptoManagerException
+ {
+ Validator.ensureNotNull(cipherTransformation, outputStream);
+
+ CipherKeyEntry keyEntry = CipherKeyEntry.getKeyEntry(
+ this, cipherTransformation, keyLengthBits);
+ if (null == keyEntry) {
+ keyEntry = CipherKeyEntry.generateKeyEntry(this,
+ cipherTransformation, keyLengthBits);
+ }
+
+ final Cipher cipher
+ = getCipher(keyEntry, Cipher.ENCRYPT_MODE, null);
+ final byte[] keyID = keyEntry.getKeyID().getByteValue();
+ try {
+ outputStream.write(keyID);
+ if (null != cipher.getIV()) {
+ outputStream.write(cipher.getIV());
+ }
+ }
+ catch (IOException ex) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_GET_CIPHER_STREAM_PROLOGUE_WRITE_ERROR.get(
+ getExceptionMessage(ex)), ex);
+ }
+
+ return new CipherOutputStream(outputStream, cipher);
+ }
+
+
+ /** {@inheritDoc} */
+ public byte[] decrypt(byte[] data)
+ throws GeneralSecurityException,
+ CryptoManagerException
+ {
+ KeyEntryID keyID;
+ try {
+ final byte[] keyIDBytes
+ = new byte[KeyEntryID.getByteValueLength()];
+ System.arraycopy(data, 0, keyIDBytes, 0, keyIDBytes.length);
+ keyID = new KeyEntryID(keyIDBytes);
+ }
+ catch (Exception ex) {
+ // IndexOutOfBoundsException, ArrayStoreException, ...
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_DECRYPT_FAILED_TO_READ_KEY_IDENTIFIER.get(),
+ ex);
+ }
+
+ CipherKeyEntry keyEntry = CipherKeyEntry.getKeyEntry(this, keyID);
+ if (null == keyEntry) {
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_DECRYPT_UNKNOWN_KEY_IDENTIFIER.get());
+ }
+
+ byte[] iv = null;
+ if (0 < keyEntry.getIVLengthBits()) {
+ iv = new byte[keyEntry.getIVLengthBits()/Byte.SIZE];
+ try {
+ System.arraycopy(data, KeyEntryID.getByteValueLength(), iv, 0,
+ iv.length);
+ }
+ catch (Exception ex) {
+ // IndexOutOfBoundsException, ArrayStoreException, ...
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_DECRYPT_FAILED_TO_READ_IV.get(), ex);
+ }
+ }
+
+ final Cipher cipher = getCipher(keyEntry, Cipher.DECRYPT_MODE,
+ iv);
+ final int prologueLength = KeyEntryID.getByteValueLength()
+ + ((null == iv) ? 0 : iv.length);
+ return cipher.doFinal(data, prologueLength,
+ data.length - prologueLength);
+ }
+
+
+ /** {@inheritDoc} */
+ public CipherInputStream getCipherInputStream(
+ InputStream inputStream) throws CryptoManagerException
+ {
+ CipherKeyEntry keyEntry;
+ byte[] iv = null;
+ try {
+ final byte[] keyID = new byte[KeyEntryID.getByteValueLength()];
+ if (keyID.length != inputStream.read(keyID)){
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_DECRYPT_FAILED_TO_READ_KEY_IDENTIFIER.get());
+ }
+ keyEntry = CipherKeyEntry.getKeyEntry(this,
+ new KeyEntryID(keyID));
+ if (null == keyEntry) {
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_DECRYPT_UNKNOWN_KEY_IDENTIFIER.get());
+ }
+
+ if (0 < keyEntry.getIVLengthBits()) {
+ iv = new byte[keyEntry.getIVLengthBits() / Byte.SIZE];
+ if (iv.length != inputStream.read(iv)) {
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_DECRYPT_FAILED_TO_READ_IV.get());
+ }
+ }
+ }
+ catch (IOException ex) {
+ throw new CryptoManagerException(
+ ERR_CRYPTOMGR_DECRYPT_CIPHER_INPUT_STREAM_ERROR.get(
+ getExceptionMessage(ex)), ex);
+ }
+
+ return new CipherInputStream(inputStream,
+ getCipher(keyEntry, Cipher.DECRYPT_MODE, iv));
+ }
+
+
+ /** {@inheritDoc} */
+ public int compress(byte[] src, byte[] dst)
+ {
+ Deflater deflater = new Deflater();
+ try
+ {
+ deflater.setInput(src);
+ deflater.finish();
+
+ int compressedLength = deflater.deflate(dst);
+ if (deflater.finished())
+ {
+ return compressedLength;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ finally
+ {
+ deflater.end();
+ }
+ }
+
+
+ /** {@inheritDoc} */
+ public int uncompress(byte[] src, byte[] dst)
+ throws DataFormatException
+ {
+ Inflater inflater = new Inflater();
+ try
+ {
+ inflater.setInput(src);
+
+ int decompressedLength = inflater.inflate(dst);
+ if (inflater.finished())
+ {
+ return decompressedLength;
+ }
+ else
+ {
+ int totalLength = decompressedLength;
+
+ while (! inflater.finished())
+ {
+ totalLength += inflater.inflate(dst);
+ }
+
+ return -totalLength;
+ }
+ }
+ finally
+ {
+ inflater.end();
+ }
+ }
+
+
+ /** {@inheritDoc} */
+ public SSLContext getSslContext(String sslCertNickname)
+ throws ConfigException
+ {
+ SSLContext sslContext;
+ try
+ {
+ TrustStoreBackend trustStoreBackend = getTrustStoreBackend();
+ KeyManager[] keyManagers = trustStoreBackend.getKeyManagers();
+ TrustManager[] trustManagers =
+ trustStoreBackend.getTrustManagers();
+
+ sslContext = SSLContext.getInstance("TLS");
+
+ if (sslCertNickname == null)
+ {
+ sslContext.init(keyManagers, trustManagers, null);
+ }
+ else
+ {
+ X509ExtendedKeyManager[] extendedKeyManagers =
+ SelectableCertificateKeyManager.wrap(
+ keyManagers,
+ sslCertNickname);
+ sslContext.init(extendedKeyManagers, trustManagers, null);
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ Message message =
+ ERR_CRYPTOMGR_SSL_CONTEXT_CANNOT_INITIALIZE.get(
+ getExceptionMessage(e));
+ throw new ConfigException(message, e);
+ }
+
+ return sslContext;
+ }
+
+
+ /** {@inheritDoc} */
+ public String getSslCertNickname()
+ {
+ return sslCertNickname;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isSslEncryption()
+ {
+ return sslEncryption;
+ }
+
+ /** {@inheritDoc} */
+ public SortedSet<String> getSslProtocols()
+ {
+ return sslProtocols;
+ }
+
+ /** {@inheritDoc} */
+ public SortedSet<String> getSslCipherSuites()
+ {
+ return sslCipherSuites;
+ }
}
--
Gitblit v1.10.0