Improvements to key store read for lwm2m.

This commit is contained in:
Andrii Shvaika 2021-07-01 17:08:41 +03:00
parent f58fe1647b
commit ee55c0bf85
9 changed files with 51 additions and 337 deletions

View File

@ -30,8 +30,12 @@ import java.math.BigInteger;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.security.spec.ECGenParameterSpec;
@ -62,49 +66,23 @@ public class LwM2MServerSecurityInfoRepository {
bsServ.setPort(serverConfig.getPort());
bsServ.setSecurityHost(serverConfig.getSecureHost());
bsServ.setSecurityPort(serverConfig.getSecurePort());
bsServ.setServerPublicKey(getPublicKey(serverConfig.getCertificateAlias(), this.serverConfig.getPublicX(), this.serverConfig.getPublicY()));
bsServ.setServerPublicKey(getPublicKey(serverConfig));
return bsServ;
}
private String getPublicKey(String alias, String publicServerX, String publicServerY) {
String publicKey = getServerPublicKeyX509(alias);
return publicKey != null ? publicKey : getRPKPublicKey(publicServerX, publicServerY);
}
private String getServerPublicKeyX509(String alias) {
private String getPublicKey(LwM2MSecureServerConfig config) {
try {
X509Certificate serverCertificate = (X509Certificate) serverConfig.getKeyStoreValue().getCertificate(alias);
return Hex.encodeHexString(serverCertificate.getEncoded());
} catch (CertificateEncodingException | KeyStoreException e) {
e.printStackTrace();
}
return null;
}
private String getRPKPublicKey(String publicServerX, String publicServerY) {
try {
/** Get Elliptic Curve Parameter spec for secp256r1 */
AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC");
algoParameters.init(new ECGenParameterSpec("secp256r1"));
ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class);
if (publicServerX != null && !publicServerX.isEmpty() && publicServerY != null && !publicServerY.isEmpty()) {
/** Get point values */
byte[] publicX = Hex.decodeHex(publicServerX.toCharArray());
byte[] publicY = Hex.decodeHex(publicServerY.toCharArray());
/** Create key specs */
KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)),
parameterSpec);
/** Get keys */
PublicKey publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec);
if (publicKey != null && publicKey.getEncoded().length > 0) {
return Hex.encodeHexString(publicKey.getEncoded());
}
KeyStore keyStore = serverConfig.getKeyStoreValue();
if (keyStore != null) {
X509Certificate serverCertificate = (X509Certificate) serverConfig.getKeyStoreValue().getCertificate(config.getCertificateAlias());
return Hex.encodeHexString(serverCertificate.getPublicKey().getEncoded());
}
} catch (GeneralSecurityException | IllegalArgumentException e) {
log.error("[{}] Failed generate Server RPK for profile", e.getMessage());
throw new RuntimeException(e);
} catch (Exception e) {
log.trace("Failed to fetch public key from key store!", e);
}
return null;
return "";
}
}

View File

@ -649,12 +649,9 @@ transport:
security:
bind_address: "${LWM2M_BIND_ADDRESS_SECURITY:0.0.0.0}"
bind_port: "${LWM2M_BIND_PORT_SECURITY:5686}"
# Only for RPK: Public & Private Key. If the keystore file is missing or not working
public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}"
public_y: "${LWM2M_SERVER_PUBLIC_Y:5eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}"
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}"
# Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}"
alias: "${LWM2M_KEYSTORE_SERVER_ALIAS:server}"
password: "${LWM2M_KEYSTORE_SERVER_PASSWORD:server_ks_password}"
skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
bootstrap:
enable: "${LWM2M_ENABLED_BS:true}"
@ -664,12 +661,9 @@ transport:
security:
bind_address: "${LWM2M_BIND_ADDRESS_SECURITY_BS:0.0.0.0}"
bind_port: "${LWM2M_BIND_PORT_SECURITY_BS:5688}"
# Only for RPK: Public & Private Key. If the keystore file is missing or not working
public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}"
public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}"
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}"
# Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_BS:bootstrap}"
alias: "${LWM2M_KEYSTORE_BS_ALIAS:bootstrap}"
password: "${LWM2M_KEYSTORE_BS_PASSWORD:server_ks_password}"
security:
# Certificate_x509:
# To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format

