org.apache.derby.impl.services.jce
Class JCECipherFactory

java.lang.Object
  extended byorg.apache.derby.impl.services.jce.JCECipherFactory
All Implemented Interfaces:
CipherFactory, ModuleControl, java.security.PrivilegedExceptionAction

public final class JCECipherFactory
extends java.lang.Object
implements CipherFactory, ModuleControl, java.security.PrivilegedExceptionAction

This CipherFactory creates new JCECipherProvider.

See Also:
CipherFactory

Field Summary
private  int action
           
private  StorageFile activeFile
           
private  java.lang.String activePerms
           
private static java.lang.String AES
           
private static int AES_IV_LENGTH
          AES encryption takes in an default Initialization vector length (IV) length of 16 bytes This is needed to generate an IV to use for encryption and decryption process
private static int BLOCK_LENGTH
           
private  java.lang.String cryptoAlgorithm
           
private  java.lang.String cryptoAlgorithmShort
           
private  java.lang.String cryptoProvider
           
private  java.lang.String cryptoProviderShort
           
private static java.lang.String DEFAULT_ALGORITHM
           
private static java.lang.String DEFAULT_PROVIDER
           
private static java.lang.String DES
           
private static java.lang.String DESede
           
private  int encodedKeyLength
           
private  int keyLengthBits
           
private  byte[] mainIV
           
private  javax.crypto.SecretKey mainSecretKey
           
private static java.lang.String MESSAGE_DIGEST
           
private  java.security.MessageDigest messageDigest
           
private static java.lang.String TripleDES
           
private static int VERIFYKEY_DATALEN
          Amount of data that is used for verification of external encryption key This does not include the MD5 checksum bytes
 
Fields inherited from interface org.apache.derby.iapi.services.crypto.CipherFactory
DECRYPT, ENCRYPT, MIN_BOOTPASS_LENGTH
 
Constructor Summary
JCECipherFactory()
           
 
Method Summary
 void boot(boolean create, java.util.Properties properties)
          Boot this module with the given properties.
 java.lang.String changeBootPassword(java.lang.String changeString, java.util.Properties properties, CipherProvider verify)
           
 CipherProvider createNewCipher(int mode)
          Returns a CipherProvider which is the encryption or decryption engine.
private  CipherProvider createNewCipher(int mode, javax.crypto.SecretKey secretKey, byte[] iv)
           
private  byte[] decryptKey(java.lang.String encryptedKey, int encodedKeyCharLength, byte[] bootPassword)
          Decrypt the secretKey with the user key .
private  int digest(byte[] input)
           
private  java.lang.String encryptKey(byte[] secretKey, byte[] bootPassword)
          Encrypt the secretKey with the boot password.
private  byte[] generateIV(byte[] secretKey)
          Generate an IV using the input secretKey that can be used by JCECipherProvider to encrypt or decrypt.
private  javax.crypto.SecretKey generateKey(byte[] secretKey)
          Generate a Key object using the input secretKey that can be used by JCECipherProvider to encrypt or decrypt.
private  byte[] generateUniqueBytes()
           
private  byte[] getDatabaseSecretKey(java.util.Properties properties, byte[] bootPassword, java.lang.String errorState)
          get the secretkey used for encryption and decryption when boot password mechanism is used for encryption Steps include retrieve the stored key, decrypt the stored key and verify if the correct boot password was passed There is a possibility that the decrypted key includes the original key and padded bytes in order to have been block size aligned during encryption phase.
private  byte[] getMD5Checksum(byte[] data)
          Use MD5 MessageDigest algorithm to generate checksum
private  byte[] getMuckFromBootPassword(byte[] bootPassword, int encodedKeyByteLength)
           
 java.security.SecureRandom getSecureRandom()
           
private  byte[] handleBootPassword(boolean create, java.util.Properties properties)
           
private  byte[] padKey(byte[] secretKey, int blockSizeAlign)
          For block ciphers, and algorithms using the NoPadding scheme, the data that has to be encrypted needs to be a multiple of the expected block size for the cipher Pad the key with appropriate padding to make it blockSize align
