0

I want to use an ECC private key for encryption because of mutual authentication. But I cannot find a method (or function) in wolfcrypt (wolfSSL) or the micro-ecc library.

Is is okay to use an (ECC) private key for encryption? And if so, how can I do this?

comomind
  • 25
  • 4
  • It will defeat the purpose of encryption if you use a private key to encrypt a message :) – StoryTeller - Unslander Monica Feb 23 '17 at 12:21
  • 1
    @StoryTeller This is what is done for cryptographical signatures or similar things and seems plausible for "mutual authentication", as stated in the question – Ctx Feb 23 '17 at 12:27
  • @Ctx - Well, I somehow completely missed the authentication part and instead focused on encryption. Naturally one should *sign* messages with a private key, and encrypt them with a public one. And it better be a different pair of keys one uses for each purpose. – StoryTeller - Unslander Monica Feb 23 '17 at 12:29
  • 1
    @StoryTeller That would be quite unusual, why would you use different keypairs for that? – Ctx Feb 23 '17 at 12:31
  • 1
    @Ctx - Using the same key-pair to sign your messages and receive encrypted ones is a good way to have them discovered by an attacker. – StoryTeller - Unslander Monica Feb 23 '17 at 12:32
  • 1
    @StoryTeller Not from a cryptographical point of view at least, neither is this common practice (i.e. pgp/gpg) – Ctx Feb 23 '17 at 12:34
  • 1
    @Ctx - [Have a read](http://crypto.stackexchange.com/questions/12090/using-the-same-rsa-keypair-to-sign-and-encrypt). It's about RSA, but the general principle follows. – StoryTeller - Unslander Monica Feb 23 '17 at 12:36
  • 1
    @StoryTeller As I said, these are not cryptographical issues but implementation specific, so these are irrelevant here – Ctx Feb 23 '17 at 12:39
  • 1
    @Ctx - "Implementation specific"!? It's an issue at the very core of information security. And if I see this backwards advise of using the same key-pair for more than two purposes, you bet I'm gonna call people out on it. There are more than "cryptographical considerations" for protecting your communication. – StoryTeller - Unslander Monica Feb 23 '17 at 12:42
  • 1
    @StoryTeller You are clearly not in-depth with cryptography, please do not pretend so. And for the record: It is perfectly safe to encrypt _and_ sign your e-mail correspondence with gpg and the same keypair, using different keypairs are no benefit to it in general. – Ctx Feb 23 '17 at 12:44
  • 1
    @StoryTeller There is no need to be offended or offensive like that. I just want to keep others from getting the impression that it is cryptographically insecure to use the same keypair for signing and encrypting. And btw: not even the article you linked above supports the claim, that this "is a good way to have it discovered by the attacker", did you read it carefully? – Ctx Feb 23 '17 at 13:24
  • 1
    Read the posts _[in this answer](http://stackoverflow.com/a/16405768/645128)_. There is some content that may be relevant to your question. In particular, I found this statement interesting: _In practice, encrypting with the private key as a kludge to generate a digital signature is a really bad idea._... In general, responses to your question are going to include opinion. Look for statements of best practice, then cross-check them with more research. – ryyker Feb 23 '17 at 14:04
  • 1
    Possible duplicate of [Is it possible to encrypt with private key using .net RSACryptoServiceProvider?](http://stackoverflow.com/questions/1181421/is-it-possible-to-encrypt-with-private-key-using-net-rsacryptoserviceprovider) – ryyker Feb 23 '17 at 14:07
  • 2
    @comomind It is not necessary to use encryption to achieve authentication. If we talk about a private key operation, we either mean decrypting ciphertext or signing plaintext. You should [edit] your question to make it clear what it is that you want to achieve. – Artjom B. Feb 23 '17 at 19:50
  • 1
    ECDH is what you would use for mutual authentication here. Use your own private key and the third-party's public key (The guy you want to encrypt and send a message to) to generate a "Shared secret key". Use the shared secret key for encrypting. See answer below. @StoryTeller hate to break it to you but you are wrong. Ctx is not pompous and is not making assertions, he is reiterating what years of research and individuals smarter than all of us here have proven to be true. – Kaleb Feb 24 '17 at 16:05
  • @comomind you said "I want to use an ECC private key for encryption because of mutual authentication" could you clarify for all of us here what you mean by "mutual authentication" and how you envision that encrypting with a private key would help to achieve this? Typically TLS or some other authentication protocol using certificates will provide authentication so I am curious what you have in mind. – Kaleb Feb 24 '17 at 16:26
  • @comomind, if you have any other questions or concerns on this topic wolfSSL provides active open-source and pre-sales support, you can always email them support@wolfssl.com or info@wolfssl.com for more in depth questions/feedback. – Kaleb Feb 28 '17 at 18:42

2 Answers2

2

To address the initial question "Is it possible to use ECC private key for encryption?"

Typically users maintain a private key and share their public key. The public key is mathematically entangled with the private key so messages encrypted with the public key can be decrypted with the private key. In this way the private key remains exactly that, private! It is not recommended to use a private key for encrypting ever. If you can justify your reason for wishing to do this by all means please explain. Happy to hear your reasoning. If however you are learning and just unsure then please avoid doing what you asked.

To address the statement about private key encryption for mutual authentication... I'm not sure how that will help to provide mutual authentication and I am genuinely curious what @comomind was talking about there. Here is a link about how SSL/TLS can solve the problem of mutual authentication: (https://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication)

For the second part of the question where wolfCrypt is concerned, the method (or function) in wolfSSL's wolfCrypt library is:

wc_ecc_encrypt

Here is the section from the manual describing this API and the arguments: (https://www.wolfssl.com/wolfSSL/Docs-wolfssl-manual-18-14-wolfcrypt-api-ecc.html)

wc_ecc_encrypt

Synopsis:

include header: wolfssl/wolfcrypt/ecc.h

int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx);

Description: This function encrypts the given input message from msg to out. This function takes an optional ctx object as parameter. When supplied, encryption proceeds based on the ecEncCtx's encAlgo, kdfAlgo, and macAlgo. If ctx is not supplied, processing completes with the default algorithms, ecAES_128_CBC, ecHKDF_SHA256 and ecHMAC_SHA256.

This function requires that the messages are padded according to the encryption type specified by ctx.

Return Values: 0: Returned upon successfully encrypting the input message BAD_FUNC_ARG: Returned if privKey, pubKey, msg, msgSz, out, or outSz are NULL, or the ctx object specifies an unsupported encryption type BAD_ENC_STATE_E: Returned if the ctx object given is in a state that is not appropriate for encryption BUFFER_E: Returned if the supplied output buffer is too small to store the encrypted ciphertext MEMORY_E: Returned if there is an error allocating memory for the shared secret key

Parameters: privKey - pointer to the ecc_key object containing the private key to use for encryption pubKey - pointer to the ecc_key object containing the public key of the peer with whom one wishes to communicate msg- pointer to the buffer holding the message to encrypt msgSz - size of the buffer to encrypt out - pointer to the buffer in which to store the encrypted ciphertext outSz - pointer to a word32 object containing the available size in the out buffer. Upon successfully encrypting the message, holds the number of bytes written to the output buffer ctx - Optional: pointer to an ecEncCtx object specifying different encryption algorithms to use

Example:

byte msg[] = { /* initialize with msg to encrypt. Ensure
padded to block size */ };
byte out[sizeof(msg)]; word32 outSz = sizeof(out);
int ret;
ecc_key cli, serv; // initialize cli with
private key // initialize serv with received public key

ecEncCtx* cliCtx, servCtx; // initialize cliCtx and servCtx //
exchange salts

ret = wc_ecc_encrypt(&cli, &serv, msg, sizeof(msg), out, &outSz,
cliCtx);

if(ret != 0) {  // error encrypting message  }

See Also: wc_ecc_decrypt

Notice this API takes in both a public and private key, where the public key came from the peer and the private key is your own private key. This API will then use ECDH to generate a shared secret. The shared secret is what should be used for encrypting and decrypting. The party you are trying to talk to will also take your public key and his private key to generate his own shared-secret key. The shared secret is never sent over the wire by either party. See more on the topic of shared secret here: (https://crypto.stackexchange.com/questions/21169/how-does-ecdh-arrive-on-a-shared-secret)

TEST CASE: (https://github.com/wolfSSL/wolfssl/blob/master/wolfcrypt/test/test.c#L8701)

#ifdef HAVE_ECC_ENCRYPT

int ecc_encrypt_test(void)
{
    WC_RNG  rng;
    int     ret;
    ecc_key userA, userB;
    byte    msg[48];
    byte    plain[48];
    byte    out[80];
    word32  outSz   = sizeof(out);
    word32  plainSz = sizeof(plain);
    int     i;

    ret = wc_InitRng(&rng);
    if (ret != 0)
        return -3001;

    wc_ecc_init(&userA);
    wc_ecc_init(&userB);

    ret  = wc_ecc_make_key(&rng, 32, &userA);
    ret += wc_ecc_make_key(&rng, 32, &userB);

    if (ret != 0)
        return -3002;

    for (i = 0; i < 48; i++)
        msg[i] = i;

    /* encrypt msg to send to userB */
    ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL);
    if (ret != 0)
        return -3003;

    /* userB decrypt the message received from userA */
    ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, NULL);
    if (ret != 0)
        return -3004;

    if (XMEMCMP(plain, msg, sizeof(msg)) != 0)
        return -3005;


    {  /* let's verify message exchange works, A is client, B is server */
        ecEncCtx* cliCtx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng);
        ecEncCtx* srvCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng);

        byte cliSalt[EXCHANGE_SALT_SZ];
        byte srvSalt[EXCHANGE_SALT_SZ];
        const byte* tmpSalt;

        if (cliCtx == NULL || srvCtx == NULL)
            return -3006;

        /* get salt to send to peer */
        tmpSalt = wc_ecc_ctx_get_own_salt(cliCtx);
        if (tmpSalt == NULL)
            return -3007;
        XMEMCPY(cliSalt, tmpSalt, EXCHANGE_SALT_SZ);

        tmpSalt = wc_ecc_ctx_get_own_salt(srvCtx);
        if (tmpSalt == NULL)
            return -3007;
        XMEMCPY(srvSalt, tmpSalt, EXCHANGE_SALT_SZ);

        /* in actual use, we'd get the peer's salt over the transport */
        ret  = wc_ecc_ctx_set_peer_salt(cliCtx, srvSalt);
        ret += wc_ecc_ctx_set_peer_salt(srvCtx, cliSalt);

        ret += wc_ecc_ctx_set_info(cliCtx, (byte*)"wolfSSL MSGE", 11);
        ret += wc_ecc_ctx_set_info(srvCtx, (byte*)"wolfSSL MSGE", 11);

        if (ret != 0)
            return -3008;

        /* get encrypted msg (request) to send to B */
        outSz  = sizeof(out);
        ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz,cliCtx);
        if (ret != 0)
            return -3009;

        /* B decrypts msg (request) from A */
        plainSz = sizeof(plain);
        ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, srvCtx);
        if (ret != 0)
            return -3010;

        if (XMEMCMP(plain, msg, sizeof(msg)) != 0)
            return -3011;

        {
            /* msg2 (response) from B to A */
            byte    msg2[48];
            byte    plain2[48];
            byte    out2[80];
            word32  outSz2   = sizeof(out2);
            word32  plainSz2 = sizeof(plain2);

            for (i = 0; i < 48; i++)
                msg2[i] = i+48;

            /* get encrypted msg (response) to send to B */
            ret = wc_ecc_encrypt(&userB, &userA, msg2, sizeof(msg2), out2,
                              &outSz2, srvCtx);
            if (ret != 0)
                return -3012;

            /* A decrypts msg (response) from B */
            ret = wc_ecc_decrypt(&userA, &userB, out2, outSz2, plain2, &plainSz2,
                             cliCtx);
            if (ret != 0)
                return -3013;

            if (XMEMCMP(plain2, msg2, sizeof(msg2)) != 0)
                return -3014;
        }

        /* cleanup */
        wc_ecc_ctx_free(srvCtx);
        wc_ecc_ctx_free(cliCtx);
    }

    /* cleanup */
    wc_ecc_free(&userB);
    wc_ecc_free(&userA);
    wc_FreeRng(&rng);

    return 0;
}

#endif /* HAVE_ECC_ENCRYPT */
Community
  • 1
  • 1
Kaleb
  • 591
  • 4
  • 17
2

I want to use an ECC private key for encryption because of mutual authentication. But I cannot find a method (or function) in wolfcrypt (wolfSSL) or the micro-ecc library.

There's a subtle difference in the definitions and operations. "Encrypting with the private key" is not a valid cryptographic operation. Usually what you want is a Signature Scheme with Recovery.

When libraries like OpenSSL or wolfSSL sign a message, they often apply a formatting function and then treat the resulting message as an instance of ciphertext. Then, the private key is used to decrypt the ciphertext.


Is is okay to use an (ECC) private key for encryption?

Probably not, but we need to hear more about what you want to do.

If you want help with designing the scheme, then you should probably visit Cryptography Stack Exchange or Information Security Stack Exchange.


[If its OK] And if so, how can I do this?

Again, it depends on what you are doing. At some point, you will need to treat a formatted message as an instance of ciphertext. I can't say anymore because I am not familiar with wolfSSL.

You might also be interested in Should we sign-then-encrypt, or encrypt-then-sign? on the Crypto.SE. It appears to have some intersection with what you are doing.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885