Led & Sustained by

G2one Logo

Developed with

Intellij

Powered by

Spring

Encryption plugin

A Grails plugin with some Groovy wrappers for both Blowfish and PGP, as well as a tool class for generating random passwords, salting passwords when hashing them, and verifying salted passwords.   Uses the Bouncy Castle encryption libraries.

To install, execute

grails install-plugin http://www.arquetipos.co.cr/blog/files/grails-crypto-1.0.1.zip

The code is documented, and you'll find many test cases for the most common tasks. Some examples, directly from the test cases:

Blowfish

The following encrypts a message with blowfish, and attempts to decrypt it with both the correct password and a bad one.

String message = 'Hush hush'
String password = 'DeVitto'
String badPassword = 'Danny'

// Encrypts the message as a byte array
byte[] encrypted = Blowfish.encrypt(message.getBytes(), password)
assert encrypted

// Decrypts with the correct password, and compares
def decrypted = Blowfish.decrypt(encrypted, password)
assert decrypted
String decryptedString = new String(decrypted)

// Decrypted strings may contain trailing char(0)s
decryptedString = decryptedString.trim()

println "$decryptedString ${decryptedString.getBytes()}"
println "$message ${message.getBytes()}"

assertEquals decryptedString, message

// Decrypting with a bad password returns null
decrypted = Blowfish.decrypt(encrypted, badPassword)
assert decrypted == null

Encrypted values can also be returned base64-encoded, where there's an extra option to trim the result string.

String message = 'Hush hush'
String password ='DeVitto'
String badPassword = 'Danny'

// Encrypts a message and returns it base64-encoded
String encrypted = Blowfish.encryptBase64(message, password)
assert encrypted
String decrypted = Blowfish.decryptBase64(encrypted, password)
assert decrypted

assertEquals decrypted, message

// There's an option to not trim the return value, even though the
// default is to do so. In that case, the decrypted value may not
// exactly match the original message
decrypted = Blowfish.decryptBase64(encrypted, password, false)
assert decrypted != message
assertEquals decrypted.trim(), message

println "The following two rows should be different:"
println "$decrypted ${decrypted.getBytes()}"

// Decrypting with an invalid password returns null
decrypted = Blowfish.decryptBase64(encrypted, badPassword)
assertEquals decrypted, null

PGP

Key generation and encoding:

// Generates a PGP key pair
def pgp = PGP.generateKeyPair()

// Verifies that all values are present
assert pgp
assert pgp.keyPair
assert pgp.publicKey
assert pgp.privateKey

assertEquals pgp.keyPair.publicKey, pgp.publicKey
assertEquals pgp.keyPair.privateKey, pgp.privateKey

// Obtains the public and private keys, encoded armored-encoded
String encodedPublic = pgp.encodedPublicKey
String encodedPrivate = pgp.encodedPrivateKey

// Creates PGP objects which contain only the public or private keys
PGP publicOnly = new PGP(encodedPublic, '')
PGP privateOnly = new PGP('', encodedPrivate)

// Verifies that the previously encoded public key matches the
// one from the object we just created with it
assertEquals encodedPublic, publicOnly.encodedPublicKey

assert publicOnly
assert privateOnly
// Key created from the private key must have the public key as well
assert privateOnly.encodedPrivateKey
assert privateOnly.encodedPublicKey

println "From privateOnly:"
println publicOnly.encodedPublicKey
println privateOnly.encodedPublicKey
println privateOnly.encodedPrivateKey

For encryption, the following code encrypts a message in three different ways, which should all be equivalent. While the example returns the encrypted text as base64-encoded, a function that returns it as a byte array is also available (the equivalent call would be pgp.decrypt)

def pgp = PGP.generateKeyPair()

String encodedPublic = pgp.encodedPublicKey
String encodedPrivate = pgp.encodedPrivateKey

PGP publicOnly = new PGP(encodedPublic, '')
PGP privateOnly = new PGP('', encodedPrivate)

assert publicOnly
assert privateOnly

assertEquals encodedPublic, publicOnly.encodedPublicKey

String message = 'Hush hush'
/* Encrypts the message in three different ways: with the original
   key pair, with the one that only has the public key, and with
   the one that was generated from the private key.  They will later
   be decrypted in several ways to ensure that all are equivalent. */
String encrypted = pgp.encryptBase64(message)
String encrypted2 = publicOnly.encryptBase64(message)
String encrypted3 = privateOnly.encryptBase64(message)

assert encrypted
assert encrypted2
assert encrypted3

println "Encrypted number one:"
println encrypted
println "Encrypted number two:"
println encrypted2


String decryptedPrivate = privateOnly.decryptBase64(encrypted)
assert decryptedPrivate

String decryptedBoth = pgp.decryptBase64(encrypted2)
assert decryptedBoth

assertEquals decryptedPrivate, decryptedBoth
assertEquals decryptedPrivate, message

decryptedPrivate = privateOnly.decryptBase64(encrypted2)
assert decryptedPrivate

decryptedBoth = pgp.decryptBase64(encrypted)
assert decryptedBoth

String decryptedPrivate3 = privateOnly.decryptBase64(encrypted3)
assert decryptedPrivate3

String decryptedBoth3 = pgp.decryptBase64(encrypted3)
assert decryptedBoth3

assertEquals decryptedPrivate, decryptedBoth
assertEquals decryptedPrivate, message
assertEquals decryptedBoth3, message
assertEquals decryptedPrivate3, message

And this code encrypts a message and instead of returning the byte array base64-encoded, returns it encoded as armored text.

def pgp = PGP.generateKeyPair()

String encodedPublic = pgp.encodedPublicKey
String encodedPrivate = pgp.encodedPrivateKey

PGP publicOnly = new PGP(encodedPublic, '')
PGP privateOnly = new PGP('', encodedPrivate)

assert publicOnly
assert privateOnly

assertEquals encodedPublic, publicOnly.encodedPublicKey

String message = 'Hush hush'
String encrypted = pgp.encryptArmored(message)
String encrypted2 = pgp.encryptArmored(message)

println "Armored 1:\n$encrypted\n"
println "Armored 2:\n$encrypted2\n"

In the case of a decryption failure, the decrypt function will return null:

def pgp = PGP.generateKeyPair()
def pgp2 = PGP.generateKeyPair()

String message = 'Hush hush'
String encrypted = pgp.encryptBase64(message)
assert encrypted

String decrypted = pgp2.decryptBase64(encrypted)
assertEquals decrypted, null

While the default encodedPrivateKey function returns the key encrypted with a blank passphrase, one can easily be added:

def pgp = PGP.generateKeyPair()

String passphrase = PasswordTools.generateRandomPassword(10)
assert passphrase
assertEquals passphrase.size(), 10

String encodedPublic = pgp.encodedPublicKey
String encodedPrivate = pgp.getEncodedPrivateKey(passphrase)

// .....
// The encoded key is later instantiated using the passphrase

PGP privateOnly = new PGP('', encodedPrivate, passphrase)
assert privateOnly
</