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: */package org.apache.geronimo.crypto;
017:
018: import java.util.Collections;
019: import java.util.HashMap;
020: import java.util.Map;
021: import java.io.Serializable;
022:
023: /**
024: * A static class that uses registered Encryption instances to encypt and decrypt objects, typically strings.
025: * The encrypted strings are preceded by the name of the Encryption object, such as {Simple}, followed by the base64
026: * encoded encrypted bytes.
027: *
028: * Any number of Encryption instances can be registered but only the first to be explicitly registered will be used.
029: * However, when decrypting the Encryption instance is looked up from the name prefix so may be any registered Encryption instance.
030: * Furthermore, encrypt and decrypt are idempotent. Calling encrypt on a string encrypted with a registered Encryption that is not
031: * the one in use will decrypt the string and re-encrypt it with the one in use. This can be useful when changing Encryption.
032: *
033: * The default Encryption instance (that does not need to be registered) is SimpleEncryption which uses a fixed key hardcoded into
034: * the Encryption class itself. Thus it is useful only to hide information from those who don't read code. On the other hand
035: * you can't lose the key and make your server permanently unusable.
036: *
037: * n.b. calling these methods idempotent is a slight exageration as this would apply only if all arguments and return values are Strings.
038: *
039: * @version $Rev: 617737 $ $Date: 2008-02-01 17:39:58 -0800 (Fri, 01 Feb 2008) $
040: */
041: public class EncryptionManager {
042:
043: private static final Map<String, Encryption> ENCRYPTORS = Collections
044: .synchronizedMap(new HashMap<String, Encryption>());
045: private final static String SIMPLE_ENCRYPTION_PREFIX = "{Simple}";
046:
047: static {
048: ENCRYPTORS.put(SIMPLE_ENCRYPTION_PREFIX,
049: SimpleEncryption.INSTANCE);
050: //login properties files used to have this
051: ENCRYPTORS.put("{Standard}", SimpleEncryption.INSTANCE);
052: }
053:
054: private static String encryptionPrefix = SIMPLE_ENCRYPTION_PREFIX;
055:
056: /**
057: * Encryption instances should call this to register themselves.
058: *
059: * @param prefix id in form {name} for the Encryption instance
060: * @param encryption Encryption instance to do the work.
061: */
062: public synchronized static void setEncryptionPrefix(String prefix,
063: Encryption encryption) {
064: if (SIMPLE_ENCRYPTION_PREFIX.equals(encryptionPrefix)) {
065: encryptionPrefix = prefix;
066: }
067: ENCRYPTORS.put(prefix, encryption);
068: }
069:
070: /**
071: * Idempotent method that outputs string starting with the active registered encryption prefix followed by
072: * the output of the registered Encryption instance. If called with a string encrypted by another
073: * registered Encryption it will re-encrypt with the active Encryption instance.
074: * @param source Serializable object to encrypt, usually a password string or an already encrypted string.
075: * @return the name of the registered Encryption followed by its output.
076: */
077: public static String encrypt(Serializable source) {
078: if (source instanceof String) {
079: String sourceString = (String) source;
080: if (sourceString.startsWith(encryptionPrefix)) {
081: return (String) source;
082: } else if (sourceString.startsWith("{")) {
083: source = decrypt(sourceString);
084: }
085: }
086: Encryption encryption = ENCRYPTORS.get(encryptionPrefix);
087: return encryptionPrefix + encryption.encrypt(source);
088: }
089:
090: /**
091: * Idempotent method that given a String starting with a registered Encryption name will remove the
092: * name prefix and return the result of applying the Encryption to the suffix. If no registered Encryption
093: * name matches the start of the string the input will be returned.
094: * @param source String that is possibly the output of calling encrypt, consisting of a Encryption name followed by its encrypt output.
095: * @return the result of applying the Encryption.decrypt method to the input suffix after identifying the Encryption from the prefix, or the
096: * input if no Encryption name matches.
097: */
098: public static Serializable decrypt(String source) {
099: String prefix = null;
100: Encryption encryption = null;
101: synchronized (ENCRYPTORS) {
102: for (Map.Entry<String, Encryption> entry : ENCRYPTORS
103: .entrySet()) {
104: prefix = entry.getKey();
105: if (source.startsWith(prefix)) {
106: encryption = entry.getValue();
107: break;
108: }
109: }
110: }
111: if (encryption != null) {
112: return encryption
113: .decrypt(source.substring(prefix.length()));
114: }
115: return source;
116: }
117: }
|