|
Cumulus4j API (1.2.0-SNAPSHOT) |
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.cumulus4j.keystore.KeyStore
public class KeyStore
KeyStore
is a storage facility for cryptographic keys.
An instance of KeyStore
manages a file in the local file system, in which it stores
the keys used by the Cumulus4j-DataNucleus-plug-in in an encrypted form. All data written to the
file is encrypted, hence plain data never touches the local file system (except for
swapping!).
For every read/write operation, the KeyStore
requires a user to authenticate via a
user-name and a password. The password is used to encrypt/decrypt an internally used master-key
which is then used to encrypt/decrypt the actual keys used by the Cumulus4j-DataNucleus-plug-in.
Due to this internal master key, a user can be added or deleted and a user's password can be
changed without the need of decrypting and encrypting all the contents of the KeyStore.
By default, a KeyStore
generates keys
with a size
of 256 bit. This can be controlled, however, by specifying the system property
"cumulus4j.KeyStore.keySize" (e.g. passing the argument "-Dcumulus4j.KeyStore.keySize=128"
to the java
command line will switch to 128-bit-keys).
Important: As the master key is generated when the first
user is created
and is then not changed anymore, you must therefore
specify the desired key-size already at the moment when you initialise the key store (i.e. create the first user). If
you change the key-size later, it will affect only those keys that are created later.
Note, that the "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files" does not
need to be installed for very strong cryptography, because we don't use the JCE (see Cipher
).
Bytes | Descrition | ||||||||||||||||||||||||||||||||||||||||||||||||
17 | Header "Cumulus4jKeyStore" (ASCII encoded) | ||||||||||||||||||||||||||||||||||||||||||||||||
4 | int: File version | ||||||||||||||||||||||||||||||||||||||||||||||||
4 | int: Number of entries in 'Block A' to follow. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||
4 | int: Number of entries in 'Block B' to follow. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||
4 | int: Number of entries in 'Block C' to follow. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||
4 | int: Number of entries in 'Block D' to follow. | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Field Summary | |
---|---|
static String |
MAC_ALGORITHM_NONE
Constant for deactivating the MAC. |
static String |
SYSTEM_PROPERTY_ENCRYPTION_ALGORITHM
System property to control the encryption algorithm that is used to encrypt data within the key-store. |
static String |
SYSTEM_PROPERTY_KEY_SIZE
System property to control the size of the keys generated . |
static String |
SYSTEM_PROPERTY_MAC_ALGORITHM
System property to control the MAC algorithm that is used to protect the data within the key-store against manipulation. |
Constructor Summary | |
---|---|
KeyStore(String keyStoreID,
File keyStoreFile)
Create a new instance of KeyStore . |
Method Summary | ||
---|---|---|
void |
changeUserPassword(String authUserName,
char[] authPassword,
String userName,
char[] newPassword)
Change a user's password. |
|
void |
clearCache(String userName)
Clear all cached data for the specified user name. |
|
void |
createUser(String authUserName,
char[] authPassword,
String userName,
char[] password)
Create a new user. |
|
void |
deleteUser(String authUserName,
char[] authPassword,
String userName)
Delete the user specified by userName . |
|
protected void |
finalize()
|
|
GeneratedKey |
generateKey(String authUserName,
char[] authPassword)
Generate a new key and store it to the file. |
|
List<GeneratedKey> |
generateKeys(String authUserName,
char[] authPassword,
int qty)
Generate qty new keys and store them to the file. |
|
byte[] |
getKey(String authUserName,
char[] authPassword,
long keyID)
Get the key identified by the given keyID . |
|
SortedSet<Long> |
getKeyIDs(String authUserName,
char[] authPassword)
|
|
String |
getKeyStoreID()
Get the identifier that is used to reference this key-store. |
|
int |
getMasterKeySize(String authUserName,
char[] authPassword)
|
|
SortedSet<Property<?>> |
getProperties(String authUserName,
char[] authPassword)
|
|
|
getProperty(String authUserName,
char[] authPassword,
Class<P> propertyType,
String name)
Get a named property. |
|
SortedSet<String> |
getUsers(String authUserName,
char[] authPassword)
Get all users who can authenticate at this KeyStore . |
|
boolean |
isEmpty()
Determine if this KeyStore is completely empty. |
|
static void |
main(String[] args)
|
|
boolean |
removeProperty(String authUserName,
char[] authPassword,
String name)
Remove a property. |
|
void |
setProperty(String authUserName,
char[] authPassword,
Property<?> property)
Set a property. |
Methods inherited from class java.lang.Object |
---|
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
public static final String SYSTEM_PROPERTY_KEY_SIZE
System property to control the size of the keys generated
. This
includes not only the actual keys for the main encryption/decryption (in the database), but also the
master key used to protect the file managed by the KeyStore
.
By default (if the system property "cumulus4j.KeyStore.keySize" is not specified), keys will have a size of 256 bit.
Note, that specifying the system property does not change any old keys - only new keys are generated
with the currently active key size. Therefore, if you want to ensure that the internal master key is
only 128 bit long, you have to make sure that the proper key size is specified when the first
user is created
!
public static final String SYSTEM_PROPERTY_ENCRYPTION_ALGORITHM
System property to control the encryption algorithm that is used to encrypt data within the key-store. Whenever a new user is created or a new key is generated, data has to be encrypted (note that the encryption does not happen directly before data is written to the file, but already most data in memory is encrypted!).
By default (if the system property "cumulus4j.KeyStore.encryptionAlgorithm" is not specified), "Twofish/GCM/NoPadding" is used. For example, to switch to "AES/CFB/NoPadding", you'd have to specify the command line argument "-Dcumulus4j.KeyStore.encryptionAlgorithm=AES/CFB/NoPadding".
See this document for further information about what values are supported.
Important: The default MAC algorithm is "NONE", which is a very bad choice for most encryption algorithms! Therefore, you must change the MAC algorithm via the system property "cumulus4j.KeyStore.macAlgorithm" if you change the encryption algorithm!
public static final String SYSTEM_PROPERTY_MAC_ALGORITHM
System property to control the MAC algorithm that is used to protect the data within the key-store against manipulation.
Whenever data is encrypted, this MAC algorithm is used to calculate a MAC over the original plain-text-data. The MAC is then stored together with the plain-text-data within the encrypted area. When data is decrypted, the MAC is calculated again over the decrypted plain-text-data and compared to the original MAC in order to make sure (1) that data was correctly decrypted [i.e. the password provided by the user is correct] and (2) that the data in the key-store was not manipulated by an attacker.
The MAC algorithm used during encryption is stored in the encryption-record's meta-data in order to use the correct algorithm during decryption, no matter what current MAC algorithm is configured. Therefore, you can safely change this setting at any time - it will affect future encryption operations, only.
Some block cipher modes (e.g. GCM) already include authentication and therefore no MAC is necessary. In this case, you can specify the MAC algorithm "NONE".
Important: If you specify the MAC algorithm "NONE" and use an encryption algorithm without authentication, the key store will not be able to detect a wrong password and instead return corrupt data!!! Be VERY careful with the MAC algorithm "NONE"!!!
The default value (used when this system property is not specified) is "NONE", because the default encryption algorithm is "Twofish/GCM/NoPadding", which (due to "GCM") does not require an additional MAC.
public static final String MAC_ALGORITHM_NONE
Constant for deactivating the MAC.
Important: Deactivating the MAC is dangerous! Choose this value only, if you are absolutely
sure that your encryption algorithm
already
provides authentication - like GCM
does for example.
SYSTEM_PROPERTY_MAC_ALGORITHM
,
Constant Field ValuesConstructor Detail |
---|
public KeyStore(String keyStoreID, File keyStoreFile) throws IOException
Create a new instance of KeyStore
.
If the file specified by keyStoreFile
exists, it is read into memory. If it does not exist,
an empty KeyStore
is created and written to this file.
keyStoreID
- the identifier that is used to reference this key-store. Usually, this is the simple file name
without path and without extension. The keyStoreID
is currently not stored in the key-store-file -
it is transient.keyStoreFile
- the file to be read (if existing) or created. Note that temporary files (and later maybe backup files, too)
are created in the same directory (i.e. in keyStoreFile.getParentFile()
).
IOException
- if reading from or writing to the local file-system failed.Method Detail |
---|
public static void main(String[] args) throws UnsupportedEncodingException
UnsupportedEncodingException
public String getKeyStoreID()
keyStoreID
is currently not stored in the key-store-file -
it is transient. Note, though, that it is used persistently inside the actual database!
public boolean isEmpty()
KeyStore
is completely empty. As soon as the first user has been
created, this method will return false
.
true
if this KeyStore
contains neither any user nor any key, i.e. is totally empty;
false
otherwise.public int getMasterKeySize(String authUserName, char[] authPassword) throws AuthenticationException
AuthenticationException
public GeneratedKey generateKey(String authUserName, char[] authPassword) throws AuthenticationException, IOException
Generate a new key and store it to the file.
The new key will be generated with the size specified by the system property "cumulus4j.KeyStore.keySize" and encrypted with the master-key and the encryption-algorithm specified by the system property "cumulus4j.KeyStore.encryptionAlgorithm".
authUserName
- the authenticated user authorizing this action.authPassword
- the password for authenticating the user specified by authUserName
.
AuthenticationException
- if the specified authUserName
does not exist or the specified authPassword
is not correct for the given authUserName
.
IOException
- if writing to the local file-system failed.public List<GeneratedKey> generateKeys(String authUserName, char[] authPassword, int qty) throws AuthenticationException, IOException
Generate qty
new keys and store them to the file.
This method behaves like generateKey(String, char[])
but is much
faster when multiple keys have to be generated (bulk operation).
authUserName
- the authenticated user authorizing this action.authPassword
- the password for authenticating the user specified by authUserName
.qty
- the number of keys to be generated. If 0, the method will do nothing and return
an empty list, if < 0, an IllegalArgumentException
will be thrown.
null
.
AuthenticationException
- if the specified authUserName
does not exist or the specified authPassword
is not correct for the given authUserName
.
IOException
- if writing to the local file-system failed.public void createUser(String authUserName, char[] authPassword, String userName, char[] password) throws AuthenticationException, UserAlreadyExistsException, IOException
Create a new user.
Before the KeyStore
can be used (i.e. before most methods work), this method has to be called
to create the first user. When the first user is created, the internal master-key is generated, which will
then not be changed anymore (double-check that the key-size
is set correctly at
this time).
authUserName
- the authenticated user authorizing this action. If the very first user is created, this value
is ignored and can be null
.authPassword
- the password for authenticating the user specified by authUserName
. If the very first user is created, this value
is ignored and can be null
.userName
- the name of the user to be created.password
- the password of the new user.
AuthenticationException
- if the specified authUserName
does not exist or the specified authPassword
is not correct for the given authUserName
.
UserAlreadyExistsException
- if a user with the name specified by userName
already exists.
IOException
- if writing to the local file-system failed.public SortedSet<String> getUsers(String authUserName, char[] authPassword) throws AuthenticationException
Get all users who can authenticate at this KeyStore
.
authUserName
- the authenticated user authorizing this action.authPassword
- the password for authenticating the user specified by authUserName
.
Set
of all user-names known to this KeyStore
. This
Set
is an unmodifiable copy of the internally used data and therefore is both thread-safe
and iteration-safe (i.e. it can be iterated while simultaneously users are deleted
).
AuthenticationException
- if the specified authUserName
does not exist or the specified authPassword
is not correct for the given authUserName
.public void deleteUser(String authUserName, char[] authPassword, String userName) throws AuthenticationException, UserNotFoundException, CannotDeleteLastUserException, IOException
Delete the user specified by userName
.
Deleting the authenticated user himself (i.e. authUserName == userName
) is possible,
as long as it is not the last user.
authUserName
- the name of the principal, i.e. the user authorizing this operation.authPassword
- the password of the principal.userName
- the name of the user to be deleted.
AuthenticationException
- if the specified authUserName
does not exist or the specified authPassword
is not correct for the given authUserName
.
UserNotFoundException
- if there is no user with the name specified by userName
.
CannotDeleteLastUserException
- if the last user would be deleted by this method invocation (thus rendering
the KeyStore
unusable and unrecoverable - i.e. totally lost).
IOException
- if writing to the local file-system failed.public void changeUserPassword(String authUserName, char[] authPassword, String userName, char[] newPassword) throws AuthenticationException, UserNotFoundException, IOException
Change a user's password.
The user identified by userName
will have the new password specified by
newPassword
immediately after this method. Authenticating this user with
his old password will fail afterwards.
authUserName
- the authenticated user authorizing this action.authPassword
- the password for authenticating the user specified by authUserName
.userName
- the user whose password is to be changed. This can be the same as authUserName
.newPassword
- the new password.
AuthenticationException
- if the specified authUserName
does not exist or the specified authPassword
is not correct for the given authUserName
.
UserNotFoundException
- if there is no user with the name specified by userName
.
IOException
- if writing to the local file-system failed.public byte[] getKey(String authUserName, char[] authPassword, long keyID) throws AuthenticationException, KeyNotFoundException
keyID
.
authUserName
- the authenticated user authorizing this action.authPassword
- the password for authenticating the user specified by authUserName
.keyID
- the identifier of the key to get.
null
(if there is no key for the given keyID
,
a KeyNotFoundException
is thrown).
AuthenticationException
- if the specified authUserName
does not exist or the specified authPassword
is not correct for the given authUserName
.
KeyNotFoundException
- if the specified keyID
does not reference any existing key. Note, that the
authentication process occurs before any lookup and therefore a KeyNotFoundException
indicates a correct authentication
(otherwise the AuthenticationException
would have been thrown before).public SortedSet<Long> getKeyIDs(String authUserName, char[] authPassword) throws AuthenticationException
AuthenticationException
public <P extends Property<?>> P getProperty(String authUserName, char[] authPassword, Class<P> propertyType, String name) throws AuthenticationException
Get a named property.
The KeyStore
supports managing arbitrary properties in the form of
name-value-pairs. The names are plain-text, but the values are encrypted.
A property-value can be of any type for which a subclass of
Property
exists.
This method will always return an instance of the given propertyType
, no matter,
if the property exists in this KeyStore
or not. If the property does not exist,
its value
will be null
.
Important: Never directly instantiate a Property
-subclass. Always use this method
as a factory for property instances.
P
- the type of the property.authUserName
- the authenticated user authorizing this action.authPassword
- the password for authenticating the user specified by authUserName
.propertyType
- the type of the property; must not be null
. If the property does not yet exist,
every type can be specified. If the property already exists, this type must match the type of the property.
If they do not match, an IllegalArgumentException
is thrown.name
- the unique name of the property; must not be null
.
null
. If the property does not yet exist, a new, empty property is returned.
AuthenticationException
- if the specified authUserName
does not exist or the specified authPassword
is not correct for the given authUserName
.setProperty(String, char[], Property)
,
removeProperty(String, char[], String)
public SortedSet<Property<?>> getProperties(String authUserName, char[] authPassword) throws AuthenticationException
AuthenticationException
public boolean removeProperty(String authUserName, char[] authPassword, String name) throws AuthenticationException, IOException
Remove a property.
If the property with the given name does not exist, this method won't do anything.
authUserName
- the authenticated user authorizing this action.authPassword
- the password for authenticating the user specified by authUserName
.name
- the unique name of the property; must not be null
.
KeyStore
was changed by the operation.
AuthenticationException
- if the specified authUserName
does not exist or the specified authPassword
is not correct for the given authUserName
.
IOException
- if writing to the local file-system failed.getProperty(String, char[], Class, String)
,
setProperty(String, char[], Property)
public void setProperty(String authUserName, char[] authPassword, Property<?> property) throws AuthenticationException, IOException
Set a property.
If the property's value
is null
, the property is
removed
instead.
If a property with the same name
already exists, it is overwritten.
The property's value is encrypted with the internal master-key. The property's name is stored in plain (unencrypted) form.
authUserName
- the authenticated user authorizing this action.authPassword
- the password for authenticating the user specified by authUserName
.property
- the property to set. Do not instantiate any property directly!
Use getProperty(String, char[], Class, String)
instead!
AuthenticationException
- if the specified authUserName
does not exist or the specified authPassword
is not correct for the given authUserName
.
IOException
- if writing to the local file-system failed.getProperty(String, char[], Class, String)
,
removeProperty(String, char[], String)
public void clearCache(String userName)
Clear all cached data for the specified user name.
Every time, a user
calls a method requiring authUserName
and authPassword
,
either an authentication process happens, or a previously cached authentication
result (i.e. a decrypted master-key) is used. In order to speed things up, authentication results are cached for a
limited time. After this time elapses, the data is cleared by a timer. If a user wants (for security reasons)
remove the cached data from the memory earlier, he can call this method.
userName
- the user for which to clear all the cached data. null
to clear the complete cache for all users.protected void finalize() throws Throwable
finalize
in class Object
Throwable
|
Cumulus4j API (1.2.0-SNAPSHOT) |
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |