1 5 package org.h2.security; 6 7 import java.io.IOException ; 8 import java.net.InetAddress ; 9 import java.net.ServerSocket ; 10 import java.net.Socket ; 11 import java.sql.SQLException ; 12 13 import java.io.ByteArrayInputStream ; 15 import java.io.ByteArrayOutputStream ; 16 import java.io.File ; 17 import java.io.FileInputStream ; 18 import java.io.FileOutputStream ; 19 import java.security.Key ; 20 import java.security.KeyFactory ; 21 import java.security.KeyStore ; 22 import java.security.KeyStoreException ; 23 import java.security.NoSuchAlgorithmException ; 24 import java.security.PrivateKey ; 25 import java.security.UnrecoverableKeyException ; 26 import java.security.cert.Certificate ; 27 import java.security.cert.CertificateEncodingException ; 28 import java.security.cert.CertificateFactory ; 29 import java.security.spec.PKCS8EncodedKeySpec ; 30 import java.util.Enumeration ; 31 import java.util.Properties ; 32 import javax.net.ServerSocketFactory; 33 import javax.net.ssl.SSLServerSocket; 34 import javax.net.ssl.SSLServerSocketFactory; 35 import javax.net.ssl.SSLSocket; 36 import javax.net.ssl.SSLSocketFactory; 37 import org.h2.message.Message; 38 import org.h2.util.ByteUtils; 39 import org.h2.util.FileUtils; 40 import org.h2.util.IOUtils; 41 43 51 public class SecureSocketFactory { 52 53 private static final String KEYSTORE = ".h2.keystore"; 54 private static final String KEYSTORE_KEY = "javax.net.ssl.keyStore"; 55 private static final String KEYSTORE_PASSWORD_KEY = "javax.net.ssl.keyStorePassword"; 56 private static final String KEYSTORE_PASSWORD = "h2pass"; 57 58 private static final boolean ENABLE_ANONYMOUS_SSL = true; 60 private static SecureSocketFactory factory; 61 private static final String ANONYMOUS_CIPHER_SUITE = "SSL_DH_anon_WITH_RC4_128_MD5"; 62 63 private static void setFactory(SecureSocketFactory f) { 64 factory = f; 65 } 66 67 public static SecureSocketFactory getInstance() { 68 if (factory == null) { 69 setFactory(new SecureSocketFactory()); 70 } 71 return factory; 72 } 73 74 public Socket createSocket(InetAddress address, int port) throws SQLException , IOException { 75 Socket socket = null; 76 setKeystore(); 78 SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault(); 79 SSLSocket secureSocket = (SSLSocket) f.createSocket(address, port); 80 if (ENABLE_ANONYMOUS_SSL) { 81 String [] list = secureSocket.getEnabledCipherSuites(); 82 list = addAnonymous(list); 83 secureSocket.setEnabledCipherSuites(list); 84 } 85 socket = secureSocket; 86 return socket; 88 } 89 90 public ServerSocket createServerSocket(int port) throws IOException , SQLException { 91 ServerSocket socket = null; 92 setKeystore(); 94 ServerSocketFactory f = SSLServerSocketFactory.getDefault(); 95 SSLServerSocket secureSocket = (SSLServerSocket) f.createServerSocket(port); 96 if (ENABLE_ANONYMOUS_SSL) { 97 String [] list = secureSocket.getEnabledCipherSuites(); 98 list = addAnonymous(list); 99 secureSocket.setEnabledCipherSuites(list); 100 } 101 socket = secureSocket; 102 return socket; 104 } 105 106 private static byte[] getBytes(String hex) throws SQLException { 108 return ByteUtils.convertStringToBytes(hex); 109 } 110 111 private byte[] getKeyStoreBytes(KeyStore store, String password) throws SQLException { 112 try { 113 ByteArrayOutputStream bout = new ByteArrayOutputStream (); 114 store.store(bout, KEYSTORE_PASSWORD.toCharArray()); 115 return bout.toByteArray(); 116 } catch(Exception e) { 117 throw Message.convert(e); 118 } 119 } 120 121 public static void main(String [] a) throws Exception { 122 KeyStore store = getKeyStore(KEYSTORE_PASSWORD); 127 printKeystore(store, KEYSTORE_PASSWORD); 128 } 129 130 private static KeyStore getKeyStore(String password) throws SQLException { 131 try { 132 137 KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType()); 140 141 store.load(null, password.toCharArray()); 142 KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 143 store.load(null, password.toCharArray()); 144 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec (getBytes("30820277020100300d06092a864886f70d0101010500048202613082025d02010002818100dc0a13c602b7141110eade2f051b54777b060d0f74e6a110f9cce81159f271ebc88d8e8aa1f743b505fc2e7dfe38d33b8d3f64d1b363d1af4d877833897954cbaec2fa384c22a415498cf306bb07ac09b76b001cd68bf77ea0a628f5101959cf2993a9c23dbee79b19305977f8715ae78d023471194cc900b231eecb0aaea98d02030100010281810099aa4ff4d0a09a5af0bd953cb10c4d08c3d98df565664ac5582e494314d5c3c92dddedd5d316a32a206be4ec084616fe57be15e27cad111aa3c21fa79e32258c6ca8430afc69eddd52d3b751b37da6b6860910b94653192c0db1d02abcfd6ce14c01f238eec7c20bd3bb750940004bacba2880349a9494d10e139ecb2355d101024100ffdc3defd9c05a2d377ef6019fa62b3fbd5b0020a04cc8533bca730e1f6fcf5dfceea1b044fbe17d9eababfbc7d955edad6bc60f9be826ad2c22ba77d19a9f65024100dc28d43fdbbc93852cc3567093157702bc16f156f709fb7db0d9eec028f41fd0edcd17224c866e66be1744141fb724a10fd741c8a96afdd9141b36d67fff6309024077b1cddbde0f69604bdcfe33263fb36ddf24aa3b9922327915b890f8a36648295d0139ecdf68c245652c4489c6257b58744fbdd961834a4cab201801a3b1e52d024100b17142e8991d1b350a0802624759d48ae2b8071a158ff91fabeb6a8f7c328e762143dc726b8529f42b1fab6220d1c676fdc27ba5d44e847c72c52064afd351a902407c6e23fe35bcfcd1a662aa82a2aa725fcece311644d5b6e3894853fd4ce9fe78218c957b1ff03fc9e5ef8ffeb6bd58235f6a215c97d354fdace7e781e4a63e8b")); 145 PrivateKey privateKey = keyFactory.generatePrivate(keySpec); 146 Certificate [] certs = new Certificate []{ 147 CertificateFactory.getInstance("X.509"). 148 generateCertificate(new ByteArrayInputStream (getBytes("3082018b3081f502044295ce6b300d06092a864886f70d0101040500300d310b3009060355040313024832301e170d3035303532363133323630335a170d3337303933303036353734375a300d310b300906035504031302483230819f300d06092a864886f70d010101050003818d0030818902818100dc0a13c602b7141110eade2f051b54777b060d0f74e6a110f9cce81159f271ebc88d8e8aa1f743b505fc2e7dfe38d33b8d3f64d1b363d1af4d877833897954cbaec2fa384c22a415498cf306bb07ac09b76b001cd68bf77ea0a628f5101959cf2993a9c23dbee79b19305977f8715ae78d023471194cc900b231eecb0aaea98d0203010001300d06092a864886f70d01010405000381810083f4401a279453701bef9a7681a5b8b24f153f7d18c7c892133d97bd5f13736be7505290a445a7d5ceb75522403e5097515cd966ded6351ff60d5193de34cd36e5cb04d380398e66286f99923fd92296645fd4ada45844d194dfd815e6cd57f385c117be982809028bba1116c85740b3d27a55b1a0948bf291ddba44bed337b9"))), 149 }; 150 store.setKeyEntry("h2", privateKey, password.toCharArray(), certs); 151 return store; 153 } catch(Exception e) { 154 throw Message.convert(e); 155 } 156 } 157 158 private static void printKeystore(KeyStore store, String password) throws KeyStoreException , NoSuchAlgorithmException , UnrecoverableKeyException , CertificateEncodingException { 159 System.out.println("KeyStore store = KeyStore.getInstance(\""+store.getType()+"\");"); 160 System.out.println("store.load(null, password.toCharArray());"); 161 Enumeration en = store.aliases(); 163 while(en.hasMoreElements()) { 164 String alias = (String ) en.nextElement(); 165 Key key = store.getKey(alias, password.toCharArray()); 166 System.out.println("KeyFactory keyFactory = KeyFactory.getInstance(\""+key.getAlgorithm()+"\");"); 167 System.out.println("store.load(null, password.toCharArray());"); 168 String pkFormat = key.getFormat(); 169 String encoded = ByteUtils.convertBytesToString(key.getEncoded()); 170 System.out.println(pkFormat+"EncodedKeySpec keySpec = new "+pkFormat+"EncodedKeySpec(getBytes(\"" +encoded+ "\"));"); 171 System.out.println("PrivateKey privateKey = keyFactory.generatePrivate(keySpec);"); 172 System.out.println("Certificate[] certs = new Certificate[]{"); 173 Certificate [] certs = store.getCertificateChain(alias); 174 for(int i=0; i<certs.length; i++) { 175 Certificate cert = certs[i]; 176 System.out.println(" CertificateFactory.getInstance(\""+cert.getType()+"\")."); 177 String enc = ByteUtils.convertBytesToString(cert.getEncoded()); 178 System.out.println(" generateCertificate(new ByteArrayInputStream(getBytes(\""+enc+"\"))),"); 179 } 184 System.out.println("};"); 185 System.out.println("store.setKeyEntry(\""+alias+"\", privateKey, password.toCharArray(), certs);"); 186 } 187 } 188 189 private void setKeystore() throws IOException , SQLException { 190 Properties p = System.getProperties(); 191 if (p.getProperty(KEYSTORE_KEY) == null) { 192 File file = FileUtils.getFileInUserHome(KEYSTORE); 193 byte[] data = getKeyStoreBytes(getKeyStore(KEYSTORE_PASSWORD), KEYSTORE_PASSWORD); 194 boolean needWrite = true; 195 if (file.exists() && file.length() == data.length) { 196 FileInputStream fin = new FileInputStream (file); 198 byte[] now = IOUtils.readBytesAndClose(fin, 0); 199 if (now != null && ByteUtils.compareNotNull(data, now) == 0) { 200 needWrite = false; 201 } 202 } 203 if (needWrite) { 204 FileOutputStream out = new FileOutputStream (file); 205 out.write(data); 206 out.close(); 207 } 208 System.setProperty(KEYSTORE_KEY, file.getAbsolutePath()); 209 } 210 if (p.getProperty(KEYSTORE_PASSWORD_KEY) == null) { 211 System.setProperty(KEYSTORE_PASSWORD_KEY, KEYSTORE_PASSWORD); 212 } 213 } 214 215 private String [] addAnonymous(String [] list) { 216 String [] newList = new String [list.length + 1]; 217 System.arraycopy(list, 0, newList, 1, list.length); 218 newList[0] = ANONYMOUS_CIPHER_SUITE; 219 return newList; 220 } 221 222 234 } 235 | Popular Tags |