PageRenderTime 59ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/android/upstream/org/bouncycastle/openssl/PEMUtilities.java

https://bitbucket.org/festevezga/xobotos
Java | 280 lines | 242 code | 29 blank | 9 comment | 32 complexity | b3d142ad1b65f8eead2adfac62e1855b MD5 | raw file
  1. package org.bouncycastle.openssl;
  2. import java.io.IOException;
  3. import java.security.Key;
  4. import java.security.Provider;
  5. import java.security.Security;
  6. import java.security.spec.AlgorithmParameterSpec;
  7. import java.util.HashMap;
  8. import java.util.HashSet;
  9. import java.util.Map;
  10. import java.util.Set;
  11. import javax.crypto.Cipher;
  12. import javax.crypto.SecretKey;
  13. import javax.crypto.spec.IvParameterSpec;
  14. import javax.crypto.spec.RC2ParameterSpec;
  15. import javax.crypto.spec.SecretKeySpec;
  16. import org.bouncycastle.asn1.DERObjectIdentifier;
  17. import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
  18. import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
  19. import org.bouncycastle.crypto.PBEParametersGenerator;
  20. import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
  21. import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
  22. import org.bouncycastle.crypto.params.KeyParameter;
  23. final class PEMUtilities
  24. {
  25. private static final Map KEYSIZES = new HashMap();
  26. private static final Set PKCS5_SCHEME_1 = new HashSet();
  27. private static final Set PKCS5_SCHEME_2 = new HashSet();
  28. static
  29. {
  30. PKCS5_SCHEME_1.add(PKCSObjectIdentifiers.pbeWithMD2AndDES_CBC);
  31. PKCS5_SCHEME_1.add(PKCSObjectIdentifiers.pbeWithMD2AndRC2_CBC);
  32. PKCS5_SCHEME_1.add(PKCSObjectIdentifiers.pbeWithMD5AndDES_CBC);
  33. PKCS5_SCHEME_1.add(PKCSObjectIdentifiers.pbeWithMD5AndRC2_CBC);
  34. PKCS5_SCHEME_1.add(PKCSObjectIdentifiers.pbeWithSHA1AndDES_CBC);
  35. PKCS5_SCHEME_1.add(PKCSObjectIdentifiers.pbeWithSHA1AndRC2_CBC);
  36. PKCS5_SCHEME_2.add(PKCSObjectIdentifiers.id_PBES2);
  37. PKCS5_SCHEME_2.add(PKCSObjectIdentifiers.des_EDE3_CBC);
  38. PKCS5_SCHEME_2.add(NISTObjectIdentifiers.id_aes128_CBC);
  39. PKCS5_SCHEME_2.add(NISTObjectIdentifiers.id_aes192_CBC);
  40. PKCS5_SCHEME_2.add(NISTObjectIdentifiers.id_aes256_CBC);
  41. // BEGIN android-changed
  42. KEYSIZES.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), Integer.valueOf(192));
  43. KEYSIZES.put(NISTObjectIdentifiers.id_aes128_CBC.getId(), Integer.valueOf(128));
  44. KEYSIZES.put(NISTObjectIdentifiers.id_aes192_CBC.getId(), Integer.valueOf(192));
  45. KEYSIZES.put(NISTObjectIdentifiers.id_aes256_CBC.getId(), Integer.valueOf(256));
  46. // END android-changed
  47. }
  48. static int getKeySize(String algorithm)
  49. {
  50. if (!KEYSIZES.containsKey(algorithm))
  51. {
  52. throw new IllegalStateException("no key size for algorithm: " + algorithm);
  53. }
  54. return ((Integer)KEYSIZES.get(algorithm)).intValue();
  55. }
  56. static boolean isPKCS5Scheme1(DERObjectIdentifier algOid)
  57. {
  58. return PKCS5_SCHEME_1.contains(algOid);
  59. }
  60. static boolean isPKCS5Scheme2(DERObjectIdentifier algOid)
  61. {
  62. return PKCS5_SCHEME_2.contains(algOid);
  63. }
  64. static boolean isPKCS12(DERObjectIdentifier algOid)
  65. {
  66. return algOid.getId().startsWith(PKCSObjectIdentifiers.pkcs_12PbeIds.getId());
  67. }
  68. static SecretKey generateSecretKeyForPKCS5Scheme2(String algorithm, char[] password, byte[] salt, int iterationCount)
  69. {
  70. PBEParametersGenerator generator = new PKCS5S2ParametersGenerator();
  71. generator.init(
  72. PBEParametersGenerator.PKCS5PasswordToBytes(password),
  73. salt,
  74. iterationCount);
  75. return new SecretKeySpec(((KeyParameter)generator.generateDerivedParameters(PEMUtilities.getKeySize(algorithm))).getKey(), algorithm);
  76. }
  77. static byte[] crypt(
  78. boolean encrypt,
  79. String provider,
  80. byte[] bytes,
  81. char[] password,
  82. String dekAlgName,
  83. byte[] iv)
  84. throws IOException
  85. {
  86. Provider prov = null;
  87. if (provider != null)
  88. {
  89. prov = Security.getProvider(provider);
  90. if (prov == null)
  91. {
  92. throw new EncryptionException("cannot find provider: " + provider);
  93. }
  94. }
  95. return crypt(encrypt, prov, bytes, password, dekAlgName, iv);
  96. }
  97. static byte[] crypt(
  98. boolean encrypt,
  99. Provider provider,
  100. byte[] bytes,
  101. char[] password,
  102. String dekAlgName,
  103. byte[] iv)
  104. throws IOException
  105. {
  106. AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
  107. String alg;
  108. String blockMode = "CBC";
  109. String padding = "PKCS5Padding";
  110. Key sKey;
  111. // Figure out block mode and padding.
  112. if (dekAlgName.endsWith("-CFB"))
  113. {
  114. blockMode = "CFB";
  115. padding = "NoPadding";
  116. }
  117. if (dekAlgName.endsWith("-ECB") ||
  118. "DES-EDE".equals(dekAlgName) ||
  119. "DES-EDE3".equals(dekAlgName))
  120. {
  121. // ECB is actually the default (though seldom used) when OpenSSL
  122. // uses DES-EDE (des2) or DES-EDE3 (des3).
  123. blockMode = "ECB";
  124. paramSpec = null;
  125. }
  126. if (dekAlgName.endsWith("-OFB"))
  127. {
  128. blockMode = "OFB";
  129. padding = "NoPadding";
  130. }
  131. // Figure out algorithm and key size.
  132. if (dekAlgName.startsWith("DES-EDE"))
  133. {
  134. alg = "DESede";
  135. // "DES-EDE" is actually des2 in OpenSSL-speak!
  136. // "DES-EDE3" is des3.
  137. boolean des2 = !dekAlgName.startsWith("DES-EDE3");
  138. sKey = getKey(password, alg, 24, iv, des2);
  139. }
  140. else if (dekAlgName.startsWith("DES-"))
  141. {
  142. alg = "DES";
  143. sKey = getKey(password, alg, 8, iv);
  144. }
  145. else if (dekAlgName.startsWith("BF-"))
  146. {
  147. alg = "Blowfish";
  148. sKey = getKey(password, alg, 16, iv);
  149. }
  150. else if (dekAlgName.startsWith("RC2-"))
  151. {
  152. alg = "RC2";
  153. int keyBits = 128;
  154. if (dekAlgName.startsWith("RC2-40-"))
  155. {
  156. keyBits = 40;
  157. }
  158. else if (dekAlgName.startsWith("RC2-64-"))
  159. {
  160. keyBits = 64;
  161. }
  162. sKey = getKey(password, alg, keyBits / 8, iv);
  163. if (paramSpec == null) // ECB block mode
  164. {
  165. paramSpec = new RC2ParameterSpec(keyBits);
  166. }
  167. else
  168. {
  169. paramSpec = new RC2ParameterSpec(keyBits, iv);
  170. }
  171. }
  172. else if (dekAlgName.startsWith("AES-"))
  173. {
  174. alg = "AES";
  175. byte[] salt = iv;
  176. if (salt.length > 8)
  177. {
  178. salt = new byte[8];
  179. System.arraycopy(iv, 0, salt, 0, 8);
  180. }
  181. int keyBits;
  182. if (dekAlgName.startsWith("AES-128-"))
  183. {
  184. keyBits = 128;
  185. }
  186. else if (dekAlgName.startsWith("AES-192-"))
  187. {
  188. keyBits = 192;
  189. }
  190. else if (dekAlgName.startsWith("AES-256-"))
  191. {
  192. keyBits = 256;
  193. }
  194. else
  195. {
  196. throw new EncryptionException("unknown AES encryption with private key");
  197. }
  198. sKey = getKey(password, "AES", keyBits / 8, salt);
  199. }
  200. else
  201. {
  202. throw new EncryptionException("unknown encryption with private key");
  203. }
  204. String transformation = alg + "/" + blockMode + "/" + padding;
  205. try
  206. {
  207. Cipher c = Cipher.getInstance(transformation, provider);
  208. int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
  209. if (paramSpec == null) // ECB block mode
  210. {
  211. c.init(mode, sKey);
  212. }
  213. else
  214. {
  215. c.init(mode, sKey, paramSpec);
  216. }
  217. return c.doFinal(bytes);
  218. }
  219. catch (Exception e)
  220. {
  221. throw new EncryptionException("exception using cipher - please check password and data.", e);
  222. }
  223. }
  224. private static SecretKey getKey(
  225. char[] password,
  226. String algorithm,
  227. int keyLength,
  228. byte[] salt)
  229. {
  230. return getKey(password, algorithm, keyLength, salt, false);
  231. }
  232. private static SecretKey getKey(
  233. char[] password,
  234. String algorithm,
  235. int keyLength,
  236. byte[] salt,
  237. boolean des2)
  238. {
  239. OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator();
  240. pGen.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), salt);
  241. KeyParameter keyParam;
  242. keyParam = (KeyParameter) pGen.generateDerivedParameters(keyLength * 8);
  243. byte[] key = keyParam.getKey();
  244. if (des2 && key.length >= 24)
  245. {
  246. // For DES2, we must copy first 8 bytes into the last 8 bytes.
  247. System.arraycopy(key, 0, key, 16, 8);
  248. }
  249. return new javax.crypto.spec.SecretKeySpec(key, algorithm);
  250. }
  251. }