Skip to content

Instantly share code, notes, and snippets.

@kimutansk
Last active October 27, 2015 08:04
Show Gist options
  • Save kimutansk/5f3e18f7bb777b0f5b49 to your computer and use it in GitHub Desktop.
Save kimutansk/5f3e18f7bb777b0f5b49 to your computer and use it in GitHub Desktop.
AWS IoTにJVM系言語(Scala)から接続するには(Publish) ref: http://qiita.com/kimutansk/items/2a4a7ce628fcd054342a
# mosquitto_sub --cafile rootCA.pem --cert cert.pem --key private.pem -h ******.iot.ap-northeast-1.amazonaws.com -p 8883 -q 1 -d -t test-topic -i mosquitto-subscriber
Client mosquitto-subscriber sending CONNECT
Client mosquitto-subscriber received CONNACK
Client mosquitto-subscriber sending SUBSCRIBE (Mid: 1, Topic: test-topic, QoS: 1)
Client mosquitto-subscriber received SUBACK
Subscribed (mid: 1): 1
Client mosquitto-subscriber received PUBLISH (d0, q1, r0, m1, 'test-topic', ... (12 bytes))
Client mosquitto-subscriber sending PUBACK (Mid: 1)
Test Message
import org.eclipse.paho.client.mqttv3.{MqttMessage, MqttConnectOptions, MqttClient}
/** MQTT Publish Test Class */
object MqttPublisher {
def main(args: Array[String]) {
// Connect Target
val brokerURI:String = "ssl://******.iot.ap-northeast-1.amazonaws.com:8883"
// SocketFactoryGenerate
val socketFactory = SocketFactoryGenerator.generateFromFilePath("/etc/cert/rootCA.pem", "/etc/cert/cert.pem", "/etc/cert/private.pem", "password")
// MQTT Client generate
val client:MqttClient = new MqttClient(brokerURI, "mqtt-publisher")
client.setCallback(new PublishMqttCallback)
val options:MqttConnectOptions = new MqttConnectOptions()
options.setSocketFactory(socketFactory)
client.connect(options)
val message:MqttMessage = new MqttMessage("Test Message".getBytes("UTF-8"))
client.publish("test-topic", message)
}
}
import org.eclipse.paho.client.mqttv3.{IMqttDeliveryToken, MqttMessage, MqttCallback}
/** Publish MqttCallBack */
class PublishMqttCallback extends MqttCallback{
// Nop
override def deliveryComplete(iMqttDeliveryToken: IMqttDeliveryToken): Unit = ???
override def messageArrived(s: String, mqttMessage: MqttMessage): Unit = ???
override def connectionLost(throwable: Throwable): Unit = ???
}
import java.io.{ByteArrayInputStream, InputStream, InputStreamReader}
import java.nio.file.{Files, Paths}
import java.security.cert.{CertificateFactory, X509Certificate}
import java.security.{KeyPair, KeyStore, Security}
import javax.net.ssl.{KeyManagerFactory, SSLContext, SSLSocketFactory, TrustManagerFactory}
import org.bouncycastle.cert.X509CertificateHolder
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter
import org.bouncycastle.openssl.{PEMKeyPair, PEMParser}
/** Factory for [[javax.net.ssl.SSLSocketFactory]] instances. */
object SocketFactoryGenerator {
/**
* Generate [[javax.net.ssl.SSLSocketFactory]] from pem file paths.
*
* @param rootCaFilePath Root CA file path
* @param certFilePath Certificate file path
* @param keyFilePath Private key file path
* @return Generated [[javax.net.ssl.SSLSocketFactory]]
*/
def generateFromFilePath(rootCaFilePath:String, certFilePath:String, keyFilePath:String, keyStorePassword:String):SSLSocketFactory = {
Security.addProvider(new BouncyCastleProvider())
// load Root CA certificate
val rootCaParser:PEMParser = new PEMParser(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(rootCaFilePath)))))
val rootCaCertHolder:X509CertificateHolder = rootCaParser.readObject().asInstanceOf[X509CertificateHolder]
val rootCaCert:X509Certificate = convertToJavaCertificate(rootCaCertHolder)
rootCaParser.close()
// load Server certificate
val certParser:PEMParser = new PEMParser(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(certFilePath)))))
val serverCertHolder:X509CertificateHolder = certParser.readObject.asInstanceOf[X509CertificateHolder]
val serverCert:X509Certificate = convertToJavaCertificate(serverCertHolder)
certParser.close()
// load Private Key
val keyParser:PEMParser = new PEMParser(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(keyFilePath)))))
val pemKeyPair:PEMKeyPair = keyParser.readObject.asInstanceOf[PEMKeyPair]
val keyPair:KeyPair = new JcaPEMKeyConverter().getKeyPair(pemKeyPair)
keyParser.close()
// Root CA certificate is used to authenticate server
val rootCAKeyStore:KeyStore = KeyStore.getInstance(KeyStore.getDefaultType())
rootCAKeyStore.load(null, null)
rootCAKeyStore.setCertificateEntry("ca-certificate", convertToJavaCertificate(rootCaCertHolder))
val tmf:TrustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(rootCAKeyStore);
// client key and certificates are sent to server so it can authenticate us
val ks:KeyStore = KeyStore.getInstance(KeyStore.getDefaultType())
ks.load(null, null)
ks.setCertificateEntry("certificate", serverCert)
ks.setKeyEntry("private-key", keyPair.getPrivate(), keyStorePassword.toCharArray, Array(serverCert))
val kmf:KeyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
kmf.init(ks, keyStorePassword.toCharArray());
// finally, create SSL socket factory
val context:SSLContext = SSLContext.getInstance("TLSv1.2")
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null)
context.getSocketFactory()
}
def convertToJavaCertificate(certificateHolder:X509CertificateHolder):X509Certificate = {
val is:InputStream = new ByteArrayInputStream(certificateHolder.toASN1Structure.getEncoded);
try {
CertificateFactory.getInstance("X.509").generateCertificate(is).asInstanceOf[X509Certificate]
} finally is.close()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment