M4 - Actividad 1: Configuración Segura de TLS y Cifrado de Datos Sensibles con AES¶
Acerca del documento
En este informe detallo los pasos para realizar una configuración segura de un servidor web usando TLS (servidor TOMCAT) y como cifrar datos sensibles usando AES en Spring Boot.
Tabla de contenidos¶
- 1 Introducción
- 1.1 Configuración del Entorno
- 2 Configuración Segura de TLS (Spring Boot + Tomcat)
- 2.1 Generación del certificado
- 2.2 Configuración TLS en Spring Boot
- 2.3 Comprovació configuració TLS
- 2.4 Comprobació funcional
- 3 Implementación AES (Java)
- 3.1 Configuración clave secreta
- 3.2 Creación de los servicios para api segura y api no segura
- 3.2.1 Controllers
- 3.2.2 Services
- 3.2.3 Fichero de configuración del proyecto Spring Boot
- 3.3 Comprobacions
- 3.3.1 Prueba API insegura
- 3.3.2 Prueba API segura
- 3.3.3 Prueba de certificado autofirmado
- 4 ANEXO - Instalación y configuración certificat Let's Encrypt
- 4.1 Solicitud certificat
- 4.2 Convertir format del certificat obtingut
- 4.3 Instalar el certificat en tomcat
- 4.4 Comprobació amb el certificat de Let's Encrypt
- 5 Conclusiones
1 Introducció¶
En aquesta pràctica es tractarà de mostrar com es pot configurar TLS en un servidor web per poder millorar la seguretat de les comunicacions amb el servidor web. Concretament es mostrarà com configurar TLS 1.3 en el servidor web de TOMCAT. Un cop configurat TLS en el servidor web, realitzarem un codi que permetrà xifrar continguts sensibles amb AES.
1.1 Configuració del Entorn¶
La configuració necessària per realitzar aquesta pràctica difereix sensiblement de l'enunciat original ja que es modifica Apache2 per TOMCAT i llenguatge de programació PHP per Java, usant el framework Spring-Boot.
En l'enunciat original, per Apache i PHP, la generació de certificats es realitza mitjançant OpenSSL. Tanmateix, Java no permet utilitzar els fitxers en format PEM de forma directa. Per tant, es faran servir les eines pròpies de Java que es comentaran més endavant.
Per al tipus de projecte que necessitem, ens n'hi haurà prou amb marcar la dependència de spring-boot-starter-web a spring-initializr.
2 Configuració Segura de TLS (Spring Boot + Tomcat)¶
Per al cas de Spring Boot i Tomcat, necessitarem configurar els paràmetres dins del propi projecte de Spring Boot, ja que el servidor TOMCAT (embedit) s'executa en l'àmbit d'aquest projecte.
D'aquesta manera, en comptes de configurar els fitxers .conf d'Apache, utilitzarem el fitxer application.properties que fem servir als projectes de Spring Boot. També necessitarem un Keystore (amb PKCS12) en comptes dels fitxers .crt i .key separats.
2.1 Generació del certificat¶
En l'enunciat original es genera server.crt i server.key amb OpenSSL. Tomcat necessita un fitxer keystore (.p12 o .jks). Una alternativa seria crear els fitxers seguint les instruccions originals i després convertir els formats, encara que he optat per utilitzar l'eina nativa de Java keytool
Creació del keystore
keytool -genkeypair \
-alias tomcat \
-keyalg RSA \
-keysize 2048 \
-keystore src/main/resources/keystore.p12 \
-storetype PKCS12 \
-validity 365 \
-storepass contrasenyasegura \
-keypass contrasenyasegura \
-dname "CN=localhost, OU=IFC, O=cifpfbmoll, L=Palma, ST=IB, C=ES" \
-ext SAN=dns:localhost
Equivalència dels paràmetres:
- -genkeypair: Genera el pare de claus (pública i privada).
- -alias tomcat: Nom intern de la clau (equivalent a subject).
- -keystore src/main/resources/keystore.p12: On es guardarà. Ho ubiquem directament a resources perquè Spring Boot ho pugui localitzar amb la resta de recursos estàtics.
- -storetype PKCS12: Format estàndard modern (recomanat sobre JKS).
- -validity 365: Vàlid per 1 any (igual que -days 365 en OpenSSL).
- -dname: Dades del certificat (Subject).
- -ext SAN=dns:localhost: Afegeix un nom alternatiu (SubjectAltName), necessari perquè el navegador o curl no es "queixin" del nom d'amfitrió (equivalent a -addext "subjectAltName=DNS:localhost" d'OpenSSL).
- -storepass / -keypass: Contrasenya de l'almacén (en producció mai deixar-la a la instrucció. Si no es posa, es sol·licitarà de forma interactiva).
Podem verificar el certificat acabat de crear:
keytool -list -v -keystore src/main/resources/keystore.p12 -storepass contrasenyasegura
2.2 Configuració TLS en Spring Boot¶
Per a aquest pas, modificarem el fitxer src/main/resources/application.properties. (Equivalente a la configuració default-ssl.conf de Apache)
A continuació les modificacions del fitxer:
# Port HTTPS (Tomcat embedded)
server.port=8443
# Habilitar SSL
server.ssl.enabled=true
# Ruta del Keystore generat amb keytool
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=changeit
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=tomcat
# Forçar TLS 1.3 (Objectiu a l'enunciat)
server.ssl.enabled-protocols=TLSv1.3
# Xifratges segurs (Equivalent a SSLCipherSuite)
server.ssl.ciphers=TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256
Més informació
Si es vol utilitzar un certificat no autofirmat, es pot fer servir el servei gratuït de certificats Let's Encrypt. En el ANEXO estan les instruccions per poder realitzar la configuració TLS amb un certificat extern.
2.3 Comprovació configuració TLS¶
Per verificar si efectivament està correctament configurat podem executar
openssl s_client -connect localhost:8443 -tls1_3
Recortaré part de la sortida per clarificar tot el text
┌──(kali㉿kali)-[~/Documents/tascaM4]
└─$ openssl s_client -connect localhost:8443 -tls1_3
Connecting to ::1
CONNECTED(00000003)
Can\'t use SSL_get_servername
depth=0 C=ES, ST=IB, L=Palma, O=cifpfbmoll, OU=IFC, CN=localhost
verify error:num=18:self-signed certificate
verify return:1
depth=0 C=ES, ST=IB, L=Palma, O=cifpfbmoll, OU=IFC, CN=localhost
verify return:1
---
Certificate chain
0 s:C=ES, ST=IB, L=Palma, O=cifpfbmoll, OU=IFC, CN=localhost
i:C=ES, ST=IB, L=Palma, O=cifpfbmoll, OU=IFC, CN=localhost
a:PKEY: RSA, 2048 (bit); sigalg: sha384WithRSAEncryption
v:NotBefore: Mar 16 15:55:36 2026 GMT; NotAfter: Mar 16 15:55:36 2027 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDezCCAmOgAwIBAgIIMTUQkqdT3fAwDQYJKoZIhvcNAQEMBQAwYTELMAkGA1UE
....
mNsBygJtW0pl/EdDfwGIBhKimSPrr+P9r8hiZixOKqcYLlBt1+0oMKE719o17Okg
+2uUn4zz526D3PG1RZBVeFimH2K4dYXUHjmkEwQuog==
-----END CERTIFICATE-----
subject=C=ES, ST=IB, L=Palma, O=cifpfbmoll, OU=IFC, CN=localhost
issuer=C=ES, ST=IB, L=Palma, O=cifpfbmoll, OU=IFC, CN=localhost
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: rsa_pss_rsae_sha256
Peer Temp Key: X25519, 253 bits
---
SSL handshake has read 1421 bytes and written 1540 bytes
Verification error: self-signed certificate
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Protocol: TLSv1.3
Server public key is 2048 bit
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 18 (self-signed certificate)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Session-ID: 014B30A3695128192F4977F6C4165D89149E070B5FF0652F423799C7A8FDBC72
Session-ID-ctx:
Resumption PSK: A21F07433384E1AE559A8B59E81096D0C1831CA5D41CFBC577CB2B0C61BCCC36D95747CFD10CF93C9972D60898E4248B
PSK identity: None
2.4 Comprobació funcional¶
En el punt anterior hem verificat que el servidor està bé configurat amb TLS sense embargo esperarem a tenir el xifrat AES funcionant per fer comprovacions addicionals.
3 Implementació AES (Java)¶
Per començar amb aquesta segona part de la pràctica anem a preparar la clau de xifrat.
Així com en l'enunciat original s'utilitza un fitxer config.php per la key, en Spring Boot ho farem servir el fitxer application.properties i habilitant un "servei de seguretat" Java (EncryptionService.java)
3.1 Configuració clau secreta¶
Crearem una clau secreta per incorporar-la al fitxer application.properties. Per a això podem utilitzar openssl:
# Clau de 32 bytes (256 bits) en hexadecimal per AES-256
app.security.aes-key=24dbd51343b440b965c9605ce596c3a5e1b11ed07d4abd48556d7971d0d6ed12
En realitat podríem haver utilitzat qualsevol clau (de 32 bytes). Però prestem atenció a la següent explicació.
Aclarem conceptes
Imaginemos que utilizamos esta clave: asdfasd
00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff
ASCII o UTF8 ocupa 8 bits (1 byte) y por tanto la clave seria de 64 bytes. Sin embargo no es correcto.
Ahora es donde debemos entender la diferencia entre representación textual i los datos reales (usados en criptografia). La cadena anterior és una representación hexadecimal en texto de una clave binaria
| Concepto | Explicación | Ejemplo |
|---|---|---|
| Carácter ASCII | Cada letra o número ocupa 1 byte en memoria como texto. | El caràcter 'a' = 1 byte (0x61) |
| Dígito Hexadecimal | Cada caracter hex (0-9, a-f) representa 4 bits (mitad de un byte) de dato real real. |
El caracter 'a' en hex = valor 10 (4 bits) |
| Relación | Se necesitan 2 caracteres hex per representar 1 byte real de datos. | "FF" (2 bytes text) = 255 (1 byte datos) |
Ejemplo práctico aplicado a la clave que habíamos empezado a tratar
Cadena hexadecimal (TEXTO):
0011223344556677...
↑↑
|└─ 2 caracteres ASCII = 2 bytes de ocupación en disco/como texto
└── Representan 1 byte real de clave criptográfica (0x00)
Cálculo per la clau AES-256
| Etapa | Quantitat | Unitat |
|---|---|---|
| Longitud de la cadena hex | 64 | caracteres ASCII |
Conversió a binari (hex2bin) |
64 ÷ 2 = 32 | bytes reals |
| Bits reals de la clau | 32 × 8 = 256 | bits |
Tant en PHP com en Java existeixen funcions per la conversió de text a binari i així evitar aquesta confusió. De fet, aquesta confusió és origen de molts disgustos en el mòdul de DAM Programació de Serveis i Processos.
PHP:
// Texto: 64 bytes en memoria
$hexKey = "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff";
// Binario: 32 bytes reales para AES-256
$binaryKey = hex2bin($hexKey);
Java:
java
// Texto: 64 bytes en memoria
String hexKey = "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff";
// Binario: 32 bytes reales para AES-256
byte[] binaryKey = HexFormat.of().parseHex(hexKey);
Com a resum: * Com text (el que escrivim): La clau ocupa 64 bytes (perquè són 64 caràcters ASCII). * Com a clau criptogràfica (el que usa l'algoritme): La clau ocupa 32 bytes (256 bits) un cop es converteix a binari.
Per això mateix quan es configura la calve en application.properties o en config.php, es defineix com una cadena de text llarga (hex), sense embargo el sistema la convertirà automàticament a la mida correcta per AES-256.
Recorda
| Algoritmo AES | Clau en bytes | Clau en hexadecimal |
|---|---|---|
| AES-128 | 16 bytes | 32 caracteres hex |
| AES-192 | 24 bytes | 48 caracteres hex |
| AES-256 | 32 bytes | 64 caràcters hex ✅ |
Importante
Com se ha mencionat anteriorment, aquesta clau no hauria de quedar en el codi font (especialment en entorns de producció) sinó que hauria de carregar-se des d'una variable d'entorn per exemple ${APP_AES_KEY} i des de llavors, tenir especial cura en no pujar-la a un repositori públic com Github.
3.2 Creación de los servicios para api segura y api no segura¶
Tras analitzar els codi proporcionats, he decidit crear dos controladors una per secure_api i un altre per insecure_api (SecureApiController.java i InsecureApiController.java respectivament. Per altra banda he creat tres serveis EncryptionService.java, NoEncryptionService.java i StoreMessageService.java. S'hagués pogut crear en un sol controller i en un sol service, però penso que és molt més didàctic i està més correctament estructurat separar-ho tot, especialment per a futures utilitzacions amb alumnes.
3.2.1 Controllers¶
Se presenta a continuación el codigo de los dos controllers
src/main/java/edu.xaviersastre.tascaM4.controller.InsecureApiController.java
package edu.xaviersastre.tascaM4.controller;
import java.util.Map;
import edu.xaviersastre.tascaM4.security.NoEncryptionService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
@RestController
@RequestMapping("/aes/insecure_api")
public class InsecureApiController {
@Autowired
private NoEncryptionService noEncryptionService;
private String storedData = ""; // Simulació de persistència (sense xifrat)
@PostMapping
public ResponseEntity<Map<String, String>> saveData(@RequestBody Map<String, String> payload) {
try {
String text = payload.get("text");
storedData = noEncryptionService.noencrypt(text);
return ResponseEntity.ok(Map.of("message", "Texto almacenado en claro"));
} catch (Exception e) {
return ResponseEntity.status(500).body(Map.of("error", e.getMessage()));
}
}
@GetMapping
public ResponseEntity<Map<String, String>> getData() {
try {
if (storedData.isEmpty()) {
return ResponseEntity.status(404).body(Map.of("error", "No hay mensajes"));
}
return ResponseEntity.ok(Map.of("plaintext", storedData));
} catch (Exception e) {
return ResponseEntity.status(500).body(Map.of("error", e.getMessage()));
}
}
}
src/main/java/edu.xaviersastre.tascaM4.controller.SecureApiController.java
package edu.xaviersastre.tascaM4.controller;
import edu.xaviersastre.tascaM4.security.EncryptionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/aes/secure_api")
public class SecureApiController {
@Autowired
private EncryptionService encryptionService;
private String storedData = ""; // Simulació de persistència
@PostMapping
public ResponseEntity<Map<String, String>> saveData(@RequestBody Map<String, String> payload) {
try {
String text = payload.get("text");
// Xifrar abans de guardar (Com a secure_api.php)
storedData = encryptionService.encrypt(text);
return ResponseEntity.ok(Map.of("message", "Texto cifrado y almacenado"));
} catch (Exception e) {
return ResponseEntity.status(500).body(Map.of("error", e.getMessage()));
}
}
@GetMapping
public ResponseEntity<Map<String, String>> getData() {
try {
if (storedData.isEmpty()) {
return ResponseEntity.status(404).body(Map.of("error", "No hay mensajes"));
}
// Desxifrar abans de retornar
String decrypted = encryptionService.decrypt(storedData);
return ResponseEntity.ok(Map.of("plaintext", decrypted));
} catch (Exception e) {
return ResponseEntity.status(500).body(Map.of("error", "Desencriptación fallida"));
}
}
}
La estructura es muy similar en ambos casos, sin embargo el primero se usará para una api sin cifrar datos y el segundo para cifrar los datos. En els controladors només hi ha la lògica de les comunicacions. La lògica de xifratge i persistència estarà als serveis que veurem a continuació.
3.2.2 Services¶
A continuació el codi de los dos services
src/main/java/edu.xaviersastre.tascaM4.security.EncryptionService.java
package edu.xaviersastre.tascaM4.security;
import edu.xaviersastre.tascaM4.service.StoreMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
@Service
public class EncryptionService {
@Autowired
private StoreMessageService storeMessageService;
@Value("${app.security.aes-key}")
private String hexKey;
private SecretKey getKey() {
// Convertir hex string a byte array per crear la SecretKey
byte[] keyBytes = hexStringToByteArray(hexKey);
return new SecretKeySpec(keyBytes, "AES");
}
public String encrypt(String plaintext) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] iv = new byte[12]; // IV de 12 bytes per GCM (recomanat)
new SecureRandom().nextBytes(iv);
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, getKey(), spec);
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
// Empaquetar: IV (12) + Ciphertext (variable)
// Nota: Java gestiona el Tag d'autenticació internament dins del ciphertext byte[] combined = new byte[iv.length + ciphertext.length];
System.arraycopy(iv, 0, combined, 0, iv.length);
System.arraycopy(ciphertext, 0, combined, iv.length, ciphertext.length);
String encryptedBase64 = Base64.getEncoder().encodeToString(combined);
// Guardar a data.txt per verificar que el contingut es xifra
storeMessageService.saveToFile(encryptedBase64);
return encryptedBase64;
}
public String decrypt(String combinedB64) throws Exception {
byte[] combined = Base64.getDecoder().decode(combinedB64);
byte[] iv = java.util.Arrays.copyOfRange(combined, 0, 12);
byte[] ciphertext = java.util.Arrays.copyOfRange(combined, 12, combined.length);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, getKey(), spec);
return new String(cipher.doFinal(ciphertext), StandardCharsets.UTF_8);
}
// Utilitat per passar de Hex a Bytes
private byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i + 1), 16));
}
return data;
}
}
src/main/java/edu.xaviersastre.tascaM4.security.NoEncryptionService.java
package edu.xaviersastre.tascaM4.security;
import edu.xaviersastre.tascaM4.service.StoreMessageService;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class NoEncryptionService {
@Autowired
private StoreMessageService storeMessageService;
public String noencrypt(String plaintext) {
// Guardar a data.txt per verificar que el contingut NO es xifra
storeMessageService.saveToFile(plaintext);
return plaintext;
}
}
Aquests dos services son els encarregats de gestionar el xifratge o no dels dades rebudes i invocar al servei d'emmagatzematge persistent que podem veure a continuació
src/main/java/edu.xaviersastre.tascaM4.service.StoreMessageService.java
package edu.xaviersastre.tascaM4.service;
import org.springframework.stereotype.Service;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
@Service
public class StoreMessageService {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final ZoneId ZONE_CET = ZoneId.of("CET");
/**
* Guarda el missatge (xifrat o en clar) al fitxer data.txt amb data i hora (CET). * * @param message el text a guardar
*/ public void saveToFile(String message) {
String timestamp = ZonedDateTime.now(ZONE_CET).format(formatter);
String lineToSave = "[" + timestamp + " CET] " + message + System.lineSeparator();
try {
Files.write(
Paths.get("data.txt"),
lineToSave.getBytes(),
StandardOpenOption.CREATE,
StandardOpenOption.APPEND
);
} catch (java.io.IOException e) {
System.err.println("Error en guardar a data.txt: " + e.getMessage());
}
}
}
Es pot observar que en l'operació d'escriptura al fitxer, s'ha afegit un timestampque després en el apartat de comprovacions ens serà útil.
3.2.3 Fichero de configuración del proyecto Spring Boot¶
Com ja s'ha comentat anteriorment en el fitxer application.properties ubicat en src/main/resources a part d'estar la configuració que hem realitzat de TLS, estan la resta de paràmetres de configuració importants del projecte.
Aquest és el seu contingut:
src/main/resources/application.properties
# Port HTTPS (Tomcat embedded)
server.port=8443
# Habilitar SSL
server.ssl.enabled=true
# Ruta del Keystore generat amb keytool
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=xxxxxxx
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=tomcat
# Forçar TLS 1.3 (Objectiu a l'enunciat)
server.ssl.enabled-protocols=TLSv1.3
# Xifratges segurs (Equivalent a SSLCipherSuite)
server.ssl.ciphers=TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256
# Clau AES-256 per al servei de xifrat (64 carà cters hex = 32 bytes = 256 bits)
app.security.aes-key=24dbd51343b440b965c9605ce596c3a5e1b11ed07d4abd48556d7971d0d6ed12
Ja s'ha comentat abans que la clau de xifratge que està especificada en aquest fitxer i paràmetre app.security.aes-key hauria d'estar especificada en una variable d'entorn. Al ser aquest un projecte divulgatiu no suposa cap perill.
3.3 Comprobacions¶
Ponem en marxa el projecte Spring Boot que al seu torn inicialitzarà el servidor TOMCAT (el nostre servidor web) i així podrem generar la nostra bateria de proves.

