Add javadoc code
[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
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
35 import javax.crypto.Cipher;
36 import javax.crypto.spec.IvParameterSpec;
37 import javax.crypto.spec.SecretKeySpec;
38
39 import org.apache.commons.codec.DecoderException;
40 import org.apache.commons.codec.binary.Hex;
41 import org.apache.commons.lang3.ArrayUtils;
42
43 /**
44  * CryptoUtils for encrypting/decrypting string based on a Key defined in
45  * application.properties (Spring config file).
46  */
47 public final class CryptoUtils {
48
49     /**
50      * Used to log.
51      */
52     private static final EELFLogger logger = EELFManager.getInstance().getLogger(CryptoUtils.class);
53     // Openssl commands:
54     // Encrypt: echo -n "123456" | openssl aes-128-cbc -e -K <Private Hex key>
55     // -iv <16 Hex Bytes iv> | xxd -u -g100
56     // Final result is to put in properties file is: IV + Outcome of openssl
57     // command
58     // ************************************************************
59     // Decrypt: echo -n 'Encrypted string' | xxd -r -ps | openssl aes-128-cbc -d
60     // -K
61     // <Private Hex Key> -iv <16 Bytes IV extracted from Encrypted String>
62     /**
63      * Definition of encryption algorithm.
64      */
65     private static final String ALGORITHM = "AES";
66     /**
67      * Detailed definition of encryption algorithm.
68      */
69     private static final String ALGORYTHM_DETAILS = ALGORITHM + "/CBC/PKCS5PADDING";
70     /**
71      * Block SIze in bits.
72      */
73     private static final int BLOCK_SIZE = 128;
74     /**
75      * Key to read in the key.properties file.
76      */
77     private static final String KEY_PARAM = "org.onap.clamp.encryption.aes.key";
78     /**
79      * The SecretKeySpec created from the Base 64 String key.
80      */
81     private static SecretKeySpec secretKeySpec = null;
82
83     // Static init
84     static {
85         Properties props = new Properties();
86         try {
87             props.load(ResourceFileUtil.getResourceAsStream("clds/key.properties"));
88             secretKeySpec = getSecretKeySpec(props.getProperty(KEY_PARAM));
89         } catch (IOException | DecoderException e) {
90             logger.error("Exception occurred during the key reading", e);
91         }
92     }
93
94     /**
95      * Encrypt a value based on the Clamp Encryption Key.
96      * 
97      * @param value
98      *            The value to encrypt
99      * @return The encrypted string
100      * @throws GeneralSecurityException
101      *             In case of issue with the encryption
102      * @throws UnsupportedEncodingException
103      *             In case of issue with the charset conversion
104      */
105     public String encrypt(String value) throws GeneralSecurityException, UnsupportedEncodingException {
106         Cipher cipher = Cipher.getInstance(CryptoUtils.ALGORYTHM_DETAILS, "SunJCE");
107         SecureRandom randomNumber = SecureRandom.getInstance("SHA1PRNG");
108         byte[] iv = new byte[BLOCK_SIZE / 8];
109         randomNumber.nextBytes(iv);
110         IvParameterSpec ivspec = new IvParameterSpec(iv);
111         cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec);
112         return Hex.encodeHexString(ArrayUtils.addAll(iv, cipher.doFinal(value.getBytes("UTF-8"))));
113     }
114
115     /**
116      * Decrypt a value based on the Clamp Encryption Key.
117      * 
118      * @param message
119      *            The encrypted string that must be decrypted using the Clamp
120      *            Encryption Key
121      * @return The String decrypted
122      * @throws GeneralSecurityException
123      *             In case of issue with the encryption
124      * @throws DecoderException
125      *             In case of issue to decode the HexString
126      */
127     public String decrypt(String message) throws GeneralSecurityException, DecoderException {
128         byte[] encryptedMessage = Hex.decodeHex(message.toCharArray());
129         Cipher cipher = Cipher.getInstance(CryptoUtils.ALGORYTHM_DETAILS, "SunJCE");
130         IvParameterSpec ivspec = new IvParameterSpec(ArrayUtils.subarray(encryptedMessage, 0, BLOCK_SIZE / 8));
131         byte[] realData = ArrayUtils.subarray(encryptedMessage, BLOCK_SIZE / 8, encryptedMessage.length);
132         cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivspec);
133         byte[] decrypted = cipher.doFinal(realData);
134         return new String(decrypted);
135     }
136
137     /**
138      * Method used to generate the SecretKeySpec from a Base64 String.
139      * 
140      * @param keyString
141      *            The key as a string in Base 64
142      * @return The SecretKeySpec created
143      * @throws DecoderException
144      *             In case of issues with the decoding of Base64
145      */
146     private static SecretKeySpec getSecretKeySpec(String keyString) throws DecoderException {
147         byte[] key = Hex.decodeHex(keyString.toCharArray());
148         return new SecretKeySpec(key, CryptoUtils.ALGORITHM);
149     }
150 }