在Android上使用HTTPS Restlet服务器“找不到服务器证书”

时间:2015-05-28 16:54:30

标签: android ssl https ssl-certificate restlet

我正在使用Restlet 2.3.2和Android 4.4.4。

我之前使用Restlet with HTTP成功运行了一个Android服务器应用程序,但现在,我遇到了尝试使用HTTPS执行相同操作的问题。

尝试使用我的Chrome浏览器连接到此服务器会返回ERR_CONNECTION_CLOSE错误。正如您所看到的,logcat中有一个异常,表明没有找到任何服务器证书。所以,我猜我的错误是围绕证书生成......

这是我的Android服务器代码:

// Creating a minimal Restlet returning "Hello World"
Restlet restlet = new Restlet() {
    @Override
    public void handle(Request request, Response response) {
        response.setEntity("Hello World!", MediaType.TEXT_PLAIN);
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final File keystore3 = new File("/storage/sdcard0/qlinks.bks");
    Log.d(TAG, "Keystore3 exists: " + keystore3.exists());
    Log.d(TAG, "Keystore3 can read: " + keystore3.canRead());

    Engine.getInstance().getRegisteredServers().add(new HttpsServerHelper(null));
    Engine.setLogLevel(Level.FINEST);

    // Create a new Component.
    Component component = new Component();

    // Add a new HTTPS server listening on port 8080
    Server server = component.getServers().add(Protocol.HTTPS, 8080);  
    Series<Parameter> parameters = server.getContext().getParameters();
    parameters.add("sslContextFactory", "org.restlet.engine.ssl.DefaultSslContextFactory");
    parameters.add("keyStorePath", "/storage/sdcard0/qlinks.bks");
    parameters.add("keyStorePassword", "password");
    parameters.add("keyPassword", "password");
    parameters.add("keyStoreType", "BKS");

    parameters.add("keyManagerAlgorithm", KeyManagerFactory.getDefaultAlgorithm());

    // Attach the sample application.
    component.getDefaultHost().attach("/test", restlet);

    // Start the component.
    try {
        server.start();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

这是logcat输出:

I/System.out(11955): debugger has settled (1315)
D/q_links.RestletServer(11955): Keystore3 exists: true
D/q_links.RestletServer(11955): Keystore3 can read: true
D/dalvikvm(11955): GC_FOR_ALLOC freed 249K, 3% free 9142K/9416K, paused 39ms, total 40ms
W/System.err(11955): Starting the internal [HTTPS/1.1] server on port 8080
[...]
W/System.err(11955): NIO controller selected 1 key(s) !
W/System.err(11955): ReadableSocketChannel created from: java.nio.SocketChannelImpl@424e2cc0,Interest= NONE , Ready=NONE , Canceling=false. Registration: Interest= NONE , Ready=NONE , Canceling=false
W/System.err(11955): ReadableSslChannel created from: org.restlet.ext.nio.internal.connection.Connection$1@424e5dc0. Registration: Interest= NONE , Ready=NONE , Canceling=false
W/System.err(11955): Connection state (old | new) : OPENING | OPEN
W/System.err(11955): InboundWay#setMessageState: START
W/System.err(11955): InboundWay#setIoState: INTEREST
W/System.err(11955): Old connection NIO interest: Interest= NONE , Ready=NONE , Canceling=false
W/System.err(11955): New connection NIO interest: Interest= READ , Ready=NONE , Canceling=false
W/System.err(11955): Connection from "/192.168.2.77:56441" accepted. New count: 1
W/System.err(11955): helper.control()
W/System.err(11955): controlConnections()
W/System.err(11955): Connection status: OPEN | true | Interest= READ , Ready=NONE , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@420f5280 | null
W/System.err(11955): registerKeys()
W/System.err(11955): Registering new NIO interest with selector: Interest= READ , Ready=NONE , Canceling=false
W/System.err(11955): updateKeys()
W/System.err(11955): selectKeys(60000)
W/System.err(11955): NIO controller about to sleep 60000 ms, selecting among 2 keys...
W/System.err(11955): NIO controller selected 2 key(s) !
W/System.err(11955): ReadableSocketChannel created from: java.nio.SocketChannelImpl@424f8670,Interest= NONE , Ready=NONE , Canceling=false. Registration: Interest= NONE , Ready=NONE , Canceling=false
W/System.err(11955): ReadableSslChannel created from: org.restlet.ext.nio.internal.connection.Connection$1@424f8cd0. Registration: Interest= NONE , Ready=NONE , Canceling=false
W/System.err(11955): Connection state (old | new) : OPENING | OPEN
W/System.err(11955): InboundWay#setMessageState: START
W/System.err(11955): InboundWay#setIoState: INTEREST
W/System.err(11955): Old connection NIO interest: Interest= NONE , Ready=NONE , Canceling=false
W/System.err(11955): New connection NIO interest: Interest= READ , Ready=NONE , Canceling=false
W/System.err(11955): Connection from "/192.168.2.77:56442" accepted. New count: 2
W/System.err(11955): NIO selection detected for key: Interest= READ , Ready=NONE , Canceling=false
W/System.err(11955): Server connection (state | empty | registration): OPEN | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@420f5280 | null
W/System.err(11955): InboundWay#setIoState: PROCESSING
W/System.err(11955): Processing IO for inbound way: PROCESSING, START, java.nio.ByteArrayBuffer[position=0,limit=16384,capacity=16384], FILLING, true
W/System.err(11955): Beginning process of buffer java.nio.ByteArrayBuffer[position=0,limit=16384,capacity=16384], FILLING, true
W/System.err(11955): 0 bytes drained from buffer at pre-processing, 16384 remaining bytes
W/System.err(11955): Filling buffer java.nio.ByteArrayBuffer[position=0,limit=16384,capacity=16384], FILLING, true
W/System.err(11955): Beginning process of buffer java.nio.ByteArrayBuffer[position=0,limit=18437,capacity=18437], FILLING, true
W/System.err(11955): 0 bytes drained from buffer at pre-processing, 18437 remaining bytes
W/System.err(11955): Filling buffer java.nio.ByteArrayBuffer[position=0,limit=18437,capacity=18437], FILLING, true
W/System.err(11955): 179 bytes filled into buffer
W/System.err(11955): Filling buffer java.nio.ByteArrayBuffer[position=179,limit=18437,capacity=18437], FILLING, false
W/System.err(11955): Draining buffer java.nio.ByteArrayBuffer[position=0,limit=179,capacity=18437], DRAINING, false
W/System.err(11955): SSL engine result: SSLEngineReport: Status = OK  HandshakeStatus = NEED_TASK
W/System.err(11955):                  bytesConsumed = 179 bytesProduced = 0
W/System.err(11955): SSL connection: OPEN | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@420f5280 | null
W/System.err(11955): 179 bytes drained from buffer, 0 remaining bytes
W/System.err(11955): Draining buffer java.nio.ByteArrayBuffer[position=179,limit=179,capacity=18437], DRAINING, true
W/System.err(11955): Filling buffer java.nio.ByteArrayBuffer[position=0,limit=18437,capacity=18437], FILLING, true
W/System.err(11955): Ending process of buffer java.nio.ByteArrayBuffer[position=0,limit=18437,capacity=18437], FILLING, true. Result: 179, try again: false, can loop: true, total filled: 179
W/System.err(11955): Handling SSL result: OK
W/System.err(11955): Handling SSL handshake: NEED_TASK
W/System.err(11955): InboundWay#setIoState: IDLE
W/System.err(11955): Running delegated tasks...
W/System.err(11955): 179 bytes filled into buffer
D/dalvikvm(11955): GC_FOR_ALLOC freed 245K, 3% free 12858K/13128K, paused 44ms, total 44ms
W/System.err(11955): Done running delegated tasks
W/System.err(11955): Ending process of buffer java.nio.ByteArrayBuffer[position=0,limit=16384,capacity=16384], FILLING, true. Result: 0, try again: true, can loop: false, total filled: 179
W/System.err(11955): Handling SSL result: OK
W/System.err(11955): Handling SSL handshake: NEED_WRAP
W/System.err(11955): OutboundWay#setIoState: READY
W/System.err(11955): NIO controller woke up
W/System.err(11955): Handling SSL result: OK
W/System.err(11955): Handling SSL handshake: NEED_WRAP
W/System.err(11955): Inbound way selected. Done for : IDLE, START, java.nio.ByteArrayBuffer[position=0,limit=16384,capacity=16384], FILLING, true
W/System.err(11955): Entering into a connection READY loop
W/System.err(11955): Processing IO for outbound way: READY, IDLE, java.nio.ByteArrayBuffer[position=0,limit=16384,capacity=16384], FILLING, true
W/System.err(11955): Beginning process of buffer java.nio.ByteArrayBuffer[position=0,limit=16384,capacity=16384], FILLING, true
W/System.err(11955): Beginning process of buffer java.nio.ByteArrayBuffer[position=0,limit=18437,capacity=18437], FILLING, true
W/System.err(11955): 0 bytes drained from buffer at pre-processing, 18437 remaining bytes
W/System.err(11955): Filling buffer java.nio.ByteArrayBuffer[position=0,limit=18437,capacity=18437], FILLING, true
W/System.err(11955): Error while processing a connection
W/System.err(11955): javax.net.ssl.SSLException: Error occured in delegated task:javax.net.ssl.SSLHandshakeException: NO SERVER CERTIFICATE FOUND
W/System.err(11955):    at org.apache.harmony.xnet.provider.jsse.HandshakeProtocol.fatalAlert(HandshakeProtocol.java:319)
W/System.err(11955):    at org.apache.harmony.xnet.provider.jsse.HandshakeProtocol.wrap(HandshakeProtocol.java:271)
W/System.err(11955):    at org.apache.harmony.xnet.provider.jsse.SSLEngineImpl.wrap(SSLEngineImpl.java:694)
W/System.err(11955):    at javax.net.ssl.SSLEngine.wrap(SSLEngine.java:462)
W/System.err(11955):    at org.restlet.ext.nio.internal.channel.WritableSslChannel.onFill(WritableSslChannel.java:125)
W/System.err(11955):    at org.restlet.ext.nio.internal.buffer.Buffer.process(Buffer.java:593)
W/System.err(11955):    at org.restlet.ext.nio.internal.channel.WritableBufferedChannel.write(WritableBufferedChannel.java:118)
W/System.err(11955):    at org.restlet.ext.nio.internal.channel.WritableSslChannel.write(WritableSslChannel.java:143)
W/System.err(11955):    at org.restlet.ext.nio.internal.buffer.Buffer.drain(Buffer.java:333)
W/System.err(11955):    at org.restlet.ext.nio.internal.way.OutboundWay.onDrain(OutboundWay.java:257)
W/System.err(11955):    at org.restlet.ext.nio.internal.way.HttpsServerOutboundWay.preProcess(HttpsServerOutboundWay.java:81)
W/System.err(11955):    at org.restlet.ext.nio.internal.buffer.Buffer.process(Buffer.java:528)
W/System.err(11955):    at org.restlet.ext.nio.internal.way.Way.processIoBuffer(Way.java:498)
W/System.err(11955):    at org.restlet.ext.nio.internal.way.OutboundWay.processIoBuffer(OutboundWay.java:463)
W/System.err(11955):    at org.restlet.ext.nio.internal.way.Way.onSelected(Way.java:451)
W/System.err(11955):    at org.restlet.ext.nio.internal.connection.Connection.onSelected(Connection.java:664)
W/System.err(11955):    at org.restlet.util.SelectionRegistration.onSelected(SelectionRegistration.java:316)
W/System.err(11955):    at org.restlet.ext.nio.internal.controller.ConnectionController.onSelected(ConnectionController.java:213)
W/System.err(11955):    at org.restlet.ext.nio.internal.controller.ServerConnectionController.onSelected(ServerConnectionController.java:109)
W/System.err(11955):    at org.restlet.ext.nio.internal.controller.ConnectionController.selectKeys(ConnectionController.java:302)
W/System.err(11955):    at org.restlet.ext.nio.internal.controller.ConnectionController.doRun(ConnectionController.java:165)
W/System.err(11955):    at org.restlet.ext.nio.internal.controller.Controller.run(Controller.java:152)
W/System.err(11955):    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390)
W/System.err(11955):    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
W/System.err(11955):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
W/System.err(11955):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
W/System.err(11955):    at java.lang.Thread.run(Thread.java:841)
W/System.err(11955): Caused by: org.apache.harmony.xnet.provider.jsse.AlertException: javax.net.ssl.SSLHandshakeException: NO SERVER CERTIFICATE FOUND
W/System.err(11955):    at org.apache.harmony.xnet.provider.jsse.HandshakeProtocol.fatalAlert(HandshakeProtocol.java:308)
W/System.err(11955):    at org.apache.harmony.xnet.provider.jsse.ServerHandshakeImpl.processClientHello(ServerHandshakeImpl.java:459)
W/System.err(11955):    at org.apache.harmony.xnet.provider.jsse.ServerHandshakeImpl$1.run(ServerHandshakeImpl.java:123)
W/System.err(11955):    at org.apache.harmony.xnet.provider.jsse.DelegatedTask.run(DelegatedTask.java:36)
W/System.err(11955):    at org.restlet.ext.nio.internal.connection.SslConnection$1.run(SslConnection.java:417)
W/System.err(11955):    ... 3 more
W/System.err(11955): Caused by: javax.net.ssl.SSLHandshakeException: NO SERVER CERTIFICATE FOUND
W/System.err(11955):    ... 8 more
W/System.err(11955): Closing connection to /192.168.2.77:56441 immediately
W/System.err(11955): InboundWay#setMessageState: IDLE
W/System.err(11955): OutboundWay#setIoState: IDLE
W/System.err(11955): Connection state (old | new) : OPEN | CLOSED
W/System.err(11955): Connection to /192.168.2.77:56441 is now closed

以下是我生成证书的方式:

> keytool -genkey -alias qlinks -keystore qlinks.keystore -validity 365
> keytool -export -alias qlinks -keystore qlinks.keystore -file qlinks.cer
> keytool -import -alias qlinks -file qlinks.cer -keystore qlinks.bks -storetype BKS -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath ~/Downloads/bcprov-jdk15on-146.jar
> adb push qlinks.bks /storage/sdcard0/

以下是我从Android项目进入/libs目录的罐子:

android-support-v4.jar
org.jsslutils.jar
org.restlet.ext.nio.jar
org.restlet.jar

1 个答案:

答案 0 :(得分:0)

我怀疑,我的证书没有正确生成。

我很确定有一种更简单的方法,但这就是我所做的(在其他answer的帮助下):

> openssl genrsa -des3 -passout pass:1 -out qlinks.pass.key 2048
> openssl rsa -passin pass:1 -in qlinks.pass.key -out qlinks.key
> openssl req -new -key qlinks.key -out qlinks.csr
> openssl x509 -req -days 365 -in qlinks.csr -signkey qlinks.key -out qlinks.crt
> keytool -keystore keystore -import -alias jetty -file qlinks.crt -trustcacerts
> openssl pkcs12 -inkey qlinks.key -in qlinks.crt -export -out qlinks.pkcs12
> keytool -importkeystore -srckeystore qlinks.pkcs12 -srcstoretype PKCS12 -destkeystore keystore

接下来,我必须使用一个名为portecle的简洁工具convert my JKS keystorekeystore文件)到BKS,因为Android只支持BouncyCastle密钥库,AFAIK。

最后,我将文件推送到目标:

  

adb push keystore /storage/sdcard0/qlinks.bks