1 | package jp.co.orkney.restlet.security; |
---|
2 | |
---|
3 | import javax.crypto.BadPaddingException; |
---|
4 | import javax.crypto.Cipher; |
---|
5 | import javax.crypto.IllegalBlockSizeException; |
---|
6 | import javax.crypto.NoSuchPaddingException; |
---|
7 | import javax.crypto.ShortBufferException; |
---|
8 | |
---|
9 | import sun.misc.BASE64Decoder; |
---|
10 | import sun.misc.BASE64Encoder; |
---|
11 | |
---|
12 | import java.io.BufferedReader; |
---|
13 | import java.io.ByteArrayOutputStream; |
---|
14 | import java.io.FileInputStream; |
---|
15 | import java.io.FileNotFoundException; |
---|
16 | import java.io.IOException; |
---|
17 | import java.security.*; |
---|
18 | import java.security.cert.Certificate; |
---|
19 | import java.security.cert.CertificateException; |
---|
20 | import java.security.spec.InvalidKeySpecException; |
---|
21 | import java.security.spec.PKCS8EncodedKeySpec; |
---|
22 | import java.security.spec.X509EncodedKeySpec; |
---|
23 | |
---|
24 | import jp.co.orkney.restlet.util.Log; |
---|
25 | |
---|
26 | public class SecurityHelper |
---|
27 | { |
---|
28 | |
---|
29 | public static final String PUB_FILE = "public.key"; |
---|
30 | |
---|
31 | public static final String PRI_FILE = "private.key"; |
---|
32 | |
---|
33 | public static final int PRIVATE = 0; |
---|
34 | |
---|
35 | public static final int PUBLIC = 1; |
---|
36 | |
---|
37 | public static final String ALGORITHM = "RSA/ECB/PKCS1Padding"; |
---|
38 | |
---|
39 | // public static final String ALGORITHM = "RSA/ECB/OAEPPadding"; |
---|
40 | // public static final String ALGORITHM = "SHA1withDSA"; |
---|
41 | |
---|
42 | public static boolean checkAPIKey(String apiKey, String encKey, |
---|
43 | String signature, String clientId, Log log) throws IOException, |
---|
44 | KeyStoreException, CertificateException, NoSuchAlgorithmException, |
---|
45 | NoSuchPaddingException, NoSuchProviderException, |
---|
46 | InvalidKeyException, SignatureException, ShortBufferException, |
---|
47 | IllegalBlockSizeException, BadPaddingException |
---|
48 | { |
---|
49 | boolean isValid = false; |
---|
50 | boolean verifies = false; |
---|
51 | |
---|
52 | // Default path to the keystore file |
---|
53 | String keyStoreFileName = "security/wrs"; |
---|
54 | |
---|
55 | // Default keystore password (you might want to change this) |
---|
56 | String keyStorePassword = "webroutingservice"; |
---|
57 | |
---|
58 | // Load the keystore |
---|
59 | KeyStore keyStore = null; |
---|
60 | |
---|
61 | keyStore = KeyStore.getInstance("jks"); |
---|
62 | FileInputStream keyStoreInputStream = null; |
---|
63 | |
---|
64 | keyStoreInputStream = new FileInputStream(keyStoreFileName); |
---|
65 | |
---|
66 | keyStore.load(keyStoreInputStream, keyStorePassword.toCharArray()); |
---|
67 | keyStoreInputStream.close(); |
---|
68 | |
---|
69 | BASE64Encoder myB64 = new BASE64Encoder(); |
---|
70 | BASE64Decoder b64 = new BASE64Decoder(); |
---|
71 | |
---|
72 | KeyPair kp = getPrivateKey(keyStore, clientId, keyStorePassword |
---|
73 | .toCharArray()); |
---|
74 | |
---|
75 | Security.addProvider(new com.sun.crypto.provider.SunJCE()); |
---|
76 | |
---|
77 | PrivateKey priKey = kp.getPrivate(); |
---|
78 | PublicKey pubKey = kp.getPublic(); |
---|
79 | |
---|
80 | Cipher c = null; |
---|
81 | |
---|
82 | c = Cipher.getInstance(ALGORITHM); |
---|
83 | |
---|
84 | Signature sig = null; |
---|
85 | sig = Signature.getInstance("SHA1withRSA", "SunRsaSign"); |
---|
86 | sig.initVerify(pubKey); |
---|
87 | |
---|
88 | // byte[] sigToVerify = signature.substring(0,176).getBytes(); |
---|
89 | byte[] sigToVerify = b64.decodeBuffer(signature); |
---|
90 | |
---|
91 | sig.update(apiKey.getBytes()); |
---|
92 | verifies = sig.verify(sigToVerify); |
---|
93 | |
---|
94 | //System.out.println("signature verifies: " + verifies); |
---|
95 | log.write("signature verifies: " + verifies, 2); |
---|
96 | |
---|
97 | // byte[] text = encKey.substring(0,176).getBytes(); |
---|
98 | byte[] text = b64.decodeBuffer(encKey); |
---|
99 | |
---|
100 | //System.out.println("Encrypting message..."); |
---|
101 | log.write("Encrypting message...", 2); |
---|
102 | |
---|
103 | // text = crypt(c, priKey, text, Cipher.DECRYPT_MODE); |
---|
104 | text = encryptDecrypt("DECRYPT", text, priKey, log); |
---|
105 | |
---|
106 | String decKey = new String(text); |
---|
107 | //System.out.println("text = " + decKey); |
---|
108 | log.write("text = " + decKey, 2); |
---|
109 | |
---|
110 | isValid = apiKey.equals(decKey); |
---|
111 | |
---|
112 | return isValid && verifies; |
---|
113 | } |
---|
114 | |
---|
115 | public static byte[] crypt(Cipher cipher, Key key, byte[] text, int type) |
---|
116 | throws ShortBufferException, IllegalBlockSizeException, |
---|
117 | BadPaddingException, InvalidKeyException |
---|
118 | { |
---|
119 | byte[] decryptedFileBytes = null; |
---|
120 | |
---|
121 | cipher.init(type, key); |
---|
122 | |
---|
123 | int encryptedFileBytesChunkLength = 128; |
---|
124 | int numberOfEncryptedChunks = text.length |
---|
125 | / encryptedFileBytesChunkLength + 1; |
---|
126 | |
---|
127 | // The limit per chunk is 117 bytes for RSA |
---|
128 | int decryptedFileBytesChunkLength = 100; |
---|
129 | int decryptedFileBytesLength = numberOfEncryptedChunks |
---|
130 | * encryptedFileBytesChunkLength; |
---|
131 | // It looks like we must create the decrypted file as long as the |
---|
132 | // encrypted since RSA need 128 for output |
---|
133 | |
---|
134 | // Create the decoded byte array |
---|
135 | decryptedFileBytes = new byte[decryptedFileBytesLength]; |
---|
136 | |
---|
137 | // Counters |
---|
138 | int decryptedByteIndex = 0; |
---|
139 | int encryptedByteIndex = 0; |
---|
140 | |
---|
141 | for (int i = 0; i < numberOfEncryptedChunks; i++) |
---|
142 | { |
---|
143 | if (i < numberOfEncryptedChunks - 1) |
---|
144 | { |
---|
145 | decryptedByteIndex = decryptedByteIndex |
---|
146 | + cipher.doFinal(text, encryptedByteIndex, |
---|
147 | encryptedFileBytesChunkLength, |
---|
148 | decryptedFileBytes, decryptedByteIndex); |
---|
149 | encryptedByteIndex = encryptedByteIndex |
---|
150 | + encryptedFileBytesChunkLength; |
---|
151 | } |
---|
152 | else |
---|
153 | { |
---|
154 | decryptedByteIndex = decryptedByteIndex |
---|
155 | + cipher.doFinal(text, encryptedByteIndex, text.length |
---|
156 | - encryptedByteIndex, decryptedFileBytes, |
---|
157 | decryptedByteIndex); |
---|
158 | } |
---|
159 | } |
---|
160 | |
---|
161 | // decryptedFileBytes = cipher.doFinal(text); |
---|
162 | |
---|
163 | return decryptedFileBytes; |
---|
164 | } |
---|
165 | |
---|
166 | public static Key getKey(String filename, int type) |
---|
167 | throws FileNotFoundException |
---|
168 | { |
---|
169 | FileInputStream fis = null; |
---|
170 | fis = new FileInputStream(filename); |
---|
171 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
---|
172 | int b; |
---|
173 | try |
---|
174 | { |
---|
175 | while ((b = fis.read()) != -1) |
---|
176 | { |
---|
177 | baos.write(b); |
---|
178 | } |
---|
179 | } |
---|
180 | catch (IOException e) |
---|
181 | { |
---|
182 | e.printStackTrace(); |
---|
183 | } |
---|
184 | byte[] keydata = baos.toByteArray(); |
---|
185 | |
---|
186 | Key key = null; |
---|
187 | try |
---|
188 | { |
---|
189 | KeyFactory kf = KeyFactory.getInstance("RSA", "BC"); |
---|
190 | switch (type) |
---|
191 | { |
---|
192 | case PRIVATE: |
---|
193 | PKCS8EncodedKeySpec encodedPrivateKey = new PKCS8EncodedKeySpec( |
---|
194 | keydata); |
---|
195 | key = kf.generatePrivate(encodedPrivateKey); |
---|
196 | return key; |
---|
197 | case PUBLIC: |
---|
198 | X509EncodedKeySpec encodedPublicKey = new X509EncodedKeySpec( |
---|
199 | keydata); |
---|
200 | key = kf.generatePublic(encodedPublicKey); |
---|
201 | return key; |
---|
202 | } |
---|
203 | } |
---|
204 | catch (NoSuchAlgorithmException e) |
---|
205 | { |
---|
206 | e.printStackTrace(); |
---|
207 | } |
---|
208 | catch (NoSuchProviderException e) |
---|
209 | { |
---|
210 | e.printStackTrace(); |
---|
211 | } |
---|
212 | catch (InvalidKeySpecException e) |
---|
213 | { |
---|
214 | e.printStackTrace(); |
---|
215 | } |
---|
216 | |
---|
217 | return key; |
---|
218 | } |
---|
219 | |
---|
220 | // From http://javaalmanac.com/egs/java.security/GetKeyFromKs.html |
---|
221 | public static KeyPair getPrivateKey(KeyStore keystore, String alias, |
---|
222 | char[] password) |
---|
223 | { |
---|
224 | try |
---|
225 | { |
---|
226 | // Get private key |
---|
227 | Key key = keystore.getKey(alias, password); |
---|
228 | if (key instanceof PrivateKey) |
---|
229 | { |
---|
230 | // Get certificate of public key |
---|
231 | Certificate cert = keystore.getCertificate(alias); |
---|
232 | |
---|
233 | // Get public key |
---|
234 | PublicKey publicKey = cert.getPublicKey(); |
---|
235 | |
---|
236 | // Return a key pair |
---|
237 | return new KeyPair(publicKey, (PrivateKey) key); |
---|
238 | } |
---|
239 | } |
---|
240 | catch (UnrecoverableKeyException e) |
---|
241 | { |
---|
242 | } |
---|
243 | catch (NoSuchAlgorithmException e) |
---|
244 | { |
---|
245 | } |
---|
246 | catch (KeyStoreException e) |
---|
247 | { |
---|
248 | } |
---|
249 | return null; |
---|
250 | } |
---|
251 | |
---|
252 | public static byte[] encryptDecrypt(String type, byte[] data, Key secretKey, Log log) |
---|
253 | throws ShortBufferException, NoSuchAlgorithmException, |
---|
254 | NoSuchPaddingException, InvalidKeyException, |
---|
255 | IllegalBlockSizeException, BadPaddingException, IOException |
---|
256 | { |
---|
257 | byte cryptedCipherText[] = null; |
---|
258 | |
---|
259 | Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); |
---|
260 | //System.out.println("Provider is-->" + cipher.getProvider().getInfo()); |
---|
261 | log.write("Provider is-->" + cipher.getProvider().getInfo(), 2); |
---|
262 | int j = 0; |
---|
263 | int k = 0; |
---|
264 | boolean flag = false; |
---|
265 | byte[] bufferedEncryption = null; |
---|
266 | |
---|
267 | if (type.equals("ENCRYPT")) |
---|
268 | { |
---|
269 | cipher.init(Cipher.ENCRYPT_MODE, secretKey); |
---|
270 | j = 112; |
---|
271 | k = 112; |
---|
272 | bufferedEncryption = new byte[k]; |
---|
273 | |
---|
274 | } |
---|
275 | else |
---|
276 | { |
---|
277 | cipher.init(Cipher.DECRYPT_MODE, secretKey); |
---|
278 | j = 128; |
---|
279 | k = 128; |
---|
280 | |
---|
281 | bufferedEncryption = new byte[k]; |
---|
282 | } |
---|
283 | |
---|
284 | int cipherlength = cipher.getOutputSize(data.length); |
---|
285 | //System.out.println("data size-->" + data.length); |
---|
286 | log.write("data size-->" + data.length, 2); |
---|
287 | //System.out.println("cipher size-->" + cipherlength); |
---|
288 | log.write("cipher size-->" + cipherlength, 2); |
---|
289 | cryptedCipherText = new byte[cipherlength]; |
---|
290 | |
---|
291 | ByteArrayOutputStream cryptedTextBuffer = new ByteArrayOutputStream(); |
---|
292 | |
---|
293 | int count = 0; |
---|
294 | int i = 0; |
---|
295 | |
---|
296 | while (i < data.length) |
---|
297 | { |
---|
298 | System.arraycopy(data, i, bufferedEncryption, 0, j); |
---|
299 | //System.out.println("sizeof bufferedencryption-->" |
---|
300 | // + bufferedEncryption.length); |
---|
301 | log.write("sizeof bufferedencryption-->" |
---|
302 | + bufferedEncryption.length, 2); |
---|
303 | cryptedCipherText = cipher.doFinal(bufferedEncryption); |
---|
304 | count += cryptedCipherText.length; |
---|
305 | //System.out.println("Length-->" + count); |
---|
306 | log.write("Length-->" + count, 2); |
---|
307 | cryptedTextBuffer.write(cryptedCipherText); |
---|
308 | //System.out.println("i-->" + i); |
---|
309 | log.write("i-->" + i, 2); |
---|
310 | |
---|
311 | i += k; |
---|
312 | bufferedEncryption = new byte[k]; |
---|
313 | if (flag == true) |
---|
314 | break; |
---|
315 | if (i + k > data.length) |
---|
316 | { |
---|
317 | j = data.length - i; |
---|
318 | flag = true; |
---|
319 | } |
---|
320 | |
---|
321 | } |
---|
322 | |
---|
323 | cryptedCipherText = cryptedTextBuffer.toByteArray(); |
---|
324 | |
---|
325 | // cryptedCipherText = cipher.doFinal(data); |
---|
326 | |
---|
327 | return cryptedCipherText; |
---|
328 | } |
---|
329 | |
---|
330 | } |
---|