PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/core/src/main/java/org/adroitlogic/ultraesb/util/encrypt/SecurePropertyManager.java

https://bitbucket.org/adroitlogic/ultraesb/
Java | 206 lines | 127 code | 33 blank | 46 comment | 26 complexity | 51b62b274940ff567fb09c6182a97450 MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*
  2. * AdroitLogic UltraESB Enterprise Service Bus
  3. *
  4. * Copyright (c) 2010-2015 AdroitLogic Private Ltd. (http://adroitlogic.org). All Rights Reserved.
  5. *
  6. * GNU Affero General Public License Usage
  7. *
  8. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
  9. * Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
  13. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License along with this program (See LICENSE-AGPL.TXT).
  17. * If not, see http://www.gnu.org/licenses/agpl-3.0.html
  18. *
  19. * Commercial Usage
  20. *
  21. * Licensees holding valid UltraESB Commercial licenses may use this file in accordance with the UltraESB Commercial
  22. * License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written
  23. * agreement between you and AdroitLogic.
  24. *
  25. * If you are unsure which license is appropriate for your use, or have questions regarding the use of this file,
  26. * please contact AdroitLogic at info@adroitlogic.com
  27. */
  28. package org.adroitlogic.ultraesb.util.encrypt;
  29. import org.adroitlogic.logging.api.Logger;
  30. import org.adroitlogic.ultraesb.api.BusRuntimeException;
  31. import org.adroitlogic.logging.api.LoggerFactory;
  32. import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
  33. import javax.crypto.Cipher;
  34. import javax.crypto.spec.SecretKeySpec;
  35. import java.math.BigInteger;
  36. import java.security.SecureRandom;
  37. /**
  38. * Allows sensitive information such as passwords specified on the configurations to be secured
  39. *
  40. * @author asankha
  41. */
  42. public class SecurePropertyManager extends PropertyPlaceholderConfigurer {
  43. private static final Logger logger = LoggerFactory.getLogger(SecurePropertyManager.class);
  44. private static final String USAGE = "Invalid arguments. Execute as follows:\n" +
  45. "java SecurePropertyManager [-decrypt] <secret> [-p<password>] [-a<algorithm>] [-salted]";
  46. private static final String SALT_PREFIX = "__salt__";
  47. private String algorithm = "Blowfish";
  48. private String password = "jaas is the way";
  49. private String passwordEnvVar = null;
  50. private boolean salted = false;
  51. private Cipher decipher;
  52. private Cipher cipher;
  53. private SecureRandom secureRandom = new SecureRandom();
  54. public void setPassword(String password) {
  55. this.password = password;
  56. }
  57. public void setAlgorithm(String algorithm) {
  58. this.algorithm = algorithm;
  59. }
  60. public void setPasswordEnvVar(String passwordEnvVar) {
  61. this.passwordEnvVar = passwordEnvVar;
  62. }
  63. public void setSalted(boolean salted) {
  64. this.salted = salted;
  65. }
  66. private String getPassword() {
  67. if (passwordEnvVar != null) {
  68. return System.getenv(passwordEnvVar);
  69. }
  70. return password;
  71. }
  72. public void init() {
  73. try {
  74. decipher = Cipher.getInstance(algorithm);
  75. decipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(getPassword().getBytes(), algorithm));
  76. cipher = Cipher.getInstance(algorithm);
  77. cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(getPassword().getBytes(), algorithm));
  78. } catch (Exception e) {
  79. logger.error("Error initializing algorithm : {}", algorithm, e);
  80. throw new BusRuntimeException("Error initializing algorithm : " + algorithm, e);
  81. }
  82. }
  83. protected String convertPropertyValue(final String originalValue) {
  84. if (originalValue.startsWith("SALTEDBIGINT16(") && originalValue.endsWith(")")) {
  85. try {
  86. BigInteger bigInteger = new BigInteger(originalValue.substring(15, originalValue.length() - 1), 16);
  87. byte[] encryptedBytes = bigInteger.toByteArray();
  88. byte[] decrypted = decipher.doFinal(encryptedBytes);
  89. final String decryptedStr = new String(decrypted);
  90. final int pos = decryptedStr.indexOf(SALT_PREFIX);
  91. return decryptedStr.substring(0, pos);
  92. } catch (Exception e) {
  93. logger.error("Error decoding encrypted and salted property key : {}", originalValue, e);
  94. throw new BusRuntimeException("Error decoding encrypted property key : " + originalValue, e);
  95. }
  96. } else if (originalValue.startsWith("BIGINT16(") && originalValue.endsWith(")")) {
  97. try {
  98. BigInteger bigInteger = new BigInteger(originalValue.substring(9, originalValue.length() - 1), 16);
  99. byte[] encryptedBytes = bigInteger.toByteArray();
  100. byte[] decrypted = decipher.doFinal(encryptedBytes);
  101. return new String(decrypted);
  102. } catch (Exception e) {
  103. logger.error("Error decoding encrypted property key : {}", originalValue, e);
  104. throw new BusRuntimeException("Error decoding encrypted property key : " + originalValue, e);
  105. }
  106. }
  107. return originalValue;
  108. }
  109. private String encrypt(String originalValue) {
  110. if (salted) {
  111. originalValue = originalValue + SALT_PREFIX + secureRandom.nextLong();
  112. }
  113. try {
  114. byte[] encrypted = cipher.doFinal(originalValue.getBytes());
  115. BigInteger bigInteger = new BigInteger(encrypted);
  116. return (salted ? "SALTEDBIGINT16(" : "BIGINT16(") + bigInteger.toString(16) + ")";
  117. } catch (Exception e) {
  118. logger.error("Error decoding encrypted property key : {}", originalValue, e);
  119. throw new BusRuntimeException("Error decoding encrypted property key : " + originalValue, e);
  120. }
  121. }
  122. /**
  123. * Encrypts (unless -decrypt is specified) the <input> using the <password> and <algorithm>, or decrypts it
  124. * <p/>
  125. * The default algorithm is Blowfish, and the password is the default used in JBoss AS
  126. * <p/>
  127. * java SecurePropertyManager [-decrypt] <input> [-p<password>] [-a<algorithm>] [-salted]
  128. * <p/>
  129. * Examples of clear text and encrypted passwords
  130. * test, 48e90df5bc00051e
  131. * esb2004db, -17741c6ab3e49477dd7a7db5da950da9
  132. * dbESB0420, -2840cadf9d9e244af66025633c93b691
  133. * aä&zz%4d, -662396de3bba58629ba2ea1ca027b24c
  134. * xyz/{\d, 3331ee4824be0100
  135. */
  136. public static void main(String[] args) throws Exception {
  137. SecurePropertyManager s = new SecurePropertyManager();
  138. if (args.length == 0 || args.length > 6) {
  139. System.out.println(USAGE);
  140. return;
  141. }
  142. boolean encrypt = true;
  143. String input = null;
  144. for (String arg : args) {
  145. if ("-decrypt".equals(arg)) {
  146. encrypt = false;
  147. } else if ("-salted".equals(arg)) {
  148. s.setSalted(true);
  149. } else if (arg.startsWith("-p")) {
  150. s.setPassword(arg.substring(2));
  151. } else if (arg.startsWith("-a")) {
  152. s.setAlgorithm(arg.substring(2));
  153. } else {
  154. input = arg;
  155. }
  156. }
  157. if (input == null) {
  158. System.out.println(USAGE);
  159. return;
  160. }
  161. s.init();
  162. if (encrypt) {
  163. final String result = s.encrypt(input);
  164. if (input.equals(s.convertPropertyValue(result))) {
  165. System.out.println(result);
  166. } else {
  167. System.out.println("Unexpected error encrypting the password - " + input);
  168. }
  169. } else {
  170. System.out.println(s.convertPropertyValue(input));
  171. }
  172. }
  173. }