/**
* Copyright © 2017 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.gateway.service;
import lombok.Data;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.internal.security.SSLSocketFactoryFactory;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Properties;
/**
* Created by ashvayka on 18.01.17.
*/
@Data
public class MqttGatewaySecurityConfiguration {
private String accessToken;
private String keystore;
private String keystorePassword;
private String keystoreKeyAlias;
private String truststore;
private String truststorePassword;
public boolean isTokenBased() {
return !StringUtils.isEmpty(accessToken);
}
public boolean isSsl() {
return !StringUtils.isEmpty(truststore);
}
public void setupSecurityOptions(MqttConnectOptions options) {
if (this.isTokenBased()) {
options.setUserName(this.getAccessToken());
if (!StringUtils.isEmpty(this.getTruststore())) {
Properties sslProperties = new Properties();
sslProperties.put(SSLSocketFactoryFactory.TRUSTSTORE, this.getTruststore());
sslProperties.put(SSLSocketFactoryFactory.TRUSTSTOREPWD, this.getTruststorePassword());
sslProperties.put(SSLSocketFactoryFactory.TRUSTSTORETYPE, "JKS");
sslProperties.put(SSLSocketFactoryFactory.CLIENTAUTH, false);
options.setSSLProperties(sslProperties);
}
} else {
//TODO: check and document this
Properties sslProperties = new Properties();
sslProperties.put(SSLSocketFactoryFactory.KEYSTORE, this.getKeystore());
sslProperties.put(SSLSocketFactoryFactory.KEYSTOREPWD, this.getKeystorePassword());
sslProperties.put(SSLSocketFactoryFactory.KEYSTORETYPE, "JKS");
sslProperties.put(SSLSocketFactoryFactory.TRUSTSTORE, this.getTruststore());
sslProperties.put(SSLSocketFactoryFactory.TRUSTSTOREPWD, this.getTruststorePassword());
sslProperties.put(SSLSocketFactoryFactory.TRUSTSTORETYPE, "JKS");
sslProperties.put(SSLSocketFactoryFactory.CLIENTAUTH, true);
options.setSSLProperties(sslProperties);
}
}
public String getClientId() {
if (this.isTokenBased()) {
return sha256(this.getAccessToken().getBytes(StandardCharsets.UTF_8));
} else {
try {
FileInputStream is = new FileInputStream(this.getKeystore());
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, this.getKeystorePassword().toCharArray());
Key key = keystore.getKey(this.getKeystoreKeyAlias(), this.getKeystorePassword().toCharArray());
if (key instanceof PrivateKey) {
// Get certificate of public key
java.security.cert.Certificate cert = keystore.getCertificate(this.getKeystoreKeyAlias());
// Get public key
PublicKey publicKey = cert.getPublicKey();
return sha256(publicKey.getEncoded());
} else {
throw new RuntimeException("No public key!");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private String sha256(byte[] data) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(data);
return Base64Utils.encodeToString(md.digest());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}