View File

@ -1,4 +1,7 @@
transport.lwm2m.security.key_store=lwm2m/credentials/serverKeyStore.jks
transport.lwm2m.security.key_store_password=server
edges.enabled=true
transport.lwm2m.bootstrap.security.alias=server
transport.lwm2m.server.security.alias=server
transport.lwm2m.server.security.password=server
transport.lwm2m.bootstrap.security.alias=server
transport.lwm2m.bootstrap.security.password=server

View File

@ -31,6 +31,7 @@ import org.thingsboard.server.transport.lwm2m.bootstrap.secure.LwM2mDefaultBoots
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC;
import org.thingsboard.server.transport.lwm2m.server.DefaultLwM2mTransportService;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@ -65,10 +66,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mNetworkConfig.g
@Component
@ConditionalOnExpression("('${service.type:null}'=='tb-transport' && '${transport.lwm2m.enabled:false}'=='true' && '${transport.lwm2m.bootstrap.enable:false}'=='true') || ('${service.type:null}'=='monolith' && '${transport.lwm2m.enabled:false}'=='true'&& '${transport.lwm2m.bootstrap.enable:false}'=='true')")
@RequiredArgsConstructor
//TODO: @ybondarenko please refactor this to be similar to DefaultLwM2mTransportService
public class LwM2MTransportBootstrapService {
private PublicKey publicKey;
private PrivateKey privateKey;
private boolean pskMode = false;
private final LwM2MTransportServerConfig serverConfig;
@ -101,44 +99,34 @@ public class LwM2MTransportBootstrapService {
builder.setLocalAddress(bootstrapConfig.getHost(), bootstrapConfig.getPort());
builder.setLocalSecureAddress(bootstrapConfig.getSecureHost(), bootstrapConfig.getSecurePort());
/** Create CoAP Config */
/* Create CoAP Config */
builder.setCoapConfig(getCoapConfig(bootstrapConfig.getPort(), bootstrapConfig.getSecurePort(), serverConfig));
/** Define model provider (Create Models )*/
/* Define model provider (Create Models )*/
/** Create credentials */
/* Create credentials */
this.setServerWithCredentials(builder);
// /** Set securityStore with new ConfigStore */
// builder.setConfigStore(lwM2MInMemoryBootstrapConfigStore);
/** SecurityStore */
/* SecurityStore */
builder.setSecurityStore(lwM2MBootstrapSecurityStore);
/** Create and Set DTLS Config */
/* Create and Set DTLS Config */
DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder();
dtlsConfig.setRecommendedSupportedGroupsOnly(serverConfig.isRecommendedSupportedGroups());
dtlsConfig.setRecommendedCipherSuitesOnly(serverConfig.isRecommendedCiphers());
if (this.pskMode) {
dtlsConfig.setSupportedCipherSuites(
TLS_PSK_WITH_AES_128_CCM_8,
TLS_PSK_WITH_AES_128_CBC_SHA256);
} else {
dtlsConfig.setSupportedCipherSuites(
TLS_PSK_WITH_AES_128_CCM_8,
TLS_PSK_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256);
}
dtlsConfig.setSupportedCipherSuites(this.pskMode ? DefaultLwM2mTransportService.PSK_CIPHER_SUITES : DefaultLwM2mTransportService.RPK_OR_X509_CIPHER_SUITES);
/** Set DTLS Config */
/* Set DTLS Config */
builder.setDtlsConfig(dtlsConfig);
BootstrapSessionManager sessionManager = new LwM2mDefaultBootstrapSessionManager(lwM2MBootstrapSecurityStore);
builder.setSessionManager(sessionManager);
/** Create BootstrapServer */
/* Create BootstrapServer */
return builder.build();
}
@ -153,19 +141,15 @@ public class LwM2MTransportBootstrapService {
trustedCertificates[0] = rootCAX509Cert;
builder.setTrustedCertificates(trustedCertificates);
} else {
/** by default trust all */
/* by default trust all */
builder.setTrustedCertificates(new X509Certificate[0]);
}
}
} else if (this.setServerRPK(builder)) {
this.infoPramsUri("RPK");
this.infoParamsBootstrapServerKey(this.publicKey, this.privateKey);
} else {
/** by default trust all */
/* by default trust all */
builder.setTrustedCertificates(new X509Certificate[0]);
log.info("Unable to load X509 files for BootStrapServer");
this.pskMode = true;
this.infoPramsUri("PSK");
}
} catch (KeyStoreException ex) {
log.error("[{}] Unable to load X509 files server", ex.getMessage());
@ -173,19 +157,14 @@ public class LwM2MTransportBootstrapService {
}
private boolean setBuilderX509(LeshanBootstrapServerBuilder builder) {
/**
* For deb => KeyStorePathFile == yml or commandline: KEY_STORE_PATH_FILE
* For idea => KeyStorePathResource == common/transport/lwm2m/src/main/resources/credentials: in LwM2MTransportContextServer: credentials/serverKeyStore.jks
*/
try {
X509Certificate serverCertificate = (X509Certificate) serverConfig.getKeyStoreValue().getCertificate(this.bootstrapConfig.getCertificateAlias());
PrivateKey privateKey = (PrivateKey) serverConfig.getKeyStoreValue().getKey(this.bootstrapConfig.getCertificateAlias(), serverConfig.getKeyStorePassword() == null ? null : serverConfig.getKeyStorePassword().toCharArray());
PrivateKey privateKey = (PrivateKey) serverConfig.getKeyStoreValue().getKey(this.bootstrapConfig.getCertificateAlias(), serverConfig.getCertificatePassword() == null ? null : serverConfig.getCertificatePassword().toCharArray());
PublicKey publicKey = serverCertificate.getPublicKey();
if (privateKey != null && privateKey.getEncoded().length > 0 && publicKey != null && publicKey.getEncoded().length > 0) {
builder.setPublicKey(serverCertificate.getPublicKey());
builder.setPrivateKey(privateKey);
builder.setCertificateChain(new X509Certificate[]{serverCertificate});
this.infoParamsServerX509(serverCertificate, publicKey, privateKey);
return true;
} else {
return false;
@ -196,105 +175,4 @@ public class LwM2MTransportBootstrapService {
}
}
private void infoParamsServerX509(X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey) {
try {
this.infoPramsUri("X509");
log.info("\n- X509 Certificate (Hex): [{}]",
Hex.encodeHexString(certificate.getEncoded()));
this.infoParamsBootstrapServerKey(publicKey, privateKey);
} catch (CertificateEncodingException e) {
log.error("", e);
}
}
private void infoPramsUri(String mode) {
log.info("Bootstrap Server uses [{}]: serverNoSecureURI : [{}:{}], serverSecureURI : [{}:{}]",
mode,
this.bootstrapConfig.getHost(),
this.bootstrapConfig.getPort(),
this.bootstrapConfig.getSecureHost(),
this.bootstrapConfig.getSecurePort());
}
private boolean setServerRPK(LeshanBootstrapServerBuilder builder) {
try {
this.generateKeyForBootstrapRPK();
if (this.publicKey != null && this.publicKey.getEncoded().length > 0 &&
this.privateKey != null && this.privateKey.getEncoded().length > 0) {
builder.setPublicKey(this.publicKey);
// builder.setCertificateChain(new X509Certificate[] { serverCertificate });
/// Trust all certificates.
builder.setTrustedCertificates(new X509Certificate[0]);
builder.setPrivateKey(this.privateKey);
return true;
}
} catch (NoSuchAlgorithmException | InvalidParameterSpecException | InvalidKeySpecException e) {
log.error("Fail create Bootstrap Server with RPK", e);
}
return false;
}
/**
* From yml: bootstrap
* public_x: "${LWM2M_SERVER_PUBLIC_X_BS:993ef2b698c6a9c0c1d8be78b13a9383c0854c7c7c7a504d289b403794648183}"
* public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:267412d5fc4e5ceb2257cb7fd7f76ebdac2fa9aa100afb162e990074cc0bfaa2}"
* private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:9dbdbb073fc63570693a9aaf1013414e261c571f27e27fc6a8c1c2ad9347875a}"
*/
private void generateKeyForBootstrapRPK() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException {
/** Get Elliptic Curve Parameter spec for secp256r1 */
AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC");
algoParameters.init(new ECGenParameterSpec("secp256r1"));
ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class);
LwM2MTransportBootstrapConfig serverConfig = this.bootstrapConfig;
if (StringUtils.isNotEmpty(serverConfig.getPublicX()) && StringUtils.isNotEmpty(serverConfig.getPublicY())) {
/** Get point values */
byte[] publicX = Hex.decodeHex(serverConfig.getPublicX().toCharArray());
byte[] publicY = Hex.decodeHex(serverConfig.getPublicY().toCharArray());
/** Create key specs */
KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)),
parameterSpec);
/** Get public key */
this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec);
}
String privateEncodedKey = serverConfig.getPrivateEncoded();
if (StringUtils.isNotEmpty(privateEncodedKey)) {
/** Get private key */
byte[] privateS = Hex.decodeHex(privateEncodedKey.toCharArray());
try {
this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS));
} catch (InvalidKeySpecException ignore2) {
log.error("Invalid Bootstrap Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", privateEncodedKey);
}
}
}
private void infoParamsBootstrapServerKey(PublicKey publicKey, PrivateKey privateKey) {
/** Get x coordinate */
byte[] x = ((ECPublicKey) publicKey).getW().getAffineX().toByteArray();
if (x[0] == 0)
x = Arrays.copyOfRange(x, 1, x.length);
/** Get Y coordinate */
byte[] y = ((ECPublicKey) publicKey).getW().getAffineY().toByteArray();
if (y[0] == 0)
y = Arrays.copyOfRange(y, 1, y.length);
/** Get Curves params */
String params = ((ECPublicKey) publicKey).getParams().toString();
String privHex = Hex.encodeHexString(privateKey.getEncoded());
log.info("\n- Public Key (Hex): [{}] \n" +
"- Private Key (Hex): [{}], \n" +
"public_x: \"${LWM2M_SERVER_PUBLIC_X_BS:{}}\" \n" +
"public_y: \"${LWM2M_SERVER_PUBLIC_Y_BS:{}}\" \n" +
"private_encoded: \"${LWM2M_SERVER_PRIVATE_ENCODED_BS:{}}\" \n" +
"- Elliptic Curve parameters : [{}]",
Hex.encodeHexString(publicKey.getEncoded()),
privHex,
Hex.encodeHexString(x),
Hex.encodeHexString(y),
privHex,
params);
}
}

