Estoy desarrollando una aplicación para asegurar las comunicaciones entre un cliente y un servidor Linux integrado. Soy muy nuevo en el campo de la criptografía, por lo que en esta etapa busco más orientación, especialmente cuando se trata de vulnerabilidades en mi enfoque.
El servidor no estará conectado a internet. Estoy buscando una manera de implementar una autenticación de contraseña única (probablemente, la OTP se generaría a través de un intercambio de secretos compartidos entre el cliente y el servidor). No quiero almacenar claves estáticas en el servidor, por lo que estaba pensando en algo similar al uso del intercambio de claves efímero Diffie-Hellman que podría usarse para intercambiar estas claves o algo así. ¿Podría alguien darme algunos consejos sobre cómo podría abordar este problema, o mejor aún si esto ya se ha hecho? Estaba pensando en usar OpenSSL para juntar las piezas del servidor y el cliente debe ser más abierto, Java / C ++ / Platform agnostic. Tal vez hay algunos ejemplos de OpenSSL que hacen algo similar a esto, si es así, envíelos.
EDITAR: Así que he estado haciendo un poco de experimentación desde que publiqué la pregunta ayer. Pude verificar que puedo crear con éxito un secreto compartido utilizando un intercambio de claves efímero Diffie-Hellman. Obtuve una prueba de concepto de C ++ utilizando la biblioteca OpenSSL, como se muestra en el bloque de código a continuación (que adapté de varios fragmentos de código que encontré en línea, lo siento, perdí los enlaces). Por lo que puedo decir, esto debería ser suficiente para que las contraseñas de un solo uso funcionen entre el cliente y el servidor. Para esta última solución, estaba pensando en enlazar con la biblioteca OATH Toolkit para HOTP o TOTP Compatibilidad con algoritmos.
La idea sería que una vez que se intercambió el secreto compartido, el servidor podría crear una OTP con el secreto compartido y algunos datos aleatorios del servidor. Una vez que el cliente conozca esta OTP, la proporcionará para iniciar sesión y autenticarse. No estoy seguro si me he equivocado por completo de si lo que estoy proponiendo no es posible (o más probablemente está lleno de agujeros).
El siguiente bloque de código muestra cómo los Diffie-Hellman secretos son idénticos (dado un generador común y primordial que se establece a través de DH_generate_parameters_ex .... y clonado para el cliente y servidor que utiliza la API DHparams_dup, las claves DH se reemplazaron a través de la llamada EVP_PKEY_set1_DH)
auto dhparams = DH_new();
if ( DH_generate_parameters_ex(dhparams, 512, DH_GENERATOR_5, nullptr) != 0 ) {
// duplicate the existing parameters for alice
auto dhparams_alice = DHparams_dup(dhparams);
// generate Alice's private and public key values
// should return 1 for success
auto res = DH_generate_key(dhparams_alice);
// Use the same generator and bitlength parameters
auto dhparams_bob = DHparams_dup(dhparams);
// generate Bob's private and public key values
// should return 1 for success
res = DH_generate_key(dhparams_bob);
auto key_alice = EVP_PKEY_new();
// should return 1 for success
res = EVP_PKEY_set1_DH(key_alice, dhparams_alice);
auto key_bob = EVP_PKEY_new();
// should return 1 for success
res = EVP_PKEY_set1_DH(key_bob, dhparams_bob);
// Compute the shared secret using Alice's private key and Bob's public key.
// unique pointer, so automatically destroyed.
size_t keyLen1 = 0;
auto key1 = dh_derive(key_alice, key_bob, keyLen1);
// Compute the shared secret using Bob's private key and Alice's public key.
// unique pointer, so automatically destroyed.
size_t keyLen2 = 0;
auto key2 = dh_derive(key_bob, key_alice, keyLen2);
// Prove correctness by showing Alicia and Beth derived the same secret
if (keyLen1 != keyLen2 || memcmp(key1.get(), key2.get(), keyLen1) != 0) {
std::cout << "Shared Secret different" << std::endl;
}
EVP_PKEY_free(key_alice);
EVP_PKEY_free(key_bob);
DH_free(dhparams_alice);
DH_free(dhparams_bob);
DH_free(dhparams);