PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/net/schmizz/sshj/common/SecurityUtils.java

https://bitbucket.org/ruraj/acwavab
Java | 282 lines | 140 code | 24 blank | 118 comment | 27 complexity | ab8047e3e573bcfd48b3c7326eb10406 MD5 | raw file
  1. /*
  2. * Copyright 2010-2012 sshj contributors
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. * This file may incorporate work covered by the following copyright and
  17. * permission notice:
  18. *
  19. * Licensed to the Apache Software Foundation (ASF) under one
  20. * or more contributor license agreements. See the NOTICE file
  21. * distributed with this work for additional information
  22. * regarding copyright ownership. The ASF licenses this file
  23. * to you under the Apache License, Version 2.0 (the
  24. * "License"); you may not use this file except in compliance
  25. * with the License. You may obtain a copy of the License at
  26. *
  27. * http://www.apache.org/licenses/LICENSE-2.0
  28. *
  29. * Unless required by applicable law or agreed to in writing,
  30. * software distributed under the License is distributed on an
  31. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  32. * KIND, either express or implied. See the License for the
  33. * specific language governing permissions and limitations
  34. * under the License.
  35. */
  36. package net.schmizz.sshj.common;
  37. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  38. import org.slf4j.Logger;
  39. import org.slf4j.LoggerFactory;
  40. import javax.crypto.Cipher;
  41. import javax.crypto.KeyAgreement;
  42. import javax.crypto.Mac;
  43. import javax.crypto.NoSuchPaddingException;
  44. import java.security.GeneralSecurityException;
  45. import java.security.KeyFactory;
  46. import java.security.KeyPairGenerator;
  47. import java.security.MessageDigest;
  48. import java.security.NoSuchAlgorithmException;
  49. import java.security.NoSuchProviderException;
  50. import java.security.PublicKey;
  51. import java.security.Signature;
  52. // TODO refactor
  53. /** Static utility method relating to security facilities. */
  54. public class SecurityUtils {
  55. private static class BouncyCastleRegistration {
  56. public void run()
  57. throws Exception {
  58. if (java.security.Security.getProvider(BOUNCY_CASTLE) == null) {
  59. LOG.debug("Trying to register BouncyCastle as a JCE provider");
  60. java.security.Security.addProvider(new BouncyCastleProvider());
  61. MessageDigest.getInstance("MD5", BOUNCY_CASTLE);
  62. KeyAgreement.getInstance("DH", BOUNCY_CASTLE);
  63. LOG.info("BouncyCastle registration succeeded");
  64. } else
  65. LOG.info("BouncyCastle already registered as a JCE provider");
  66. securityProvider = BOUNCY_CASTLE;
  67. }
  68. }
  69. private static final Logger LOG = LoggerFactory.getLogger(SecurityUtils.class);
  70. /** Identifier for the BouncyCastle JCE provider */
  71. public static final String BOUNCY_CASTLE = "BC";
  72. /*
  73. * Security provider identifier. null = default JCE
  74. */
  75. private static String securityProvider = null;
  76. // relate to BC registration
  77. private static Boolean registerBouncyCastle;
  78. private static boolean registrationDone;
  79. public static synchronized Cipher getCipher(String transformation)
  80. throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
  81. register();
  82. if (getSecurityProvider() == null)
  83. return Cipher.getInstance(transformation);
  84. else
  85. return Cipher.getInstance(transformation, getSecurityProvider());
  86. }
  87. /**
  88. * Computes the fingerprint for a public key, in the standard SSH format, e.g. "4b:69:6c:72:6f:79:20:77:61:73:20:68:65:72:65:21"
  89. *
  90. * @param key the public key
  91. *
  92. * @return the fingerprint
  93. *
  94. * @see <a href="http://tools.ietf.org/html/draft-friedl-secsh-fingerprint-00">specification</a>
  95. */
  96. public static String getFingerprint(PublicKey key) {
  97. MessageDigest md5;
  98. try {
  99. md5 = getMessageDigest("MD5");
  100. } catch (GeneralSecurityException e) {
  101. throw new SSHRuntimeException(e);
  102. }
  103. md5.update(new Buffer.PlainBuffer().putPublicKey(key).getCompactData());
  104. final String undelimited = ByteArrayUtils.toHex(md5.digest());
  105. assert undelimited.length() == 32 : "md5 contract";
  106. StringBuilder fp = new StringBuilder(undelimited.substring(0, 2));
  107. for (int i = 2; i <= undelimited.length() - 2; i += 2)
  108. fp.append(":").append(undelimited.substring(i, i + 2));
  109. return fp.toString();
  110. }
  111. /**
  112. * Creates a new instance of {@link KeyAgreement} with the given algorithm.
  113. *
  114. * @param algorithm key agreement algorithm
  115. *
  116. * @return new instance
  117. *
  118. * @throws NoSuchAlgorithmException
  119. * @throws NoSuchProviderException
  120. */
  121. public static synchronized KeyAgreement getKeyAgreement(String algorithm)
  122. throws NoSuchAlgorithmException, NoSuchProviderException {
  123. register();
  124. if (getSecurityProvider() == null)
  125. return KeyAgreement.getInstance(algorithm);
  126. else
  127. return KeyAgreement.getInstance(algorithm, getSecurityProvider());
  128. }
  129. /**
  130. * Creates a new instance of {@link KeyFactory} with the given algorithm.
  131. *
  132. * @param algorithm key factory algorithm e.g. RSA, DSA
  133. *
  134. * @return new instance
  135. *
  136. * @throws NoSuchAlgorithmException
  137. * @throws NoSuchProviderException
  138. */
  139. public static synchronized KeyFactory getKeyFactory(String algorithm)
  140. throws NoSuchAlgorithmException, NoSuchProviderException {
  141. register();
  142. if (getSecurityProvider() == null)
  143. return KeyFactory.getInstance(algorithm);
  144. else
  145. return KeyFactory.getInstance(algorithm, getSecurityProvider());
  146. }
  147. /**
  148. * Creates a new instance of {@link KeyPairGenerator} with the given algorithm.
  149. *
  150. * @param algorithm key pair generator algorithm
  151. *
  152. * @return new instance
  153. *
  154. * @throws NoSuchAlgorithmException
  155. * @throws NoSuchProviderException
  156. */
  157. public static synchronized KeyPairGenerator getKeyPairGenerator(String algorithm)
  158. throws NoSuchAlgorithmException, NoSuchProviderException {
  159. register();
  160. if (getSecurityProvider() == null)
  161. return KeyPairGenerator.getInstance(algorithm);
  162. else
  163. return KeyPairGenerator.getInstance(algorithm, getSecurityProvider());
  164. }
  165. /**
  166. * Create a new instance of {@link Mac} with the given algorithm.
  167. *
  168. * @param algorithm MAC algorithm
  169. *
  170. * @return new instance
  171. *
  172. * @throws NoSuchAlgorithmException
  173. * @throws NoSuchProviderException
  174. */
  175. public static synchronized Mac getMAC(String algorithm)
  176. throws NoSuchAlgorithmException, NoSuchProviderException {
  177. register();
  178. if (getSecurityProvider() == null)
  179. return Mac.getInstance(algorithm);
  180. else
  181. return Mac.getInstance(algorithm, getSecurityProvider());
  182. }
  183. /**
  184. * Create a new instance of {@link MessageDigest} with the given algorithm.
  185. *
  186. * @param algorithm MessageDigest algorithm name
  187. *
  188. * @return new instance
  189. *
  190. * @throws NoSuchAlgorithmException
  191. * @throws NoSuchProviderException
  192. */
  193. public static synchronized MessageDigest getMessageDigest(String algorithm)
  194. throws NoSuchAlgorithmException, NoSuchProviderException {
  195. register();
  196. if (getSecurityProvider() == null)
  197. return MessageDigest.getInstance(algorithm);
  198. else
  199. return MessageDigest.getInstance(algorithm, getSecurityProvider());
  200. }
  201. /**
  202. * Get the identifier for the registered security provider.
  203. *
  204. * @return JCE provider identifier
  205. */
  206. public static synchronized String getSecurityProvider() {
  207. register();
  208. return securityProvider;
  209. }
  210. public static synchronized Signature getSignature(String algorithm)
  211. throws NoSuchAlgorithmException, NoSuchProviderException {
  212. register();
  213. if (getSecurityProvider() == null)
  214. return Signature.getInstance(algorithm);
  215. else
  216. return Signature.getInstance(algorithm, getSecurityProvider());
  217. }
  218. /**
  219. * Attempts registering BouncyCastle as security provider if it has not been previously attempted and returns
  220. * whether the registration succeeded.
  221. *
  222. * @return whether BC registered
  223. */
  224. public static synchronized boolean isBouncyCastleRegistered() {
  225. register();
  226. return BOUNCY_CASTLE.equals(securityProvider);
  227. }
  228. public static synchronized void setRegisterBouncyCastle(boolean registerBouncyCastle) {
  229. SecurityUtils.registerBouncyCastle = registerBouncyCastle;
  230. registrationDone = false;
  231. }
  232. /**
  233. * Specifies the JCE security provider that should be used.
  234. *
  235. * @param securityProvider identifier for the security provider
  236. */
  237. public static synchronized void setSecurityProvider(String securityProvider) {
  238. SecurityUtils.securityProvider = securityProvider;
  239. registrationDone = false;
  240. }
  241. private static void register() {
  242. if (!registrationDone) {
  243. if (securityProvider == null && (registerBouncyCastle == null || registerBouncyCastle))
  244. // Use an inner class to avoid a strong dependency on BouncyCastle
  245. try {
  246. new BouncyCastleRegistration().run();
  247. } catch (Throwable t) {
  248. if (registerBouncyCastle == null)
  249. LOG.info("BouncyCastle not registered, using the default JCE provider");
  250. else {
  251. LOG.error("Failed to register BouncyCastle as the defaut JCE provider");
  252. throw new SSHRuntimeException("Failed to register BouncyCastle as the defaut JCE provider", t);
  253. }
  254. }
  255. registrationDone = true;
  256. }
  257. }
  258. }