【问题标题】:Is it possible to use ECC private key for encryption? [closed]是否可以使用 ECC 私钥进行加密? [关闭]
【发布时间】:2017-02-23 12:19:41
【问题描述】:

由于相互身份验证,我想使用 ECC 私钥进行加密。 但我在 wolfcrypt (wolfSSL) 或 micro-ecc 库中找不到方法(或函数)。

可以使用 (ECC) 私钥进行加密吗? 如果是这样,我该怎么做?

【问题讨论】:

  • @StoryTeller 这是针对加密签名或类似事情所做的,并且对于“相互身份验证”似乎是合理的,如问题中所述
  • @StoryTeller 这很不寻常,你为什么要使用不同的密钥对呢?
  • @Ctx - 使用相同的密钥对签署您的消息并接收加密消息是让攻击者发现它们的好方法。
  • @StoryTeller 至少从密码学的角度来看,这种做法也不是常见的做法(即 pgp/gpg)
  • @comomind 不需要使用加密来实现认证。如果我们谈论私钥操作,我们的意思要么是解密密文,要么是签署明文。您应该edit您的问题,以明确您想要实现的目标。

标签: c encryption cryptography elliptic-curve wolfssl


【解决方案1】:

解决最初的问题“是否可以使用 ECC 私钥进行加密?”

通常用户会维护一个私钥并共享他们的公钥。公钥与私钥在数学上纠缠在一起,因此用公钥加密的消息可以用私钥解密。通过这种方式,私钥仍然是私有的!不建议使用私钥进行加密。如果您可以通过各种方式证明您希望这样做的理由,请解释。很高兴听到你的推理。但是,如果您正在学习并且不确定,请避免按照您的要求进行操作。

为了解决有关用于相互身份验证的私钥加密的声明......我不确定这将如何帮助提供相互身份验证,我真的很好奇 @comomind 在那里谈论什么。下面是一个关于 SSL/TLS 如何解决相互认证问题的链接: (https://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication)

关于wolfCrypt问题的第二部分,wolfSSL的wolfCrypt库中的方法(或函数)是:

wc_ecc_encrypt

这是手册中描述此 API 和参数的部分: (https://www.wolfssl.com/wolfSSL/Docs-wolfssl-manual-18-14-wolfcrypt-api-ecc.html)

wc_ecc_encrypt

简介:

包含头文件: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);

描述:此函数对来自 msg 的给定输入消息进行加密 出去。此函数将可选的 ctx 对象作为参数。什么时候 提供,加密基于 ecEncCtx 的 encAlgo 进行, kdfAlgo 和 macAlgo。如果未提供 ctx,则处理完成 使用默认算法 ecAES_128_CBC、ecHKDF_SHA256 和 ecHMAC_SHA256。

此功能要求消息根据 ctx 指定的加密类型。

返回值:0:成功加密输入后返回 消息 BAD_FUNC_ARG:如果 privKey、pubKey、msg、msgSz、out 或 outSz 为 NULL,或者 ctx 对象指定了不受支持的加密 type BAD_ENC_STATE_E:如果给定的 ctx 对象处于状态则返回 不适合加密 BUFFER_E:如果 提供的输出缓冲区太小,无法存储加密的密文 MEMORY_E:如果为 共享密钥

参数: privKey - 指向包含 用于加密的私钥 pubKey - 指向 ecc_key 的指针 对象包含一个希望与之建立对等点的公钥 将 msg- 指针传递给保存要加密的消息的缓冲区 msgSz - 要加密的缓冲区的大小 - 指向缓冲区的指针 用于存储加密密文 outSz - 指向 word32 的指针 包含输出缓冲区中可用大小的对象。之上 成功加密消息,保存写入的字节数 到输出缓冲区 ctx - 可选:指向 ecEncCtx 对象的指针 指定要使用的不同加密算法

例子:

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  }

另见:wc_ecc_decrypt

请注意,此 API 接受公钥和私钥,其中公钥来自对等方,私钥是您自己的私钥。然后,此 API 将使用 ECDH 生成共享密钥。共享密钥应该用于加密和解密。您尝试与之交谈的一方也将使用您的公钥和他的私钥来生成他自己的共享密钥。任何一方都不会通过网络发送共享的秘密。在此处查看有关共享机密主题的更多信息:(https://crypto.stackexchange.com/questions/21169/how-does-ecdh-arrive-on-a-shared-secret)

测试用例: (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 */

【讨论】:

    【解决方案2】:

    由于相互身份验证,我想使用 ECC 私钥进行加密。但我在 wolfcrypt (wolfSSL) 或 micro-ecc 库中找不到方法(或函数)。

    定义和操作存在细微差别。 “使用私钥加密”不是有效的加密操作。通常您需要的是具有恢复功能的签名方案

    当 OpenSSL 或 wolfSSL 等库对消息进行签名时,它们通常会应用格式化函数,然后将生成的消息视为密文实例。然后用私钥解密密文。


    是否可以使用 (ECC) 私钥进行加密?

    可能不会,但我们需要了解更多关于您想要做什么的信息。

    如果您在设计方案方面需要帮助,那么您应该访问Cryptography Stack ExchangeInformation Security Stack Exchange


    [如果没问题]如果是这样,我该怎么做?

    同样,这取决于您在做什么。在某些时候,您需要将格式化的消息视为密文的一个实例。我不能再说了,因为我对 wolfSSL 不熟悉。

    您可能还对 Crypto.SE 上的 Should we sign-then-encrypt, or encrypt-then-sign? 感兴趣。它似乎与你正在做的事情有一些交集。

    【讨论】:

      猜你喜欢
      • 2011-06-04
      • 2010-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-08
      • 1970-01-01
      • 2017-03-12
      相关资源
      最近更新 更多