Repository navigation
Encryption
Zuul utilizes PBE (Password Based Encryption) algorithms from the JCE (Java Cryptography Extension) and Bouncy Castle via the Jasypt API.
The Zuul server and spring client are both bundled with everything except for the JCE Policy files. You'll need to download and install them into your JAVA_HOME/jre/lib/security directory.
If you're using Jasypt directly or using another language such as Node.js, Ruby, etc., The following details will help you get started. I'm working on a Node.js client which should be available soon.
By default, every JVM is able to do simple encryption. Without any modifications, any java client can use DES encryption but it's no longer considered secure due to its small key size. Zuul has the ability to use stronger algorithms but the server and clients will have extra dependencies.
AES (Bouncy Castle)
- Name: PBEWITHSHA256AND128BITAES-CBC-BC
- Requirements: Bouncy Castle API and JCE Unlimited Strength Policy Files
- Hashing Algorithm: SHA256
- Hashing Iterations: 1000
Triple DES (Bouncy Castle)
- Name: PBEWithSHAAnd2-KeyTripleDES-CBC
- Requirements: Bouncy Castle API and JCE Unlimited Strength Policy Files
- Hashing Algorithm: SHA2 (TODO: verify which size)
- Hashing Iterations: 1000
Triple DES (JCE)
- Name: PBEWithMD5AndTripleDES
- Requirements: JCE Unlimited Strength Policy Files
- Hashing Algorithm: MD5
- Hashing Iterations: 1000
DES (JCE)
- Name: PBEWithMD5AndDES
- Requirements: none (but not secure)
- Hashing Algorithm: MD5
- Hashing Iterations: 1000
Essentially, algorithms must have a key of x bits and should be relatively random. Using passwords as keys posses two problems:
- They probably aren't going to match the number of bits you'll need to create a key
- They're based on a limited number of characters which restricts the amount of randomness available even if you have a super, duper, really great password.
To overcome this limitation, RSA Labs created a few specs such as PKCS#5 which outlines how to create cryptography keys from passwords with increased security.
Essentially, the password is combined with a salt (usually random bits). This is then fed through a hashing algorithm many (1000+) times to create the secret key via a Key Derivation Function (KDF). The salt, hashing algorithm and iteration counts are not considered to be secret and may be freely exchanged.
The encrypted values produced by Jasypt (and thus Zuul) are are prefixed with the salt (usually 8 or 16 bytes depending on the algorithm requirements). They are then Base64 encoded. Decrypting the results goes something like this:
- Convert the Base64 string to bytes
- Strip off the first 8 or 16 bytes as the salt
- Keep the remaining bytes for the encrypted payload
- Invoke the KDF function with the salt, iteration count and the password to create the secret key.
- Use the secret key to decrypt the encrypted payload
The main issue that you're likely to run into is the version of the KDF function used. Although Java supports PKDF2 (which is more secure), Jasypt still uses PKDF1. There have been requests to enhance it but they've been declined:
http://brianrepko.wordpress.com/2010/07/21/extending-jasypt-aes-and-blowfish-support/ http://sourceforge.net/tracker/?func=detail&aid=3032821&group_id=183612&atid=905947
PKDF2 is predominant in most other platforms. Replicating the PDKF1 behavior is relatively easy. The following is a Node.js (javascript) example using its crypto lib:
Mocha Test
var should = require('should'),
crypto = require('crypto');
describe('Crypto Spike Tests', function () {
var password = new Buffer('test', 'utf8');
var KDF = function(password, salt, iterations) {
var key = Buffer.concat([password, salt]);
for (var i = 0; i < iterations; i++) {
key = crypto.createHash("md5").update(key).digest();
}
return key;
};
it('should decrypt PBEWithMD5AndDES with 1000 hash iterations', function () {
var encryptedBuffer = new Buffer('/w5a6LHjfwbjhTLUAKiPKg==', 'base64');
var salt = encryptedBuffer.slice(0, 8);
var payload = encryptedBuffer.slice(8);
var key = KDF(password, salt, 1000);
var keyBuffer = new Buffer(key, 'binary').slice(0,8);
var ivBuffer = new Buffer(key, 'binary').slice(8,16);
var decipher = crypto.createDecipheriv('des', keyBuffer, ivBuffer);
var msg = [];
msg.push(decipher.update(payload));
msg.push(decipher.final());
var decrypted = msg.join("");
decrypted.should.eql('abc');
});
});
Zuul 1.4 adds increased encryption security and portability with the introduction of PGP public key encryption. You may now upload your ASCII armored public key:

With PGP support adds increased security but comes a few limitations:
- Decryption features are disabled because no secret key exists on the server. Clients are responsible for maintaining the secret key and decryption operations.
- Once a settings group has been updated to use a PGP key, it may not be changed to another key until all values are deleted or manually unencrypted
- Updating a PGP public key has the same limitations. Any assigned groups must have no encrypted values.
Zuul has error handling and warnings around these rules but keep all of this in mind before you choose to use PGP encryption.
If you need help generating keys, etc. Please see the PGP Help page.
- Home
- Installation
- [Client Integration] (https://github.com/mcantrell/Zuul/wiki/Client-Integration)
- [Encryption] (https://github.com/mcantrell/Zuul/wiki/Encryption)
- [Security] (https://github.com/mcantrell/Zuul/wiki/Security)
- [Developers] (https://github.com/mcantrell/Zuul/wiki/Developers)