private  StorageRandomAccessFile privAccessFile(StorageFactory storageFactory, java.lang.String fileName, java.lang.String filePerms)
          access a file for either read/write
(package private) static java.lang.String providerErrorName(java.lang.String cps)
           
 java.lang.Object run()
          perform actions with privileges enabled.
private  java.lang.String saveSecretKey(byte[] secretKey, byte[] bootPassword)
           
 void stop()
          Stop the module.
 void verifyKey(boolean create, StorageFactory sf, java.util.Properties properties)
          The database can be encrypted with an encryption key given in connection url.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

MESSAGE_DIGEST

private static final java.lang.String MESSAGE_DIGEST
See Also:
Constant Field Values

DEFAULT_PROVIDER

private static final java.lang.String DEFAULT_PROVIDER
See Also:
Constant Field Values

DEFAULT_ALGORITHM

private static final java.lang.String DEFAULT_ALGORITHM
See Also:
Constant Field Values

DES

private static final java.lang.String DES
See Also:
Constant Field Values

DESede

private static final java.lang.String DESede
See Also:
Constant Field Values

TripleDES

private static final java.lang.String TripleDES
See Also:
Constant Field Values

AES

private static final java.lang.String AES
See Also:
Constant Field Values

BLOCK_LENGTH

private static final int BLOCK_LENGTH
See Also:
Constant Field Values

AES_IV_LENGTH

private static final int AES_IV_LENGTH
AES encryption takes in an default Initialization vector length (IV) length of 16 bytes This is needed to generate an IV to use for encryption and decryption process

See Also:
CipherProvider, Constant Field Values

keyLengthBits

private int keyLengthBits

encodedKeyLength

private int encodedKeyLength

cryptoAlgorithm

private java.lang.String cryptoAlgorithm

cryptoAlgorithmShort

private java.lang.String cryptoAlgorithmShort

cryptoProvider

private java.lang.String cryptoProvider

cryptoProviderShort

private java.lang.String cryptoProviderShort

messageDigest

private java.security.MessageDigest messageDigest

mainSecretKey

private javax.crypto.SecretKey mainSecretKey

mainIV

private byte[] mainIV

VERIFYKEY_DATALEN

private static final int VERIFYKEY_DATALEN
Amount of data that is used for verification of external encryption key This does not include the MD5 checksum bytes

See Also:
Constant Field Values

activeFile

private StorageFile activeFile

action

private int action

activePerms

private java.lang.String activePerms
Constructor Detail

JCECipherFactory

public JCECipherFactory()
Method Detail

providerErrorName

static java.lang.String providerErrorName(java.lang.String cps)

generateUniqueBytes

private byte[] generateUniqueBytes()
                            throws StandardException
Throws:
StandardException

encryptKey

private java.lang.String encryptKey(byte[] secretKey,
                                    byte[] bootPassword)
                             throws StandardException
Encrypt the secretKey with the boot password. This includes the following steps, getting muck from the boot password and then using this to generate a key, generating an appropriate IV using the muck using the key and IV thus generated to create the appropriate cipher provider and encrypting the secretKey

Returns:
hexadecimal string of the encrypted secretKey
Throws:
StandardException - Standard Cloudscape error policy

padKey

private byte[] padKey(byte[] secretKey,
                      int blockSizeAlign)
For block ciphers, and algorithms using the NoPadding scheme, the data that has to be encrypted needs to be a multiple of the expected block size for the cipher Pad the key with appropriate padding to make it blockSize align

Parameters:
secretKey - the data that needs blocksize alignment
blockSizeAlign - secretKey needs to be blocksize aligned
Returns:
a byte array with the contents of secretKey along with padded bytes in the end to make it blockSize aligned

decryptKey

private byte[] decryptKey(java.lang.String encryptedKey,
                          int encodedKeyCharLength,
                          byte[] bootPassword)
                   throws StandardException
