· 7 years ago · Jan 21, 2019, 07:04 AM
1-----BEGIN RSA PRIVATE KEY-----
2Proc-Type: 4,ENCRYPTED
3DEK-Info: DES-EDE3-CBC,56F3A98D9CFFA77A
4
5X5h7SUDStF1tL16lRM+AfZb1UBDQ0D1YbQ6vmIlXiK....
6.....
7/KK5CZmIGw==
8-----END RSA PRIVATE KEY-----
9
10import java.security.Key;
11import java.security.KeyFactory;
12import java.security.PrivateKey;
13import java.security.spec.PKCS8EncodedKeySpec;
14import javax.crypto.EncryptedPrivateKeyInfo;
15import javax.crypto.SecretKeyFactory;
16import javax.crypto.spec.PBEKeySpec;
17
18public String decrypt(String keyDataStr, String passwordStr){
19 // This key data start from "X5... to =="
20 char [] password=passwordStr.toCharArray();
21 byte [] keyDataBytes=com.sun.jersey.core.util.Base64.decode(keyDataStr);
22
23 PBEKeySpec pbeSpec = new PBEKeySpec(password);
24 EncryptedPrivateKeyInfo pkinfo = new EncryptedPrivateKeyInfo(keyDataBytes);
25 SecretKeyFactory skf = SecretKeyFactory.getInstance(pkinfo.getAlgName());
26 Key secret = skf.generateSecret(pbeSpec);
27 PKCS8EncodedKeySpec keySpec = pkinfo.getKeySpec(secret);
28 KeyFactory kf = KeyFactory.getInstance("RSA");
29 PrivateKey pk=kf.generatePrivate(keySpec);
30 return pk.toString();
31}
32
33java.io.IOException: DerInputStream.getLength(): lengthTag=50, too big.
34 at sun.security.util.DerInputStream.getLength(DerInputStream.java:561)
35 at sun.security.util.DerValue.init(DerValue.java:365)
36 at sun.security.util.DerValue.<init>(DerValue.java:294)
37 at javax.crypto.EncryptedPrivateKeyInfo.<init> (EncryptedPrivateKeyInfo.java:84)
38
39static RSAPrivateKey decrypt(String keyDataStr, String ivHex, String password)
40 throws GeneralSecurityException, UnsupportedEncodingException
41 {
42 byte[] pw = password.getBytes(StandardCharsets.UTF_8);
43 byte[] iv = h2b(ivHex);
44 SecretKey secret = opensslKDF(pw, iv);
45 Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");
46 cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
47 byte [] keyBytes=Base64.decode(keyDataStr.getBytes("UTF-8"));
48 byte[] pkcs1 = cipher.doFinal(keyBytes);
49 /* See note for definition of "decodeRSAPrivatePKCS1" */
50 RSAPrivateCrtKeySpec spec = decodeRSAPrivatePKCS1(pkcs1);
51 KeyFactory rsa = KeyFactory.getInstance("RSA");
52 return (RSAPrivateKey) rsa.generatePrivate(spec);
53 }
54
55 private static SecretKey opensslKDF(byte[] pw, byte[] iv)
56 throws NoSuchAlgorithmException
57 {
58 MessageDigest md5 = MessageDigest.getInstance("MD5");
59 md5.update(pw);
60 md5.update(iv);
61 byte[] d0 = md5.digest();
62 md5.update(d0);
63 md5.update(pw);
64 md5.update(iv);
65 byte[] d1 = md5.digest();
66 byte[] key = new byte[24];
67 System.arraycopy(d0, 0, key, 0, 16);
68 System.arraycopy(d1, 0, key, 16, 8);
69 return new SecretKeySpec(key, "DESede");
70 }
71
72 private static byte[] h2b(CharSequence s)
73 {
74 int len = s.length();
75 byte[] b = new byte[len / 2];
76 for (int src = 0, dst = 0; src < len; ++dst) {
77 int hi = Character.digit(s.charAt(src++), 16);
78 int lo = Character.digit(s.charAt(src++), 16);
79 b[dst] = (byte) (hi << 4 | lo);
80 }
81 return b;
82 }
83 static RSAPrivateCrtKeySpec decodeRSAPrivatePKCS1(byte[] encoded)
84 {
85 ByteBuffer input = ByteBuffer.wrap(encoded);
86 if (der(input, 0x30) != input.remaining())
87 throw new IllegalArgumentException("Excess data");
88 if (!BigInteger.ZERO.equals(derint(input)))
89 throw new IllegalArgumentException("Unsupported version");
90 BigInteger n = derint(input);
91 BigInteger e = derint(input);
92 BigInteger d = derint(input);
93 BigInteger p = derint(input);
94 BigInteger q = derint(input);
95 BigInteger ep = derint(input);
96 BigInteger eq = derint(input);
97 BigInteger c = derint(input);
98 return new RSAPrivateCrtKeySpec(n, e, d, p, q, ep, eq, c);
99 }
100
101 private static BigInteger derint(ByteBuffer input)
102 {
103 byte[] value = new byte[der(input, 0x02)];
104 input.get(value);
105 return new BigInteger(+1, value);
106 }
107
108
109 private static int der(ByteBuffer input, int exp)
110 {
111 int tag = input.get() & 0xFF;
112 if (tag != exp)
113 throw new IllegalArgumentException("Unexpected tag");
114 int n = input.get() & 0xFF;
115 if (n < 128)
116 return n;
117 n &= 0x7F;
118 if ((n < 1) || (n > 2))
119 throw new IllegalArgumentException("Invalid length");
120 int len = 0;
121 while (n-- > 0) {
122 len <<= 8;
123 len |= input.get() & 0xFF;
124 }
125 return len;
126 }
127
128static RSAPrivateKey decrypt(String keyDataStr, String ivHex, String password)
129 throws GeneralSecurityException
130 {
131 byte[] pw = password.getBytes(StandardCharsets.UTF_8);
132 byte[] iv = h2b(ivHex);
133 SecretKey secret = opensslKDF(pw, iv);
134 Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
135 cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
136 byte[] pkcs1 = cipher.doFinal(Base64.getMimeDecoder().decode(keyDataStr));
137 /* See note for definition of "decodeRSAPrivatePKCS1" */
138 RSAPrivateCrtKeySpec spec = decodeRSAPrivatePKCS1(pkcs1);
139 KeyFactory rsa = KeyFactory.getInstance("RSA");
140 return (RSAPrivateKey) rsa.generatePrivate(spec);
141 }
142
143 private static SecretKey opensslKDF(byte[] pw, byte[] iv)
144 throws NoSuchAlgorithmException
145 {
146 MessageDigest md5 = MessageDigest.getInstance("MD5");
147 md5.update(pw);
148 md5.update(iv);
149 byte[] d0 = md5.digest();
150 md5.update(d0);
151 md5.update(pw);
152 md5.update(iv);
153 byte[] d1 = md5.digest();
154 byte[] key = new byte[24];
155 System.arraycopy(d0, 0, key, 0, 16);
156 System.arraycopy(d1, 0, key, 16, 8);
157 return new SecretKeySpec(key, "DESede");
158 }
159
160 private static byte[] h2b(CharSequence s)
161 {
162 int len = s.length();
163 byte[] b = new byte[len / 2];
164 for (int src = 0, dst = 0; src < len; ++dst) {
165 int hi = Character.digit(s.charAt(src++), 16);
166 int lo = Character.digit(s.charAt(src++), 16);
167 b[dst] = (byte) (hi << 4 | lo);
168 }
169 return b;
170 }
171
172Matcher matcher = OPENSSL_ENCRYPTED_RSA_PRIVATEKEY_PATTERN.matcher(pemContents);
173 if (matcher.matches())
174 {
175 String encryptionDetails = matcher.group(1).trim(); // e.g. AES-256-CBC,XXXXXXX
176 String encryptedKey = matcher.group(2).replaceAll("\s", ""); // remove tabs / spaces / newlines / carriage return etc
177
178 System.out.println("PEM appears to be OpenSSL Encrypted RSA Private Key; Encryption details : "
179 + encryptionDetails + "; Key : " + encryptedKey);
180
181 byte[] encryptedBinaryKey = Base64.fromBase64(encryptedKey);
182
183 String[] encryptionDetailsParts = encryptionDetails.split(",");
184 if (encryptionDetailsParts.length == 2)
185 {
186 String encryptionAlgorithm = encryptionDetailsParts[0];
187 String encryptedAlgorithmParams = encryptionDetailsParts[1]; // i.e. the initialization vector in hex
188
189 byte[] pw = new String(password).getBytes(StandardCharsets.UTF_8);
190 byte[] iv = fromHex(encryptedAlgorithmParams);
191
192 MessageDigest digest = MessageDigest.getInstance("MD5");
193
194 // we need to come up with the encryption key
195
196 // first round digest based on password and first 8-bytes of IV ..
197 digest.update(pw);
198 digest.update(iv, 0, 8);
199
200 byte[] round1Digest = digest.digest(); // The digest is reset after this call is made.
201
202 // secound round digest based on first round digest, password, and first 8-bytes of IV ...
203 digest.update(round1Digest);
204 digest.update(pw);
205 digest.update(iv, 0, 8);
206
207 byte[] round2Digest = digest.digest();
208
209 Cipher cipher = null;
210 SecretKey secretKey = null;
211 byte[] key = null;
212 byte[] pkcs1 = null;
213
214 if ("AES-256-CBC".equals(encryptionAlgorithm))
215 {
216 cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
217
218 key = new byte[32]; // 256 bit key (block size still 128-bit)
219 System.arraycopy(round1Digest, 0, key, 0, 16);
220 System.arraycopy(round2Digest, 0, key, 16, 16);
221
222 secretKey = new SecretKeySpec(key, "AES");
223 }
224 else if ("AES-192-CBC".equals(encryptionAlgorithm))
225 {
226 cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
227
228 key = new byte[24]; // key size of 24 bytes
229 System.arraycopy(round1Digest, 0, key, 0, 16);
230 System.arraycopy(round2Digest, 0, key, 16, 8);
231
232 secretKey = new SecretKeySpec(key, "AES");
233 }
234 else if ("AES-128-CBC".equals(encryptionAlgorithm))
235 {
236 cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
237
238 key = new byte[16]; // 128 bit key
239 System.arraycopy(round1Digest, 0, key, 0, 16);
240
241 secretKey = new SecretKeySpec(key, "AES");
242 }
243 else if ("DES-EDE3-CBC".equals(encryptionAlgorithm))
244 {
245 cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
246
247 key = new byte[24]; // key size of 24 bytes
248 System.arraycopy(round1Digest, 0, key, 0, 16);
249 System.arraycopy(round2Digest, 0, key, 16, 8);
250
251 secretKey = new SecretKeySpec(key, "DESede");
252 }
253 else if ("DES-CBC".equals(encryptionAlgorithm))
254 {
255 cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
256
257 key = new byte[8]; // key size of 8 bytes
258 System.arraycopy(round1Digest, 0, key, 0, 8);
259
260 secretKey = new SecretKeySpec(key, "DES");
261 }
262
263 cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
264
265 pkcs1 = cipher.doFinal(encryptedBinaryKey);
266
267 keySpec = pkcs1ParsePrivateKey(pkcs1);
268
269 privateKey = (RSAPrivateKey) factory.generatePrivate(keySpec);
270 }
271 }