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