Appropriate creation of an encryption codec for Datasource at startup

74 views
Skip to first unread message

Doug Snitker

unread,
Dec 2, 2014, 11:23:14 AM12/2/14
to grails-de...@googlegroups.com
Jeff Scott Brown recommended I start a discussion to answer this question based on a topic I posted on StackOverflow here:


Basically I have the following situation.  I'm working with a large client that has multiple grails applications, and more in the pipeline.  These applications are primarily internal to the customer, but some do face their external customers.

My client wants to encrypt some password information in each application to a varying degree.  For instance, they want to encrypt the Database password referenced in their DataSource.groovy for their database.  They also want to encrypt credentials used for some external service calls, and a few other items.

Originally, the client created a DES Codec that would serve most of these needs, but the Codec had a hard coded salt phrase, and thus all of their applications would have used the same "passphrase" so to speak for the encryption of every application if they used this codec everywhere.

After some discussion, I suggested that we look at creating a Codec Factory that will enable them to change the salt phrase and encryption algorithm for their applications based on some type of configuration.  This way they can salt/pepper each application differently and switch algorithms depending on security and jurisdiction requirements (ie, DES for some older applications, AES-256 for domestic apps with JCE, AES-128 for some situations, etc.).  I'm implementing this factory as a Grails plug-in so that it can be dropped easily into the clients other applications, and provide an easy replacement for the codecs they have currently.

My original thought, was to create a factory that used an ApplicationContextAware static class to access the grailsApplication config, I would then externalize the configuration I needed into Config.groovy (saltphrase, algorithm, etc.).  As mentioned in the stackOverflow item above - this worked well for downline services, but the ApplicationContext wasn't available when the connection to the database was established at application launch.  So I ran into a dead end at that point.  I have a "fix" in place right now that stores the values in question in the application.properties file and has the factory pull the configuration from that location when a codec is requested.

This method is functioning ok, but seems kind of clunky (basically a POJO processing a config file on request, not very IoC-ish).  I'm looking for the "correct" way to externalize configuration that might need to be available when the application is starting up. 

Any help understanding this, or suggestions would be welcome.

Doug Snitker

unread,
Dec 2, 2014, 11:27:16 AM12/2/14
to grails-de...@googlegroups.com
I should have mentioned, the apps in question are mostly Grails 2.3.7 - I am hoping to upgrade some of the future development to Grails 2.4+, but for now my plugin will need to be backwards compatible to 2.3.7 at a minimum.

Jeff Scott Brown

unread,
Dec 2, 2014, 11:44:42 AM12/2/14
to grails-de...@googlegroups.com

> On Dec 2, 2014, at 10:23 AM, Doug Snitker <dougs...@gmail.com> wrote:
>
>
> My client wants to encrypt some password information in each application to a varying degree. For instance, they want to encrypt the Database password referenced in their DataSource.groovy for their database. They also want to encrypt credentials used for some external service calls, and a few other items.

Those might end up being 2 different things with 2 different solutions.

Does https://jira.grails.org/browse/GRAILS-3620 address the first requirement you mentioned?



JSB

--
Jeff Scott Brown
jbr...@gopivotal.com

Autism Strikes 1 in 166
Find The Cause ~ Find The Cure
http://www.autismspeaks.org/



Doug Snitker

unread,
Dec 2, 2014, 12:21:58 PM12/2/14
to grails-de...@googlegroups.com
Hi Jeff,

That's dead on with what I'm doing, Inside my DataSource.groovy:

      dataSource {
        dbCreate = 'validate'
        dialect = 'org.hibernate.dialect.Oracle10gDialect'
        driverClassName = 'oracle.jdbc.OracleDriver'
        url = 'obfuscated'
        username = 'obfuscated'
        password = 'obfuscated'
        passwordEncryptionCodec = 'CodecReference'
      }

The thing to note is - those examples are using a static string inside the codec for the encryption salting (in those examples "secret12"). I am attempting to externalize that salt phrase as well as the algorithm type used - ("DES" vs "AES" strings in the def keyFactory = SecretKeyFactory.getInstance("DES") code). If that salt phrase becomes publicized, all of the applications that use it can be decrypted - sort of an "all your eggs in one basket" kind of thing.

