2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.appc.ccadaptor;
23 import java.security.Provider;
24 import java.security.Provider.Service;
25 import java.security.Security;
26 import javax.crypto.Cipher;
27 import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64;
28 import org.jasypt.util.text.BasicTextEncryptor;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * This class is used to encapsulate the encryption and decryption support in one place and to provide a utility to
34 * encrypt and decrypt data.
36 public class EncryptionTool {
39 * The prefix we insert onto any data we encrypt so that we can tell if it is encrpyted later and therefore decrypt
42 @SuppressWarnings("nls")
43 public static final String ENCRYPTED_VALUE_PREFIX = "enc:";
45 * This lock object is used ONLY if the singleton has not been set up.
47 private static final Object lock = new Object();
49 * The salt is used to initialize the PBE (password Based Encrpytion) algorithm.
51 private static final byte[] DEFAULT_SALT = {
52 (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99
55 * The iteration count used to initialize the PBE algorithm and to generate the key spec
57 private static final int ITERATION_COUNT = 20;
59 * The logger for this class.
61 private static final Logger LOG = LoggerFactory.getLogger(EncryptionTool.class);
63 * The algorithm to encrypt and decrpyt data is "Password (or passphrase) Based Encryption with Message Digest #5
64 * and the Data Encryption Standard", i.e., PBEWithMD5AndDES.
66 @SuppressWarnings("nls")
67 private static final String SECURITY_ALGORITHM = "PBEWITHMD5AND256BITAES";// "PBEWithMD5AndDES";
69 * The instance of the encryption utility object
71 private static EncryptionTool instance = null;
73 * The secret passphrase (PBE) that we use to perform encryption and decryption. The algorithm we are using is a
76 private static char[] secret = {
77 'C', '_', 'z', 'l', '!', 'K', '!', '4', '?', 'O', 'z', 'E', 'K', 'E', '>', 'U', 'R', '/', '%', 'Y', '\\', 'f',
78 'b', '"', 'e', 'n', '{', '"', 'l', 'U', 'F', '+', 'E', '\'', 'R', 'T', 'p', '1', 'V', '4', 'l', 'a', '9', 'w',
79 'v', '5', 'Z', '#', 'i', 'V', '"', 'd', 'l', '!', 'L', 'M', 'g', 'L', 'Q', '{', 'v', 'v', 'K', 'V'
82 * The decryption cipher object
84 private Cipher decryptCipher = null;
87 * The encryption cipher object
89 private Cipher encryptCipher = null;
91 private BasicTextEncryptor encryptor;
94 * Get an instance of the EncryptionTool
96 * @return The encryption tool to be used
98 public static final EncryptionTool getInstance() {
99 if (instance == null) {
100 synchronized (lock) {
101 if (instance == null) {
102 instance = new EncryptionTool();
110 * Create the EncryptionTool instance
112 @SuppressWarnings("nls")
113 private EncryptionTool() {
114 // encryptor = new BasicTextEncryptor();
115 // encryptor.setPassword(secret.toString());
116 String out = "Found the following security algorithms:";
117 for (Provider p : Security.getProviders()) {
118 for (Service s : p.getServices()) {
119 String algo = s.getAlgorithm();
121 String.format("\n -Algorithm [ %s ] in provider [ %s ] and service [ %s ]", algo, p.getName(),
129 * Decrypt the provided encrypted text
131 * @param cipherText THe cipher text to be decrypted. If the ciphertext is not encrypted, then it is returned as
133 * @return the clear test of the (possibly) encrypted value. The original value if the string is not encrypted.
135 @SuppressWarnings("nls")
136 public synchronized String decrypt(String cipherText) {
137 if (isEncrypted(cipherText)) {
138 String encValue = cipherText.substring(ENCRYPTED_VALUE_PREFIX.length());
139 // return encryptor.decrypt(encValue);
140 byte[] plainByte = Base64.decodeBase64(encValue.getBytes());
141 byte[] decryptByte = xorWithSecret(plainByte);
142 return new String(decryptByte);
150 * Encrypt the provided clear text
152 * @param clearText The clear text to be encrypted
153 * @return the encrypted text. If the clear text is empty (null or zero length), then an empty string is returned.
154 * If the clear text is already encrypted, it is not encrypted again and is returned as is. Otherwise, the clear
155 * text is encrypted and returned.
157 @SuppressWarnings("nls")
158 public synchronized String encrypt(String clearText) {
159 if (clearText != null) {
160 byte[] encByte = xorWithSecret(clearText.getBytes());
161 String encryptedValue = new String(Base64.encodeBase64(encByte));
162 return ENCRYPTED_VALUE_PREFIX + encryptedValue;
169 * Is a value encrypted? A value is considered to be encrypted if it begins with the {@linkplain
170 * #ENCRYPTED_VALUE_PREFIX encrypted value prefix}.
172 * @param value the value to check.
173 * @return true/false;
175 private static boolean isEncrypted(final String value) {
176 return value != null && value.startsWith(ENCRYPTED_VALUE_PREFIX);
180 * XORs the input byte array with the secret key, padding 0x0 to the end of the secret key if the input is longer
181 * and returns a byte array the same size as input
183 * @param inp The byte array to be XORed with secret
184 * @return A byte array the same size as inp or null if input is null.
186 private byte[] xorWithSecret(byte[] inp) {
191 byte[] secretBytes = new String(secret).getBytes();
192 int size = inp.length;
194 byte[] out = new byte[size];
195 for (int i = 0; i < size; i++) {
196 out[i] = (byte) ((inp[i]) ^ (secretBytes[i % secretBytes.length]));