Decrypt the secretKey with the user key . This includes the following steps, retrieve the encryptedKey, generate the muck from the boot password and generate an appropriate IV using the muck,and using the key and IV decrypt the encryptedKey

Returns:
decrypted key
Throws:
StandardException - Standard Cloudscape error policy

getMuckFromBootPassword

private byte[] getMuckFromBootPassword(byte[] bootPassword,
                                       int encodedKeyByteLength)

generateKey

private javax.crypto.SecretKey generateKey(byte[] secretKey)
                                    throws StandardException
Generate a Key object using the input secretKey that can be used by JCECipherProvider to encrypt or decrypt.

Throws:
StandardException - Standard Cloudscape Error Policy

generateIV

private byte[] generateIV(byte[] secretKey)
Generate an IV using the input secretKey that can be used by JCECipherProvider to encrypt or decrypt.


digest

private int digest(byte[] input)

getSecureRandom

public java.security.SecureRandom getSecureRandom()
Specified by:
getSecureRandom in interface CipherFactory

createNewCipher

public CipherProvider createNewCipher(int mode)
                               throws StandardException
Description copied from interface: CipherFactory
Returns a CipherProvider which is the encryption or decryption engine.

Specified by:
createNewCipher in interface CipherFactory
Parameters:
mode - is either ENCRYPT or DECRYPT. The CipherProvider can only do encryption or decryption but not both.
Throws:
StandardException - Standard Cloudscape Error Policy

createNewCipher

private CipherProvider createNewCipher(int mode,
                                       javax.crypto.SecretKey secretKey,
                                       byte[] iv)
                                throws StandardException
Throws:
StandardException

boot

public void boot(boolean create,
                 java.util.Properties properties)
          throws StandardException
Description copied from interface: ModuleControl
Boot this module with the given properties. Creates a module instance that can be found using the findModule() methods of Monitor. The module can only be found using one of these findModule() methods once this method has returned.

An implementation's boot method can throw StandardException. If it is thrown the module is not registered by the monitor and therefore cannot be found through a findModule(). In this case the module's stop() method is not called, thus throwing this exception must free up any resources.

When create is true the contents of the properties object will be written to the service.properties of the persistent service. Thus any code that requires an entry in service.properties must explicitly place the value in this properties set using the put method.
Typically the properties object contains one or more default properties sets, which are not written out to service.properties. These default sets are how callers modify the create process. In a JDBC connection database create the first set of defaults is a properties object that contains the attributes that were set on the jdbc:derby: URL. This attributes properties set has the second default properties set as its default. This set (which could be null) contains the properties that the user set on their DriverManager.getConnection() call, and are thus not owned by cloudscape code, and thus must not be modified by cloudscape code.

When create is false the properties object contains all the properties set in the service.properties file plus a limited number of attributes from the JDBC URL attributes or connection properties set. This avoids properties set by the user compromising the boot process. An example of a property passed in from the JDBC world is the bootPassword for encrypted databases.

Code should not hold onto the passed in properties reference after boot time as its contents may change underneath it. At least after the complete boot is completed, the links to all the default sets will be removed.

Specified by:
boot in interface ModuleControl
Throws:
StandardException - Module cannot be started.
See Also:
Monitor, ModuleFactory

handleBootPassword

private byte[] handleBootPassword(boolean create,
                                  java.util.Properties properties)
                           throws StandardException
Throws:
StandardException

stop

public void stop()
Description copied from interface: ModuleControl
Stop the module. The module may be found via a findModule() method until some time after this method returns. Therefore the factory must be prepared to reject requests to it once it has been stopped. In addition other modules may cache a reference to the module and make requests of it after it has been stopped, these requests should be rejected as well.

Specified by:
stop in interface ModuleControl
See Also:
Monitor, ModuleFactory

getDatabaseSecretKey

private byte[] getDatabaseSecretKey(java.util.Properties properties,
                                    byte[] bootPassword,
                                    java.lang.String errorState)
                             throws StandardException
