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.openecomp.vid.encryption;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.security.MessageDigest;
27 import java.util.Properties;
29 import javax.crypto.Cipher;
30 import javax.crypto.spec.SecretKeySpec;
32 import org.apache.commons.cli.CommandLine;
33 import org.apache.commons.cli.CommandLineParser;
34 import org.apache.commons.cli.DefaultParser;
35 import org.apache.commons.cli.Options;
36 import org.apache.commons.cli.ParseException;
37 import org.openecomp.portalsdk.core.logging.logic.EELFLoggerDelegate;
41 * Class to manage encrypted configuration values.
43 public class EncryptedConfiguration {
46 static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(EncryptedConfiguration.class);
49 /** Our secret key and method. */
50 private String encryptionKey;
52 /** The encryption method. */
53 private String encryptionMethod;
56 * Where to log when things go wrong.
59 * @param method the method
62 public EncryptedConfiguration(String key, String method) {
63 encryptionKey = key.trim();
64 encryptionMethod = method;
68 * Retrieve an encrypted string from the given configuration.
69 * The name will have ".x" appended to it.
70 * Decoded from hex, it will be "method:hexsalt:hexvalue".
71 * The format of the value will be in hex.
72 * Method will be "r" to begin with, for "rc4".
75 * @param name the name
76 * @param deflt the deflt
78 * @throws Exception the exception
80 public String getString(String f, String name, String deflt)
82 logger.debug(EELFLoggerDelegate.debugLogger, "==> getString");
83 return getString(f, name, deflt, encryptionKey);
87 * Retrieve an encrypted string from the given configuration.
88 * The name will have ".x" appended to it.
89 * Decoded from hex, it will be "method:hexsalt:hexvalue".
90 * The format of the value will be in hex.
91 * Method will be "r" to begin with, for "rc4".
94 * @param name the name
95 * @param deflt the deflt
98 * @throws Exception the exception
100 public String getString(String f, String name, String deflt, String key)
103 logger.debug(EELFLoggerDelegate.debugLogger, "==> getString");
104 logger.debug(EELFLoggerDelegate.debugLogger, " key = " + key);
105 Properties prop = new Properties();
106 InputStream input = null;
109 input = new FileInputStream(f);
113 /* for testing, a dump of all key-value pairs
114 Enumeration<?> e = prop.propertyNames();
115 while (e.hasMoreElements()) {
116 String k = (String) e.nextElement();
117 String value = prop.getProperty(k);
118 System.out.println("Key : " + k + ", Value : " + value);
122 } catch (IOException ex) {
123 ex.printStackTrace(); // TODO: fix
128 String str = prop.getProperty(name + ".x");
129 logger.debug(EELFLoggerDelegate.debugLogger, "str = " + str);
132 // not encrypted version
133 str = prop.getProperty(name);
140 String method = encryptionMethod;
141 logger.debug(EELFLoggerDelegate.debugLogger, "method = " + method);
142 String salt = EncryptedConfiguration.generateSalt();
143 logger.debug(EELFLoggerDelegate.debugLogger, "salt = " + salt);
145 return decrypt(str, key, method, salt);
149 * Decrypt a string in 'method:hexsalt:hexvalue' format.
151 * @param triple the triple
153 * @param method the method
154 * @param salt the salt
156 * @throws Exception the exception
158 public static String decrypt(String triple, String key, String method, String salt) throws Exception {
160 String[] strParts = triple.trim().split(":");
161 if (strParts.length != 3) throw new Exception("Encrypted value must look like 'x:y:z'");
162 return decrypt(strParts[0], Convert.stringFromHex(strParts[1]), key, Convert.bytesFromHex(strParts[2]));
165 return decrypt(method, salt, key, EncryptConvertor.bytesFromHex(triple));
169 * Decrypt a string 'method:hexsalt:hexvalue' format.
171 * @param method the method
172 * @param salt the salt
174 * @param bvalue the bvalue
176 * @throws Exception the exception
178 public static String decrypt(String method, String salt, String key, byte[] bvalue) throws Exception {
179 logger.debug(EELFLoggerDelegate.debugLogger, "==> decrypt method");
180 logger.debug(EELFLoggerDelegate.debugLogger, " method = " + method);
181 logger.debug(EELFLoggerDelegate.debugLogger, " salt = " + salt);
182 logger.debug(EELFLoggerDelegate.debugLogger, " key = " + key);
183 byte[] secretKey = runDigest(salt + "." + key);
185 SecretKeySpec skeySpec = new SecretKeySpec(secretKey, method);
187 Cipher cipher = Cipher.getInstance(method); // "AES"
188 cipher.init(Cipher.DECRYPT_MODE, skeySpec);
190 byte[] decrypted = cipher.doFinal(bvalue);
191 return new String(decrypted);
195 * Encrypt a string using the given method, salt and key.
197 * @param method the method
198 * @param salt the salt
200 * @param value the value
202 * @throws Exception the exception
204 public static byte[] encrypt(String method, String salt, String key, String value) throws Exception {
205 logger.debug(EELFLoggerDelegate.debugLogger, "==> encrypt() method");
206 byte[] bvalue = value.getBytes();
207 byte[] secretKey = runDigest(salt + "." + key);
209 SecretKeySpec skeySpec = new SecretKeySpec(secretKey, method);
211 Cipher cipher = Cipher.getInstance(method); // "AES"
212 cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
214 byte[] encrypted = cipher.doFinal(bvalue);
219 * Prepare a secret key by running a digest on it.
221 * @param text the text
223 * @throws Exception the exception
225 private static byte[] runDigest(String text) throws Exception {
226 logger.debug(EELFLoggerDelegate.debugLogger, "==> runDigest() method");
227 MessageDigest md = MessageDigest.getInstance("MD5");
229 md.update(text.getBytes(), 0, text.length());
234 * Encrypt a string using the given method, salt and key, and return it as a hex-formated triple.
236 * @param method the method
237 * @param salt the salt
239 * @param value the value
241 * @throws Exception the exception
243 public static String encryptToTriple(String method, String salt, String key, String value) throws Exception {
244 logger.debug(EELFLoggerDelegate.debugLogger, "==> Enter encryptToTriple()");
245 logger.debug(EELFLoggerDelegate.debugLogger, "method = " + method);
246 logger.debug(EELFLoggerDelegate.debugLogger, "salt = " + salt);
247 logger.debug(EELFLoggerDelegate.debugLogger, "key = " + key);
248 logger.debug(EELFLoggerDelegate.debugLogger, "valye = " + value);
251 StringBuffer sb = new StringBuffer(method);
252 sb.append(":").append(Convert.toHexString(salt))
253 .append(":").append(Convert.toHexString(encrypt(method, salt, key, value)));
254 logger.debug("s = " + sb.toString());
257 StringBuffer sb2 = new StringBuffer("");
258 sb2.append(EncryptConvertor.toHexString(encrypt(method, salt, key, value)));
259 String s = sb2.toString();
260 logger.debug(EELFLoggerDelegate.debugLogger, "s = " + s);
265 * Create a value that can be used as a salt.
269 public static String generateSalt() {
270 logger.debug(EELFLoggerDelegate.debugLogger, "==> generaltSalt");
272 // G2 wants to hard code the value for salt.
273 // set the value as 123456789
274 // return Long.toString(System.currentTimeMillis() % 1000) + Pid.getPidStr();
275 return Long.toString(123456789 % 10000);
281 public static void usage() {
290 public static void usage(String msg) {
291 if (msg != null) System.out.println(msg);
292 System.out.println("Usage: java EncryptedConfiguration -D triple -k key\n" +
293 "java EncryptedConfiguration -d string -m method [-s salt | -S] -k key\n" +
294 "java EncryptedConfiguration -e string -m method [-s salt | -S] -k key\n" +
295 "-D\tdecrypt x:y:z triple\n" +
296 "-d\tdecrypt string (in hex)\n" +
297 "-e\tencrypt string\n" +
298 "-S\tgenerate a salt\n"
308 * @param args the arguments
310 public static void main(String[] args) {
312 Options options = new Options();
313 options.addOption("s", true, "salt");
314 options.addOption("S", false, "Generate salt");
315 options.addOption("k", true, "key");
316 options.addOption("m", true, "method");
317 options.addOption("e", true, "encryptString");
318 options.addOption("d", true, "decryptString");
319 options.addOption("D", true, "triple x:y:z");
320 options.addOption("h", false, "show help");
321 options.addOption("?", false, "show help");
323 String salt = null, key = null, method = null, encStr = null, decStr = null, triple = null;
324 boolean genSalt = false;
326 CommandLineParser parser = new DefaultParser();
327 CommandLine cmd = null;
330 cmd = parser.parse(options, args);
332 System.out.println("You picked " + cmd.toString() + "\n");
333 if (cmd.hasOption("s")) {
334 salt = cmd.getOptionValue("s");
336 if (cmd.hasOption("S")) {
338 System.out.println("here in S");
340 if (cmd.hasOption("k")) {
341 key = cmd.getOptionValue("k");
343 if (cmd.hasOption("m")) {
344 method = cmd.getOptionValue("m");
346 if (cmd.hasOption("e")) {
347 encStr = cmd.getOptionValue("e");
349 if (cmd.hasOption("d")) {
350 decStr = cmd.getOptionValue("d");
352 if (cmd.hasOption("D")) {
353 triple = cmd.getOptionValue("D");
355 if (cmd.hasOption("?") || cmd.hasOption("h")) {
360 if (triple == null) {
361 if ((salt == null) && !genSalt) usage("one of -s or -S must be specified");
362 if ((salt != null) && genSalt) usage("only one of -s or -S must be specified");
363 if (key == null) usage("-k must be specified");
364 if (method == null) usage("-m must be specified");
365 if ((encStr == null) && (decStr == null)) usage("one of -d or -e must be specified");
366 if ((encStr != null) && (decStr != null)) usage("only one of -d or -e may be specified");
368 salt = generateSalt();
369 System.out.println("salt = " + salt);
373 System.out.println(encryptToTriple(method, salt, key, encStr));
375 System.out.println(decrypt(method, salt, key, EncryptConvertor.bytesFromHex(decStr)));
378 usage("-k not specified");
381 System.out.println(decrypt(triple, key, method, salt));
384 } catch (ParseException e) {
385 System.out.println("Failed to parse command line properties e="+e.toString());
386 } catch (Exception e) {
387 System.out.println("Failed to run EncryptedConfiguration main() e="+e.toString());
390 // http://forums.sun.com/thread.jspa?threadID=5290983
392 // String message = "Strong Versus Unlimited Strength Cryptography";
393 // SecretKeySpec skeySpec = new SecretKeySpec("0123456789ABCDEF".getBytes(), "AES"); //AES-128
395 // Cipher cipher = Cipher.getInstance("AES"); // "AES/ECB/NoPadding"
396 // cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
398 // byte[] encrypted = cipher.doFinal(message.getBytes());
399 // System.out.println("encrypted string: " + encrypted); //storing into MySQL DB
400 // System.out.println("in hex: '" + Convert.toHexString(encrypted) + "'");
402 // cipher.init(Cipher.DECRYPT_MODE, skeySpec);
403 // byte[] original = cipher.doFinal(encrypted);
404 // String originalString = new String(original);
405 // System.out.println("Original string: " + originalString);
406 // } catch (Exception e) {
407 // System.err.println("Exception caught: " + e.toString());