C#与ECDH实现

本文最后更新于$day天前,文中所描述的信息可能已发生改变。

ECC算法和DH结合使用,用于密钥磋商,这个密钥交换算法称为ECDH。交换双方可以在不共享任何秘密的情况下协商出一个密钥。ECC是建立在基于椭圆曲线的离散对数问题上的密码体制,给定椭圆曲线上的一个点P,一个整数k,求解Q=kP很容易;给定一个点P、Q,知道Q=kP,求整数k确是一个难题。ECDH即建立在此数学难题之上。

ECDH是一个密钥交换算法,常用在微信、QQ协议上。微信的椭圆曲线是 713( secp224r1 ),而QQ是711(secp192k1)。

经过研究这个算法可以防止中间人攻击,是一个不错的方法。但是,如果能把协议了解透彻,我相信,也可以模拟中间人进行攻击的(参考如何抓取Https封包),但是对于协议不明的协议,能起到一个非常棒的效果。

http://www-cs-students.stanford.edu/~tjw/jsbn/ecdh.html

上面是一个ECDH JS算法实现的Demo,通过操作,可以很直观了解到。 Alice、 Bob 从生成私钥、到发送公钥,到通过私钥和对方公钥协商出 secret key 的过程。

C#实现

ECDH 有各种椭圆曲线,但是和Java支持的椭圆曲线不一样。What The F?我在UWP Windows.Security.Cryptography.Core 里面找到其他椭圆算法选项,但是不支持Windows From啊?!

①、原生实现

C#实现ECDH有几个类

ECDiffieHellman
ECDiffieHellmanCng

本来搜到一个叫 ECDiffieHellmanOpenSsl 的类,但是上面写着一句话

Provides cryptographic algorithm implementations and key management for non-Windows systems with OpenSSL.

原来也不支持Windows平台,所以方法比较好只有第三项。

原生只支持几个椭圆算法,不支持 secp224r1 等。所以很郁闷,于是我找了IBM文档和几个英文文档。 https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.gska100/ecsup.htm http://csharpforwindesk.blogspot.com/2018/02/c-ecdsa-common-curve-between-openssl-c.html

可以通过指定ECCurve来指定算法(未测试)

ECDiffieHellman 的使用方法和我上篇RSA使用方法差不多。所以不再重复。

②、借助OpenSSLNativeClass.dll

这个方法我认为挺简单,2个函数,就完事。但是需要依赖libeay32.dll和C++库(版本不明)否则会直接运行报错。

OpenSSLNativeClass.ECDH.GenEcdh(713, ref pub_key_buf, ref pri_key_buf); //生成一个公钥和私钥
OpenSSLNativeClass.ECDH.DoEcdh(ManualAuth.authParam.ecdh.nid, strECServrPubKey, pri_key_buf); 利用对方的公钥和自己的私密钥产生共享密钥。

③、借助BouncyCastle

BouncyCastle 适用于Java和C#的轻量级加密API。 所以和Java加密是同步的,但是我没测试过。所以只提出方法。

④、借助OpenCrypto.net

GitHub项目 https://github.com/kazuki/opencrypto.net 里面有方法实现,暂时没研究先记录。