Encryption
KeyService
The KeyService is a service for SDK users which helps developers dealing with standard encryption and decryption problems. To facilitate this the KeyService allows to define aliases for cypher keys which can then be used to encrypt and decrypt data.
The service API focuses on the following topics:
- Securely storing and managing passwords
- Handling password changes via KeyChangeEvent
- Providing encryption and decryption methods for strings and streams
The KeyService uses a master password for encrypting the secure store which will hold the passwords that have been registered with the service. By default the master password is not set and a default encryption is used. If security policies require strong encryption the master password can be provided via: environment variable, java VM parameter, servlet context initialization parameter, sertlet context attribute or via a user dialog at startup of the application.
The KeyService allows a trusted administrator to create new keys and update or delete existing keys. The administrator will be the only one who knows the keys.
The benefits of using the KeyService are:
- The knowledge about keys is seperated from their usage thus, taking simple administrative measures, a developer can do his job without knowing the security keys (for example passwords) that are used in the solution. This increases security because less people know about password and keys that are in use.
- Key changes can be handled in a defined and generic way. SDK developers can take measures for handling events like key created, key changed and key deleted. This further enhances security because policies which require key expiration can now easily be implemented.
- Encrypting and decrypting data is becoming simple using the cryptographic methods provided by the KeyService. This simple access to strong encryption further enhances security since the hurdle of using cryptographic methods has been taken away from SDK developers.
Key Service API
Figure 1: class diagram
The KeyService provides all the functions and objects needed for handling security keys.
This service can be retrieved using:
Nm.getInstance().getKeyService()
The KeyService implements the EventSource interface which allows an SDK developer to create event listeners and register with the KeyService to be notified when key change events occur.
Creating a new alias
Nm.getInstance().getKeyService().setKey("masterPassword", "alias", "key");
After successfully creating a new alias the KeyService will fire a KeyChangeEvent. The old cipher of the KeyChangeEvent will be null.
Update / change an existing alias
Nm.getInstance().getKeyService().changeKey("masterPassword", "alias", "newkey");
After successfully updating an existing alias the KeyService will fire a KeyChangeEvent.
Delete / remove an existing alias
Nm.getInstance().getKeyService().deleteKey("masterPassword", "alias");
After successfully updating an existing alias the KeyService will fire a KeyChangeEvent. The new cipher of the KeyChangeEvent will be null.
Using ciphers
Encrypt / Decrypt a text
// create an encryptor using the key referenced by "myalias"
StringEncryptor enc=Nm.getInstance().getKeyService().getEncryptor("myalias");
// use the encryptor to encrypt a string
String encrypted=enc.encrypt(TXT);
// use the encryptor to decrypt an encrypted string
String txt=enc.decrypt(encrypted);
Encrypt / Decrypt a stream
// encrypt an output stream by wrapping it with a cipher stream
OutputStream cos = Nm.getInstance().getKeyService().encrypt("myalias", outputStream);
// use the cipher output stream
cos.write(bytes);
// flush and close when done
cos.flush();
cos.close();
// decrypt an input stream by wrapping it with a decipher stream
InputStream cis = Nm.getInstance().getKeyService().decrypt("myalias", inputStream);
// use the cipher input stream
cis.read(bytes);
// close when done
cis.close();
Handling key changes
For handling key changes we have to create an EventListener and register at the KeyService.
Then let the EventListener handle the KeyChangeEvent, cases that must be handled are:
- key updated
- key created
- key deleted
The following code illustrates how a KeyChangeEvent listener might look like. Of course proper exception handling must be applied (left away for sake of readability).
import com.nm.Nm;
import com.nm.sdk.events.Event;
import com.nm.sdk.events.EventListener;
import com.nm.sdk.utils.StringUtils;
import com.nm.utils.KeyService;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.*;
public class KeyChangeEventListener implements EventListener {
public KeyChangeEventListener() {
Nm.getInstance().getKeyService().registerListener(this);
}
@Override
public boolean handleEvent(Event event) {
if (event instanceof KeyService.KeyChangeEvent) {
KeyService.KeyChangeEvent kce = (KeyService.KeyChangeEvent) event;
// only handle key changes for alias "myalias"
if (!StringUtils.equals(kce.getAlias(), "myalias")) {
return false;
}
KeyService.KeyServiceEncoderFactory oldK = kce.getOldCipher();
KeyService.KeyServiceEncoderFactory newK = kce.getNewCipher();
if (oldK != null && newK != null) { // key has been updated
File source = null;
File temp = null;
File target = null;
// read with old encryption
InputStream in = oldK.getCipherInputStream(new FileInputStream(source));
// write with new encryption
OutputStream out = newK.getCipherOutputStream(new FileOutputStream(temp));
// copy
IOUtils.copy(in, out);
// move tempfile to final destination
FileUtils.moveFile(temp, target);
} else if (oldK == null && newK != null) { // key has been created
// handle key created case...
} else if (oldK != null && newK == null) { // key has been deleted
// handle key delete case...
} else {
// old and new ciphers are null, BAILOUT!
}
}
return true;
}
}
Application Startup & Master Password
Depending on security policies Appway provides two modes of starting the application. If no master password is defined or if the master password is given via a configuration property the application will startup going through startup phases One and Two without requiring user interaction.
If - on the other hand - a master password has been set, but it is not provided via a configuration property, the application will startup with phase One and then wait, requiring an Administrator to enter the master password in a web dialogue in order to continue with startup phase Two.
The diagram below illustrates the startup procedure:

Figure 2: application startup
Master Password Configuration
See the dedicated Master Password for details on the configuration.