So the trick is externalizing those variables and making them configurable on an application basis, in combination with a pepper phrase similar to what's listed in that JIRA. In that case, our getPassword method would be something closer to:

byte[] key = (salt + ( usePepper ? pepper : "" ) ).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-256");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
return key

Where "salt" is something configured on a per application basis, and pepper is similar to the "secret12" phrase in the example.  So in order to reuse the code that's encrypting/decrypting these passwords across applications and have that phrase differ between applications I need to externalize it.  That phrase is what I ended up moving to application.properties and pulling into the codec with a standard properties object using a factory:

static Codec getCodec(){
Properties properties = loadProperties()

String saltValue = properties["crypto.salt"]
int pepperEnabled = properties["crypto.pepper"]
String algorithmValue = properties["crypto.algorithm"]

switch( algorithmValue ) {
case "AES": return new AESCodec( saltValue, pepperEnabled, algorithmValue )
break
case "DES": return new DESCodec( saltValue, pepperEnabled, algorithmValue )
break
}
}

private static Properties loadProperties() {
Properties properties = new Properties()
File propertiesFile = new File("application.properties")
propertiesFile.withInputStream {
properties.load(it)
}
properties
}

The codecs themselves then look pretty much identical to the JIRA code samples from Graeme/Peter with just subtle changes for each algorithms specific requirements.

package edu.psu.ids.security

import groovy.util.logging.Log4j

import javax.crypto.*
import javax.crypto.spec.*
import java.security.Key
import java.security.MessageDigest

@Log4j
class AESCodec extends ConfiguredCodec{

AESCodec(String salt, int pepper, String algorithm) {
super( salt, pepper, algorithm)
}

@Override
def getCipher(mode) {
def cipher = Cipher.getInstance(algorithm)
def secretKey = generateSecretKey(getEncryptionPhrase())
cipher.init(mode, secretKey)
return cipher
}

def Key generateSecretKey(byte[] keySpec) {
SecretKeySpec encodedPass = new SecretKeySpec(keySpec, algorithm)
return encodedPass
}

def byte[] getEncryptionPhrase() {
byte[] key = (salt + ( usePepper ? pepper : "" ) ).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-256");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit
return key
}
}

The ConfiguredCodec base class has the encode/decode methods you see referenced in the Jira item you linked.  The getEncryptionPhrase and getCipher methods vary substantially between AES and DES hence the derived class.

So really, it's that loadProperties item that's my core problem - I wanted to use the doWithSpring block of my plugin to create a static bean with access to the applications configuration information and a container bean with the values of the keys I was after. The bean would then basically have the configuration values for those phrases injected from the parent application and could go about with doing it's business.  So instead of doing all the properties file stuff you see there, my loadProperties method would basically do something like "return <someObjectThatReferencesApplicationConfiguration>" as setup in the doWithSpring block.  Based on my research and our earlier discussion we can rule that out since the ApplicationContext isn't available at the time the database connection is established when the application starts up.  So I guess I'm looking for an alternative to processing that properties file that's Springier :).

Hopefully that makes a bit of sense out of what I'm trying to get to.

Side Note - I appreciate the signature as the parent of one of the 1s in 1 in 166.

-Doug

Christian Knoblauch

unread,
Dec 2, 2014, 1:06:18 PM12/2/14
to grails-de...@googlegroups.com
Doug, have you tried setting your plugin to load before dataSource? Something like this might do the trick:
def loadBefore = ['dataSource']

   Christian

--
You received this message because you are subscribed to the Google Groups "Grails Dev Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to grails-dev-disc...@googlegroups.com.
To post to this group, send email to grails-de...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/grails-dev-discuss/0b5e22e3-1185-4be1-b2ce-71f233dc2303%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Owen Rubel

unread,
Dec 2, 2014, 2:29:56 PM12/2/14
to grails-de...@googlegroups.com
Stego. 
step1 >   Embed partial pass in an image as bytecode, extract from said location, read in bytecode.
step2 >   Embed partial pass2 in an image as bytecode, extract from said location, read in bytecode.
step3 > Assemble.
Reply all
Reply to author
Forward
0 new messages