由于相互身份验证,我想使用 ECC 私钥进行加密。但是我在 wolfcrypt (wolfSSL) 或 micro-ecc 库中找不到方法(或函数)。
可以使用(ECC)私钥进行加密吗?如果是这样,我该怎么做?
由于相互身份验证,我想使用 ECC 私钥进行加密。但是我在 wolfcrypt (wolfSSL) 或 micro-ecc 库中找不到方法(或函数)。
可以使用(ECC)私钥进行加密吗?如果是这样,我该怎么做?
由于相互身份验证,我想使用 ECC 私钥进行加密。但是我在 wolfcrypt (wolfSSL) 或 micro-ecc 库中找不到方法(或函数)。
定义和操作存在细微差别。“使用私钥加密”不是有效的加密操作。通常你想要的是一个带有 Recovery 的签名方案。
当 OpenSSL 或 wolfSSL 等库对消息进行签名时,它们通常会应用格式化函数,然后将生成的消息视为密文的实例。然后,使用私钥对密文进行解密。
可以使用(ECC)私钥进行加密吗?
可能不会,但我们需要更多地了解您想要做什么。
如果您在设计方案方面需要帮助,那么您可能应该访问Cryptography Stack Exchange或Information Security Stack Exchange。
[如果没问题] 如果是这样,我该怎么做?
同样,这取决于你在做什么。在某些时候,您需要将格式化的消息视为密文的一个实例。我不能再说了,因为我不熟悉 wolfSSL。
您可能还对我们应该先签名后加密还是先加密后签名感兴趣?在 Crypto.SE 上。它似乎与你正在做的事情有一些交集。
解决最初的问题“是否可以使用 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 加密到 out。此函数将可选的 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 对象指定了不支持的加密类型,则返回 BAD_ENC_STATE_E:如果给定的 ctx 对象在不适合加密的状态 BUFFER_E:如果提供的输出缓冲区太小而无法存储加密的密文,则返回 MEMORY_E:如果为共享密钥分配内存时出错,则返回
参数: privKey - 指向包含用于加密的私钥的 ecc_key 对象的指针 pubKey - 指向包含希望与之通信的对等方的公钥的 ecc_key 对象的指针 msg- 指向保存要加密的消息的缓冲区的指针 msgSz -要加密的缓冲区的大小 out - 指向存储加密密文的缓冲区的指针 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 */