001/**
002 * Copyright 2010-2013 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.common.util.enc;
017
018import java.util.ArrayList;
019import java.util.List;
020
021import org.jasypt.util.text.BasicTextEncryptor;
022import org.jasypt.util.text.StrongTextEncryptor;
023import org.jasypt.util.text.TextEncryptor;
024import org.kuali.common.util.Assert;
025import org.kuali.common.util.Str;
026
027import com.google.common.base.Optional;
028import com.google.common.collect.ImmutableList;
029
030public class EncUtils {
031
032        private static final String MAGIC_PREFIX = "enc--"; // Handy for passing encrypted args via CLI. Parenthesis tend to confuse CLI shells
033        private static final String PREFIX = "ENC("; // Jasypt prefers this for values in properties files
034        private static final String SUFFIX = ")";
035
036        public static final Optional<EncryptionService> ABSENT = Optional.absent();
037
038        /**
039         * Return true if the text is enclosed with <code>ENC()</code> or starts with <code>enc--</code>
040         */
041        public static boolean isEncrypted(String text) {
042                if (text == null) {
043                        return false;
044                }
045                return Str.matches(text, PREFIX, SUFFIX) || text.startsWith(MAGIC_PREFIX);
046        }
047
048        public static String unwrap(String text) {
049                Assert.noBlanks(text);
050                Assert.encrypted(text);
051                if (text.startsWith(MAGIC_PREFIX)) {
052                        return Str.removePrefix(text, MAGIC_PREFIX);
053                } else {
054                        return Str.remove(text, PREFIX, SUFFIX);
055                }
056        }
057
058        public static String wrap(String text) {
059                Assert.noBlanks(text);
060                Assert.notEncrypted(text);
061                return MAGIC_PREFIX + text;
062        }
063
064        /**
065         * Returns a <code>BasicTextEncryptor</code> that uses <code>password</code> to encrypt/decrypt.
066         */
067        public static TextEncryptor getTextEncryptor(String password) {
068                return getTextEncryptor(password, EncStrength.DEFAULT_VALUE);
069        }
070
071        /**
072         * Return a <code>BasicTextEncryptor</code> or <code>StrongTextEncryptor</code> depending on what <code>strength</code> is set to
073         */
074        public static TextEncryptor getTextEncryptor(String password, EncStrength strength) {
075                Assert.noBlanks(password);
076                switch (strength) {
077                case BASIC:
078                        BasicTextEncryptor basic = new BasicTextEncryptor();
079                        basic.setPassword(password);
080                        return basic;
081                case STRONG:
082                        StrongTextEncryptor strong = new StrongTextEncryptor();
083                        strong.setPassword(password);
084                        return strong;
085                default:
086                        throw new IllegalArgumentException("Encryption strength [" + strength + "] is unknown");
087                }
088        }
089
090        /**
091         * If enc and string are both present and the string is encrypted, return the decrypted string. Otherwise do nothing.
092         */
093        public static Optional<String> decrypt(Optional<EncryptionService> enc, Optional<String> string) {
094                if (enc.isPresent() && string.isPresent()) {
095                        return Optional.of(enc.get().decrypt(string.get()));
096                } else {
097                        return string;
098                }
099        }
100
101        /**
102         * If enc is present and the string is encrypted, return the decrypted string. Otherwise do nothing.
103         */
104        public static String decrypt(Optional<EncryptionService> enc, String string) {
105                return decrypt(enc, Optional.of(string)).get();
106        }
107
108        /**
109         * If enc is present, return a new list containing the same elements in the same order only with any encrypted strings having been decrypted.
110         */
111        public static List<String> decrypt(Optional<EncryptionService> enc, List<String> strings) {
112                if (!enc.isPresent()) {
113                        return strings;
114                }
115                List<String> decrypted = new ArrayList<String>();
116                for (String string : strings) {
117                        decrypted.add(enc.get().decrypt(string));
118                }
119                return ImmutableList.copyOf(decrypted);
120        }
121
122        /**
123         * Return a new list containing the same elements in the same order only with any encrypted strings having been decrypted.
124         */
125        public static List<String> decrypt(EncryptionService enc, List<String> strings) {
126                return decrypt(Optional.of(enc), strings);
127        }
128
129        public static Optional<String> decrypt(EncryptionService enc, Optional<String> optional) {
130                return decrypt(Optional.of(enc), optional);
131        }
132
133}