Wadjet-Security supplies a set of classes representing different credential and principal types, for manipulating key stores and for working ciphers for encryption.
The following sections describe how to use some of the components in the Wadjet-Security package:
The CipherFactory class is designed to work in collaboration with a key store containing key pairs and secret keys. As with most services in the Wadjet Libraries , a CipherFactory is obtained using a locator:
CipherFactory cf = CipherFactory.getCipherFactory(".store",
"BouncyCastle",
"BC",
"password".toCharArray());
The CipherFactory instances are stored internally in a map which is keyed by the key store name.
On creation, the CipherFactory opens and loads the key store. This implies that any changes made to the key store outside of the CipherFactory will not be reflected in the data held by the factory.
The CipherFactory gives you easy access to ciphers created from the keys in the key store or to the certificates and certificate chains contained in the store. The correct cipher type will be created from a secret key without having to specify the algorithm (it’s in the key data). The CipherFactory returns CipherImpl instances:
CipherImpl cipher = CipherImpl.getSysmetricCipher(alias, "password".toCharArray());
The CipherImpl class is obtained using the CipherFactory . CipherImpl instances always have the same mode and padding:
The cipher type is determined by the cipher algorithm of the key passed to the constructor. The CipherImpl class allows you to encrypt and decrypt data without having to code the changes to the Cipher class yourself. It also handles conversions for you, making life a lot easier:
CipherImpl cipher = cipherFactory.getSymetricalCipher( alias, pass);
byte[] encrypted = cipher.encrypt("Any string you want to encrypt");
String original = cipher.decryptToString(encrypted);
or
byte[] original = cipher.decrypt(encrypted);
If you need to encrypt/decrypt passwords you would use the Conversions class:
byte[] encrypted = cipher.encrypt(Conversions.charArrayToBytes(pass));
char[] original = Conversions.bytesToChars(cipher.decrypt(encrypted));
If you want use a asymetrical encryption using X.509 certificates and their private keys, remember that you can only encrypt using the private key, and you use the public key to decrypt.
CipherImpl private = cipherFactory.getPrivateCipher(alias, pass);
byte[] encrypted = private.encrypt(Conversions.charArrayToBytes(pass));
CipherImpl public = cipherFactory.getPublicCipher(alias);
char[] original = Conversions.bytesToChars(public.decrypt(encrypted));
The PBECipher class supplies you with a Password Based Encryption (PBE) cipher. This cipher has to be created in two steps:
PBECipher cipher = new PBECipher();
cipher.init(password);
The cipher is a strong encryption cipher and used in other ADDC products like the Isis Keystore Service . The algorithm is PBEWithSHAAndTwofish-CBC and uses 1000 iterations with an 8 byte salt in the encryption.
The class supplies methods for encrypting and decrypting byte arrays, char arrays and Strings:
byte[] ba = cipher.encrypt("password",toCharArray());
Gives the same result as either
ba = cipher.encrypt("password");
or
ba = cipher.encrypt(Conversions.stringToBytes("password"));
The encrypted byte array can be decrypted to char[], byte[] or String:
char[] ca = cipher.decryptToChars(ba);
byte[] ba = cipher.decrypt(ba);
String str = cipher.decryptToString(ba);
NOTE The result of the encryption using a PBE Cipher is always different, the idea being that the same input produces different output each time it is run through the cipher making it practically impossible to detect a pattern that can be used to break the encryption.
The KeyTool class suplies an interface to key stores that supplies the functionality of the Java keytool program. This allows you to
All from within your program.
This class is used by the ksTool in the Wadjet-Tools package which supplies a replacement for the Java keytool that will deal with stores that require a password to open them (BoucyCastle). As such the output from the tool does not use a Log4j logger, it writes to an instance of IOCallback from the Wadjet-Utils package, the default is to write to System.out , however you can implement your own IOCallback implementation and set this on the instance to write where you want:
KeyTool kt = KeyTool.getInstance();
kt.setCallback(myIOCallbackImplementation);
or
KeyTool kt = KeyTool.getInstance(myIOCallbackImplementation);
You can then start working with a key store:
KeyTool.KeyStoreData ksd = kt.getKeyStore("path/to/.keystore",
"BouncyCastle",
passwd,
"BC");
If the key store exists it will be loaded, otherwise it will be created in memory.
You could then create your own CA certificate like this:
X509Name x509name = kt.createX509Name(
"CN=CA,OU=Security,O=ADDC Infotech GmbH,L=Estepona,ST=Malaga,C=ES");
kt.generateCAKey("signer",
x509name,
360,
ksd.getKeyStore(),
passwd,
2048,
3,
"path/to/ca.crt",
true,
true);
This will create a signing certificate and private key and export the certificate to a file in RFC format. Thsi certificate can then be used to sign other certificates:
x509name = kt.createX509Name(
"CN=Peter,OU=Testing,O=ADDC Infotech GmbH,L=Estepona,C=es");
kt.generateKeyPair("test",
x509name,
360,
ksd.getKeyStore(),
passwd,
null,
1024,
null,
null,
false,
true);
kt.signCertificate("test",
"signer",
ksd.getKeyStore(),
passwd,
ksd.getKeyStore(),
passwd,
"test.crt",
false,
true,
true);
You will notice that serveral parameters are set to null , this forces the use of default values which are RSA for the key algorithm and SHA1WITHRSA for the signing algorithm.
The Wadjet-Security package also supplies 3 implementations of the principal interface:
and 2 types of Credential which can be added to a javax.security.auth.Subject instance: