Взаимная аутентификация с использованием сертификата pkcs12 в java-клиенте с сервером weblogic

Я не могу получить mbeans с сервера Weblogic, используя ssl-сертификат PKCS12 через Java-клиент.

  • Сервер: Веблоджик
  • Клиент: Java-клиент/JConsole

Команды на стороне сервера, используемые для создания самозаверяющих сертификатов: Создан сертификат с помощью утилиты Weblogic CertGen, Weblogic CertGenCA.der и Центра сертификации.

java utils.CertGen -certfile ServerCert -keyfile ServerKey -keyfilepass keypass

java utils.der2pem CertGenCA.der

type serverCert.pem CertGenCA.pem >> myCert.pem

Server Keystore created>>
java utils.ImportPrivateKey -keystore  SeverIdentity.jks -storepass storepass -storetype JKS \
    -keypass keypass -alias mykey -certfile myCert.pem -keyfile ServerKey.pem \
    -keyfilepass keypass

Server Truststore used>>
DemoTrust.jks (Default Weblogic truststore)

Команды на стороне клиента, используемые для создания самозаверяющего сертификата PKCS12:

java utils.CertGen -certfile ClientCert -keyfile ClientKey -keyfilepass keypass

openssl pkcs12 -export -in ClientCert.pem -inkey ClientKey.pem -out client-pkcs-12-cert

Конфигурации, выполненные в консоли администратора Weblogic:

Keystores: Custom Identity Custom Trust.
Custom Identity Keystore:  D:\certificate\latest\pkcs\SeverIdentity.jks
Custom Identity Keystore Type: JKS
Custom Identity Keystore Passphrase: storepass (same as –storepass value of ImportPrivateKey)
Confirm Custom Identity Keystore Passphrase: storepass
Custom Trust Keystore: D:\certificate\latest\pkcs\DemoTrust.jks
Custom Trust Keystore Type: JKS
Custom Trust Keystore Passphrase: DemoTrustKeyStorePassPhrase
Custom Trust Keystore Passphrase: DemoTrustKeyStorePassPhrase

Конфигурации, сделанные в setDomainEnv.cmd:

set JAVA_OPTIONS=%JAVA_OPTIONS% -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9191 \
    -Dcom.sun.management.jmxremote.ssl=true -Dcom.sun.management.jmxremote.authenticate=false \
    -Djavax.net.ssl.keyStore=D:\certificate\latest\pkcs\SeverIdentity.jks \
    -Djavax.net.ssl.keyStorePassword=keypass -Djavax.net.ssl.trustStore=D:\certificate\latest\pkcs\DemoTrust.jks \
    -Djavax.net.ssl.trustStorePassword=DemoTrustKeyStorePassPhrase -Djava.rmi.server.hostname=10.112.69.200

Ссылка: http://www.weblogic-tips.com/2010/05/20/two-way-ssl-on-weblogic-server/

Код Java-клиента:

public static void main22(String args[]) {

try {

    System.setProperty("javax.net.ssl.keyStore",
            "D://certificate//latest//client-pkcs-12-cert");
    System.setProperty("javax.net.ssl.keyStorePassword", "keypass");

    HashMap<String, Object> env = new HashMap<String, Object>();
    String truststore = "D://certificate//latest//client-pkcs-12-cert";
    char truststorepass[] = "keypass".toCharArray();
    KeyStore ks = KeyStore.getInstance("pkcs12");
    ks.load(new FileInputStream(truststore), truststorepass);

    TrustManagerFactory tmf = TrustManagerFactory
            .getInstance("SunX509");

    tmf.init(ks);
    SSLContext ctx = SSLContext.getInstance("TLSv1");
    ctx.init(null, tmf.getTrustManagers(), null);
    SSLSocketFactory ssf = ctx.getSocketFactory();

    env.put("jmx.remote.tls.socket.factory", ssf);

    JMXServiceURL address = new JMXServiceURL("rmi", "", 0,
            "/jndi/rmi://localhost:9191/jmxrmi");

    JMXConnector jmxc = JMXConnectorFactory.connect(address, env);
    MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
    Set<ObjectInstance> beans = mbsc.queryMBeans(null, null);

    for (ObjectInstance instance : beans) {
        MBeanInfo info = mbsc.getMBeanInfo(instance.getObjectName());
        System.out.println(info);
    }

    jmxc.close();
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("error :" + e.getMessage());
    }
}

Я могу получить mbeans, когда используется сертификат JKS, но когда я использую сертификат PKCS12, он дает следующую ошибку при подключении через JMXConnectorFactory: Исключение в строке: JMXConnector jmxc = JMXConnectorFactory.connect(address, env);

Исключения:

java.rmi.ConnectIOException: Exception creating connection to: 10.112.69.200; nested exception is: 
       java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)
       at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:614)
       at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
       at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
       at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:110)
       at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
       at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2327)
       at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:277)
       at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:248)
       at test.Test.main(Test.java:68)
