All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.owasp.esapi.reference.crypto.ReferenceEncryptedProperties 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.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Set;

import org.owasp.esapi.ESAPI;
import org.owasp.esapi.EncryptedProperties;
import org.owasp.esapi.Logger;
import org.owasp.esapi.crypto.CipherText;
import org.owasp.esapi.crypto.PlainText;
import org.owasp.esapi.errors.EncryptionRuntimeException;

/**
 * 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}.
 * 

* This implementation differs from {@code DefaultEncryptedProperties} in that * it actually extends from {@code java.util.Properties} for applications that need an * instance of that class. In order to do so, the {@code getProperty} and * {@code setProperty} methods were modified to throw {@code EncryptionRuntimeException} * instead of {@code EncryptionException}. * * @author August Detlefsen (augustd at codemagi dot com) * CodeMagi, Inc. * @author [email protected] * @since October 8, 2010 * @see org.owasp.esapi.EncryptedProperties * @see org.owasp.esapi.reference.crypto.DefaultEncryptedProperties */ public class ReferenceEncryptedProperties extends java.util.Properties implements EncryptedProperties { /** * serverVersionUID; use format of YYYYMMDD. */ private static final long serialVersionUID = 20120718L; /** The logger. */ private final Logger logger = ESAPI.getLogger(this.getClass()); private static final String[] GET_ERROR_MESSAGES = new String[]{ ": failed decoding from base64", ": failed to deserialize properly", ": failed to decrypt properly" }; private static final String[] SET_ERROR_MESSAGES = 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?" }; /** * Instantiates a new encrypted properties. */ public ReferenceEncryptedProperties() { super(); } public ReferenceEncryptedProperties(Properties defaults) { super(); for (Object oKey : defaults.keySet()) { String key = (oKey instanceof String) ? (String)oKey : oKey.toString(); String value = defaults.getProperty(key); this.setProperty(key, value); } } /** * {@inheritDoc} * * @throws EncryptionRuntimeException Thrown if decryption fails. */ @Override public synchronized String getProperty(String key) throws EncryptionRuntimeException { int progressMark = 0; try { String encryptedValue = super.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 EncryptionRuntimeException("Property retrieval failure", "Couldn't retrieve encrypted property for property " + key + GET_ERROR_MESSAGES[progressMark], e); } } /** * {@inheritDoc} * * @throws EncryptionRuntimeException Thrown if decryption fails. */ @Override public synchronized String getProperty(String key, String defaultValue) throws EncryptionRuntimeException { String value = getProperty(key); if (value == null) return defaultValue; return value; } /** * {@inheritDoc} * * @throws EncryptionRuntimeException Thrown if encryption fails. */ @Override public synchronized String setProperty(String key, String value) throws EncryptionRuntimeException { 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++; return (String)super.put(key, b64str); } catch (Exception e) { throw new EncryptionRuntimeException("Property setting failure", "Couldn't set encrypted property " + key + SET_ERROR_MESSAGES[progressMark], e); } } /** * {@inheritDoc} * @throws IOException Thrown if input stream invalid or does not * correspond to Java properties file format. */ @Override public void load(InputStream in) throws IOException { super.load(in); logger.trace(Logger.SECURITY_SUCCESS, "Encrypted properties loaded successfully"); } /** * {@inheritDoc} * * For JDK 1.5 compatibility, this method has been overridden convert the Reader * into an InputStream and call the superclass constructor. * * @throws IOException Thrown if {@code Reader} input stream invalid or does not * correspond to Java properties file format. */ public void load(Reader in) throws IOException { if (in == null) return; //read from the reader into a StringBuffer char[] cbuf = new char[65536]; BufferedReader buff = new BufferedReader(in); StringBuilder contents = new StringBuilder(); int read_this_time = 0; while (read_this_time != -1) { read_this_time = buff.read(cbuf, 0, 65536); if (read_this_time > 0) contents.append(cbuf, 0, read_this_time); } //create a new InputStream from the StringBuffer InputStream is = new ByteArrayInputStream(contents.toString().getBytes()); super.load(is); logger.trace(Logger.SECURITY_SUCCESS, "Encrypted properties loaded successfully"); } /** * This method has been overridden to throw an {@code UnsupportedOperationException} */ @Override public void list(PrintStream out) { throw new UnsupportedOperationException("This method has been removed for security."); } /** * This method has been overridden to throw an {@code UnsupportedOperationException} */ @Override public void list(PrintWriter out) { throw new UnsupportedOperationException("This method has been removed for security."); } /** * This method has been overridden to throw an {@code UnsupportedOperationException} */ @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Collection values() { throw new UnsupportedOperationException("This method has been removed for security."); } /** * This method has been overridden to throw an {@code UnsupportedOperationException} */ @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Set entrySet() { throw new UnsupportedOperationException("This method has been removed for security."); } /** * This method has been overridden to throw an {@code UnsupportedOperationException} */ @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Enumeration elements() { throw new UnsupportedOperationException("This method has been removed for security."); } /** * This method has been overridden to only accept Strings for key and value, and to encrypt * those Strings before storing them. Outside classes should always use {@code setProperty} * to add values to the Properties map. If an outside class does erroneously call this method * with non-String parameters an {@code IllegalArgumentException} will be thrown. * * @param key A String key to add * @param value A String value to add * @return The old value associated with the specified key, or {@code null} * if the key did not exist. */ @Override public synchronized Object put(Object key, Object value) { //if java.util.Properties is calling this method, just forward to the implementation in //the superclass (java.util.Hashtable) Throwable t = new Throwable(); for (StackTraceElement trace : t.getStackTrace()) { if ("java.util.Properties".equals(trace.getClassName()) ) return super.put(key, value); } //otherwise, if both arguments are Strings, encrypt and store them if (key instanceof String && value instanceof String) return setProperty((String)key, (String)value); //other Object types are not allowed throw new IllegalArgumentException("This method has been overridden to only accept Strings for key and value."); } /** * This method has been overridden to not print out the keys and values stored in this properties file. * * @return The minimal String representation of this class, as per java.lang.Object. */ @Override public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy