It's a bug.  Key password must be respected.  I would be more than happy if you are coming up with a patch!
 And, here's the ICLA form: https://docs.google.com/spreadsheet/viewform?formkey=dHBjc1YzdWhsZERUQnhlSklsbG1KT1E6MQ
 Alright, I filled in the ICLA form and will do my best to help.

Why not make this class final and add a private constructor? Seems like it only contains a static method anyway.
 Add empty line 
 Also I think we can make it package private
 After thinking a bit more about it maybe we could also just merge it into `JdkSslServerContext`. Or is there any reasons to not do so ?
 It was part of `JSSC` but then I extracted a class in order to separate concerns since key spec generation doesn't require the class context of `JSSC`. However, `JSSC` is the only class using it, so I might as well merge it back into it, for the sake of simplicity.
 Yep just merge it for now.

JdkSslContext ignores key password
I'm using **5.0.0.Alpha2-SNAPSHOT** with java 1.7.0_51 on OS X 10.9.3.

When `JdkSslContext` is initialized it creates a  `java.security.spec.PKCS8EncodedKeySpec` from the `byte[]` read by `PemReader` which is passed to a `java.security.KeyFactory` in order to obtain a `java.security.PrivateKey`. This only works if the contents of the key file are **not ecrypted**. Otherwise this fails with an exception like `java.security.InvalidKeyException: IOException : DER input, Integer tag error`.

I'd expect that if a password is passed the contents of the key file are be considered encrypted and therefore have to be decrypted first ([see this answer](http://stackoverflow.com/a/3985508)).

Unless this is somehow intended, I'd try to come up with a patch.

handler/src/main/java/io/netty/handler/ssl/JdkSslServerContext.java
handler/src/main/java/io/netty/handler/ssl/JdkSslServerContext.java
handler/src/test/java/io/netty/handler/ssl/JdkSslServerContextTest.java handler/src/test/resources/io/netty/handler/ssl/netty_test handler/src/test/resources/io/netty/handler/ssl/netty_test.crt handler/src/test/resources/io/netty/handler/ssl/netty_test_unencrypted
diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkSslServerContext.java b/handler/src/main/java/io/netty/handler/ssl/JdkSslServerContext.java
index 6fcd2445215..92ba7fa74b8 100644
--- a/handler/src/main/java/io/netty/handler/ssl/JdkSslServerContext.java
+++ b/handler/src/main/java/io/netty/handler/ssl/JdkSslServerContext.java
@@ -13,19 +13,15 @@
  * License for the specific language governing permissions and limitations
  * under the License.
  */
-
 package io.netty.handler.ssl;
 
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufInputStream;
-
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSessionContext;
 import java.io.File;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
 import java.security.KeyFactory;
 import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.Security;
 import java.security.cert.Certificate;
@@ -36,6 +32,20 @@
 import java.util.Collections;
 import java.util.List;
 
+import javax.crypto.Cipher;
+import javax.crypto.EncryptedPrivateKeyInfo;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSessionContext;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufInputStream;
+
 /**
  * A server-side {@link SslContext} which uses JDK's SSL/TLS implementation.
  */
@@ -59,8 +69,7 @@ public JdkSslServerContext(File certChainFile, File keyFile) throws SSLException
      *
      * @param certChainFile an X.509 certificate chain file in PEM format
      * @param keyFile a PKCS#8 private key file in PEM format
