Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ss:laboratoare:09 [2025/02/20 16:30]
127.0.0.1 external edit
ss:laboratoare:09 [2026/05/04 19:40] (current)
ciprian.popescu0411 [Laborator 9: Implementarea mTLS în aplicația mobilă Android]
Line 1: Line 1:
-===== Laboratorul 09. =====+====== Laborator 9: Implementarea mTLS în aplicația mobilă ======
  
 +În cadrul acestui laborator vom implementa **Mutual TLS (mTLS)** pentru aplicația Android, asigurând autentificarea bidirecțională între clientul mobil și brokerul MQTT.
  
 +===== Ce este mTLS? =====
 +
 +**Mutual TLS** (mTLS) este un mecanism de autentificare bidirecțională în care:
 +  * **Serverul se autentifică** față de client (TLS standard)
 +  * **Clientul se autentifică** față de server (autentificare mutuală)
 +
 +Acest lucru asigură că:
 +  * Datele sunt criptate în tranzit
 +  * Doar dispozitivele autorizate se pot conecta la broker
 +  * Atacurile de tip man-in-the-middle sunt prevenite
 +
 +==== Diferența față de TLS simplu ====
 +
 +^ Aspect ^ TLS simplu ^ mTLS ^
 +| Autentificare server | DA | DA |
 +| Autentificare client | NU | DA |
 +| Certificat client necesar | NU | DA |
 +| Protecție împotriva clienților neautorizați | NU | DA |
 +
 +===== Fișiere de modificat =====
 +
 +^ Fișier ^ Scop ^ Modificări necesare ^
 +| ''​broker/​mosquitto.conf''​ | Configurare broker | Activarea mTLS pe portul 8883 |
 +| ''​MqttHandler.kt''​ | Client MQTT Android | Configurarea ''​SSLSocketFactory''​ cu certificate client |
 +| ''​SetupActivity.kt''​ | Ecran de setup | Adăugarea opțiunii de selectare a protocolului (TCP/SSL) |
 +| ''​MqttConstants.kt''​ | Constante | Adăugarea constantelor pentru TLS |
 +| ''​app/​src/​main/​res/​raw/''​ | Resurse | Stocarea certificatelor CA și client |
 +
 +===== Cerințe preliminare =====
 +
 +  * OpenSSL instalat (''​sudo apt install openssl''​ pe Linux)
 +  * Un broker MQTT Mosquitto funcțional
 +  * Proiectul Android funcțional cu conexiune MQTT simplă (laboratoarele anterioare)
 +
 +===== Pasul 1: Generarea certificatelor =====
 +
 +==== 1.1 Crearea Autorității de Certificare (CA) ====
 +
 +**Într-un terminal:**
 +<code bash>
 +mkdir -p certs && cd certs
 +
 +# Generarea cheii private a CA (4096 biți)
 +openssl genrsa -out ca.key 4096
 +
 +# Generarea certificatului CA (auto-semnat,​ valabil 10 ani)
 +openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
 +    -subj "/​C=RO/​ST=Romania/​L=Bucharest/​O=SSProject/​OU=Security/​CN=SSProject-CA"​
 +</​code>​
 +
 +==== 1.2 Crearea certificatului de server (pentru brokerul Mosquitto) ====
 +
 +Înlocuiți ''​ADRESA_IP_BROKER''​ cu IP-ul real al mașinii pe care rulează Mosquitto:
 +
 +**Într-un terminal:**
 +<code bash>
 +# Generarea cheii private a serverului
 +openssl genrsa -out server.key 2048
 +
 +# Generarea cererii de semnare (CSR) cu Subject Alternative Name
 +openssl req -new -key server.key -out server.csr \
 +    -subj "/​C=RO/​ST=Romania/​L=Bucharest/​O=SSProject/​OU=Broker/​CN=ADRESA_IP_BROKER"​ \
 +    -addext "​subjectAltName=IP:​ADRESA_IP_BROKER"​
 +
 +# Semnarea certificatului de server cu CA (valabil 1 an)
 +openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key \
 +    -CAcreateserial -out server.crt -sha256 \
 +    -copy_extensions copyall
 +
 +# Curățare CSR
 +rm server.csr
 +</​code>​
 +
 +==== 1.3 Crearea certificatului de client (pentru aplicația Android) ====
 +
 +**Într-un terminal:**
 +<code bash>
 +# Generarea cheii private a clientului
 +openssl genrsa -out android.key 2048
 +
 +# Generarea cererii de semnare a certificatului de client (CSR)
 +openssl req -new -key android.key -out android.csr \
 +    -subj "/​C=RO/​ST=Romania/​L=Bucharest/​O=SSProject/​OU=MobileClient/​CN=android"​
 +
 +# Semnarea certificatului de client cu CA (valabil 1 an)
 +openssl x509 -req -days 365 -in android.csr -CA ca.crt -CAkey ca.key \
 +    -CAcreateserial -out android.crt -sha256
 +
 +# Curățare CSR
 +rm android.csr
 +</​code>​
 +
 +==== 1.4 Crearea fișierului BKS (BouncyCastle KeyStore) pentru Android ====
 +
 +Android nu suportă nativ fișiere PEM. Trebuie să convertim certificatele într-un format compatibil. Vom crea două keystore-uri:​
 +  * **''​truststore.bks''​** — conține certificatul CA (pentru a verifica identitatea serverului)
 +  * **''​keystore.bks''​** — conține certificatul și cheia clientului (pentru a ne autentifica față de server)
 +
 +**Într-un terminal:**
 +<code bash>
 +# Crearea unui fișier PKCS12 cu certificatul și cheia clientului
 +openssl pkcs12 -export -in android.crt -inkey android.key \
 +    -out android.p12 -name "​android-client"​ \
 +    -password pass:​changeit
 +
 +# Descărcarea BouncyCastle Provider (necesar pentru format BKS)
 +wget https://​repo1.maven.org/​maven2/​org/​bouncycastle/​bcprov-jdk18on/​1.80/​bcprov-jdk18on-1.80.jar
 +
 +# Crearea truststore-ului BKS (conține CA)
 +keytool -importcert -v -trustcacerts \
 +    -file ca.crt -alias ca \
 +    -keystore truststore.bks \
 +    -storetype BKS \
 +    -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \
 +    -providerpath ./​bcprov-jdk18on-1.80.jar \
 +    -storepass changeit -noprompt
 +
 +# Crearea keystore-ului BKS (conține certificatul client)
 +keytool -importkeystore \
 +    -srckeystore android.p12 -srcstoretype PKCS12 -srcstorepass changeit \
 +    -destkeystore keystore.bks -deststoretype BKS -deststorepass changeit \
 +    -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \
 +    -providerpath ./​bcprov-jdk18on-1.80.jar
 +</​code>​
 +
 +==== 1.5 Verificarea certificatelor ====
 +
 +**Într-un terminal:**
 +<code bash>
 +# Verificarea certificatului CA
 +openssl x509 -in ca.crt -text -noout | head -15
 +
 +# Verificarea certificatului de server
 +openssl verify -CAfile ca.crt server.crt
 +
 +# Verificarea certificatului de client
 +openssl verify -CAfile ca.crt android.crt
 +
 +# Verificarea conținutului truststore-ului BKS
 +keytool -list -keystore truststore.bks -storetype BKS \
 +    -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \
 +    -providerpath ./​bcprov-jdk18on-1.80.jar \
 +    -storepass changeit
 +</​code>​
 +
 +==== 1.6 Lista fișierelor generate ====
 +
 +După generare, directorul ''​certs/''​ ar trebui să conțină:
 +
 +<code text>
 +certs/
 +├── ca.crt ​         # Certificatul CA
 +├── ca.key ​         # Cheia privată CA (NU se distribuie!)
 +├── server.crt ​     # Certificatul serverului
 +├── server.key ​     # Cheia privată a serverului
 +├── android.crt ​    # Certificatul clientului Android
 +├── android.key ​    # Cheia privată a clientului Android
 +├── android.p12 ​    # Fișier PKCS12 intermediar
 +├── truststore.bks ​ # Truststore BKS → va fi copiat în proiectul Android
 +└── keystore.bks ​   # Keystore BKS → va fi copiat în proiectul Android
 +</​code>​
 +
 +===== Pasul 2: Configurarea brokerului Mosquitto cu mTLS =====
 +
 +Creați sau editați fișierul ''​mosquitto_mtls.conf'':​
 +
 +<file bash mosquitto_mtls.conf>​
 +# MQTT securizat cu mTLS
 +listener 8883
 +cafile ./​certs/​ca.crt
 +certfile ./​certs/​server.crt
 +keyfile ./​certs/​server.key
 +require_certificate true
 +use_subject_as_username true
 +allow_anonymous true
 +
 +# Logare
 +log_type all
 +connection_messages true
 +log_timestamp true
 +</​file>​
 +
 +Porniți brokerul securizat:
 +
 +**Într-un terminal:**
 +<code bash>
 +sudo systemctl stop mosquitto.service
 +mosquitto -c mosquitto_mtls.conf -v
 +</​code>​
 +
 +**Setări cheie:**
 +  * ''​cafile''​ — certificatul CA pentru verificarea certificatelor clienților
 +  * ''​certfile/​keyfile''​ — certificatul propriu al serverului și cheia privată
 +  * ''​require_certificate true''​ — **activează mTLS**: clienții trebuie să prezinte un certificat valid
 +  * ''​use_subject_as_username true''​ — folosește CN-ul certificatului ca nume de utilizator MQTT
 +
 +===== Pasul 3: Copierea certificatelor în proiectul Android =====
 +
 +Copiați fișierele ''​truststore.bks''​ și ''​keystore.bks''​ în directorul de resurse raw al aplicației:​
 +
 +**Într-un terminal:**
 +<code bash>
 +mkdir -p app/​src/​main/​res/​raw
 +cp certs/​truststore.bks app/​src/​main/​res/​raw/​truststore.bks
 +cp certs/​keystore.bks app/​src/​main/​res/​raw/​keystore.bks
 +</​code>​
 +
 +<note tip>
 +Directorul ''​res/​raw/''​ este accesibil din cod prin ''​R.raw.truststore''​ și ''​R.raw.keystore''​.
 +</​note>​
 +<​note>​
 +Fișierele BKS sunt incluse în APK, deci nu trebuie să le distribuiți separat.
 +</​note>​
 +
 +===== Pasul 4: Actualizarea constantelor MQTT =====
 +
 +Adăugați constantele necesare pentru TLS în ''​MqttConstants.kt'':​
 +
 +<file kotlin MqttConstants.kt>​
 +package ro.pub.cs.systems.ssproject.mqtt
 +
 +object MqttConstants {
 +    const val TAG = "​MqttHandler"​
 +    const val TOPIC_IMAGES = "​ssproject/​images"​
 +    const val TOPIC_COMMANDS = "​ssproject/​commands"​
 +
 +    const val CMD_CAPTURE = "​CAPTURE"​
 +    const val CMD_START_LIVE = "​START-LIVE"​
 +    const val CMD_STOP_LIVE = "​STOP-LIVE"​
 +
 +    // TLS
 +    const val BKS_STORE_TYPE = "​BKS"​
 +    const val TLS_PROTOCOL = "​TLSv1.2"​
 +    const val KEYSTORE_PASSWORD = "​changeit"​
 +    const val TRUSTSTORE_PASSWORD = "​changeit"​
 +    const val DEFAULT_TLS_PORT = "​8883"​
 +}
 +</​file>​
 +
 +===== Pasul 5: Crearea clasei ''​TlsHelper''​ =====
 +
 +Creați o clasă nouă care gestionează crearea contextului SSL:
 +
 +<file kotlin TlsHelper.kt>​
 +package ro.pub.cs.systems.ssproject.mqtt
 +
 +import android.content.Context
 +import java.security.KeyStore
 +import javax.net.ssl.KeyManagerFactory
 +import javax.net.ssl.SSLContext
 +import javax.net.ssl.SSLSocketFactory
 +import javax.net.ssl.TrustManagerFactory
 +
 +object TlsHelper {
 +
 +    /**
 +     * Creează un SSLSocketFactory configurat pentru mTLS.
 +     *
 +     * @param context Contextul Android (necesar pentru accesarea resurselor raw)
 +     * @param trustStoreResId ID-ul resursei raw pentru truststore (R.raw.truststore)
 +     * @param keyStoreResId ID-ul resursei raw pentru keystore (R.raw.keystore)
 +     * @return SSLSocketFactory configurat cu certificatele client și CA
 +     */
 +    fun createMtlsSocketFactory(
 +        context: Context,
 +        trustStoreResId:​ Int,
 +        keyStoreResId:​ Int
 +    ): SSLSocketFactory {
 +        // 1. Încărcarea TrustStore-ului (conține certificatul CA)
 +        val trustStore = KeyStore.getInstance(MqttConstants.BKS_STORE_TYPE)
 +        context.resources.openRawResource(trustStoreResId).use { input ->
 +            trustStore.load(input,​ MqttConstants.TRUSTSTORE_PASSWORD.toCharArray())
 +        }
 +
 +        val trustManagerFactory = TrustManagerFactory.getInstance(
 +            TrustManagerFactory.getDefaultAlgorithm()
 +        )
 +        trustManagerFactory.init(trustStore)
 +
 +        // 2. Încărcarea KeyStore-ului (conține certificatul și cheia clientului)
 +        val keyStore = KeyStore.getInstance(MqttConstants.BKS_STORE_TYPE)
 +        context.resources.openRawResource(keyStoreResId).use { input ->
 +            keyStore.load(input,​ MqttConstants.KEYSTORE_PASSWORD.toCharArray())
 +        }
 +
 +        val keyManagerFactory = KeyManagerFactory.getInstance(
 +            KeyManagerFactory.getDefaultAlgorithm()
 +        )
 +        keyManagerFactory.init(keyStore,​ MqttConstants.KEYSTORE_PASSWORD.toCharArray())
 +
 +        // 3. Crearea contextului SSL cu ambele componente (mTLS)
 +        val sslContext = SSLContext.getInstance(MqttConstants.TLS_PROTOCOL)
 +        sslContext.init(
 +            keyManagerFactory.keyManagers, ​  // Autentificarea clientului
 +            trustManagerFactory.trustManagers,​ // Verificarea serverului
 +            null
 +        )
 +
 +        return sslContext.socketFactory
 +    }
 +}
 +</​file>​
 +
 +**Explicarea codului:**
 +
 +  - **TrustStore** — conține certificatul CA. Este folosit pentru a **verifica identitatea serverului** (echivalentul ''​ca_certs''​ din Python).
 +  - **KeyStore** — conține certificatul și cheia privată a clientului. Este folosit pentru **autentificarea clientului** față de server (echivalentul ''​certfile''​ + ''​keyfile''​ din Python).
 +  - **SSLContext** — combină cele două componente într-un context SSL complet pentru mTLS.
 +
 +===== Pasul 6: Actualizarea ''​MqttHandler''​ pentru suportul TLS =====
 +
 +Modificați constructorul și metoda ''​connect()''​ din ''​MqttHandler.kt''​ pentru a suporta atât conexiuni simple (TCP), cât și conexiuni securizate (SSL/TLS):
 +
 +<file kotlin MqttHandler.kt>​
 +package ro.pub.cs.systems.ssproject.mqtt
 +
 +import android.os.Build
 +import android.util.Log
 +import kotlinx.coroutines.Dispatchers
 +import kotlinx.coroutines.withContext
 +import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken
 +import org.eclipse.paho.client.mqttv3.MqttCallback
 +import org.eclipse.paho.client.mqttv3.MqttClient
 +import org.eclipse.paho.client.mqttv3.MqttConnectOptions
 +import org.eclipse.paho.client.mqttv3.MqttMessage
 +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
 +import javax.net.ssl.SSLSocketFactory
 +
 +class MqttHandler(
 +    brokerIp: String,
 +    brokerPort: String,
 +    private val sslSocketFactory:​ SSLSocketFactory?​ = null,
 +    private val isConnectedCallback:​ (Boolean) -> Unit,
 +    private val onCommandReceived:​ (String) -> Unit
 +) : MqttCallback {
 +    // Determinăm protocolul pe baza prezenței SSLSocketFactory
 +    private val protocol = if (sslSocketFactory != null) "​ssl"​ else "​tcp"​
 +    private val brokerUrl = "​$protocol://​$brokerIp:​$brokerPort"​
 +    private val clientId = "​${Build.MANUFACTURER}_${Build.MODEL}_${MqttClient.generateClientId()}"​
 +    private var client: MqttClient? = null
 +
 +    suspend fun connect() {
 +        withContext(Dispatchers.IO) {
 +            if (client?​.isConnected == true) {
 +                return@withContext
 +            }
 +
 +            try {
 +                client = MqttClient(brokerUrl,​ clientId, MemoryPersistence())
 +                client?​.setCallback(this@MqttHandler)
 +
 +                val options = MqttConnectOptions().apply {
 +                    isCleanSession = true
 +                    connectionTimeout = 10
 +                    keepAliveInterval = 60
 +
 +                    // Configurarea TLS dacă SSLSocketFactory este disponibil
 +                    if (sslSocketFactory != null) {
 +                        socketFactory = sslSocketFactory
 +                    }
 +                }
 +
 +                client?​.connect(options)
 +                Log.i(MqttConstants.TAG,​ "​Connected to $brokerUrl"​)
 +
 +                client?​.subscribe(MqttConstants.TOPIC_COMMANDS,​ 1)
 +                Log.i(MqttConstants.TAG,​ "​Subscribed to ${MqttConstants.TOPIC_COMMANDS}"​)
 +            } catch (e: Exception) {
 +                Log.e(MqttConstants.TAG,​ "​Connection error: ${e.message}"​)
 +                e.printStackTrace()
 +            } finally {
 +                isConnectedCallback(isConnected())
 +            }
 +        }
 +    }
 +
 +    // ... restul metodelor rămân neschimbate (disconnect,​ isConnected,​
 +    //    publishImage,​ connectionLost,​ messageArrived,​ deliveryComplete)
 +}
 +</​file>​
 +
 +**Modificări cheie:**
 +  * Constructorul primește opțional un ''​SSLSocketFactory''​
 +  * Protocolul se determină automat: ''​ssl://''​ pentru TLS, ''​tcp://''​ pentru conexiuni simple
 +  * ''​MqttConnectOptions.socketFactory''​ este configurat cu ''​SSLSocketFactory''​ pentru handshake-ul TLS
 +
 +===== Pasul 7: Actualizarea ''​SetupActivity''​ pentru selecția protocolului =====
 +
 +Modificați ecranul de setup pentru a permite utilizatorului să aleagă între conexiune simplă și conexiune securizată:​
 +
 +==== 7.1 Actualizarea layout-ului ====
 +
 +Adăugați un switch pentru activarea TLS în ''​activity_setup.xml'',​ **înainte** de butonul de conectare:
 +
 +<file xml activity_setup.xml>​
 +            <!-- ... după TextInputLayout-ul pentru port ... -->
 +
 +            <​com.google.android.material.materialswitch.MaterialSwitch
 +                android:​id="​@+id/​setup_card_view_tls_switch"​
 +                android:​layout_width="​match_parent"​
 +                android:​layout_height="​wrap_content"​
 +                android:​layout_marginTop="​8dp"​
 +                android:​layout_marginBottom="​8dp"​
 +                android:​text="​Conexiune securizată (mTLS)"​
 +                android:​checked="​false"​ />
 +
 +            <​com.google.android.material.button.MaterialButton
 +                android:​id="​@+id/​setup_card_view_connect_btn"​
 +                android:​layout_width="​wrap_content"​
 +                android:​layout_height="​wrap_content"​
 +                android:​layout_gravity="​end|center"​
 +                android:​text="​@string/​setup_connect_btn"​ />
 +</​file>​
 +
 +==== 7.2 Actualizarea ''​SetupActivity.kt''​ ====
 +
 +<file kotlin SetupActivity.kt>​
 +package ro.pub.cs.systems.ssproject.ui.setup
 +
 +import android.content.Intent
 +import android.os.Bundle
 +import android.util.Patterns
 +import android.widget.Button
 +import android.widget.EditText
 +import androidx.activity.ComponentActivity
 +import androidx.activity.enableEdgeToEdge
 +import com.google.android.material.materialswitch.MaterialSwitch
 +import ro.pub.cs.systems.ssproject.mqtt.MqttConstants
 +import ro.pub.cs.systems.ssproject.ui.dashboard.MainActivity
 +import ro.pub.cs.systems.ssproject.R
 +
 +class SetupActivity : ComponentActivity() {
 +    override fun onCreate(savedInstanceState:​ Bundle?) {
 +        super.onCreate(savedInstanceState)
 +        enableEdgeToEdge()
 +        setContentView(R.layout.activity_setup)
 +
 +        val ipField = findViewById<​EditText>​(R.id.setup_card_view_ip_field)
 +        val portField = findViewById<​EditText>​(R.id.setup_card_view_port_field)
 +        val tlsSwitch = findViewById<​MaterialSwitch>​(R.id.setup_card_view_tls_switch)
 +        val connect = findViewById<​Button>​(R.id.setup_card_view_connect_btn)
 +
 +        // Actualizarea portului implicit la activarea TLS
 +        tlsSwitch.setOnCheckedChangeListener { _, isChecked ->
 +            if (isChecked && portField.text.toString() == "​1883"​) {
 +                portField.setText(MqttConstants.DEFAULT_TLS_PORT)
 +            } else if (!isChecked && portField.text.toString() ==
 +                MqttConstants.DEFAULT_TLS_PORT) {
 +                portField.setText("​1883"​)
 +            }
 +        }
 +
 +        connect.setOnClickListener {
 +            val inputIp = ipField.text.toString().trim()
 +            val inputPort = portField.text.toString().trim()
 +
 +            if (inputIp.isEmpty() || !Patterns.IP_ADDRESS.matcher(inputIp).matches()) {
 +                ipField.error = "​Invalid IP address"​
 +                ipField.requestFocus()
 +                return@setOnClickListener
 +            }
 +
 +            val portNumber = inputPort.toIntOrNull()
 +            if (portNumber == null || portNumber !in 1..65535) {
 +                portField.error = "​Invalid port"
 +                portField.requestFocus()
 +                return@setOnClickListener
 +            }
 +
 +            val intent = Intent(this,​ MainActivity::​class.java)
 +            intent.putExtra("​brokerIp",​ inputIp)
 +            intent.putExtra("​brokerPort",​ inputPort)
 +            intent.putExtra("​useTls",​ tlsSwitch.isChecked)
 +            startActivity(intent)
 +        }
 +    }
 +}
 +</​file>​
 +
 +==== 7.3 Actualizarea ''​MainActivity.kt''​ ====
 +
 +Modificați crearea ''​MqttHandler''​ în ''​MainActivity''​ pentru a include configurația TLS:
 +
 +<file kotlin MainActivity.kt>​
 +// În metoda onCreate(), înlocuiți blocul de creare a MqttHandler cu:
 +
 +val useTls = intent.getBooleanExtra("​useTls",​ false)
 +
 +val sslSocketFactory = if (useTls) {
 +    TlsHelper.createMtlsSocketFactory(
 +        context = this,
 +        trustStoreResId = R.raw.truststore,​
 +        keyStoreResId = R.raw.keystore
 +    )
 +} else {
 +    null
 +}
 +
 +mqttHandler = MqttHandler(
 +    brokerIp,
 +    brokerPort,
 +    sslSocketFactory = sslSocketFactory,​
 +    isConnectedCallback = { isConnected ->
 +        runOnUiThread {
 +            handleConnectionStateChange(isConnected)
 +        }
 +    },
 +    onCommandReceived = { command ->
 +        runOnUiThread {
 +            appendLog(getString(R.string.main_logs_command_received_entry,​ command))
 +            handleReceivedCommand(command)
 +        }
 +    }
 +)
 +</​file>​
 +
 +===== Pasul 8: Testarea conexiunii mTLS =====
 +
 +  * Porniți brokerul Mosquitto cu configurația mTLS:
 +<code bash>
 +mosquitto -c mosquitto_mtls.conf -v
 +</​code>​
 +  * Compilați și rulați aplicația pe dispozitivul Android / emulator.
 +  * În ecranul de setup, activați switch-ul **Conexiune securizată (mTLS)** și introduceți IP-ul brokerului. Portul se va actualiza automat la ''​8883''​.
 +  * Verificați log-urile brokerului pentru a confirma conexiunea mTLS:
 +<code bash>
 +# New connection from X.X.X.X:​XXXXX on port 8883.
 +# New client connected from X.X.X.X:​XXXXX as ... (p1, c1, k60, u'​android'​).
 +</​code>​
 +  * Verificați cu Wireshark că traficul pe portul 8883 este criptat (comparativ cu portul 1883).
 +
 +===== Depanare =====
 +
 +==== ''​SSLHandshakeException:​ ...''​ la conectare ====
 +  * Asigurați-vă că toate certificatele sunt semnate de același CA
 +  * Verificați datele de expirare:
 +<code bash>
 +openssl x509 -in android.crt -noout -dates
 +</​code>​
 +  * Verificați că fișierele BKS au fost generate corect și copiate în ''​res/​raw/''​
 +
 +==== ''​Connection refused''​ pe portul 8883 ====
 +  * Verificați că brokerul Mosquitto ascultă pe portul 8883:
 +<code bash>
 +netstat -tlnp | grep 8883
 +</​code>​
 +  * Verificați setările firewall-ului pe mașina broker
 +
 +==== ''​java.io.IOException:​ Wrong version of key store''​ la încărcarea BKS ====
 +  * Asigurați-vă că folosiți versiunea corectă a BouncyCastle Provider
 +  * Recreați fișierele BKS cu comanda din Pasul 1.4
 +
 +==== Emulator Android nu poate accesa broker-ul de pe host ====
 +  * Folosiți adresa ''​10.0.2.2''​ în loc de ''​127.0.0.1''​ (adresa specială a emulatorului Android pentru host-ul gazdă)
 +
 +===== Bune practici de securitate =====
 +
 +  * **Nu comiteți niciodată certificate în git** — adăugați ''​certs/''​ în ''​.gitignore''​
 +  * **Nu hardcodați parolele keystore-urilor** — folosiți ''​BuildConfig''​ sau fișiere ''​secrets.properties''​ adăugate în ''​.gitignore''​
 +  * **Folosiți certificate cu durată scurtă de viață** — schimbați-le periodic
 +  * **Folosiți dimensiuni mari ale cheilor** — 4096 biți pentru CA, minim 2048 biți pentru server/​client
 +  * **Stocați cheile private în siguranță** — cheia CA (''​ca.key''​) nu trebuie să părăsească niciodată mașina pe care a fost generată
 +
 +===== Cerințe =====
 +
 +  - Urmăriți toți pașii din acest laborator pentru a implementa mTLS în aplicația Android.
 +  - Demonstrați că aplicația se conectează cu succes la broker prin mTLS (screenshot cu log-urile brokerului care arată conexiunea securizată).
 +  - Verificați cu Wireshark că traficul pe portul 8883 este criptat (comparativ cu portul 1883 din laboratoarele anterioare).
 +  - Implementați un mecanism prin care parolele keystore-urilor să nu mai fie hardcodate în cod (de exemplu, folosind ''​BuildConfig''​ cu valori din ''​local.properties''​).
ss/laboratoare/09.1740061822.txt.gz · Last modified: 2025/02/26 00:45 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0