【发布时间】:2015-01-17 22:57:02
【问题描述】:
我正在使用 OpenSSL 库进行 BIGNUM 操作的嵌入式设备和使用 System.Numerics.BigInteger 方法计算秘密共享密钥生成的 C# 软件之间实现 Diffie-Hellman 密钥交换算法。
但是在 Alice 和 Bob 交换密钥之后,他们计算出不同的共享秘密。
每边都打印出密钥(PubA, PrivA, PubB, PrivB, DHPrime, DHGenerator),我可以看到它们是相同的。
我怀疑存在关于小/大字节序的问题,或者 openssl 不关心指数的负数,我不知道如何调试这些操作。我现在没有代码,但所有操作都保持简单,就像这样。
C#端
BigInteger bintA = new BigInteger(baByteArrayReceived);
BigInteger bintb = new BigInteger(baRandomBobSecret);
BigInteger bintDHPrime = new BigInteger(baDHPrime2048);
BigInteger bintSharedSecret = bintA.ModPow(bintb,bintDHPrime);
C端
BIGNUM *bnB = BN_new();
BIGNUM *bna = BN_new();
BIGNUM *bnDHPrime = BN_new();
BIGNUM *bnResult = BN_new();
BN_CTX *bnctx = BN_CTX_new();
BN_bin2bn(baBReceived, 256,bnB);
BN_bin2bn(baRandomAliceSecret, 256,bna);
BN_bin2bn(baDHPrime2048, 256,bnDHPrime);
BN_mod_exp(bnResult,bnB,bna,bnDHPrime,bnctx);
OpenSSL 的 C 方法的一些附加信息: >
BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret);BN_bin2bn 集|*ret|到 |len| 的值来自|in| 的字节,解释为大端数,并返回|ret|。如果 |ret|为 NULL 则为新的 |BIGNUM|被分配并返回。它在分配失败时返回 NULL。
int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx);BN_mod_exp 集|r|等于 |a|^{|p|} mod |m|。它使用提供的值的最佳算法来执行此操作,并且如果 |BN_FLG_CONSTTIME| 可以在恒定时间内运行设置为 |p|。成功则返回 1,否则返回 0。
它们会产生不同的结果。
我该怎么办?你接下来要检查什么?
提前致谢。
【问题讨论】:
-
如果这只是 C# 开发(使用 OpenSSL 验证结果),那么您应该转到 Crypto++。它更清洁,更易于使用。 C++ 中的运算符重载使得做大数学变得非常容易(根据经验)。
-
通常您使用公钥和私钥部分。因此,对于未经身份验证的 DH (ephemeral-ephemeral),有六个对象在起作用:
pubA、privA、sharedA、pubB、privB、sharedB。看起来你缺少一些片段。经过身份验证的 DH(临时静态)为 A 和 B 添加了长期密钥,因此还有四个似乎丢失了。 -
“我正在嵌入式设备之间实现 Diffie-Hellman 密钥交换算法...” - 对于低功耗、资源受限的设备,您通常避免使用 DH,因为它太昂贵了。在这种情况下,通常使用预共享密钥协议,例如预共享密钥 (PSK)。 PSK 是Password Authenticated Key Exchange (PAKE)。安全远程密码 (SRP) 是另一个 PAKE,但它的根本问题是 Diffie-Hellman(您通常会避免)。
-
@jww,我们可以访问双方的代码级别,但是在这些设备之间应用 diffie-hellman 是必须的,我们没有决定。这使得 openssl(也用于嵌入式端的其他部分)对我们来说更加重要。问题是,当输入相同时,我们如何确保双方计算相同?
标签: c# c openssl biginteger diffie-hellman