非对称加密
在我们认知里面,通常说到非对称加密,就会弹出2个词,RSA和ECC,做过对称加密的都非常清楚,RSA其实就是模指运算。用公钥来加密,私钥来解密;私钥签名,公钥验签。但是提到ECC的实际使用,很多人就摸不着头脑了,因为一般标准代码库里面,根本没有ECC加解密的词汇。
以下是golang代码库里面的加密,发现,大部分加密都有,就是缺了ECC,但是我们可以看到,有几个类似ECC的字样。
ECC的概念
其实,ECC只是个Elliptic Curve Cryptography,翻译过来就是椭圆曲率密码学,这里我们不深入理解里面的数学算法,只讲核心应用。
既然名字是个密码学,就是个概念的意思。里面最最核心的东西就是
A1 * B2 = B1 * A2
公式的理解
非对称加密,就是有公钥和私钥,我们假设秘钥对A,其中A1是私钥, A2是公钥。 秘钥对B,B1是私钥,B2是公钥。
那使用同一根曲线生成出来的2对不同的秘钥,始终都满足这个公式:A1 * B2 = B1 * A2
这里画个重点,“同一根曲线”。在生成公私钥时,选择的一条曲线。
我们以下面Golang的代码来讲解这个特性:
func TestEcdh(t *testing.T) {
curve := elliptic.P256()
pri1, x1, y1, _ := elliptic.GenerateKey(curve, rand.Reader) // 随机生成秘钥A, x1, y1 为公钥A2,pri1为私钥A1
pri2, x2, y2, _ := elliptic.GenerateKey(curve, rand.Reader) // 随机生成秘钥B, x2, y2 为公钥B2,pri2为私钥B1
ret1, ret11 := curve.ScalarMult(x1, y1, pri2) // B1 * A2
ret2, ret22 := curve.ScalarMult(x2, y2, pri1) // A1 * B2
fmt.Println("ret1:", ret1)
fmt.Println("ret2:", ret2)
fmt.Println("ret11:", ret11)
fmt.Println("ret22:", ret22)
}
// Run result
=== RUN TestEcdh
ret1: 26996158176686521373743015083149004542435294973837101268950353997964087993718
ret2: 26996158176686521373743015083149004542435294973837101268950353997964087993718
ret11: 50996642934285637232692495514710136619292820085348488595432751403713569264240
ret22: 50996642934285637232692495514710136619292820085348488595432751403713569264240
curve := elliptic.P256() // P384, P521
其实,这就是选择一根曲线,我们可以理解为RSA里面选择1024,2048,4096或者……
那利用这个特性,我们就可以client端和server端,同时各自生成一对秘钥A和B,然后互发公钥A2,那这样,2边拿到公钥后,和自己的私钥进行"乘法"运算,就能得到一个相同的值,利用这个相同的值,作为AES对称秘钥。后面的数据传输,就可以使用这个AES对称秘钥进行了。
所以,ECC更加算是用于秘钥交换,而不是个加密功能。
基于这个功能,实际的常见的使用场景有:
- TLS里面秘钥交换
- Applapy token解密
- 以太坊里面用到的Ecies加密