get the secretkey used for encryption and decryption when boot password mechanism is used for encryption Steps include retrieve the stored key, decrypt the stored key and verify if the correct boot password was passed There is a possibility that the decrypted key includes the original key and padded bytes in order to have been block size aligned during encryption phase. Hence extract the original key

Parameters:
properties - properties to retrieve the encrypted key
bootPassword - boot password used to connect to the encrypted database
errorState - errorstate to account for any errors during retrieval /creation of the secretKey
Returns:
the original unencrypted key bytes to use for encryption and decrytion
Throws:
StandardException

saveSecretKey

private java.lang.String saveSecretKey(byte[] secretKey,
                                       byte[] bootPassword)
                                throws StandardException
Throws:
StandardException

changeBootPassword

public java.lang.String changeBootPassword(java.lang.String changeString,
                                           java.util.Properties properties,
                                           CipherProvider verify)
                                    throws StandardException
Specified by:
changeBootPassword in interface CipherFactory
Throws:
StandardException

run

public final java.lang.Object run()
                           throws StandardException,
                                  java.lang.InstantiationException,
                                  java.lang.IllegalAccessException
perform actions with privileges enabled.

Specified by:
run in interface java.security.PrivilegedExceptionAction
Throws:
StandardException
java.lang.InstantiationException
java.lang.IllegalAccessException

verifyKey

public void verifyKey(boolean create,
                      StorageFactory sf,
                      java.util.Properties properties)
               throws StandardException
The database can be encrypted with an encryption key given in connection url. For security reasons, this key is not made persistent in the database. But it is necessary to verify the encryption key when booting the database if it is similar to the one used when creating the database This needs to happen before we access the data/logs to avoid the risk of corrupting the database because of a wrong encryption key. This method performs the steps necessary to verify the encryption key if an external encryption key is given. At database creation, 4k of random data is generated using SecureRandom and MD5 is used to compute the checksum for the random data thus generated. This 4k page of random data is then encrypted using the encryption key. The checksum of unencrypted data and encrypted data is made persistent in the database in file by name given by Attribute.CRYPTO_EXTERNAL_KEY_VERIFYFILE (verifyKey.dat). This file exists directly under the database root directory. When trying to boot an existing encrypted database, the given encryption key is used to decrypt the data in the verifyKey.dat and the checksum is calculated and compared against the original stored checksum. If these checksums dont match an exception is thrown. Please note, this process of verifying the key does not provide any added security but only is intended to allow to fail gracefully if a wrong encryption key is used

Specified by:
verifyKey in interface CipherFactory
Parameters:
create - true means database is being created, whereas false implies that the database has already been created
sf - storageFactory is used to access any stored data that might be needed for verification process of the encryption key
properties - properties at time of database connection as well as those in service.properties
Returns:
StandardException is thrown if there are any problems during the process of verification of the encryption key or if there is any mismatch of the encryption key.
Throws:
StandardException

getMD5Checksum

private byte[] getMD5Checksum(byte[] data)
                       throws StandardException
Use MD5 MessageDigest algorithm to generate checksum

Parameters:
data - data to be used to compute the hash value
Returns:
returns the hash value computed using the data
Throws:
StandardException

privAccessFile

private StorageRandomAccessFile privAccessFile(StorageFactory storageFactory,
                                               java.lang.String fileName,
                                               java.lang.String filePerms)
                                        throws java.io.IOException
access a file for either read/write

Parameters:
storageFactory - factory used for io access
fileName - name of the file to create and open for write The file will be created directly under the database root directory
filePerms - file permissions, if "rw" open file with read and write permissions if "r" , open file with read permissions
Returns:
StorageRandomAccessFile returns file with fileName for writing
Throws:
java.io.IOException - Any exception during accessing the file for read/write


Apache Derby V10.0 Engine Documentation - Copyright © 1997,2004 The Apache Software Foundation or its licensors, as applicable.