Cleanup of utils classes.
[clamp.git] / src / main / java / org / onap / clamp / clds / util / CryptoUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                             reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END============================================
20  * ===================================================================
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  */
23
24 package org.onap.clamp.clds.util;
25
26 import com.att.eelf.configuration.EELFLogger;
27 import com.att.eelf.configuration.EELFManager;
28 import com.google.common.base.Charsets;
29 import java.io.IOException;
30 import java.io.UnsupportedEncodingException;
31 import java.security.GeneralSecurityException;
32 import java.security.SecureRandom;
33 import java.util.Properties;
34 import javax.crypto.Cipher;
35 import javax.crypto.spec.IvParameterSpec;
36 import javax.crypto.spec.SecretKeySpec;
37 import org.apache.commons.codec.DecoderException;
38 import org.apache.commons.codec.binary.Hex;
39 import org.apache.commons.lang3.ArrayUtils;
40
41 /**
42  * CryptoUtils for encrypting/decrypting string based on a Key defined in
43  * application.properties (Spring config file).
44  */
45 public final class CryptoUtils {
46
47     private static final EELFLogger logger = EELFManager.getInstance().getLogger(CryptoUtils.class);
48     // Openssl commands:
49     // Encrypt: echo -n "123456" | openssl aes-128-cbc -e -K <Private Hex key>
50     // -iv <16 Hex Bytes iv> | xxd -u -g100
51     // Final result is to put in properties file is: IV + Outcome of openssl
52     // command
53     // ************************************************************
54     // Decrypt: echo -n 'Encrypted string' | xxd -r -ps | openssl aes-128-cbc -d
55     // -K
56     // <Private Hex Key> -iv <16 Bytes IV extracted from Encrypted String>
57     /**
58      * Definition of encryption algorithm.
59      */
60     private static final String ALGORITHM = "AES";
61     /**
62      * Detailed definition of encryption algorithm.
63      */
64     private static final String ALGORITHM_DETAILS = ALGORITHM + "/CBC/PKCS5PADDING";
65     private static final int BLOCK_SIZE_IN_BITS = 128;
66     private static final int BLOCK_SIZE_IN_BYTES = BLOCK_SIZE_IN_BITS / 8;
67     /**
68      * Key to read in the key.properties file.
69      */
70     private static final String KEY_PARAM = "org.onap.clamp.encryption.aes.key";
71     private static final String PROPERTIES_FILE_NAME = "clds/key.properties";
72     /**
73      * The SecretKeySpec created from the Base 64 String key.
74      */
75     private static final SecretKeySpec SECRET_KEY_SPEC = readSecretKeySpec(PROPERTIES_FILE_NAME);
76
77     /**
78      * Private constructor to avoid creating instances of util class.
79      */
80     private CryptoUtils() {
81     }
82
83     /**
84      * Encrypt a value based on the Clamp Encryption Key.
85      *
86      * @param value The value to encrypt
87      * @return The encrypted string
88      * @throws GeneralSecurityException In case of issue with the encryption
89      * @throws UnsupportedEncodingException In case of issue with the charset conversion
90      */
91     public static String encrypt(String value) throws GeneralSecurityException, UnsupportedEncodingException {
92         Cipher cipher = Cipher.getInstance(ALGORITHM_DETAILS, "SunJCE");
93         SecureRandom randomNumber = SecureRandom.getInstance("SHA1PRNG");
94         byte[] iv = new byte[BLOCK_SIZE_IN_BYTES];
95         randomNumber.nextBytes(iv);
96         IvParameterSpec ivspec = new IvParameterSpec(iv);
97         cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY_SPEC, ivspec);
98         return Hex.encodeHexString(ArrayUtils.addAll(iv, cipher.doFinal(value.getBytes(Charsets.UTF_8))));
99     }
100
101     /**
102      * Decrypt a value based on the Clamp Encryption Key.
103      *
104      * @param message The encrypted string that must be decrypted using the Clamp Encryption Key
105      * @return The String decrypted
106      * @throws GeneralSecurityException In case of issue with the encryption
107      * @throws DecoderException In case of issue to decode the HexString
108      */
109     public static String decrypt(String message) throws GeneralSecurityException, DecoderException {
110         byte[] encryptedMessage = Hex.decodeHex(message.toCharArray());
111         Cipher cipher = Cipher.getInstance(ALGORITHM_DETAILS, "SunJCE");
112         IvParameterSpec ivspec = new IvParameterSpec(ArrayUtils.subarray(encryptedMessage, 0, BLOCK_SIZE_IN_BYTES));
113         byte[] realData = ArrayUtils.subarray(encryptedMessage, BLOCK_SIZE_IN_BYTES, encryptedMessage.length);
114         cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY_SPEC, ivspec);
115         byte[] decrypted = cipher.doFinal(realData);
116         return new String(decrypted);
117     }
118
119     /**
120      * Method used to generate the SecretKeySpec from a Base64 String.
121      *
122      * @param keyString The key as a string in Base 64
123      * @return The SecretKeySpec created
124      * @throws DecoderException In case of issues with the decoding of Base64
125      */
126     private static SecretKeySpec getSecretKeySpec(String keyString) throws DecoderException {
127         byte[] key = Hex.decodeHex(keyString.toCharArray());
128         return new SecretKeySpec(key, ALGORITHM);
129     }
130
131     /**
132      * Reads SecretKeySpec from file specified by propertiesFileName
133      *
134      * @param propertiesFileName File name with properties
135      * @return SecretKeySpec secret key spec read from propertiesFileName
136      */
137     private static SecretKeySpec readSecretKeySpec(String propertiesFileName) {
138         Properties props = new Properties();
139         try {
140             props.load(ResourceFileUtil.getResourceAsStream(propertiesFileName));
141             return getSecretKeySpec(props.getProperty(KEY_PARAM));
142         } catch (IOException | DecoderException e) {
143             logger.error("Exception occurred during the key reading", e);
144             return null;
145         }
146     }
147 }