1

I am developing an application to secure communications between a client and an embedded linux server. I am very new to the field of cryptography, so at this stage I am looking more for guidance - especially when it comes to vulnerabilities in my approach.

The server will not be connected to the internet. I am looking for a way to implement a one time password authentication - (presumably the OTP would be generated via some shared secret exchanged between the client and server). I do not want to store static keys on the server, so I was thinking something along the lines of using Diffie-Hellman ephemeral key exchange could be used to exchange these keys or something along those lines. Could someone give me some pointers as to how I could approach solving this problem - or better still if this has already been done. I was thinking of using OpenSSL to put the server pieces together and the client needs to be more open ended - Java/C++/Platform agnostic. Perhaps there are some OpenSSL examples that do something similar to this, if so please send them along.

EDIT: So I've been doing a bit of experimentation since posting the question yesterday. I was able to verify that I can successfully create a shared secret using an ephemeral Diffie-Hellman key exchange. I got a C++ proof of concept working using the OpenSSL library, as shown in block of code below (which I adapted from various snippets I found online, sorry I lost the links). From what I can tell, this should be sufficient to get One Time Passwords working between the client and the server. For this latter solution, I was thinking about linking to the OATH Toolkit library for HOTP or TOTP Algorithm support.

The idea would be that once the shared secret was exchanged, the server could make up an OTP with both the shared secret and some server random data. Once the client knows this OTP they would provide it to login and authenticate. I am not sure if I have completely gotten this wrong of if what I am proposing is not possible (or more likely full of holes).

The following block of code shows how to the Diffie-Hellman shared secrets are identical (given a common generator and prime which is established via the DH_generate_parameters_ex.... and cloned for the client and server using the DHparams_dup API the DH keys replaced via the EVP_PKEY_set1_DH call)

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);
1
  • Are you authenticating the client or the server? What is your threat model (in particular, why don't you want to store static keys on the server)? Commented May 31, 2017 at 18:40

1 Answer 1

2

So you basicly want to do Two-Factor-Authorisation? (Or did I misunderstand?)

I'd simply use TOTP (Time based One Time Password) which became the standard for two-factor-authorisation.

Advantages

  • Standarized method
  • Compatible to Google Authentificator or pretty much every alternative
  • Really easy to either use an existing implementation or implement on your own
  • You don't need to be online nor connected to the server.

Disadvantages

  • You have to store the client's secret in a secure way to ensure it's not leaked upon a data breach.
  • Who knows the secret is able to generate passwords at any time he wants. (But that's pretty common when it comes to encryption)
3
  • Thanks, yes it does sound like is similar to what I need. Do you have any idea if this can be done via OpenSSL, Regarding the disadvantages of a leaked client secret, do you think using a DH ephemeral shared key could be useful to avoid this kind of disadvantage?
    – johnco3
    Commented May 31, 2017 at 17:18
  • 1
    No, DH hellman wouldn't help you saving the secrets since you have to recreate them (whereas DH would cause you generating a new password every time). Also 2 secs. of Google led me to this implementation already using OpenSSL github.com/gonrada/TOTP-Generator Commented May 31, 2017 at 17:21
  • A way to delay the leakage of the secrets could be using a secure cipher like rijndael (AES) or chacha20 and generate the keys using the users normal plain password. Once your database is leaked, the attacker would have to break the hashes to decrypt the secrets, which delays but doesn't secure. Commented May 31, 2017 at 17:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .