org.owasp.esapi.reference.crypto.DefaultEncryptedProperties Maven / Gradle / Ivy
/**
* OWASP Enterprise Security API (ESAPI)
*
* This file is part of the Open Web Application Security Project (OWASP)
* Enterprise Security API (ESAPI) project. For details, please see
* http://www.owasp.org/index.php/ESAPI.
*
* Copyright (c) 2007 - The OWASP Foundation
*
* The ESAPI is published by OWASP under the BSD license. You should read and accept the
* LICENSE before you use, modify, and/or redistribute this software.
*
* @author Jeff Williams Aspect Security
* @created 2007
*/
package org.owasp.esapi.reference.crypto;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import org.owasp.esapi.ESAPI;
import org.owasp.esapi.Logger;
import org.owasp.esapi.crypto.CipherText;
import org.owasp.esapi.crypto.PlainText;
import org.owasp.esapi.errors.EncryptionException;
/**
* Reference implementation of the {@code EncryptedProperties} interface. This
* implementation wraps a normal properties file, and creates surrogates for the
* {@code getProperty} and {@code setProperty} methods that perform encryption
* and decryption based on {@code Encryptor}.
*
* A very simple main program is provided that can be used to create an
* encrypted properties file. A better approach would be to allow unencrypted
* properties in the file and to encrypt them the first time the file is
* accessed.
*
* @author Jeff Williams (jeff.williams .at. aspectsecurity.com) Aspect Security
* @author [email protected]
* @since June 1, 2007
* @see org.owasp.esapi.EncryptedProperties
* @see org.owasp.esapi.reference.crypto.ReferenceEncryptedProperties
*/
public class DefaultEncryptedProperties implements org.owasp.esapi.EncryptedProperties {
/** The properties. */
private final Properties properties = new Properties();
/** The logger. */
private final Logger logger = ESAPI.getLogger("EncryptedProperties");
/**
* Instantiates a new encrypted properties.
*/
public DefaultEncryptedProperties() {
// hidden
}
/**
* {@inheritDoc}
*/
public synchronized String getProperty(String key) throws EncryptionException {
String[] errorMsgs = new String[] {
": failed decoding from base64",
": failed to deserialize properly",
": failed to decrypt properly"
};
int progressMark = 0;
try {
String encryptedValue = properties.getProperty(key);
if(encryptedValue==null)
return null;
progressMark = 0;
byte[] serializedCiphertext = ESAPI.encoder().decodeFromBase64(encryptedValue);
progressMark++;
CipherText restoredCipherText = CipherText.fromPortableSerializedBytes(serializedCiphertext);
progressMark++;
PlainText plaintext = ESAPI.encryptor().decrypt(restoredCipherText);
return plaintext.toString();
} catch (Exception e) {
throw new EncryptionException("Property retrieval failure",
"Couldn't retrieve encrypted property for property " + key +
errorMsgs[progressMark], e);
}
}
/**
* {@inheritDoc}
*/
public synchronized String setProperty(String key, String value) throws EncryptionException {
String[] errorMsgs = new String[] {
": failed to encrypt properly",
": failed to serialize correctly",
": failed to base64-encode properly",
": failed to set base64-encoded value as property. Illegal key name?"
};
int progressMark = 0;
try {
if ( key == null ) {
throw new NullPointerException("Property name may not be null.");
}
if ( value == null ) {
throw new NullPointerException("Property value may not be null.");
}
// NOTE: Not backward compatible w/ ESAPI 1.4.
PlainText pt = new PlainText(value);
CipherText ct = ESAPI.encryptor().encrypt(pt);
progressMark++;
byte[] serializedCiphertext = ct.asPortableSerializedByteArray();
progressMark++;
String b64str = ESAPI.encoder().encodeForBase64(serializedCiphertext, false);
progressMark++;
String encryptedValue = (String)properties.setProperty(key, b64str);
progressMark++;
return encryptedValue;
} catch (Exception e) {
throw new EncryptionException("Property setting failure",
"Couldn't set encrypted property " + key +
errorMsgs[progressMark], e);
}
}
/**
* {@inheritDoc}
*/
public Set keySet() {
return properties.keySet();
}
/**
* {@inheritDoc}
*/
public void load(InputStream in) throws IOException {
properties.load(in);
logger.trace(Logger.SECURITY_SUCCESS, "Encrypted properties loaded successfully");
}
/**
* {@inheritDoc}
*/
public void store(OutputStream out, String comments) throws IOException {
properties.store(out, comments);
}
/**
* Loads encrypted properties file based on the location passed in args then prompts the
* user to input key-value pairs. When the user enters a null or blank key, the values
* are stored to the properties file.
*
* @param args
* the location of the properties file to load and write to
*
* @throws Exception
* Any exception thrown
* @deprecated Use {@code EncryptedPropertiesUtils} instead, which allows creating, reading,
* and writing encrypted properties. {@code main} method will be removed in a
* future release.
*/
@Deprecated
public static void main(String[] args) throws Exception {
File f = new File(args[0]);
ESAPI.getLogger( "EncryptedProperties.main" ).debug(Logger.SECURITY_SUCCESS, "Loading encrypted properties from " + f.getAbsolutePath() );
if ( !f.exists() ) throw new IOException( "Properties file not found: " + f.getAbsolutePath() );
ESAPI.getLogger( "EncryptedProperties.main" ).debug(Logger.SECURITY_SUCCESS, "Encrypted properties found in " + f.getAbsolutePath() );
DefaultEncryptedProperties ep = new DefaultEncryptedProperties();
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(f);
out = new FileOutputStream(f);
ep.load(in);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String key = null;
do {
System.out.print("Enter key: ");
key = br.readLine();
System.out.print("Enter value: ");
String value = br.readLine();
if (key != null && key.length() > 0 && value != null && value.length() > 0) {
ep.setProperty(key, value);
}
} while (key != null && key.length() > 0);
ep.store(out, "Encrypted Properties File");
} finally {
// FindBugs and PMD both complain about these next lines, that they may
// ignore thrown exceptions. Really!!! That's the whole point.
try { if ( in != null ) in.close(); } catch( Exception e ) {}
try { if ( out != null ) out.close(); } catch( Exception e ) {}
}
Iterator i = ep.keySet().iterator();
while (i.hasNext()) {
String k = (String) i.next();
String value = ep.getProperty(k);
System.out.println(" " + k + "=" + value);
}
}
}