Appropriate creation of an encryption codec for Datasource at startup

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Appropriate creation of an encryption codec for Datasource at startup

Doug Snitker
Jeff Scott Brown recommended I start a discussion to answer this question based on a topic I posted on StackOverflow here:

http://stackoverflow.com/questions/27219836/datasource-groovy-executed-prior-to-application-context-loading/27222415?noredirect=1#comment42979488_27222415

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.

--
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 [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/grails-dev-discuss/8d43bbea-0dcb-4010-a795-b53e089ea382%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Appropriate creation of an encryption codec for Datasource at startup

Doug Snitker
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.

On Tuesday, December 2, 2014 10:23:14 AM UTC-6, Doug Snitker wrote:
Jeff Scott Brown recommended I start a discussion to answer this question based on a topic I posted on StackOverflow here:

<a href="http://stackoverflow.com/questions/27219836/datasource-groovy-executed-prior-to-application-context-loading/27222415?noredirect=1#comment42979488_27222415" target="_blank" onmousedown="this.href='http://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestions%2F27219836%2Fdatasource-groovy-executed-prior-to-application-context-loading%2F27222415%3Fnoredirect%3D1%23comment42979488_27222415\46sa\75D\46sntz\0751\46usg\75AFQjCNGFibI7jGhQ6GXm0DJSuKP334eHJw';return true;" onclick="this.href='http://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestions%2F27219836%2Fdatasource-groovy-executed-prior-to-application-context-loading%2F27222415%3Fnoredirect%3D1%23comment42979488_27222415\46sa\75D\46sntz\0751\46usg\75AFQjCNGFibI7jGhQ6GXm0DJSuKP334eHJw';return true;">http://stackoverflow.com/questions/27219836/datasource-groovy-executed-prior-to-application-context-loading/27222415?noredirect=1#comment42979488_27222415

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.

--
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 [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/grails-dev-discuss/0e39cbc9-cbf6-432f-9bc0-769ec93a0a5a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Appropriate creation of an encryption codec for Datasource at startup

Jeff Scott Brown-3
In reply to this post by Doug Snitker

> On Dec 2, 2014, at 10:23 AM, Doug Snitker <[hidden email]> 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
[hidden email]

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



--
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 [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/grails-dev-discuss/36CE2BE3-A5D9-4178-ACCA-ECD3EAA43D3F%40pivotal.io.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Appropriate creation of an encryption codec for Datasource at startup

Doug Snitker
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

On Tuesday, December 2, 2014 10:44:42 AM UTC-6, jbrown wrote:

> On Dec 2, 2014, at 10:23 AM, Doug Snitker <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="yo7IbRhvj9MJ" onmousedown="this.href='javascript:';return true;" onclick="this.href='javascript:';return true;">dougs...@...> 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 <a href="https://jira.grails.org/browse/GRAILS-3620" target="_blank" onmousedown="this.href='https://www.google.com/url?q\75https%3A%2F%2Fjira.grails.org%2Fbrowse%2FGRAILS-3620\46sa\75D\46sntz\0751\46usg\75AFQjCNFOoVLOTKnj8-v0WEy7nihycpPLkg';return true;" onclick="this.href='https://www.google.com/url?q\75https%3A%2F%2Fjira.grails.org%2Fbrowse%2FGRAILS-3620\46sa\75D\46sntz\0751\46usg\75AFQjCNFOoVLOTKnj8-v0WEy7nihycpPLkg';return true;">https://jira.grails.org/browse/GRAILS-3620 address the first requirement you mentioned?



JSB

--
Jeff Scott Brown
<a href="javascript:" target="_blank" gdf-obfuscated-mailto="yo7IbRhvj9MJ" onmousedown="this.href='javascript:';return true;" onclick="this.href='javascript:';return true;">jbr...@...

Autism Strikes 1 in 166
Find The Cause ~ Find The Cure
<a href="http://www.autismspeaks.org/" target="_blank" onmousedown="this.href='http://www.google.com/url?q\75http%3A%2F%2Fwww.autismspeaks.org%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNHLOilSQBYB1lzLN6Ms6K6DtQY5DQ';return true;" onclick="this.href='http://www.google.com/url?q\75http%3A%2F%2Fwww.autismspeaks.org%2F\46sa\75D\46sntz\0751\46usg\75AFQjCNHLOilSQBYB1lzLN6Ms6K6DtQY5DQ';return true;">http://www.autismspeaks.org/



--
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 [hidden email].
To post to this group, send email to [hidden email].
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.
Reply | Threaded
Open this post in threaded view
|

Re: Appropriate creation of an encryption codec for Datasource at startup

Christian Knoblauch
Doug, have you tried setting your plugin to load before dataSource? Something like this might do the trick:
def loadBefore = ['dataSource']

   Christian

On Tue, Dec 2, 2014 at 2:21 PM, Doug Snitker <[hidden email]> wrote:
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

On Tuesday, December 2, 2014 10:44:42 AM UTC-6, jbrown wrote:

> On Dec 2, 2014, at 10:23 AM, Doug Snitker <[hidden email]> 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
[hidden email]

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



--
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 [hidden email].
To post to this group, send email to [hidden email].
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.

--
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 [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/grails-dev-discuss/CAHnbsiN-%2BURCD8B3yCe2w4iCEwWq-kiCMg11gzVwX1g5tX3Q%2Bg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Appropriate creation of an encryption codec for Datasource at startup

Owen Rubel
In reply to this post by Doug Snitker
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.


On Tuesday, December 2, 2014 8:23:14 AM UTC-8, Doug Snitker wrote:
Jeff Scott Brown recommended I start a discussion to answer this question based on a topic I posted on StackOverflow here:

<a href="http://stackoverflow.com/questions/27219836/datasource-groovy-executed-prior-to-application-context-loading/27222415?noredirect=1#comment42979488_27222415" target="_blank" onmousedown="this.href='http://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestions%2F27219836%2Fdatasource-groovy-executed-prior-to-application-context-loading%2F27222415%3Fnoredirect%3D1%23comment42979488_27222415\46sa\75D\46sntz\0751\46usg\75AFQjCNGFibI7jGhQ6GXm0DJSuKP334eHJw';return true;" onclick="this.href='http://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestions%2F27219836%2Fdatasource-groovy-executed-prior-to-application-context-loading%2F27222415%3Fnoredirect%3D1%23comment42979488_27222415\46sa\75D\46sntz\0751\46usg\75AFQjCNGFibI7jGhQ6GXm0DJSuKP334eHJw';return true;">http://stackoverflow.com/questions/27219836/datasource-groovy-executed-prior-to-application-context-loading/27222415?noredirect=1#comment42979488_27222415

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.

--
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 [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/grails-dev-discuss/98df28e0-fc8c-4e2d-a9fa-2f1e2577c66f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.