File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\security\CipherFactory.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.security;
8
9 import java.io.ByteArrayInputStream;
10 import java.io.ByteArrayOutputStream;
11 import java.io.IOException;
12 import java.io.InputStream;
13 import java.io.OutputStream;
14 import java.net.InetAddress;
15 import java.net.InetSocketAddress;
16 import java.net.ServerSocket;
17 import java.net.Socket;
18 import java.security.KeyFactory;
19 import java.security.KeyStore;
20 import java.security.PrivateKey;
21 import java.security.cert.Certificate;
22 import java.security.cert.CertificateFactory;
23 import java.security.spec.PKCS8EncodedKeySpec;
24 import java.util.Properties;
25 import javax.net.ServerSocketFactory;
26 import javax.net.ssl.SSLServerSocket;
27 import javax.net.ssl.SSLServerSocketFactory;
28 import javax.net.ssl.SSLSocket;
29 import javax.net.ssl.SSLSocketFactory;
30 import org.h2.constant.ErrorCode;
31 import org.h2.constant.SysProperties;
32 import org.h2.message.DbException;
33 import org.h2.store.fs.FileUtils;
34 import org.h2.util.IOUtils;
35 import org.h2.util.StringUtils;
36 import org.h2.util.Utils;
37
38 /**
39 * A factory to create new block cipher objects.
40 */
41 public class CipherFactory {
42
43 /**
44 * The default password to use for the .h2.keystore file
45 */
46 public static final String KEYSTORE_PASSWORD = "h2pass";
47
48 private static final String KEYSTORE = "~/.h2.keystore";
49 private static final String KEYSTORE_KEY = "javax.net.ssl.keyStore";
50 private static final String KEYSTORE_PASSWORD_KEY = "javax.net.ssl.keyStorePassword";
51 private static final String ANONYMOUS_CIPHER_SUITE = "SSL_DH_anon_WITH_RC4_128_MD5";
52
53 private CipherFactory() {
54 // utility class
55 }
56
57 /**
58 * Get a new block cipher object for the given algorithm.
59 *
60 * @param algorithm the algorithm
61 * @return a new cipher object
62 */
63 public static BlockCipher getBlockCipher(String algorithm) {
64 if ("XTEA".equalsIgnoreCase(algorithm)) {
65 return new XTEA();
66 } else if ("AES".equalsIgnoreCase(algorithm)) {
67 return new AES();
68 } else if ("FOG".equalsIgnoreCase(algorithm)) {
69 return new Fog();
70 }
71 throw DbException.get(ErrorCode.UNSUPPORTED_CIPHER, algorithm);
72 }
73
74 /**
75 * Create a secure client socket that is connected to the given address and port.
76 *
77 * @param address the address to connect to
78 * @param port the port
79 * @return the socket
80 */
81 public static Socket createSocket(InetAddress address, int port) throws IOException {
82 Socket socket = null;
83 setKeystore();
84 SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
85 SSLSocket secureSocket = (SSLSocket) f.createSocket();
86 secureSocket.connect(new InetSocketAddress(address, port),
87 SysProperties.SOCKET_CONNECT_TIMEOUT);
88 if (SysProperties.ENABLE_ANONYMOUS_SSL) {
89 String[] list = secureSocket.getEnabledCipherSuites();
90 list = addAnonymous(list);
91 secureSocket.setEnabledCipherSuites(list);
92 }
93 socket = secureSocket;
94 return socket;
95 }
96
97 /**
98 * Create a secure server socket. If a bind address is specified, the socket
99 * is only bound to this address.
100 *
101 * @param port the port to listen on
102 * @param bindAddress the address to bind to, or null to bind to all
103 * addresses
104 * @return the server socket
105 */
106 public static ServerSocket createServerSocket(int port, InetAddress bindAddress) throws IOException {
107 ServerSocket socket = null;
108 setKeystore();
109 ServerSocketFactory f = SSLServerSocketFactory.getDefault();
110 SSLServerSocket secureSocket;
111 if (bindAddress == null) {
112 secureSocket = (SSLServerSocket) f.createServerSocket(port);
113 } else {
114 secureSocket = (SSLServerSocket) f.createServerSocket(port, 0, bindAddress);
115 }
116 if (SysProperties.ENABLE_ANONYMOUS_SSL) {
117 String[] list = secureSocket.getEnabledCipherSuites();
118 list = addAnonymous(list);
119 secureSocket.setEnabledCipherSuites(list);
120 }
121 socket = secureSocket;
122 return socket;
123 }
124
125 private static byte[] getKeyStoreBytes(KeyStore store, String password) throws IOException {
126 ByteArrayOutputStream bout = new ByteArrayOutputStream();
127 try {
128 store.store(bout, password.toCharArray());
129 } catch (Exception e) {
130 throw DbException.convertToIOException(e);
131 }
132 return bout.toByteArray();
133 }
134
135 /**
136 * Get the keystore object using the given password.
137 *
138 * @param password the keystore password
139 * @return the keystore
140 */
141 public static KeyStore getKeyStore(String password) throws IOException {
142 try {
143 // The following source code can be re-generated
144 // if you have a keystore file.
145 // This code is (hopefully) more Java version independent
146 // than using keystores directly. See also:
147 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4887561
148 // (1.4.2 cannot read keystore written with 1.4.1)
149 // --- generated code start ---
150
151 KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
152
153 store.load(null, password.toCharArray());
154 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
155 store.load(null, password.toCharArray());
156 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(
157 StringUtils.convertHexToBytes(
158 "30820277020100300d06092a864886f70d010101" +
159 "0500048202613082025d02010002818100dc0a13" +
160 "c602b7141110eade2f051b54777b060d0f74e6a1" +
161 "10f9cce81159f271ebc88d8e8aa1f743b505fc2e" +
162 "7dfe38d33b8d3f64d1b363d1af4d877833897954" +
163 "cbaec2fa384c22a415498cf306bb07ac09b76b00" +
164 "1cd68bf77ea0a628f5101959cf2993a9c23dbee7" +
165 "9b19305977f8715ae78d023471194cc900b231ee" +
166 "cb0aaea98d02030100010281810099aa4ff4d0a0" +
167 "9a5af0bd953cb10c4d08c3d98df565664ac5582e" +
168 "494314d5c3c92dddedd5d316a32a206be4ec0846" +
169 "16fe57be15e27cad111aa3c21fa79e32258c6ca8" +
170 "430afc69eddd52d3b751b37da6b6860910b94653" +
171 "192c0db1d02abcfd6ce14c01f238eec7c20bd3bb" +
172 "750940004bacba2880349a9494d10e139ecb2355" +
173 "d101024100ffdc3defd9c05a2d377ef6019fa62b" +
174 "3fbd5b0020a04cc8533bca730e1f6fcf5dfceea1" +
175 "b044fbe17d9eababfbc7d955edad6bc60f9be826" +
176 "ad2c22ba77d19a9f65024100dc28d43fdbbc9385" +
177 "2cc3567093157702bc16f156f709fb7db0d9eec0" +
178 "28f41fd0edcd17224c866e66be1744141fb724a1" +
179 "0fd741c8a96afdd9141b36d67fff6309024077b1" +
180 "cddbde0f69604bdcfe33263fb36ddf24aa3b9922" +
181 "327915b890f8a36648295d0139ecdf68c245652c" +
182 "4489c6257b58744fbdd961834a4cab201801a3b1" +
183 "e52d024100b17142e8991d1b350a0802624759d4" +
184 "8ae2b8071a158ff91fabeb6a8f7c328e762143dc" +
185 "726b8529f42b1fab6220d1c676fdc27ba5d44e84" +
186 "7c72c52064afd351a902407c6e23fe35bcfcd1a6" +
187 "62aa82a2aa725fcece311644d5b6e3894853fd4c" +
188 "e9fe78218c957b1ff03fc9e5ef8ffeb6bd58235f" +
189 "6a215c97d354fdace7e781e4a63e8b"));
190 PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
191 Certificate[] certs = { CertificateFactory
192 .getInstance("X.509")
193 .generateCertificate(
194 new ByteArrayInputStream(
195 StringUtils.convertHexToBytes(
196 "3082018b3081f502044295ce6b300d06092a8648" +
197 "86f70d0101040500300d310b3009060355040313" +
198 "024832301e170d3035303532363133323630335a" +
199 "170d3337303933303036353734375a300d310b30" +
200 "0906035504031302483230819f300d06092a8648" +
201 "86f70d010101050003818d0030818902818100dc" +
202 "0a13c602b7141110eade2f051b54777b060d0f74" +
203 "e6a110f9cce81159f271ebc88d8e8aa1f743b505" +
204 "fc2e7dfe38d33b8d3f64d1b363d1af4d87783389" +
205 "7954cbaec2fa384c22a415498cf306bb07ac09b7" +
206 "6b001cd68bf77ea0a628f5101959cf2993a9c23d" +
207 "bee79b19305977f8715ae78d023471194cc900b2" +
208 "31eecb0aaea98d0203010001300d06092a864886" +
209 "f70d01010405000381810083f4401a279453701b" +
210 "ef9a7681a5b8b24f153f7d18c7c892133d97bd5f" +
211 "13736be7505290a445a7d5ceb75522403e509751" +
212 "5cd966ded6351ff60d5193de34cd36e5cb04d380" +
213 "398e66286f99923fd92296645fd4ada45844d194" +
214 "dfd815e6cd57f385c117be982809028bba1116c8" +
215 "5740b3d27a55b1a0948bf291ddba44bed337b9"))), };
216 store.setKeyEntry("h2", privateKey, password.toCharArray(), certs);
217 // --- generated code end ---
218 return store;
219 } catch (Exception e) {
220 throw DbException.convertToIOException(e);
221 }
222 }
223
224 private static void setKeystore() throws IOException {
225 Properties p = System.getProperties();
226 if (p.getProperty(KEYSTORE_KEY) == null) {
227 String fileName = KEYSTORE;
228 byte[] data = getKeyStoreBytes(getKeyStore(KEYSTORE_PASSWORD), KEYSTORE_PASSWORD);
229 boolean needWrite = true;
230 if (FileUtils.exists(fileName) && FileUtils.size(fileName) == data.length) {
231 // don't need to overwrite the file if it did not change
232 InputStream fin = FileUtils.newInputStream(fileName);
233 byte[] now = IOUtils.readBytesAndClose(fin, 0);
234 if (now != null && Utils.compareNotNull(data, now) == 0) {
235 needWrite = false;
236 }
237 }
238 if (needWrite) {
239 try {
240 OutputStream out = FileUtils.newOutputStream(fileName, false);
241 out.write(data);
242 out.close();
243 } catch (Exception e) {
244 throw DbException.convertToIOException(e);
245 }
246 }
247 String absolutePath = FileUtils.toRealPath(fileName);
248 System.setProperty(KEYSTORE_KEY, absolutePath);
249 }
250 if (p.getProperty(KEYSTORE_PASSWORD_KEY) == null) {
251 System.setProperty(KEYSTORE_PASSWORD_KEY, KEYSTORE_PASSWORD);
252 }
253 }
254
255 private static String[] addAnonymous(String[] list) {
256 String[] newList = new String[list.length + 1];
257 System.arraycopy(list, 0, newList, 1, list.length);
258 newList[0] = ANONYMOUS_CIPHER_SUITE;
259 return newList;
260 }
261
262 }
263