Added oparent to sdc main
[sdc.git] / openecomp-be / backend / openecomp-sdc-security-util / src / main / java / org / openecomp / sdc / securityutil / SecurityUtil.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.sdc.securityutil;
22
23 import fj.data.Either;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 import javax.crypto.BadPaddingException;
28 import javax.crypto.Cipher;
29 import javax.crypto.IllegalBlockSizeException;
30 import javax.crypto.NoSuchPaddingException;
31 import javax.crypto.spec.SecretKeySpec;
32 import java.io.UnsupportedEncodingException;
33 import java.nio.charset.StandardCharsets;
34 import java.security.InvalidKeyException;
35 import java.security.Key;
36 import java.security.NoSuchAlgorithmException;
37 import java.util.Base64;
38
39 public class SecurityUtil {
40
41     private static final Logger LOG = LoggerFactory.getLogger( SecurityUtil.class );
42     private static final byte[] KEY = new byte[]{-64,5,-32 ,-117 ,-44,8,-39, 1, -9, 36,-46,-81, 62,-15,-63,-75};
43     public static final SecurityUtil INSTANCE = new SecurityUtil();
44     public static final String ALGORITHM = "AES" ;
45     public static final String CHARSET = StandardCharsets.UTF_8.name();
46
47     public static Key secKey = null ;
48
49     /**
50      *
51      * cmd commands >$PROGRAM_NAME decrypt "$ENCRYPTED_MSG"
52      *              >$PROGRAM_NAME encrypt "message"
53     **/
54
55     private SecurityUtil(){ super(); }
56
57     static {
58         try{
59             secKey = generateKey( KEY, ALGORITHM );
60         }
61         catch(Exception e){
62             LOG.warn("cannot generate key for {}", ALGORITHM);
63         }
64     }
65
66
67
68     public static Key generateKey(final byte[] KEY, String algorithm){
69         return new SecretKeySpec(KEY, algorithm);
70     }
71
72     //obfuscates key prefix -> **********
73     public String obfuscateKey(String sensitiveData){
74
75         if (sensitiveData != null){
76             int len = sensitiveData.length();
77             StringBuilder builder = new StringBuilder(sensitiveData);
78             for (int i=0; i<len/2; i++){
79                 builder.setCharAt(i, '*');
80             }
81             return builder.toString();
82         }
83         return sensitiveData;
84     }
85
86     /**
87      *  @param strDataToEncrypt - plain string to encrypt
88      *  Encrypt the Data
89      *          a. Declare / Initialize the Data. Here the data is of type String
90      *          b. Convert the Input Text to Bytes
91      *          c. Encrypt the bytes using doFinal method
92      */
93     public Either<String,String> encrypt(String strDataToEncrypt){
94         if (strDataToEncrypt != null ){
95             try {
96                 LOG.debug("Encrypt key -> {}", secKey);
97                 Cipher aesCipherForEncryption = Cipher.getInstance("AES");          // Must specify the mode explicitly as most JCE providers default to ECB mode!!
98                 aesCipherForEncryption.init(Cipher.ENCRYPT_MODE, secKey);
99                 byte[] byteDataToEncrypt = strDataToEncrypt.getBytes();
100                 byte[] byteCipherText = aesCipherForEncryption.doFinal(byteDataToEncrypt);
101                 String strCipherText = new String( Base64.getMimeEncoder().encode(byteCipherText), CHARSET );
102                 LOG.debug("Cipher Text generated using AES is {}", strCipherText);
103                 return Either.left(strCipherText);
104             } catch( NoSuchAlgorithmException | UnsupportedEncodingException e){
105                 LOG.warn( "cannot encrypt data unknown algorithm or missing encoding for {}" ,secKey.getAlgorithm());
106             } catch( InvalidKeyException e){
107                 LOG.warn( "invalid key recieved - > {} | {}" , Base64.getDecoder().decode( secKey.getEncoded() ), e.getMessage() );
108             } catch( IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException  e){
109                 LOG.warn( "bad algorithm definition (Illegal Block Size or padding), please review you algorithm block&padding" , e.getMessage() );
110             }
111         }
112         return Either.right("Cannot encrypt "+strDataToEncrypt);
113     }
114
115     /**
116      * Decrypt the Data
117      * @param byteCipherText - should be valid bae64 input in the length of 16bytes
118      * @param isBase64Decoded - is data already base64 encoded&aligned to 16 bytes
119      *          a. Initialize a new instance of Cipher for Decryption (normally don't reuse the same object)
120      *          b. Decrypt the cipher bytes using doFinal method
121      */
122     public Either<String,String> decrypt(byte[] byteCipherText , boolean isBase64Decoded){
123         if (byteCipherText != null){
124             byte[] alignedCipherText = byteCipherText;
125             try{
126                 if (isBase64Decoded)
127                     alignedCipherText = Base64.getDecoder().decode(byteCipherText);
128                 LOG.debug("Decrypt key -> "+secKey.getEncoded());
129                 Cipher aesCipherForDecryption = Cipher.getInstance("AES"); // Must specify the mode explicitly as most JCE providers default to ECB mode!!
130                 aesCipherForDecryption.init(Cipher.DECRYPT_MODE, secKey);
131                 byte[] byteDecryptedText = aesCipherForDecryption.doFinal(alignedCipherText);
132                 String strDecryptedText = new String(byteDecryptedText);
133                 LOG.debug("Decrypted Text message is: {}" , obfuscateKey( strDecryptedText ));
134                 return Either.left(strDecryptedText);
135             } catch( NoSuchAlgorithmException e){
136                 LOG.warn( "cannot encrypt data unknown algorithm or missing encoding for {}" ,secKey.getAlgorithm());
137             } catch( InvalidKeyException e){
138                 LOG.warn( "invalid key recieved - > {} | {}" , Base64.getDecoder().decode( secKey.getEncoded() ), e.getMessage() );
139             } catch( IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException  e){
140                 LOG.warn( "bad algorithm definition (Illegal Block Size or padding), please review you algorithm block&padding" , e.getMessage() );
141             }
142         }
143         return Either.right("Decrypt FAILED");
144     }
145
146     public Either<String,String> decrypt(String byteCipherText){
147         try {
148             return decrypt(byteCipherText.getBytes(CHARSET),true);
149         } catch( UnsupportedEncodingException e ){
150             LOG.warn( "Missing encoding for {} | {} " ,secKey.getAlgorithm() , e.getMessage());
151         }
152         return Either.right("Decrypt FAILED");
153     }
154 }