001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.crypto;
018
019 import java.util.Collections;
020 import java.util.HashMap;
021 import java.util.Map;
022 import java.io.Serializable;
023
024 /**
025 * A static class that uses registered Encryption instances to encypt and decrypt objects, typically strings.
026 * The encrypted strings are preceded by the name of the Encryption object, such as {Simple}, followed by the base64
027 * encoded encrypted bytes.
028 *
029 * Any number of Encryption instances can be registered but only the first to be explicitly registered will be used.
030 * However, when decrypting the Encryption instance is looked up from the name prefix so may be any registered Encryption instance.
031 * Furthermore, encrypt and decrypt are idempotent. Calling encrypt on a string encrypted with a registered Encryption that is not
032 * the one in use will decrypt the string and re-encrypt it with the one in use. This can be useful when changing Encryption.
033 *
034 * The default Encryption instance (that does not need to be registered) is SimpleEncryption which uses a fixed key hardcoded into
035 * the Encryption class itself. Thus it is useful only to hide information from those who don't read code. On the other hand
036 * you can't lose the key and make your server permanently unusable.
037 *
038 * n.b. calling these methods idempotent is a slight exageration as this would apply only if all arguments and return values are Strings.
039 *
040 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
041 */
042 public class EncryptionManager {
043
044 private static final Map<String, Encryption> ENCRYPTORS = Collections.synchronizedMap(new HashMap<String, Encryption>());
045 private final static String SIMPLE_ENCRYPTION_PREFIX = "{Simple}";
046
047 static {
048 ENCRYPTORS.put(SIMPLE_ENCRYPTION_PREFIX, SimpleEncryption.INSTANCE);
049 //login properties files used to have this
050 ENCRYPTORS.put("{Standard}", SimpleEncryption.INSTANCE);
051 }
052
053 private static String encryptionPrefix = SIMPLE_ENCRYPTION_PREFIX;
054
055 /**
056 * Encryption instances should call this to register themselves.
057 *
058 * @param prefix id in form {name} for the Encryption instance
059 * @param encryption Encryption instance to do the work.
060 */
061 public synchronized static void setEncryptionPrefix(String prefix, Encryption encryption) {
062 if (SIMPLE_ENCRYPTION_PREFIX.equals(encryptionPrefix)) {
063 encryptionPrefix = prefix;
064 }
065 ENCRYPTORS.put(prefix, encryption);
066 }
067
068 /**
069 * Idempotent method that outputs string starting with the active registered encryption prefix followed by
070 * the output of the registered Encryption instance. If called with a string encrypted by another
071 * registered Encryption it will re-encrypt with the active Encryption instance.
072 * @param source Serializable object to encrypt, usually a password string or an already encrypted string.
073 * @return the name of the registered Encryption followed by its output.
074 */
075 public static String encrypt(Serializable source) {
076 if (source instanceof String) {
077 String sourceString = (String) source;
078 if (sourceString.startsWith(encryptionPrefix)) {
079 return (String) source;
080 } else if (sourceString.startsWith("{")) {
081 source = decrypt(sourceString);
082 }
083 }
084 Encryption encryption = ENCRYPTORS.get(encryptionPrefix);
085 return encryptionPrefix + encryption.encrypt(source);
086 }
087
088 /**
089 * Idempotent method that given a String starting with a registered Encryption name will remove the
090 * name prefix and return the result of applying the Encryption to the suffix. If no registered Encryption
091 * name matches the start of the string the input will be returned.
092 * @param source String that is possibly the output of calling encrypt, consisting of a Encryption name followed by its encrypt output.
093 * @return the result of applying the Encryption.decrypt method to the input suffix after identifying the Encryption from the prefix, or the
094 * input if no Encryption name matches.
095 */
096 public static Serializable decrypt(String source) {
097 String prefix = null;
098 Encryption encryption = null;
099 synchronized (ENCRYPTORS) {
100 for (Map.Entry<String, Encryption> entry : ENCRYPTORS.entrySet()) {
101 prefix = entry.getKey();
102 if (source.startsWith(prefix)) {
103 encryption = entry.getValue();
104 break;
105 }
106 }
107 }
108 if (encryption != null) {
109 return encryption.decrypt(source.substring(prefix.length()));
110 }
111 return source;
112 }
113 }