From d403afb0e6815bd28da12e8f5e70b5f6fe629341 Mon Sep 17 00:00:00 2001 From: nickAS21 Date: Tue, 28 Sep 2021 14:11:32 +0300 Subject: [PATCH] Lwm2m credentials base64 validate (with /n and "...BEGIN...") back --- .../AbstractCoapProvisionJsonDeviceTest.java | 2 +- .../AbstractCoapProvisionProtoDeviceTest.java | 2 +- .../AbstractMqttProvisionJsonDeviceTest.java | 2 +- .../AbstractMqttProvisionProtoDeviceTest.java | 2 +- .../server/common/msg/EncryptionUtil.java | 23 ++++++-- .../server/common/transport/util/SslUtil.java | 2 +- .../device/DeviceCredentialsServiceImpl.java | 53 +++++++++++-------- 7 files changed, 56 insertions(+), 30 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/provision/AbstractCoapProvisionJsonDeviceTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/provision/AbstractCoapProvisionJsonDeviceTest.java index eccba64ddc..091900488b 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/provision/AbstractCoapProvisionJsonDeviceTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/provision/AbstractCoapProvisionJsonDeviceTest.java @@ -146,7 +146,7 @@ public abstract class AbstractCoapProvisionJsonDeviceTest extends AbstractCoapIn Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString()); Assert.assertEquals(deviceCredentials.getCredentialsType().name(), "X509_CERTIFICATE"); - String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue()); + String cert = EncryptionUtil.certTrimNewLines(deviceCredentials.getCredentialsValue()); String sha3Hash = EncryptionUtil.getSha3Hash(cert); Assert.assertEquals(deviceCredentials.getCredentialsId(), sha3Hash); diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/provision/AbstractCoapProvisionProtoDeviceTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/provision/AbstractCoapProvisionProtoDeviceTest.java index 14d72297a4..671741c7d0 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/provision/AbstractCoapProvisionProtoDeviceTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/provision/AbstractCoapProvisionProtoDeviceTest.java @@ -145,7 +145,7 @@ public abstract class AbstractCoapProvisionProtoDeviceTest extends AbstractCoapI Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString()); Assert.assertEquals(deviceCredentials.getCredentialsType(), DeviceCredentialsType.X509_CERTIFICATE); - String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue()); + String cert = EncryptionUtil.certTrimNewLines(deviceCredentials.getCredentialsValue()); String sha3Hash = EncryptionUtil.getSha3Hash(cert); Assert.assertEquals(deviceCredentials.getCredentialsId(), sha3Hash); diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/provision/AbstractMqttProvisionJsonDeviceTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/provision/AbstractMqttProvisionJsonDeviceTest.java index 870b62b195..e1b0269138 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/provision/AbstractMqttProvisionJsonDeviceTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/provision/AbstractMqttProvisionJsonDeviceTest.java @@ -152,7 +152,7 @@ public abstract class AbstractMqttProvisionJsonDeviceTest extends AbstractMqttIn Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.get("credentialsType").getAsString()); Assert.assertEquals(deviceCredentials.getCredentialsType().name(), "X509_CERTIFICATE"); - String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue()); + String cert = EncryptionUtil.certTrimNewLines(deviceCredentials.getCredentialsValue()); String sha3Hash = EncryptionUtil.getSha3Hash(cert); Assert.assertEquals(deviceCredentials.getCredentialsId(), sha3Hash); diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/provision/AbstractMqttProvisionProtoDeviceTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/provision/AbstractMqttProvisionProtoDeviceTest.java index 97ebbfe4a7..7816db5de0 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/provision/AbstractMqttProvisionProtoDeviceTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/provision/AbstractMqttProvisionProtoDeviceTest.java @@ -154,7 +154,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI Assert.assertEquals(deviceCredentials.getCredentialsType().name(), response.getCredentialsType().toString()); Assert.assertEquals(deviceCredentials.getCredentialsType(), DeviceCredentialsType.X509_CERTIFICATE); - String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue()); + String cert = EncryptionUtil.certTrimNewLines(deviceCredentials.getCredentialsValue()); String sha3Hash = EncryptionUtil.getSha3Hash(cert); Assert.assertEquals(deviceCredentials.getCredentialsId(), sha3Hash); diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java b/common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java index d8fbbad543..1421d4c64e 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java @@ -28,15 +28,30 @@ public class EncryptionUtil { private EncryptionUtil() { } - public static String trimNewLines(String input) { + public static String certTrimNewLines(String input) { return input.replaceAll("-----BEGIN CERTIFICATE-----", "") - .replaceAll("-----END CERTIFICATE-----", "") .replaceAll("\n", "") - .replaceAll("\r", ""); + .replaceAll("\r", "") + .replaceAll("-----END CERTIFICATE-----", ""); } + public static String pubkTrimNewLines(String input) { + return input.replaceAll("-----BEGIN PUBLIC KEY-----", "") + .replaceAll("\n", "") + .replaceAll("\r", "") + .replaceAll("-----END PUBLIC KEY-----", ""); + } + + public static String prikTrimNewLines(String input) { + return input.replaceAll("-----BEGIN EC PRIVATE KEY-----", "") + .replaceAll("\n", "") + .replaceAll("\r", "") + .replaceAll("-----END EC PRIVATE KEY-----", ""); + } + + public static String getSha3Hash(String data) { - String trimmedData = trimNewLines(data); + String trimmedData = certTrimNewLines(data); byte[] dataBytes = trimmedData.getBytes(); SHA3Digest md = new SHA3Digest(256); md.reset(); diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java index 77e4045655..2a17a4791d 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java @@ -33,6 +33,6 @@ public class SslUtil { public static String getCertificateString(Certificate cert) throws CertificateEncodingException { - return EncryptionUtil.trimNewLines(Base64Utils.encodeToString(cert.getEncoded())); + return EncryptionUtil.certTrimNewLines(Base64Utils.encodeToString(cert.getEncoded())); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java index 68370b95e6..84db68f4fc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsServiceImpl.java @@ -154,7 +154,7 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen } private void formatCertData(DeviceCredentials deviceCredentials) { - String cert = EncryptionUtil.trimNewLines(deviceCredentials.getCredentialsValue()); + String cert = EncryptionUtil.certTrimNewLines(deviceCredentials.getCredentialsValue()); String sha3Hash = EncryptionUtil.getSha3Hash(cert); deviceCredentials.setCredentialsId(sha3Hash); deviceCredentials.setCredentialsValue(cert); @@ -171,26 +171,25 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen String credentialsId = null; LwM2MClientCredentials clientCredentials = lwM2MCredentials.getClient(); - + LwM2MServerCredentials bootstrapServer = lwM2MCredentials.getBootstrap().getBootstrapServer(); + LwM2MServerCredentials lwm2mServer = lwM2MCredentials.getBootstrap().getLwm2mServer(); switch (clientCredentials.getSecurityConfigClientMode()) { case NO_SEC: case RPK: + deviceCredentials.setCredentialsValue(JacksonUtil.toString(lwM2MCredentials)); credentialsId = clientCredentials.getEndpoint(); break; case PSK: credentialsId = ((PSKClientCredentials) clientCredentials).getIdentity(); break; case X509: - X509ClientCredentials x509Config = (X509ClientCredentials) clientCredentials; - if ((StringUtils.isNotBlank(x509Config.getCert()))) { - String cert = EncryptionUtil.trimNewLines(x509Config.getCert()); - String sha3Hash = EncryptionUtil.getSha3Hash(cert); - x509Config.setCert(cert); - ((X509ClientCredentials) clientCredentials).setCert(cert); - deviceCredentials.setCredentialsValue(JacksonUtil.toString(lwM2MCredentials)); + deviceCredentials.setCredentialsValue(JacksonUtil.toString(lwM2MCredentials)); + X509ClientCredentials x509ClientConfig = (X509ClientCredentials) clientCredentials; + if ((StringUtils.isNotBlank(x509ClientConfig.getCert()))) { + String sha3Hash = EncryptionUtil.getSha3Hash(x509ClientConfig.getCert()); credentialsId = sha3Hash; } else { - credentialsId = x509Config.getEndpoint(); + credentialsId = x509ClientConfig.getEndpoint(); } break; } @@ -263,6 +262,8 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen } try { + String pubkClient = EncryptionUtil.pubkTrimNewLines(rpkCredentials.getKey()); + rpkCredentials.setKey(pubkClient); SecurityUtil.publicKey.decode(rpkCredentials.getDecodedKey()); } catch (Exception e) { throw new DeviceCredentialsValidationException("LwM2M client RPK key should be in RFC7250 standard and support only EC algorithm and encoded to Bas64 format!"); @@ -272,6 +273,8 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen X509ClientCredentials x509CCredentials = (X509ClientCredentials) clientCredentials; if (StringUtils.isNotBlank(x509CCredentials.getCert())) { try { + String certClient = EncryptionUtil.certTrimNewLines(x509CCredentials.getCert()); + x509CCredentials.setCert(certClient); SecurityUtil.certificate.decode(x509CCredentials.getDecodedCert()); } catch (Exception e) { throw new DeviceCredentialsValidationException("LwM2M client X509 certificate should be in DER-encoded X509v3 format and support only EC algorithm and encoded to Bas64 format!"); @@ -300,48 +303,56 @@ public class DeviceCredentialsServiceImpl extends AbstractEntityService implemen throw new DeviceCredentialsValidationException(server + " client PSK key should be random sequence in hex encoding!"); } - if (pskKey.length()% 32 != 0 || pskKey.length() > 128) { + if (pskKey.length() % 32 != 0 || pskKey.length() > 128) { throw new DeviceCredentialsValidationException(server + " client PSK key length = " + pskKey.length() + ". Key should be HexDec format: 32, 64, 128 characters!"); } break; case RPK: - RPKServerCredentials rpkCredentials = (RPKServerCredentials) serverCredentials; - if (StringUtils.isEmpty(rpkCredentials.getClientPublicKeyOrId())) { + RPKServerCredentials rpkServerCredentials = (RPKServerCredentials) serverCredentials; + if (StringUtils.isEmpty(rpkServerCredentials.getClientPublicKeyOrId())) { throw new DeviceCredentialsValidationException(server + " client RPK public key or id should be specified!"); } try { - SecurityUtil.publicKey.decode(rpkCredentials.getDecodedClientPublicKeyOrId()); + String pubkRpkSever = EncryptionUtil.pubkTrimNewLines(rpkServerCredentials.getClientPublicKeyOrId()); + rpkServerCredentials.setClientPublicKeyOrId(pubkRpkSever); + SecurityUtil.publicKey.decode(rpkServerCredentials.getDecodedClientPublicKeyOrId()); } catch (Exception e) { throw new DeviceCredentialsValidationException(server + " client RPK public key or id should be in RFC7250 standard and encoded to Bas64 format!"); } - if (StringUtils.isEmpty(rpkCredentials.getClientSecretKey())) { + if (StringUtils.isEmpty(rpkServerCredentials.getClientSecretKey())) { throw new DeviceCredentialsValidationException(server + " client RPK secret key should be specified!"); } try { - SecurityUtil.privateKey.decode(rpkCredentials.getDecodedClientSecretKey()); + String prikRpkSever = EncryptionUtil.prikTrimNewLines(rpkServerCredentials.getClientSecretKey()); + rpkServerCredentials.setClientSecretKey(prikRpkSever); + SecurityUtil.privateKey.decode(rpkServerCredentials.getDecodedClientSecretKey()); } catch (Exception e) { throw new DeviceCredentialsValidationException(server + " client RPK secret key should be in PKCS#8 format (DER encoding, RFC5958 standard) and encoded to Bas64 format!"); } break; case X509: - X509ServerCredentials x509CCredentials = (X509ServerCredentials) serverCredentials; - if (StringUtils.isBlank(x509CCredentials.getClientPublicKeyOrId())) { + X509ServerCredentials x509ServerCredentials = (X509ServerCredentials) serverCredentials; + if (StringUtils.isBlank(x509ServerCredentials.getClientPublicKeyOrId())) { throw new DeviceCredentialsValidationException(server + " client X509 public key or id should be specified!"); } try { - SecurityUtil.certificate.decode(x509CCredentials.getDecodedClientPublicKeyOrId()); + String certServer = EncryptionUtil.certTrimNewLines(x509ServerCredentials.getClientPublicKeyOrId()); + x509ServerCredentials.setClientPublicKeyOrId(certServer); + SecurityUtil.certificate.decode(x509ServerCredentials.getDecodedClientPublicKeyOrId()); } catch (Exception e) { throw new DeviceCredentialsValidationException(server + " client X509 public key or id should be in DER-encoded X509v3 format and support only EC algorithm and encoded to Bas64 format!"); } - if (StringUtils.isBlank(x509CCredentials.getClientSecretKey())) { + if (StringUtils.isBlank(x509ServerCredentials.getClientSecretKey())) { throw new DeviceCredentialsValidationException(server + " client X509 secret key should be specified!"); } try { - SecurityUtil.privateKey.decode(x509CCredentials.getDecodedClientSecretKey()); + String prikX509Sever = EncryptionUtil.prikTrimNewLines(x509ServerCredentials.getClientSecretKey()); + x509ServerCredentials.setClientSecretKey(prikX509Sever); + SecurityUtil.privateKey.decode(x509ServerCredentials.getDecodedClientSecretKey()); } catch (Exception e) { throw new DeviceCredentialsValidationException(server + " client X509 secret key should be in PKCS#8 format (DER encoding, RFC5958 standard) and encoded to Bas64 format!"); }