This document describes a demo of an OSS (Open Secret Service) that securely generates, stores, and retrieves secrets using cryptographic techniques like Shamir secret sharing and symmetric/asymmetric encryption. The demo shows how to initialize the OSS with a master key split into shares, generate and retrieve secrets, modify access control lists, wrap data with secrets, and retrieve the original data by unwrapping it with the secret. The goal is to eliminate storing secrets in clear text files, environment variables, or other unsecure locations.
2. No more (unsecure) secrets, Marty
Mathias Herberts
Disruptive Engineer – Crédit Mutuel Arkéa
@herberts
27 au 29 mars 2013
3.
4.
5. Does any of those look familiar?
SecretConstants.java secrets.properties
public class SecretConstants { user = foo
password = bar
/**
* Database User
*/
public static final String USER = "foo"; secrets.xml
/** <secret>
* Database Password <user>foo</user>
*/ <password>bar</password>
public static final String PASSWORD = "bar"; </secret>
}
secrets.yaml
secret:
user: foo
password: bar
…
6. Or maybe one of these?
SuperStrongCryptoConfig.java Use environment variables
public class SuperStrongCryptoConfig {
export PASSWORD = 'foo'
/** java -jar app.jar
* Encrypted User Name
*/ advanced spying tools:
public static final byte[] USER = { 0x33, 0x3a, 0x3a };
/** ps -H e (ps -E)
* Encryption key cat /proc/xxxx/environ
*/
private static final byte KEY = 0x55;
Use system properties
//
// Decrypt the User Name using advanced crypto java -Dpassword=foo -jar app.jar
//
static { more advanced spying tools:
for (int i = 0; i < USER.length; i++) {
USER[i] = (byte) ((USER[i] ^ KEY) & 0xff); ps
} cat /proc/xxxx/cmdline
}
}
…
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20. Demo #1 – OSS Initialization
GenMasterSecret
Offline operation
Generate master key
Split key using a N / K Shamir sharing scheme
Init
Online operation
Needs an SSH key specified in oss.init.sshkeys loaded in the SSH agent
Send K shares of master key to OSS instance
<WRAPPED(<TS><SHARE><SSH SIGNING KEY BLOB><SSH SIGNATURE BLOB>)><SEALED WRAPPING KEY>
OSS instance reassembles shares into master key
27 au 29 mars 2013
21. Demo #1 – OSS Initialization
#
# Generate Master Secret (do it once)
#
java -cp build/libs/oss-client.jar com.geoxp.oss.client.OSSGenMasterSecret secops.gpg ID1,...,IDN K
#
# Launch OSS (in production, run it in your webapp container of choice)
# Check logs for session RSA public key (-Doss.rsa=......:...)
#
gradle -Doss.init.sshkeys=...
-Doss.gensecret.sshkeys=...
-Doss.acl.sshkeys=...
-Doss.keystore.dir=... jettyRun
#
# Send K parts to OSS (need to have authorized SSH keys loaded in SSH agent)
#
gpg -d share-1 | java -Doss.rsa=......:...
-cp build/libs/oss-client.jar
com.geoxp.oss.client.OSSInit http://127.0.0.1:8080/oss
...
gpg -d share-K | java -Doss.rsa=......:...
-cp build/libs/oss-client.jar
com.geoxp.oss.client.OSSInit http://127.0.0.1:8080/oss
27 au 29 mars 2013
22. Demo #2 – OSS Secret Generation
GenSecret
Online operation
Needs an SSH key specified in oss.gensecret.sshkeys loaded in the SSH agent
Send secret name to OSS instance
<TS><SECRET NAME><SSH SIGNING KEY BLOB><SSH SIGNATURE BLOB>
Generate 256 random bits
Encrypt random bits using OSS Master Key
Store blob under oss.keystore.dir (in .secret file, converting dot to path separator)
27 au 29 mars 2013
23. Demo #2 – OSS Secret Generation
#
# Generate Secret named 'devoxx.secret1'
#
java -cp build/libs/oss-client.jar com.geoxp.oss.client.OSSGenSecret devoxx.secret1
#
# Secret file under oss.keystore.dir
#
find oss.keystore.dir -type f
oss.keystore.dir/devoxx/secret1.secret
27 au 29 mars 2013
24. Demo #3 – Modify ACLs for secret
{Add,Remove}ACL
Online operation
Needs an SSH key specified in oss.acl.sshkeys loaded in the SSH agent
Send secret name and SSH key fingeprints to add/remove from ACL to OSS instance
WRAPPED<<TS><<SECRET NAME> <FPR1>...<FPRN>> <SSH SIGNING KEY BLOB><SSH SIGNATURE BLOB>> <SEALED WRAPPING KEY>
OSS instance checks SSH signing key
OSS instance updates ACL file (.acl file at same level as .secret file)
27 au 29 mars 2013
25. Demo #3 – Modify ACLs for secret
#
# Add ACL for devoxx.secret1
#
SSH_FINGERPRINT=2a:e8:a3:c1:e7:89:e3:84:ba:7e:46:3a:0c:24:aa:09
java -cp build/libs/oss-client.jar com.geoxp.oss.client.OSSAddACL URL devoxx.secret1 ${SSH_FINGERPRINT}
#
# ACL file under oss.keystore.dir
#
find oss.keystore.dir -type f
oss.keystore.dir/devoxx/secret1.acl
oss.keystore.dir/devoxx/secret1.secret
#
# Retrieve ACL
#
java -cp build/libs/oss-client.jar com.geoxp.oss.client.OSSGetACL URL devoxx.secret1
[devoxx.secret1]
2a:e8:a3:c1:e7:89:e3:84:ba:7e:46:3a:0c:24:aa:09:
27 au 29 mars 2013
26. Demo #4 – Retrieve secret
GetSecret
Online operation
Needs an SSH key specified in secret ACL file
Send secret name and a temporary RSA public key to OSS instance
<TS><<SECRET NAME> <RSA PUBLIC KEY>> <SSH SIGNING KEY BLOB><SSH SIGNATURE BLOB>
OSS instance checks SSH signing key against secret ACL
OSS instance reads secret from .secret file
OSS instance unwraps secret using its Master Key
OSS instance wraps secret using a random AES key and sends response to client
<WRAPPED SECRET><SEALED WRAPPING KEY>
27 au 29 mars 2013
28. Demo #5 – Wrap secret data
Wrap
Online operation
Needs an SSH key specified in secret ACL file
Retrieve secret (cf GetSecret)
Wrap data read on stdin using secret (with a random 8 bytes prefix)
27 au 29 mars 2013
29. Demo #5 – Wrap secret data
#
# Wrap data using secret
#
echo -n “Hello Devoxx” | java -cp build/libs/oss-client.jar com.geoxp.oss.client.OSSWrap URL devoxx.secret1
Wrapped (8 bytes nonce prefix) = 8476e13e2254e7d276b3dc1616aaa794bdd69cd5916f528cebd6c3527663642f
27 au 29 mars 2013
30. Demo #6 – No more unsecure secrets
import org.apache.commons.codec.binary.Hex;
import com.geoxp.oss.CryptoHelper;
import com.geoxp.oss.client.OSSClient;
public class NoMoreUnsecureSecretsMarty {
private static final String OSS_URL = "oss.url";
private static final String OSS_SECRET = "devoxx.secret1";
private static final String SECRET_DATA = "8476e13e2254e7d276b3dc1616aaa794bdd69cd5916f528cebd6c3527663642f";
public static void main(String[] args) throws Exception {
byte[] secret = OSSClient.getSecret(System.getProperty(OSS_URL), OSS_SECRET, null);
byte[] blob = CryptoHelper.unwrapBlob(secret, Hex.decodeHex(SECRET_DATA.toCharArray()));
System.out.println(new String(blob));
}
}
27 au 29 mars 2013