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