Podem observar que efectivament s'ha iniciat Tomcat i en el port 8443
3.3.1 Prueba API insegura¶
Realitzarem la primera prova amb l'API insegura

i si comprovem el fitxer data.txt del servidor hauria d'aparèixer Mensaje Secreto juntament amb el timestamp que hem comentat abans
3.3.2 Prueba API segura¶
i si comprovem el fitxer data.txthauria d'aparèixer una nova línia amb Mensaje Secreto però xifrat amb AES
Verificar
Podemos observar en ambos casos (seguro e inseguro) el timestamp coincide
3.3.3 Prueba de certificado autofirmado¶
Anem a realitzar qualsevol de les proves anteriors sense el paràmetre -k en la instrucció curl

Efectivament apareix l'error descrit en l'enunciat de la tasca. Si ara provem amb l'adreça vàlida a internet vinculada al certificat configurat en l'ANEXO, vegem quin és el resultat
i efectivament el missatge no apareix i per tant la configuració realitzada és correcta i segura.
4 ANEXO - Instalación y configuración certificat Let's Encrypt¶
4.1 Solicitud certificat¶
Per començar necessitarem instal·lar la utilitat certbot
sudo apt install certbot
Un cop instal·lat anem a sol·licitar el nostre certificat amb la utilitat recentment instal·lada
sudo certbot certonly --standalone -d domini.cat
Los ficheros correspondientes al certificado se instalarán en `/etc/letsencrypt/live/domini.cat/
4.2 Convertir format del certificat obtingut¶
sudo openssl pkcs12 -export \
-in /etc/letsencrypt/live/domini.cat/fullchain.pem \
-inkey /etc/letsencrypt/live/domini.cat/privkey.pem \
-out keystore.p12 \
-name tomcat \
-CAfile /etc/letsencrypt/live/domini.cat/chain.pem \
-caname root
Es importantte substituir keystore.p12 per el keystore que hàgim creat per al projecte original.
4.3 Instalar el certificat en tomcat¶
Un cop ja tenim el certificat convertit i en el keystore.p12 del nostre projecte hem de configurar els paràmetres en el fitxer application.properties
# Ruta del nou fitxer de Let's Encrypt
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=la_teva_contrasenya_nova
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=tomcat
# Protocol i xifratges (ja configurats anteriorment)
server.ssl.enabled-protocols=TLSv1.3
server.ssl.ciphers=TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA25
En principi hauria de coincidir amb la configuració anterior.
4.4 Comprovació amb el certificat de Let's Encrypt¶
Tal i com es va fer en el apartat 2.3 es pot verificar la correcta configuració
Tener en cuenta ...
En la següent sortida es han difuminat dades sensibles com la ip pública o el nom de domini real. També s'ha omès tota la sortida, per no allargar massa el document.
5 Conclusiones¶
Se podrían realizar muchas más pruebas como las especificadas en el enunciado con Wireshark o cualquier otra herramienta que permita capturar paquetes circulando por la red. De esta manera se podría comprobar que efectivamente todo funciona como esperamos. Por falta de tiempo se han omitido este tipo de pruebas, sin embargo en un supuesto de utilizar esta práctica en aula amb alumnes, el més recomanable seria preparar l'entorn on poder efectivament confirmar que la informació és visible en text pla o encriptada en funció dels diferents paràmetres utilitzats per la comunicació. També seria ideal poder provar un altre tipus de xifrats i fins i tot diferents algoritmes.







