I'm trying to connect a CoAP + DTLS client using Python's CoAPthon library to the CoAP Secure Server from one of the Eclipse Californium examples. Heres the server code:
/*******************************************************************************
* Copyright (c) 2015, 2017 Institute for Pervasive Computing, ETH Zurich and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Matthias Kovatsch - creator and main architect
* Achim Kraus (Bosch Software Innovations GmbH) - use credentials util to setup
* DtlsConnectorConfig.Builder.
* Bosch Software Innovations GmbH - migrate to SLF4J
******************************************************************************/
package org.eclipse.californium.examples;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.List;
import org.eclipse.californium.core.CoapResource;
import org.eclipse.californium.core.CoapServer;
import org.eclipse.californium.core.coap.CoAP.ResponseCode;
import org.eclipse.californium.core.config.CoapConfig;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.core.network.Endpoint;
import org.eclipse.californium.core.network.interceptors.MessageTracer;
import org.eclipse.californium.core.server.resources.CoapExchange;
import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.californium.elements.config.Configuration.DefinitionsProvider;
import org.eclipse.californium.elements.util.SslContextUtil;
import org.eclipse.californium.examples.CredentialsUtil.Mode;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.californium.scandium.MdcConnectionListener;
import org.eclipse.californium.scandium.config.DtlsConfig;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.californium.scandium.config.DtlsConfig.DtlsRole;
import org.eclipse.californium.scandium.dtls.CertificateType;
import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
import org.eclipse.californium.scandium.dtls.x509.SingleCertificateProvider;
import org.eclipse.californium.scandium.dtls.x509.StaticNewAdvancedCertificateVerifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SecureServer2 {
private static final char[] KEY_STORE_PASSWORD = "endPass".toCharArray();
private static final String KEY_STORE_LOCATION = "certs/keyStore.jks";
private static final char[] TRUST_STORE_PASSWORD = "rootPass".toCharArray();
private static final String TRUST_STORE_LOCATION = "certs/trustStore.jks";
private static final File CONFIG_FILE = new File("Californium3SecureServer.properties");
private static final String CONFIG_HEADER = "Californium CoAP Properties file for Secure Server";
private static final int DEFAULT_PORT = 5684;
private static final Logger LOG = LoggerFactory
.getLogger(SecureServer2.class.getName());
static {
CoapConfig.register();
DtlsConfig.register();
}
private static DefinitionsProvider DEFAULTS = new DefinitionsProvider() {
@Override
public void applyDefinitions(Configuration config) {
config.set(DtlsConfig.DTLS_ROLE, DtlsRole.SERVER_ONLY);
config.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, false);
config.set(DtlsConfig.DTLS_PRESELECTED_CIPHER_SUITES, CipherSuite.STRONG_ENCRYPTION_PREFERENCE);
}
};
public static final List<Mode> SUPPORTED_MODES = Arrays.asList(Mode.PSK, Mode.ECDHE_PSK, Mode.RPK, Mode.X509,
Mode.WANT_AUTH, Mode.NO_AUTH);
public static void main(String[] args) throws IOException, GeneralSecurityException {
System.out.println("Usage: java -jar ... [PSK] [ECDHE_PSK] [RPK] [X509] [WANT_AUTH|NO_AUTH]");
System.out.println("Default : [PSK] [ECDHE_PSK] [RPK] [X509]");
Configuration configuration = Configuration.createWithFile(CONFIG_FILE, CONFIG_HEADER, DEFAULTS);
Configuration.setStandard(configuration);
int dtlsPort = configuration.get(CoapConfig.COAP_SECURE_PORT);
CoapServer server = new CoapServer();
server.add(new CoapResource("secure") {
@Override
public void handleGET(CoapExchange exchange) {
exchange.respond(ResponseCode.CONTENT, "hello security23");
}
});
// load the key store
SslContextUtil.Credentials serverCredentials = SslContextUtil.loadCredentials(
SslContextUtil.CLASSPATH_SCHEME + KEY_STORE_LOCATION, "server", KEY_STORE_PASSWORD,
KEY_STORE_PASSWORD);
Certificate[] trustedCertificates = SslContextUtil.loadTrustedCertificates(
SslContextUtil.CLASSPATH_SCHEME + TRUST_STORE_LOCATION, "root", TRUST_STORE_PASSWORD);
DtlsConnectorConfig.Builder builder = DtlsConnectorConfig.builder(configuration)
.setAddress(new InetSocketAddress("127.0.0.1",dtlsPort))
.setCertificateIdentityProvider(
new SingleCertificateProvider(serverCredentials.getPrivateKey(), serverCredentials.getCertificateChain(), CertificateType.RAW_PUBLIC_KEY, CertificateType.X_509))
.setAdvancedCertificateVerifier(StaticNewAdvancedCertificateVerifier.builder()
.setTrustedCertificates(trustedCertificates).setTrustAllRPKs().build());
DTLSConnector connector = new DTLSConnector(builder.build());
CoapEndpoint.Builder coapBuilder = new CoapEndpoint.Builder()
.setConfiguration(configuration)
.setConnector(connector);
server.addEndpoint(coapBuilder.build());
server.start();
// add special interceptor for message traces
for (Endpoint ep : server.getEndpoints()) {
ep.addInterceptor(new MessageTracer());
}
System.out.println("Secure CoAP server powered by Scandium (Sc) is listening on port " + dtlsPort);
}
}
Here's the correspondent Client on java that is able to connect to this server:
/*******************************************************************************
* Copyright (c) 2015, 2017 Institute for Pervasive Computing, ETH Zurich and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Matthias Kovatsch - creator and main architect
* Achim Kraus (Bosch Software Innovations GmbH) - use credentials util to setup
* DtlsConnectorConfig.Builder.
* Bosch Software Innovations GmbH - migrate to SLF4J
******************************************************************************/
package org.eclipse.californium.examples;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.Arrays;
import java.util.List;
import org.eclipse.californium.core.CoapClient;
import org.eclipse.californium.core.CoapResponse;
import org.eclipse.californium.core.Utils;
import org.eclipse.californium.core.config.CoapConfig;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.elements.DtlsEndpointContext;
import org.eclipse.californium.elements.EndpointContext;
import org.eclipse.californium.elements.config.Configuration;
import org.eclipse.californium.elements.config.Configuration.DefinitionsProvider;
import org.eclipse.californium.elements.exception.ConnectorException;
import org.eclipse.californium.examples.CredentialsUtil.Mode;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.californium.scandium.config.DtlsConfig;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.californium.scandium.config.DtlsConfig.DtlsRole;
import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
import org.eclipse.californium.scandium.dtls.pskstore.AdvancedSinglePskStore;
public class SecureClient2 {
private static final File CONFIG_FILE = new File("Californium3SecureClient.properties");
private static final String CONFIG_HEADER = "Californium CoAP Properties file for Secure Client";
static {
CoapConfig.register();
DtlsConfig.register();
}
private static DefinitionsProvider DEFAULTS = new DefinitionsProvider() {
@Override
public void applyDefinitions(Configuration config) {
config.set(CoapConfig.MAX_ACTIVE_PEERS, 10);
config.set(DtlsConfig.DTLS_ROLE, DtlsRole.CLIENT_ONLY);
config.set(DtlsConfig.DTLS_USE_SERVER_NAME_INDICATION, false);
config.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, false);
config.set(DtlsConfig.DTLS_PRESELECTED_CIPHER_SUITES, CipherSuite.STRONG_ENCRYPTION_PREFERENCE);
config.setTransient(DtlsConfig.DTLS_CIPHER_SUITES);
}
};
public static final List<Mode> SUPPORTED_MODES = Arrays.asList(Mode.PSK, Mode.ECDHE_PSK, Mode.RPK, Mode.X509,
Mode.RPK_TRUST, Mode.X509_TRUST);
private static final String SERVER_URI = "coaps://192.168.1.14:5684/secure";
private final DTLSConnector dtlsConnector;
private final Configuration configuration;
public SecureClient2(DTLSConnector dtlsConnector, Configuration configuration) {
this.dtlsConnector = dtlsConnector;
this.configuration = configuration;
}
public void test() {
CoapResponse response = null;
try {
URI uri = new URI(SERVER_URI);
CoapClient client = new CoapClient(uri);
CoapEndpoint.Builder builder = new CoapEndpoint.Builder()
.setConfiguration(configuration)
.setConnector(dtlsConnector);
client.setEndpoint(builder.build());
response = client.get();
client.shutdown();
} catch (URISyntaxException e) {
System.err.println("Invalid URI: " + e.getMessage());
System.exit(-1);
} catch (ConnectorException | IOException e) {
System.err.println("Error occurred while sending request: " + e);
System.exit(-1);
}
if (response != null) {
System.out.println(response.getCode() + " - " + response.getCode().name());
System.out.println(response.getOptions());
System.out.println(response.getResponseText());
System.out.println();
System.out.println("ADVANCED:");
EndpointContext context = response.advanced().getSourceContext();
Principal identity = context.getPeerIdentity();
if (identity != null) {
System.out.println(context.getPeerIdentity());
} else {
System.out.println("anonymous");
}
System.out.println("CIPHER - " + context.get(DtlsEndpointContext.KEY_CIPHER));
System.out.println(Utils.prettyPrint(response));
} else {
System.out.println("No response received.");
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("Usage: java -cp ... org.eclipse.californium.examples.SecureClient [PSK|ECDHE_PSK] [RPK|RPK_TRUST] [X509|X509_TRUST]");
System.out.println("Default: [PSK] [RPK] [X509]");
Configuration configuration = Configuration.createWithFile(CONFIG_FILE, CONFIG_HEADER, DEFAULTS);
Configuration.setStandard(configuration);
DtlsConnectorConfig.Builder builder = DtlsConnectorConfig.builder(configuration);
CredentialsUtil.setupCid(args, builder);
List<Mode> modes = CredentialsUtil.parse(args, CredentialsUtil.DEFAULT_CLIENT_MODES, SUPPORTED_MODES);
// if (modes.contains(CredentialsUtil.Mode.PSK) || modes.contains(CredentialsUtil.Mode.ECDHE_PSK)) {
// builder.setAdvancedPskStore(new AdvancedSinglePskStore(CredentialsUtil.OPEN_PSK_IDENTITY, CredentialsUtil.OPEN_PSK_SECRET));
// }
System.out.println("pass- " + CredentialsUtil.OPEN_PSK_IDENTITY + " - " + new String(CredentialsUtil.OPEN_PSK_SECRET, StandardCharsets.UTF_8));
CredentialsUtil.setupCredentials(builder, CredentialsUtil.CLIENT_NAME, modes);
// uncomment next line to load pem file for the example
// CredentialsUtil.loadCredentials(builder, "client.pem");
DTLSConnector dtlsConnector = new DTLSConnector(builder.build());
SecureClient2 client = new SecureClient2(dtlsConnector, configuration);
client.test();
}
}
Now I'm trying to connect to the server using this Python code that is based on CoAPton's test_secure.py, more specifically the test_ok_with_handshake_on_connect() function:
#setup a client side DTLS socket
_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
_sock.setsockopt(socket.SOL SOCKET, socket.so REUSEADDR, 1)
_sock.wrap_client( sock,cert_reqs=ssl.CERT_REQUIRED, ca_certs="./certificate.pem",do_handshake_on_connect=True,ciphers="SHA256")
client = HelperCIient(server=(host, port), sock=_sock)
request = Request()
request.destination = (host, port)
request.code = defines. Codes.GET.number
request.uri path = path
response = client. request)
response = client.get(path)
print(response.pretty_print())
client.stop()
I generated the .pem file used on the python script from a keystone file provided on the Eclipse Californium repository (demo_certs)
I'm rather new to this, I only need the python client and the eclipse server to share a certificate so that the connection is secure. When I run the Python code I get this info on the server side (13:11:51.704 INFO [] [ServerHandshaker]: Start certificate identity.) but nothing else. Can you help me? Thanks in advance.