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 }