-     * @param keyPassword the password of the {@code keyFile}.
-     *                    {@code null} if it's not password-protected.
+     * @param keyPassword the password of the {@code keyFile}. {@code null} if it's not password-protected.
      */
     public JdkSslServerContext(File certChainFile, File keyFile, String keyPassword) throws SSLException {
         this(certChainFile, keyFile, keyPassword, null, null, 0, 0);
@@ -71,16 +80,15 @@ public JdkSslServerContext(File certChainFile, File keyFile, String keyPassword)
      *
      * @param certChainFile an X.509 certificate chain file in PEM format
      * @param keyFile a PKCS#8 private key file in PEM format
-     * @param keyPassword the password of the {@code keyFile}.
-     *                    {@code null} if it's not password-protected.
-     * @param ciphers the cipher suites to enable, in the order of preference.
-     *                {@code null} to use the default cipher suites.
-     * @param nextProtocols the application layer protocols to accept, in the order of preference.
-     *                      {@code null} to disable TLS NPN/ALPN extension.
-     * @param sessionCacheSize the size of the cache used for storing SSL session objects.
-     *                         {@code 0} to use the default value.
-     * @param sessionTimeout the timeout for the cached SSL session objects, in seconds.
-     *                       {@code 0} to use the default value.
+     * @param keyPassword the password of the {@code keyFile}. {@code null} if it's not password-protected.
+     * @param ciphers the cipher suites to enable, in the order of preference. {@code null} to use the default cipher
+     * suites.
+     * @param nextProtocols the application layer protocols to accept, in the order of preference. {@code null} to
+     * disable TLS NPN/ALPN extension.
+     * @param sessionCacheSize the size of the cache used for storing SSL session objects. {@code 0} to use the default
+     * value.
+     * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. {@code 0} to use the default
+     * value.
      */
     public JdkSslServerContext(
             File certChainFile, File keyFile, String keyPassword,
@@ -106,7 +114,7 @@ public JdkSslServerContext(
             }
 
             List<String> list = new ArrayList<String>();
-            for (String p: nextProtocols) {
+            for (String p : nextProtocols) {
                 if (p == null) {
                     break;
                 }
@@ -133,7 +141,9 @@ public JdkSslServerContext(
             ByteBuf encodedKeyBuf = PemReader.readPrivateKey(keyFile);
             byte[] encodedKey = new byte[encodedKeyBuf.readableBytes()];
             encodedKeyBuf.readBytes(encodedKey).release();
-            PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(encodedKey);
+
+            char[] keyPasswordChars = keyPassword.toCharArray();
+            PKCS8EncodedKeySpec encodedKeySpec = generateKeySpec(keyPasswordChars, encodedKey);
 
             PrivateKey key;
             try {
@@ -145,20 +155,20 @@ public JdkSslServerContext(
             List<Certificate> certChain = new ArrayList<Certificate>();
             ByteBuf[] certs = PemReader.readCertificates(certChainFile);
             try {
-                for (ByteBuf buf: certs) {
+                for (ByteBuf buf : certs) {
                     certChain.add(cf.generateCertificate(new ByteBufInputStream(buf)));
                 }
             } finally {
-                for (ByteBuf buf: certs) {
+                for (ByteBuf buf : certs) {
                     buf.release();
                 }
             }
 
-            ks.setKeyEntry("key", key, keyPassword.toCharArray(), certChain.toArray(new Certificate[certChain.size()]));
+            ks.setKeyEntry("key", key, keyPasswordChars, certChain.toArray(new Certificate[certChain.size()]));
 
             // Set up key manager factory to use our key store
             KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
-            kmf.init(ks, keyPassword.toCharArray());
+            kmf.init(ks, keyPasswordChars);
 
             // Initialize the SSLContext to work with our key managers.
             ctx = SSLContext.getInstance(PROTOCOL);
@@ -190,4 +200,36 @@ public List<String> nextProtocols() {
     public SSLContext context() {
         return ctx;
     }
+
+    /**
+     * Generates a key specification for an (encrypted) private key.
+     *
+     * @param password characters, if {@code null} or empty an unencrypted key is assumed
+     * @param key bytes of the DER encoded private key
+     * @return a key specification
+     * @throws IOException if parsing {@code key} fails
+     * @throws NoSuchAlgorithmException if the algorithm used to encrypt {@code key} is unkown
+     * @throws NoSuchPaddingException if the padding scheme specified in the decryption algorithm is unkown
+     * @throws InvalidKeySpecException if the decryption key based on {@code password} cannot be generated
+     * @throws InvalidKeyException if the decryption key based on {@code password} cannot be used to decrypt {@code key}
+     * @throws InvalidAlgorithmParameterException if decryption algorithm parameters are somehow faulty
+     */
+    private static PKCS8EncodedKeySpec generateKeySpec(char[] password, byte[] key) throws IOException,
+        NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException,
+        InvalidAlgorithmParameterException {
+
+        if (password == null || password.length == 0) {
+            return new PKCS8EncodedKeySpec(key);
+        }
+
+        EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(key);
+        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(encryptedPrivateKeyInfo.getAlgName());
+        PBEKeySpec pbeKeySpec = new PBEKeySpec(password);
+        SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec);
+
+        Cipher cipher = Cipher.getInstance(encryptedPrivateKeyInfo.getAlgName());
+        cipher.init(Cipher.DECRYPT_MODE, pbeKey, encryptedPrivateKeyInfo.getAlgParameters());
+
+        return encryptedPrivateKeyInfo.getKeySpec(cipher);
+    }
 }

diff --git a/handler/src/test/java/io/netty/handler/ssl/JdkSslServerContextTest.java b/handler/src/test/java/io/netty/handler/ssl/JdkSslServerContextTest.java
new file mode 100644
index 00000000000..eb0863002ad
--- /dev/null
+++ b/handler/src/test/java/io/netty/handler/ssl/JdkSslServerContextTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.netty.handler.ssl;
+
+import java.io.File;
+
+import javax.net.ssl.SSLException;
+
+import org.junit.Test;
+
+/**
+ * Tests for JDK SSL Server Context.
+ */
+public class JdkSslServerContextTest {
+
+    @Test
+    public void testJdkSslServerWithEncryptedPrivateKey() throws SSLException {
+        File keyFile = new File(getClass().getResource("netty_test").getFile());
+        File crtFile = new File(getClass().getResource("netty_test.crt").getFile());
+
+        new JdkSslServerContext(crtFile, keyFile, "12345");
+    }
+
+    @Test
+    public void testJdkSslServerWithUnencryptedPrivateKey() throws SSLException {
+        File keyFile = new File(getClass().getResource("netty_test_unencrypted").getFile());
+        File crtFile = new File(getClass().getResource("netty_test.crt").getFile());
+
+        new JdkSslServerContext(crtFile, keyFile, "");
+        new JdkSslServerContext(crtFile, keyFile, null);
+    }
+
+}
diff --git a/handler/src/test/resources/io/netty/handler/ssl/netty_test b/handler/src/test/resources/io/netty/handler/ssl/netty_test
new file mode 100644
index 00000000000..58d181e1161
--- /dev/null
+++ b/handler/src/test/resources/io/netty/handler/ssl/netty_test
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE9jAoBgoqhkiG9w0BDAEDMBoEFDBlaUwB8TQ9ImbApCmAyVRTTX+kAgIIAASC
+BMhC8QFNyn0VbVp7I+R9Yvmr+Ksl0xZshGg3zaUN8/HRblNSS3gPiP673rmnhcU3
+PfSNFR9hOrTqdtd5i6Qq4HznECs81KBlqRNB9ihgy++ByFkf6GTzdfBA6zJInhNx
+qSWjUwpFtV4or1w/N23bTcpdGmjfdCSFBMQdbkIDgT7GaWxd3mCLxSbfVzF64tev
+x+V22nA/TR0VWnG+aj7aVbReK6VpepiCX7ZmQ5KehXAeB0SDrgT89kcz2VIfDxvE
+hkCymNTcJY/ETdPfTSiR+DSZvVJMgVmfk7j1toZZSnoMwl4IhlXmIPmDOUE465l3
+sNWLygkNKymTmMI5FTT1hChAIdsmeVTfDmVzNPK4HQi5gfEnTCy0uxj9U3HCZWr1
+Zlzmw7/430TRqNYSEJ/XkhFaV5V+6LfeZOyuwf2VJAs+CwNo+UYzEQqkW11JMqhA
+i9fz8bCNoy4/dyWbE/wEK8UPGif1rzCpoodBYeWTt0QtHcIokE3ylXWyTTarz7jV
+u9Rnbq4HAXYYEwPjLmWFQ6NeD/rx/t44oEAyekxS+ZPIHNTVXRLBH5Tl/LDkpK15
+x0FoIZ0vrDiFbmtHCq/TeDyFtudSbmihnn0Of6PtXKZJpXgEADQBnak/P4IE39/d
+1hWd3H635goC6OkqHv9IAAyLlCNZCOVqC5Wa8TvyZdaKi5A2mZfGrpxPrUQDlnqN
+8d3xlysNCaRH1hSMw4hGHu0xxGJaK4DQtklxfZB7IMMw5MkQh6Rim5TOXfopmzmK
+PISJge1atiHbVIBP6sr3Egik3h6v0j7xXVmwj3UUQRaSBznZ43ShlYieLnin9sh8
+x/gLyvQrtJRvScN6skgrXFKVH3Jojxut9if64jjLo4C61UgNrvuka05treRTI+jT
+hHB3GLy7hwSHnbsOvwvYbG3WgyePPq6jIM+LV4Vm3fPX6NPNI/jZMebROGwjTL0C
+2403yvgeIpEOQyZpKsDBqAwgKB91Na53K05qGSbr8AgcZvgFflJdLzai+5Cg7hNg
+YTEff0NKPeYnk4u3xQ8EqxI2jwdqfgzd0RcPcx60CHRBTULaKOU2sAYTSpwQmApj
++TnJNcQnWRAEcZ35b/b+oGlVH/BUmvjSdu2qvvU3g4GoHL7MuVGvzk0Cgo1Esktt
+S6gO/pTQPaKGJ1ztxoHu2zzi7/URaus3sqI5qV9krWMSa35BMG21Eik/y9rou6LC
+yT0EtMLOCxSrfM1I26XTU/7qPIEJlVZg0CJ39niZ7EEm1Hef0cmT8Aq9t5cRTyvR
+BqbqBCJpcsgeIZUMH6RJ1zv616eJvY7wjd13Sl0Tbj9+nNS482D9PIlaXSD8UySh
+mZ0bMPhCeyOsmRmz2qT1X+Zct8XtdXc/NPKBA6rnOtH8vJAHn7S120le5XIn5t9l
+rDiO1Hozhb+0xcTk+SNc/vIORA6KrBoZrNpJpmyL3BzRp+/VLbR+/S3ikTDkYj7J
+sktK2ap6vK7u50Jnrt9C/wynVACzGx1tlDVxiVerDmwjfQWL08qCXHlouEdjh9dD
+L5XyVlT2FxEXXLRgKGHxFaSQw3Fzzug/o4SgizbNjKffJU5xQlC0aq3WX5+/l3Ic
+LWTalgdli3edsR/9RGuu8EsZ11dmNh3csGs=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/handler/src/test/resources/io/netty/handler/ssl/netty_test.crt b/handler/src/test/resources/io/netty/handler/ssl/netty_test.crt
new file mode 100644
index 00000000000..7d3437e13e2
--- /dev/null
+++ b/handler/src/test/resources/io/netty/handler/ssl/netty_test.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIC/jCCAeagAwIBAgIIIMONxElm0AIwDQYJKoZIhvcNAQELBQAwPjE8MDoGA1UE
+AwwzZThhYzAyZmEwZDY1YTg0MjE5MDE2MDQ1ZGI4YjA1YzQ4NWI0ZWNkZi5uZXR0
+eS50ZXN0MCAXDTEzMDgwMjA3NTEzNloYDzk5OTkxMjMxMjM1OTU5WjA+MTwwOgYD
+VQQDDDNlOGFjMDJmYTBkNjVhODQyMTkwMTYwNDVkYjhiMDVjNDg1YjRlY2RmLm5l
+dHR5LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDb+HBO3C0U
+RBKvDUgJHbhIlBye8X/cbNH3lDq3XOOFBz7L4XZKLDIXS+FeQqSAUMo2otmU+Vkj
+0KorshMjbUXfE1KkTijTMJlaga2M2xVVt21fRIkJNWbIL0dWFLWyRq7OXdygyFkI
+iW9b2/LYaePBgET22kbtHSCAEj+BlSf265+1rNxyAXBGGGccCKzEbcqASBKHOgVp
+6pLqlQAfuSy6g/OzGzces3zXRrGu1N3pBIzAIwCW429n52ZlYfYR0nr+REKDnRrP
+IIDsWASmEHhBezTD+v0qCJRyLz2usFgWY+7agUJE2yHHI2mTu2RAFngBilJXlMCt
+VwT0xGuQxkbHAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEv8N7Xm8qaY2FgrOc6P
+a1GTgA+AOb3aU33TGwAR86f+nLf6BSPaohcQfOeJid7FkFuYInuXl+oqs+RqM/j8
+R0E5BuGYY2wOKpL/PbFi1yf/Kyvft7KVh8e1IUUec/i1DdYTDB0lNWvXXxjfMKGL
+ct3GMbEHKvLfHx42Iwz/+fva6LUrO4u2TDfv0ycHuR7UZEuC1DJ4xtFhbpq/QRAj
+CyfNx3cDc7L2EtJWnCmivTFA9l8MF1ZPMDSVd4ecQ7B0xZIFQ5cSSFt7WGaJCsGM
+zYkU4Fp4IykQcWxdlNX7wJZRwQ2TZJFFglpTiFZdeq6I6Ad9An1Encpz5W8UJ4tv
+hmw=
+-----END CERTIFICATE-----
diff --git a/handler/src/test/resources/io/netty/handler/ssl/netty_test_unencrypted b/handler/src/test/resources/io/netty/handler/ssl/netty_test_unencrypted
new file mode 100644
index 00000000000..608e7f4da0f
--- /dev/null
+++ b/handler/src/test/resources/io/netty/handler/ssl/netty_test_unencrypted
@@ -0,0 +1,24 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDb+HBO3C0URBKvDUgJHbhIlBye
+8X/cbNH3lDq3XOOFBz7L4XZKLDIXS+FeQqSAUMo2otmU+Vkj0KorshMjbUXfE1KkTijTMJlaga2M
+2xVVt21fRIkJNWbIL0dWFLWyRq7OXdygyFkIiW9b2/LYaePBgET22kbtHSCAEj+BlSf265+1rNxy
+AXBGGGccCKzEbcqASBKHOgVp6pLqlQAfuSy6g/OzGzces3zXRrGu1N3pBIzAIwCW429n52ZlYfYR
+0nr+REKDnRrPIIDsWASmEHhBezTD+v0qCJRyLz2usFgWY+7agUJE2yHHI2mTu2RAFngBilJXlMCt
+VwT0xGuQxkbHAgMBAAECggEBAJJdKaVfXWNptCDkLnVaYB9y5eRgfppVkhQxfiw5023Vl1QjrgjG
+hYH4zHli0IBMwXA/RZWZoFVzZ3dxoshk0iQPgGKxWvrDEJcnSCo8MGL7jPvh52jILp6uzsGZQBji
+bTgFPmOBS7ShdgZiQKD9PD2psrmqHZ1yTwjIm5cGfzQM8Y6tjm0xLBn676ecJNdS1TL10y9vmSUM
+Ofdkmeg9Z9TEK95lP2fF/NIcxCo0LF9JcHUvTuYBDnBH0XMZi0w0ZcRReMSdAZ2lLiXgBeCO53el
+2NIrtkRx+qOvLua9UfwO2h/0rs66ZeV0YuFCjv067nytyZf2zhU/QbCHRypzfrkCgYEA/facuAJs
+6MQKsNvhozoBeDRMkrZPMh8Sb0w50EqzIGz3pdms6UvCiggoMbhxKOwuYWZ689fBPGwm7x0RdwDO
+jyUuEbFnQFe+CpdHy6VK7vIQed1SwAcdTMDwCYbkJNglqHEB7qUYYTFLr8okGyWVdthUoh4IAubU
+TR3TFbGraDUCgYEA3bwJ/UNA5pHtb/nh4/dNL7/bRMwXyPZPpC5z+gjjgUMgsSRBz8+iPNTB4iSQ
+1j9zm+pnXGi35zWZcI4jvIcFusb08eS7xcZDb+7X2r2wenLNmyuTOa1812y233FicU+ah91fa9aD
+yUfTjj3GFawbgNNhMyWa3aEMV+c73t6sKosCgYEA35oQZhsMlOx2lT0jrzlVLeauPMZzeCfPbVrp
+1DDRAg2vBcFf8pCXmjyQVyaTy3oXY/585tDh/DclGIa5Z9O4CmSr6TwPMqGOW3jS58SC81sBkqqB
+Pz2EWJ3POjQgDyiYD3RgRSPrETf78azCmXw/2sGh0pMqbpOZ/MPzpDgoOLkCgYEAsdv4g09kCs75
+Dz34hRzErE2P+8JePdPdlEuyudhRbUlEOvNjWucpMvRSRSyhhUnGWUWP/V7+TRcAanmJjtsbrHOU
+3Udlm0HqrCmAubQ4kC/wXsx4Pua7Yi2RDvBrT4rT4LGgreaXNWhI+Srx7kZslUx5Bkbez3I0bXpM
+2vvwS/sCgYAducNt1KC4W7jzMWUivvuy5hQQmX/G0JHtu1pfv9cmA8agnc1I/r7xoirftuSG25Pm
+r+eP5SKbKb8ZQlp10JeBkNnk8eAG8OkQyBaECYDBadEr1/LK2LmIEjYKzKAjYQ4cX2KMtY271jjX
+WrzzXNqBdThFfMHiJE8k9xYmaLDKhQ==
+-----END PRIVATE KEY-----