Caused by: java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)
       at javax.net.ssl.DefaultSSLSocketFactory.throwException(SSLSocketFactory.java:179)
       at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:192)
       at javax.rmi.ssl.SslRMIClientSocketFactory.createSocket(SslRMIClientSocketFactory.java:105)
       at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)
       ... 8 more
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)
       at java.security.Provider$Service.newInstance(Provider.java:1245)
       at sun.security.jca.GetInstance.getInstance(GetInstance.java:220)
       at sun.security.jca.GetInstance.getInstance(GetInstance.java:147)
       at javax.net.ssl.SSLContext.getInstance(SSLContext.java:125)
       at javax.net.ssl.SSLContext.getDefault(SSLContext.java:68)
       at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:102)
       at javax.rmi.ssl.SslRMIClientSocketFactory.getDefaultClientSocketFactory(SslRMIClientSocketFactory.java:192)
       at javax.rmi.ssl.SslRMIClientSocketFactory.createSocket(SslRMIClientSocketFactory.java:102)
       at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:595)
       at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:198)
       at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
       at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
       at sun.rmi.transport.DGCImpl_Stub.dirty(Unknown Source)
       at sun.rmi.transport.DGCClient$EndpointEntry.makeDirtyCall(DGCClient.java:342)
       at sun.rmi.transport.DGCClient$EndpointEntry.registerRefs(DGCClient.java:285)
       at sun.rmi.transport.DGCClient.registerRefs(DGCClient.java:121)
       at sun.rmi.transport.ConnectionInputStream.registerRefs(ConnectionInputStream.java:80)
       at sun.rmi.transport.StreamRemoteCall.releaseInputStream(StreamRemoteCall.java:138)
       at sun.rmi.transport.StreamRemoteCall.done(StreamRemoteCall.java:292)
       at sun.rmi.server.UnicastRef.done(UnicastRef.java:431)
       at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
       at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:97)
       at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:185)
       at javax.naming.InitialContext.lookup(InitialContext.java:392)
       at javax.management.remote.rmi.RMIConnector.findRMIServerJNDI(RMIConnector.java:1886)
       at javax.management.remote.rmi.RMIConnector.findRMIServer(RMIConnector.java:1856)
       at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:255)
       ... 2 more
Caused by: java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.
       at sun.security.util.DerInputStream.getLength(DerInputStream.java:544)
       at sun.security.util.DerValue.init(DerValue.java:347)
       at sun.security.util.DerValue.<init>(DerValue.java:303)
       at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1200)
       at java.security.KeyStore.load(KeyStore.java:1185)
       at com.sun.net.ssl.internal.ssl.TrustManagerFactoryImpl.getCacertsKeyStore(TrustManagerFactoryImpl.java:202)
       at com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl.getDefaultTrustManager(DefaultSSLContextImpl.java:70)
       at com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl.<init>(DefaultSSLContextImpl.java:40)
       at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
       at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
       at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
       at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
       at java.lang.Class.newInstance0(Class.java:357)
       at java.lang.Class.newInstance(Class.java:310)
       at java.security.Provider$Service.newInstance(Provider.java:1221)
       ... 28 more
error :Exception creating connection to: 10.112.69.200; nested exception is: 
       java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)

person user3588245    schedule 07.05.2014    source источник
comment
Команды на стороне клиента, используемые для создания самозаверяющего сертификата PKCS12 ... - это будет непросто. Он не масштабируется до 10 000 или 25 000 клиентов...   -  person jww    schedule 07.05.2014
comment
java.security.NoSuchAlgorithmException – Попробуйте добавить -Djavax.net.debug=ssl или хотя бы -Djavax.net.debug=ssl,keymanager для получения дополнительной информации.   -  person jww    schedule 07.05.2014
comment
Также см. Java и SSL — java.security.NoSuchAlgorithmException.   -  person jww    schedule 07.05.2014
comment
возможный дубликат Столкновение с проблемой при аутентификации pkcs12 cer в weblogic   -  person Display Name is missing    schedule 07.05.2014
comment
Вы также задали этот вопрос здесь, не зная, на какой из них вы хотите получить ответ, но, пожалуйста, не задавайте один и тот же вопрос несколько раз: stackoverflow.com/questions/23384672/ И почему бы не использовать файл JKS с клиентом, если это работает? Мы не используем p12 для клиентов, мы используем только JKS.   -  person Display Name is missing    schedule 07.05.2014


Ответы (1)


Во-первых, ... (РЕДАКТИРОВАТЬ: я понял, что неправильно понял часть ошибки, мой первый пункт наверняка был, по крайней мере, частично неверным.)

Быстрый поиск вашего сообщения об ошибке (java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.) указывает на эту страницу поддержки IBM, который предлагает использовать хранилище ключей JKS вместо PKCS#12 (на стороне сервера, чего вы не делаете) или что в сертификате есть неправильные символы.

Во-вторых, у вас нет шансов заставить аутентификацию клиентского сертификата работать с этим кодом, даже если проблемы с сертификатом вашего сервера будут устранены.

String truststore = "D://certificate//latest//client-pkcs-12-cert";
char truststorepass[] = "keypass".toCharArray();
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(new FileInputStream(truststore), truststorepass);

TrustManagerFactory tmf = TrustManagerFactory
        .getInstance("SunX509");

tmf.init(ks);
SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(null, tmf.getTrustManagers(), null);

Файл PKCS#12 должен содержать сертификат вашего клиента и его закрытый ключ. Он предназначен для использования в качестве хранилища ключей, а не доверительного хранилища. То есть, хотя сущность и называется хранилищем ключей в обоих случаях, вы должны использовать ее с диспетчером ключей, а не с диспетчером доверия.

Здесь вы используете файл PKCS#12 для инициализации менеджера доверия вашего SSLContext. Вместо этого вы должны инициализировать менеджер ключей.

Кроме того, если вы используете свой код с JRE, который не связан с Sun/Oracle/OpenJDK, вам, вероятно, следует избегать жесткого кода «SunX509», вместо этого используйте TrustManagerFactory.getDefaultAlgorthim() (то же самое для KeyManagerFactory при реализации этого этапа ).

person Bruno    schedule 07.05.2014