-
Notifications
You must be signed in to change notification settings - Fork 0
/
DesempaquetarExamen.java
182 lines (144 loc) · 7.19 KB
/
DesempaquetarExamen.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
*
* @author lfcounago
*/
public class DesempaquetarExamen {
public static void main(String[] args)
throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException,
InvalidKeyException, SignatureException, NoSuchPaddingException, IllegalBlockSizeException,
BadPaddingException {
if (args.length != 3) {
mensajeAyuda();
System.exit(1);
}
/* Cargar "provider" */
Security.addProvider(new BouncyCastleProvider()); // Usa provider BC
/* RECUPERAMOS EL PAQUETE */
System.out.println("------Recuperando paquete-------");
Paquete paquete = new Paquete(args[0]);
// Recuperamos los datos del paquete
byte[] examenCifrado = paquete.getContenidoBloque("Examen cifrado");
byte[] claveSimetricaCifrada = paquete.getContenidoBloque("Clave secreta cifrada");
byte[] fecha = paquete.getContenidoBloque("Fecha");
byte[] sello = paquete.getContenidoBloque("Sello");
System.out.println("Paquete recuperado correctamente");
System.out.println("--------------------------------\n");
/* RECUPERAMOS LA CLAVE PÚBLICA DE LA AUTORIDAD DE SELLADO */
PublicKey KUautoridad = recuperClavePublica(args[1]);
/* RECUPERAMOS LA CLAVE PRIVADA DEL PROFESOR */
PrivateKey KRprofesor = recuperClavePrivada(args[2]);
/* COMPRAMOS FIRMA RECIBIDA EN EL PAQUETE */
System.out.println("----------Validando sello del alumno----------");
boolean selloValido = validarSelloAlumno(fecha, sello, examenCifrado, KUautoridad, claveSimetricaCifrada);
// Si el sello es válido procedemos a desencriptar el examen
if (selloValido) {
System.out.println("Sello del alumno validada correctamente");
System.out.println("------------------------------------------\n");
/* DESCIFRAMOS LA CLAVE SECRETA */
System.out.println("--Descifrando clave simétrica--");
byte[] claveDescifrada = descifrarClaveSimetrica(claveSimetricaCifrada, KRprofesor);
System.out.println(" Clave descifrada correctamente");
System.out.println("-------------------------------\n");
/* DESCIFRAMOS EL EXAMEN */
System.out.println("-----Descifrando el examen-----");
byte[] examenDescifrado = descifradoDES(claveDescifrada, examenCifrado);
System.out.println("Examen descifrado correctamente");
System.out.println("-------------------------------\n");
System.out.println("---Contenido del examen---\n");
System.out.write(examenDescifrado);
System.out.println("\n\n---Fin del examen---");
} else {
System.out.println("ERROR: Sello del alumno no validado");
System.exit(1);
}
}
/*
* Función para validar el sello que generó el alumno cuando selló el examen
* Devuelve un boolean de si está validad o no
*/
public static boolean validarSelloAlumno(byte[] fecha, byte[] sello, byte[] examenCifrado,
PublicKey KUautoridad, byte[] claveSimetricaCifrada)
throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException {
boolean validada = false;
Signature firmaComprobar = Signature.getInstance("MD5withRSA", "BC");
firmaComprobar.initVerify(KUautoridad);
firmaComprobar.update(examenCifrado);
firmaComprobar.update(claveSimetricaCifrada);
firmaComprobar.update(fecha);
if (firmaComprobar.verify(sello)) {
System.out.println("El sello enviado y el recibido es el mismo");
validada = true;
} else {
System.out.println("El sello enviado y el recibido no coinciden");
System.exit(1);
}
return validada;
}
/*
* Función para decifrar la clave simétrica (clave con la que se cifró el
* examen) con la clave privada del profesor
* Devolverá la clave descifrada
*/
public static byte[] descifrarClaveSimetrica(byte[] clave, PrivateKey KRprofesor)
throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
// Obtener Cipher RSA
Cipher cifradorRSA = Cipher.getInstance("RSA", "BC");
// Poner CipherRSA en modo DESCIFRADO
cifradorRSA.init(Cipher.DECRYPT_MODE, KRprofesor);
byte[] claveDescifrada = cifradorRSA.doFinal(clave);
return claveDescifrada;
}
/*
* Función para descifrar el examen con la clave secreta
* Devolvemos el examen descifrado
*/
public static byte[] descifradoDES(byte[] claveDescifrada, byte[] examen) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
// Obtener Cipher DES
Cipher cifradorDES = Cipher.getInstance("DES/ECB/PKCS5Padding");
// Poner CipherDES en modo DESCIFRADO
SecretKey claveDescifradaBack = new SecretKeySpec(claveDescifrada, 0, claveDescifrada.length, "DES");
cifradorDES.init(Cipher.DECRYPT_MODE, claveDescifradaBack);
byte[] examenDescifrado = cifradorDES.doFinal(examen);
return examenDescifrado;
}
/*
* Función para recuperar la clave pública
* Devuelve la PublicKey correspondiente
*/
public static PublicKey recuperClavePublica(String clavePublica)
throws NoSuchAlgorithmException, NoSuchProviderException, IOException, InvalidKeySpecException {
// Crear KeyFactory formato RSA
KeyFactory keyFactoryRSA = KeyFactory.getInstance("RSA", "BC"); // Hace uso del provider BC
// Recuperar clave publica desde datos codificados en formato X509
X509EncodedKeySpec clavePublicaSpec = new X509EncodedKeySpec(Files.readAllBytes(Paths.get(clavePublica)));
PublicKey KU = keyFactoryRSA.generatePublic(clavePublicaSpec);
return KU;
}
/*
* Función para recuperar la clave privada
* Devuelve la PrivateKey correspondiente
*/
public static PrivateKey recuperClavePrivada(String clavePrivada)
throws NoSuchAlgorithmException, NoSuchProviderException, IOException, InvalidKeySpecException {
KeyFactory keyFactoryRSA = KeyFactory.getInstance("RSA", "BC"); // Hace uso del provider BC
PKCS8EncodedKeySpec clavePrivadaSpec = new PKCS8EncodedKeySpec(Files.readAllBytes(Paths.get(clavePrivada)));
PrivateKey KR = keyFactoryRSA.generatePrivate(clavePrivadaSpec);
return KR;
}
public static void mensajeAyuda() {
System.out.println("Desempaquetador de exámenes");
System.out.println(
"\tSintaxis: java -cp \".;bcprov-jdk18on-176.jar\" DesempaquetarExamen paquete .\\autoridadSellado.publica .\\profesor.privada");
System.out.println();
}
}