View File

@ -27,12 +27,8 @@ public interface LwM2MSecureServerConfig {
Integer getSecurePort();
String getPublicX();
String getPublicY();
String getPrivateEncoded();
String getCertificateAlias();
String getCertificatePassword();
}

View File

@ -46,20 +46,12 @@ public class LwM2MTransportBootstrapConfig implements LwM2MSecureServerConfig {
@Value("${transport.lwm2m.bootstrap.security.bind_port:}")
private Integer securePort;
@Getter
@Value("${transport.lwm2m.bootstrap.security.public_x:}")
private String publicX;
@Getter
@Value("${transport.lwm2m.bootstrap.security.public_y:}")
private String publicY;
@Getter
@Value("${transport.lwm2m.bootstrap.security.private_encoded:}")
private String privateEncoded;
@Getter
@Value("${transport.lwm2m.bootstrap.security.alias:}")
private String certificateAlias;
@Getter
@Value("${transport.lwm2m.bootstrap.security.password:}")
private String certificatePassword;
}

View File

@ -120,22 +120,14 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig {
@Value("${transport.lwm2m.server.security.bind_port:}")
private Integer securePort;
@Getter
@Value("${transport.lwm2m.server.security.public_x:}")
private String publicX;
@Getter
@Value("${transport.lwm2m.server.security.public_y:}")
private String publicY;
@Getter
@Value("${transport.lwm2m.server.security.private_encoded:}")
private String privateEncoded;
@Getter
@Value("${transport.lwm2m.server.security.alias:}")
private String certificateAlias;
@Getter
@Value("${transport.lwm2m.server.security.password:}")
private String certificatePassword;
@Getter
@Value("${transport.lwm2m.log_max_length:}")
private int logMaxLength;

View File

@ -21,14 +21,12 @@ import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.californium.scandium.dtls.cipher.CipherSuite;
import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeDecoder;
import org.eclipse.leshan.core.node.codec.DefaultLwM2mNodeEncoder;
import org.eclipse.leshan.core.util.Hex;
import org.eclipse.leshan.server.californium.LeshanServer;
import org.eclipse.leshan.server.californium.LeshanServerBuilder;
import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore;
import org.eclipse.leshan.server.model.LwM2mModelProvider;
import org.springframework.stereotype.Component;
import org.thingsboard.server.cache.ota.OtaPackageDataCache;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.queue.util.TbLwM2mTransportComponent;
import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig;
import org.thingsboard.server.transport.lwm2m.secure.LWM2MGenerationPSkRPkECC;
@ -41,24 +39,9 @@ import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.math.BigInteger;
import java.security.AlgorithmParameters;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
@ -75,8 +58,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
public static final CipherSuite[] RPK_OR_X509_CIPHER_SUITES = {TLS_PSK_WITH_AES_128_CCM_8, TLS_PSK_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256};
public static final CipherSuite[] PSK_CIPHER_SUITES = {TLS_PSK_WITH_AES_128_CCM_8, TLS_PSK_WITH_AES_128_CBC_SHA256};
private PublicKey publicKey;
private PrivateKey privateKey;
private final LwM2mTransportContext context;
private final LwM2MTransportServerConfig config;
@ -97,14 +78,13 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
new LWM2MGenerationPSkRPkECC();
}
this.server = getLhServer();
/**
/*
* Add a resource to the server.
* CoapResource ->
* path = FW_PACKAGE or SW_PACKAGE
* nameFile = "BC68JAR01A09_TO_BC68JAR01A10.bin"
* "coap://host:port/{path}/{token}/{nameFile}"
*/
LwM2mTransportCoapResource otaCoapResource = new LwM2mTransportCoapResource(otaPackageDataCache, FIRMWARE_UPDATE_COAP_RESOURCE);
this.server.coap().getServer().add(otaCoapResource);
this.startLhServer();
@ -170,29 +150,23 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
dtlsConfig.setAdvancedCertificateVerifier(certificateVerifier);
builder.setAuthorizer(authorizer);
dtlsConfig.setSupportedCipherSuites(RPK_OR_X509_CIPHER_SUITES);
} else if (this.setServerRPK(builder)) {
this.infoPramsUri("RPK");
this.infoParamsServerKey(this.publicKey, this.privateKey);
dtlsConfig.setSupportedCipherSuites(RPK_OR_X509_CIPHER_SUITES);
} else {
/* by default trust all */
builder.setTrustedCertificates(new X509Certificate[0]);
log.info("Unable to load X509 files for LWM2MServer");
dtlsConfig.setSupportedCipherSuites(PSK_CIPHER_SUITES);
this.infoPramsUri("PSK");
}
}
private boolean setBuilderX509(LeshanServerBuilder builder) {
try {
X509Certificate serverCertificate = (X509Certificate) config.getKeyStoreValue().getCertificate(config.getCertificateAlias());
PrivateKey privateKey = (PrivateKey) config.getKeyStoreValue().getKey(config.getCertificateAlias(), config.getKeyStorePassword() == null ? null : config.getKeyStorePassword().toCharArray());
PrivateKey privateKey = (PrivateKey) config.getKeyStoreValue().getKey(config.getCertificateAlias(), config.getCertificatePassword() == null ? null : config.getCertificatePassword().toCharArray());
PublicKey publicKey = serverCertificate.getPublicKey();
if (privateKey != null && privateKey.getEncoded().length > 0 && publicKey != null && publicKey.getEncoded().length > 0) {
builder.setPublicKey(serverCertificate.getPublicKey());
builder.setPrivateKey(privateKey);
builder.setCertificateChain(new X509Certificate[]{serverCertificate});
this.infoParamsServerX509(serverCertificate, publicKey, privateKey);
return true;
} else {
return false;
@ -203,93 +177,6 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService {
}
}
private void infoParamsServerX509(X509Certificate certificate, PublicKey publicKey, PrivateKey privateKey) {
try {
infoPramsUri("X509");
log.info("\n- X509 Certificate (Hex): [{}]",
Hex.encodeHexString(certificate.getEncoded()));
this.infoParamsServerKey(publicKey, privateKey);
} catch (CertificateEncodingException e) {
log.error("", e);
}
}
private void infoPramsUri(String mode) {
LwM2MTransportServerConfig lwM2MTransportServerConfig = config;
log.info("Server uses [{}]: serverNoSecureURI : [{}:{}], serverSecureURI : [{}:{}]", mode,
lwM2MTransportServerConfig.getHost(),
lwM2MTransportServerConfig.getPort(),
lwM2MTransportServerConfig.getSecureHost(),
lwM2MTransportServerConfig.getSecurePort());
}
private boolean setServerRPK(LeshanServerBuilder builder) {
try {
this.loadOrGenerateRPKKeys();
if (this.publicKey != null && this.publicKey.getEncoded().length > 0 &&
this.privateKey != null && this.privateKey.getEncoded().length > 0) {
builder.setPublicKey(this.publicKey);
builder.setPrivateKey(this.privateKey);
return true;
}
} catch (NoSuchAlgorithmException | InvalidParameterSpecException | InvalidKeySpecException e) {
log.error("Fail create Server with RPK", e);
}
return false;
}
private void loadOrGenerateRPKKeys() throws NoSuchAlgorithmException, InvalidParameterSpecException, InvalidKeySpecException {
/* Get Elliptic Curve Parameter spec for secp256r1 */
AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC");
algoParameters.init(new ECGenParameterSpec("secp256r1"));
ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class);
LwM2MTransportServerConfig serverConfig = config;
if (StringUtils.isNotEmpty(serverConfig.getPublicX()) && StringUtils.isNotEmpty(serverConfig.getPublicY())) {
byte[] publicX = Hex.decodeHex(serverConfig.getPublicX().toCharArray());
byte[] publicY = Hex.decodeHex(serverConfig.getPublicY().toCharArray());
KeySpec publicKeySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(publicX), new BigInteger(publicY)),
parameterSpec);
this.publicKey = KeyFactory.getInstance("EC").generatePublic(publicKeySpec);
}
String privateEncodedKey = serverConfig.getPrivateEncoded();
if (StringUtils.isNotEmpty(privateEncodedKey)) {
byte[] privateS = Hex.decodeHex(privateEncodedKey.toCharArray());
try {
this.privateKey = KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateS));
} catch (InvalidKeySpecException ignore2) {
log.error("Invalid Server rpk.PrivateKey.getEncoded () [{}}]. PrivateKey has no EC algorithm", privateEncodedKey);
}
}
}
private void infoParamsServerKey(PublicKey publicKey, PrivateKey privateKey) {
/* Get x coordinate */
byte[] x = ((ECPublicKey) publicKey).getW().getAffineX().toByteArray();
if (x[0] == 0)
x = Arrays.copyOfRange(x, 1, x.length);
/* Get Y coordinate */
byte[] y = ((ECPublicKey) publicKey).getW().getAffineY().toByteArray();
if (y[0] == 0)
y = Arrays.copyOfRange(y, 1, y.length);
/* Get Curves params */
String params = ((ECPublicKey) publicKey).getParams().toString();
String privHex = Hex.encodeHexString(privateKey.getEncoded());
log.info(" \n- Public Key (Hex): [{}] \n" +
"- Private Key (Hex): [{}], \n" +
"public_x: \"${LWM2M_SERVER_PUBLIC_X:{}}\" \n" +
"public_y: \"${LWM2M_SERVER_PUBLIC_Y:{}}\" \n" +
"private_encoded: \"${LWM2M_SERVER_PRIVATE_ENCODED:{}}\" \n" +
"- Elliptic Curve parameters : [{}]",
Hex.encodeHexString(publicKey.getEncoded()),
privHex,
Hex.encodeHexString(x),
Hex.encodeHexString(y),
privHex,
params);
}
@Override
public String getName() {
return "LWM2M";

View File

@ -108,12 +108,9 @@ transport:
security:
bind_address: "${LWM2M_BIND_ADDRESS_SECURITY:0.0.0.0}"
bind_port: "${LWM2M_BIND_PORT_SECURITY:5686}"
# Only for RPK: Public & Private Key. If the keystore file is missing or not working
public_x: "${LWM2M_SERVER_PUBLIC_X:05064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f358}"
public_y: "${LWM2M_SERVER_PUBLIC_Y:5eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}"
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED:308193020100301306072a8648ce3d020106082a8648ce3d030107047930770201010420dc774b309e547ceb48fee547e104ce201a9c48c449dc5414cd04e7f5cf05f67ba00a06082a8648ce3d030107a1440342000405064b9e6762dd8d8b8a52355d7b4d8b9a3d64e6d2ee277d76c248861353f3585eeb1838e4f9e37b31fa347aef5ce3431eb54e0a2506910c5e0298817445721b}"
# Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_SERVER:server}"
alias: "${LWM2M_KEYSTORE_SERVER_ALIAS:server}"
password: "${LWM2M_KEYSTORE_SERVER_PASSWORD:server_ks_password}"
skip_validity_check_for_client_cert: "${TB_LWM2M_SERVER_SECURITY_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}"
bootstrap:
enable: "${LWM2M_ENABLED_BS:true}"
@ -123,12 +120,9 @@ transport:
security:
bind_address: "${LWM2M_BIND_ADDRESS_SECURITY_BS:0.0.0.0}"
bind_port: "${LWM2M_BIND_PORT_SECURITY_BS:5688}"
# Only for RPK: Public & Private Key. If the keystore file is missing or not working
public_x: "${LWM2M_SERVER_PUBLIC_X_BS:5017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f91}"
public_y: "${LWM2M_SERVER_PUBLIC_Y_BS:3fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}"
private_encoded: "${LWM2M_SERVER_PRIVATE_ENCODED_BS:308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104205ecafd90caa7be45c42e1f3f32571632b8409e6e6249d7124f4ba56fab3c8083a00a06082a8648ce3d030107a144034200045017c87a1c1768264656b3b355434b0def6edb8b9bf166a4762d9930cd730f913fc4e61bcd8901ec27c424114c3e887ed372497f0c2cf85839b8443e76988b34}"
# Only Certificate_x509:
alias: "${LWM2M_KEYSTORE_ALIAS_BS:bootstrap}"
alias: "${LWM2M_KEYSTORE_BS_ALIAS:bootstrap}"
password: "${LWM2M_KEYSTORE_BS_PASSWORD:server_ks_password}"
security:
# Certificate_x509:
# To get helps about files format and how to generate it, see: https://github.com/eclipse/leshan/wiki/Credential-files-format