打印

一个ECC加密算法的使用范例

[复制链接]
1381|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
keer_zu|  楼主 | 2022-5-17 22:01 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
沙发
keer_zu|  楼主 | 2022-5-17 22:09 | 只看该作者
准备知识:非对称加密和对称加密的区别
在了解对称加密和非对称加密的区别之前我们先了解一下它们的定义:

对称加密(Symmetric Cryptography),又称私钥加密
对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key),这种方法在密码学中叫做对称加密算法。对称加密有很多种算法,由于它效率很高,所以被广泛使用在很多加密协议的核心当中。对称加密通常使用的是相对较小的密钥,一般小于256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。如果你只用1 bit来做这个密钥,那黑客们可以先试着用0来解密,不行的话就再用1解;但如果你的密钥有1 MB大,黑客们可能永远也无法**,但加密和解密的过程要花费很长的时间。密钥的大小既要照顾到安全性,也要照顾到效率,是一个trade-off。

非对称加密(Asymmetric Cryptography),又称公钥加密
1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。相对于“对称加密算法”这种方法也叫做“非对称加密算法”。非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。比如,你向银行请求公钥,银行将公钥发给你,你使用公钥对消息加密,那么只有私钥的持有人--银行才能对你的消息解密。与对称加密不同的是,银行不需要将私钥通过网络发送出去,因此安全性大大提高。

下面说一下这两种方式的使用
对称密钥加密我们从定义中应该就可以明白,它是信息的发送方和接收方都用同一个秘钥去加密和解密数据。这样做它的最大优势是加/解密速度快,适合于对大数据量进行密,但密钥管理困难。

非对称密钥加密,它需要使用“一对”密钥来分别完成加密和解密操作,一个公开发布,即公开密钥,另一个由用户自己秘密保存,即私用密钥。信息发送者用公开密钥去加密,而信息接收者则用私用密钥去解密。公钥机制灵活,但加密和解密速度却比对称密钥加密慢得多。
非对称密钥加密的使用过程:
1. A要向B发送信息,A和B都要产生一对用于加密和解密的公钥和私钥。
2. A的私钥保密,A的公钥告诉B;B的私钥保密,B的公钥告诉A。
3. A要给B发送信息时,A用B的公钥加密信息,因为A知道B的公钥。
4. A将这个消息发给B(已经用B的公钥加密消息)。
5. B收到这个消息后,B用自己的私钥解密A的消息,其他所有收到这个报文的人都无法解密,因为只有B才有B的私钥。
6. 反过来,B向A发送消息也是一样。

从上面大家应该可以看出对称加密和非对称加密的区别,下面稍微进行一下总结:

(1) 对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以安全性不高。
(2) 非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。
(3) 解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。

标红色的地方是重点,这是目前在通信方面最安全的做法。




使用特权

评论回复
板凳
keer_zu|  楼主 | 2022-5-17 22:22 | 只看该作者
准备知识:ECC (一)

前言
ECC英文全称"Ellipse Curve Cryptography"
与传统的基于大质数因子分解困难性的加密方法不同,ECC通过椭圆曲线方程式的性质产生密钥
ECC164位的密钥产生一个安全级,相当于RSA 1024位密钥提供的保密强度,而且计算量较小,处理速度更快,存储空间和传输带宽占用较少。目前我国居民二代身份*正在使用 256 位的椭圆曲线密码,虚拟货币比特币也选择ECC作为加密算法。
从射影平面讲起
古希腊数学家欧几里得的《几何原本》提出了五条公设。
  • 1.由任意一点到任意一点可作直线。
  • 2.一条有限直线可以继续延长。
  • 3.以任意点为心及任意的距离可以画圆。
  • 4.凡直角都相等。
  • 5.同一平面内一条直线a和另外两条直线b.c相交,若在a某一侧的两个内角的和小于两直角,则b.c两直线经无限延长后在该侧相交。


《几何原本》只有在第29个命题
一条直线与两条平行直线相交,则所成的内错角相等,同位角相等,且同旁内角之和等于两直角
中才用到第五公设,即《几何原本》中可不依靠第五公设而推出前28命题。因此,一些数学家提出,第五公设能不能不作为公设,而作为定理?能不能依靠前四个公设来证明第五公设?这就是几何发展史上最著名的,争论了长达两千多年的关于“平行线理论”的讨论
1820年代,俄国喀山大学罗巴切夫斯基用“至少可以找到两条相异的直线,且都通过P点,并不与直线R相交”代替第五公设,然后与欧氏几何的前四个公设结合成一个公理系统,他经过细致深入的推理过程中,得出了一个又一个在直觉上匪夷所思,但在逻辑上毫无矛盾的几何体系。
这种几何学被称为罗巴切夫斯基几何,简称罗氏几何。从罗氏几何学中,可以得出这样一个结论:逻辑上不矛盾的一些公理都有可能提供一种几何学。现存非欧几何的类型可以概括如下:
1.坚持第五公设,引出欧几里得几何。
2.“可以引最少两条平行线”为公设,罗氏几何(双曲几何)。
3.“一条平行线也不能引”为公设,黎曼几何(椭圆几何)


左:双曲几何,即罗氏几何;中:欧几里德几何;右:椭圆几何,即黎曼几何

了解非欧式几何,就可以理解平行线的交点。
定义平行线相交于无穷远点P∞,使平面上所有直线都统一为有唯一的交点
性质:
  • 1.一条直线只有一个无穷远点;一对平行线有公共的无穷远点
  • 2.任何两条不平行的直线有不同的无穷远点(否则会造成有两个交点)
  • 3.平面上全体无穷远点构成一条无穷远直线


射影平面:平面上全体无穷远点与全体平常点构成射影平面
射影平面点的定义
对普通平面上点(x,y),令x=X/Z,y=Y/Z,Z≠0,则投影为射影平面上的点(X:Y:Z)
求点(1,2)在新的坐标体系下的坐标
∵X/Z=1 ,Y/Z=2(Z≠0)
∴X=Z,Y=2Z ∴坐标为(Z:2Z:Z),Z≠0
即(1:2:1)(2:4:2)(1.2:2.4:1.2)等形如(Z:2Z:Z),Z≠0的坐标都是(1,2)在新的坐标体系下的坐标
(2) 求平行线L1:X+2Y+3Z=0 与L2:X+2Y+Z=0 相交的无穷远点
∵ L1∥L2 所以有Z=0, X+2Y=0
∴坐标为(-2Y:Y:0),Y≠0
即(-2:1:0)(-4:2:0)(-2.4:1.2:0)等形如(-2Y:Y:0),Y≠0

469556283ad350726b.png (9.59 KB )

469556283ad350726b.png

812036283af90766e7.png (22.85 KB )

812036283af90766e7.png

90716283afa993ef3.png (62.99 KB )

90716283afa993ef3.png

1180694-20170818223309475-680292287.png (13.9 KB )

1180694-20170818223309475-680292287.png

使用特权

评论回复
地板
keer_zu|  楼主 | 2022-5-17 22:27 | 只看该作者
准备知识:ECC (二)


椭圆曲线
一条椭圆曲线是在射影平面上满足威尔斯特拉斯方程(Weierstrass)所有点的集合


  • 1椭圆曲线方程是一个齐次方程
  • 2曲线上的每个点都必须是非奇异的(光滑的),偏导数FX(X,Y,Z)、FY(X,Y,Z)、FZ(X,Y,Z)不同为0
  • 3圆曲线的形状,并不是椭圆的。只是因为椭圆曲线的描述方程,类似于计算一个椭圆周长的方程故得名




椭圆曲线示例



非椭圆曲线示例


这两个方程都不是椭圆曲线,因为他们在(0:0:1)点处(即原点)没有切线,不满足椭圆曲线每个点都必须是非奇异的(光滑的),
椭圆曲线普通方程
椭圆曲线普通方程:

无穷远点 (0, Y, 0)
平常点(x,y)斜率k:




使用特权

评论回复
5
keer_zu|  楼主 | 2022-5-17 22:28 | 只看该作者
准备知识:ECC (三)


椭圆曲线阿贝尔群
我们已经看到了椭圆曲线的图象,但点与点之间好象没有什么联系。我们能不能建立一个类似于在实数轴上加法的运算法则呢?这就要定义椭圆曲线的加法群,这里需要用到近世代数中阿贝尔群。
在数学中,群是一种代数结构,由一个集合以及一个二元运算所组成。已知集合和运算(G,*)如果是群则必须满足如下要求
  • 封闭性:∀a,b∈G,a*b ∈ G
  • 结合性: ∀a,b,c∈G ,有 (ab)c = a* (b*c)
  • 单位元:ョe∈G, ∀a ∈G,有ea = ae = a
  • 逆元: ∀a ∈G ,ョb∈G 使得 ab = ba = e

阿贝尔群除了上面的性质还满足交换律公理a * b = b * a
同样在椭圆曲线也可以定义阿贝尔群。
任意取椭圆曲线上两点P、Q(若P、Q两点重合,则作P点的切线),作直线交于椭圆曲线的另一点R',过R'做y轴的平行线交于R,定义P+Q=R。这样,加法的和也在椭圆曲线上,并同样具备加法的交换律、结合律



同点加法
若有k个相同的点P相加,记作kP
P+P+P=2P+P=3P



使用特权

评论回复
6
keer_zu|  楼主 | 2022-5-17 22:31 | 只看该作者
准备知识:ECC (四)

有限域椭圆曲线
椭圆曲线是连续的,并不适合用于加密;所以,我们必须把椭圆曲线变成离散的点,我们要把椭圆曲线定义在有限域上。
我们给出一个有限域Fp
  • Fp中有p(p为质数)个元素0,1,2,…, p-2,p-1
  • Fp的加法是a+b≡c(mod p)
  • Fp的乘法是a×b≡c(mod p)
  • Fp的除法是a÷b≡c(mod p),即 a×b^(-1)≡c (mod p),b-1也是一个0到p-1之间的整数,但满足b×b-1≡1 (mod p)
  • Fp的单位元是1,零元是 0
  • Fp域内运算满足交换律、结合律、分配律

椭圆曲线Ep(a,b),p为质数,x,y∈[0,p-1]


选择两个满足下列约束条件的小于p的非负整数a、b



Fp上的椭圆曲线同样有加法
  • 1.无穷远点 O∞是零元,有O∞+ O∞= O∞,O∞+P=P
  • 2.P(x,y)的负元是 (x,-y mod p)= (x,p-y) ,有P+(-P)= O∞
  • 3.P(x1,y1),Q(x2,y2)的和R(x3,y3) 有如下关系:

x3≡k2-x1-x2(mod p)
y3≡k(x1-x3)-y1(mod p)
若P=Q 则 k=(3x2+a)/2y1mod p
若P≠Q,则k=(y2-y1)/(x2-x1) mod p
例题椭圆曲线已知E23(1,1)上两点P(3,10),Q(9,7),求(1)-P,(2)P+Q,(3) 2P


补充:
-2^(-1) mod 23 进行两部分计算
(1) 先算 2^(-1) 对应的数A, 在这里2^(-1)不是2的-1次方,而是2的逆元
(2) 再算-A mod 23
(1) 计算第一步
根据有限域除法规则 2 * 2^(-1) = 1 mod 23
即 2A = 1 mod 23 ==> 2A = 23 + 1 == > A = 12
(2) 计算第二步
-A mod 23 ==> -12 mod 23 即 23 -12 = 11
所以有
-2^(-1) mod 23 = 11
有限域椭圆曲线点的阶
如果椭圆曲线上一点P,存在最小的正整数n使得数乘nP=O∞ ,则将n称为P的阶
若n不存在,则P是无限阶的

计算可得27P=-P=(3,13)
所以28P=O ∞ P的阶为28
这些点做成了一个循环阿贝尔群,其中生成元为P,阶数为29。显然点的分布与顺序都是杂乱无章






使用特权

评论回复
7
keer_zu|  楼主 | 2022-5-17 22:32 | 只看该作者
准备知识:ECC (五)


椭圆曲线加密
考虑K=kG ,其中K、G为椭圆曲线Ep(a,b)上的点,n为G的阶(nG=O∞ ),k为小于n的整数。则给定k和G,根据加法法则,计算K很容易但反过来,给定K和G,求k就非常困难。因为实际使用中的ECC原则上把p取得相当大,n也相当大,要把n个解点逐一算出来列成上表是不可能的。这就是椭圆曲线加密算法的数学依据
点G称为基点(base point)
k(k<n)为私有密钥(privte key)
K为公开密钥(public key)
ECC保密通信算法
  • 1.Alice选定一条椭圆曲线E,并取椭圆曲线上一点作为基点G 假设选定E29(4,20),基点G(13,23) , 基点G的阶数n=37
  • 2.Alice选择一个私有密钥p(p<n),并生成公开密钥K=pG 比如25, K= pG = 25G = (14,6)
  • 3.Alice将E和点K、G传给Bob
  • 4.Bob收到信息后,将待传输的明文编码到上的一点M(编码方法略),并产生一个随机整数r(r<n,n为G的阶数) 假设r=6 要加密的信息为3,因为M也要在E29(4,20) 所以M=(3,28)
  • 5.Bob计算点C1=M+rK和C2=rG C1= M+6K = (3,28)+6*(14,6)=(3,28)+(27,27)=(6,12) C2= 6G =(5,7)
  • 6.Bob将C1、C2传给Alice
  • 7.Alice收到信息后,计算C1-kC2,结果就应该是点M C1-kC2 =(6,12)-25C2 =(6,12)-25*6G =(6,12)-2G =(6,12)-(27,27) =(6,12)+(27,2) =(3,28)

数学原来上能解密是因为:C1-kC2=M+rK-krG=M+rkG-krG-M
ECC技术要求
通常将Fp上的一条椭圆曲线描述为T=(p,a,b,G,n,h)p、a、b确定一条椭圆曲线(p为质数,(mod p)运算)G为基点,n为点G的阶,h是椭圆曲线上所有点的个数m与n相除的商的整数部分
参量选择要求:
  • p越大安全性越好,但会导致计算速度变慢
  • 200-bit左右可满足一般安全要求
  • n应为质数
  • h≤4;p≠n×h ;pt≠1(mod n) (1≤t<20)
  • 4a3+27b2≠0 (mod p)
ECC的应用
比特币系统选用的secp256k1中,参数为
p = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F = 2^256 − 2^32 − 2^9 − 2^8 − 2^7 − 2^6 − 2^4 − 1
a = 0, b = 7
G=(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798, 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8)
n = 0xFFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
h = 01
ECC vs. RSA - 优缺点
优点
  • 安全性能更高
  • 160位ECC与1024位RSA、DSA有相同的安全强度
  • 处理速度更快
  • 在私钥的处理速度上,ECC远 比RSA、DSA快得多
  • 带宽要求更低
  • 存储空间更小
  • ECC的密钥尺寸和系统参数与RSA、DSA相比要小得多

缺点
  • 设计困难,实现复杂
  • 如果序列号设计过短,那么安全性并没有想象中的完善


使用特权

评论回复
8
keer_zu|  楼主 | 2022-5-17 22:34 | 只看该作者
ECC+AES
Bob给Alice发消息,Bob用AES密钥mB加密消息得到密文M,用Alice的公钥PA加密AES的密钥mB得到mB',将M和mB'发给Alice,Alice拿到后用自己的私钥解密mB'得到mB,再用mB解密M得到明文。
为什么不能直接用ECC进行非对称加密,要用ECC加密AES的密钥?
如果单独使用AES,没有经过加密的密钥不方便传递,很容易在传输中被截获。
如果单独使用ECC,非对称加密的速度慢、加密效率低。
因此对称与非对称加密结合可以兼顾效率和安全性,也在微信等成熟通讯软件中被广泛使用。




使用特权

评论回复
9
keer_zu|  楼主 | 2022-5-17 22:37 | 只看该作者
代码
ECC椭圆曲线加密算法目前的应用还不是很成熟,crypto-js中没有应用ECC的加密函数。
通过npm搜索eccrypto会找到一些由个人发布的package,大多涉及JavaScript中的Promise对象,不熟悉的小伙伴可以先了解一下Promise。
我选择了使用eccrypto-js(www.npmjs.com),这个package包含了实现AES和ECC的函数,且参数类型都是buffer,如果不能同时包含就要import不同的package,参数类型等可能不兼容,会带来一些麻烦。
该示例是前端加解密的示例,在实际应用中适用于端对端加密,不涉及服务器的加解密。
由于**只能给出一个加密示例,没有具体的通讯接口,所以我就用注释Alice来表示Alice端,Bob来表示Bob端,并模拟Alice向Bob通讯的过程,Bob向Alice通讯就是反向过程,不多赘述。加解密得到的信息输出到控制台中。
PS:
1.在代码中,ECC的公私钥和AES的密钥都是随机产生的,实际生产中私钥通常和钱包或者账户关联。
2.加解密和通讯过程中都是使用buffer类型,在控制台显示时注意转换成string。

import * as eccryptoJS from 'eccrypto-js'
//加解密函数的参数都是buffer类

//Alice
//一个新的随机的32字节私钥,私钥对应的未压缩(65字节)公钥。
const keyPairA = eccryptoJS.generateKeyPair();
console.info("privateKey:", keyPairA.privateKey);
console.info("publicKey:", keyPairA.publicKey);
//send publicKey to Bob

//Bob
//随机生成AES的密钥
const AESKey = eccryptoJS.randomBytes(32);
console.info("AESKey:", AESKey);
const iv = eccryptoJS.randomBytes(16);

//用ECC加密AES密钥
const EncryptedAESKey = await eccryptoJS.encrypt(keyPairA.publicKey, AESKey);
console.info("EncryptedAESKey:", EncryptedAESKey);

//待发送的明文str,先转成buffer格式
const str = 'test message to encrypt';
const msg = eccryptoJS.utf8ToBuffer(str);

//用未加密的AES密钥加密明文
const ciphertext = await eccryptoJS.aesCbcEncrypt(iv, AESKey, msg);
console.info("ciphertext:", ciphertext);
//send 密文encrypt_str and AESKeyEncrypt to Alice,iv?

//Alice
//用私钥解密加密后的AES密钥
const DecryptedAESKey = await eccryptoJS.decrypt(keyPairA.privateKey, EncryptedAESKey);
console.info("decryptedAESKey:", DecryptedAESKey);
//用AES密钥解密明文
const decrypted = await eccryptoJS.aesCbcDecrypt(iv, DecryptedAESKey, ciphertext);
console.info("decrypted:", decrypted.toString());







使用特权

评论回复
10
keer_zu|  楼主 | 2022-5-18 00:20 | 只看该作者
椭圆曲线加解密算法原理建立基于椭圆曲线的加密机制,需要找到类似RSA质因子分解或其他求离散对数这样的难题。而椭圆曲线上的已知G和xG求x,是非常困难的,此即为椭圆曲线上的的离散对数问题。此处x即为私钥,xG即为公钥。
椭圆曲线加密算法原理如下:
设私钥、公钥分别为k、K,即K = kG,其中G为G点。
公钥加密:  选择随机数r,将消息M生成密文C,该密文是一个点对,即:  C = {rG, M+rK},其中K为公钥
私钥解密:  M + rK - k(rG) = M + r(kG) - k(rG) = M  其中k、K分别为私钥、公钥。
椭圆曲线签名算法原理椭圆曲线签名算法,即ECDSA。  设私钥、公钥分别为k、K,即K = kG,其中G为G点。
私钥签名:  1、选择随机数r,计算点rG(x, y)。  2、根据随机数r、消息M的哈希h、私钥k,计算s = (h + kx)/r。  3、将消息M、和签名{rG, s}发给接收方。
公钥验证签名:  1、接收方收到消息M、以及签名{rG=(x,y), s}。  2、根据消息求哈希h。  3、使用发送方公钥K计算:hG/s + xK/s,并与rG比较,如相等即验签成功。
原理如下:  hG/s + xK/s = hG/s + x(kG)/s = (h+xk)G/s  = r(h+xk)G / (h+kx) = rG
签名过程假设要签名的消息是一个字符串:“Hello World!”。DSA签名的第一个步骤是对待签名的消息生成一个消息摘要。不同的签名算法使用不同的消息摘要算法。而ECDSA256使用SHA256生成256比特的摘要。
摘要生成结束后,应用签名算法对摘要进行签名:
产生一个随机数k
利用随机数k,计算出两个大数r和s。将r和s拼在一起就构成了对消息摘要的签名。
这里需要注意的是,因为随机数k的存在,对于同一条消息,使用同一个算法,产生的签名是不一样的。从函数的角度来理解,签名函数对同样的输入会产生不同的输出。因为函数内部会将随机值混入签名的过程。
验证过程关于验证过程,这里不讨论它的算法细节。从宏观上看,消息的接收方从签名中分离出r和s,然后利用公开的密钥信息和s计算出r。如果计算出的r和接收到的r值相同,则表示验证成功。否则,表示验证失败。


    package main
   
    import (
        "fmt"
        "crypto/ecdsa"
        "crypto/elliptic"
        "crypto/rand"
        "crypto/sha256"
        "math/big"
    )
   
    func main() {
        //明文
        message := []byte("Hello world")
        
        key, err := NewSigningKey()
        if err != nil {
            return
        }
   
        signature, err := Sign(message, key)
   
        fmt.Printf("签名后:%x\n", signature)
        if err != nil {
            return
        }
   
        if !Verify(message, signature, &key.PublicKey) {
            fmt.Println("验证失败!")
            return
        }else{
            fmt.Println("验证成功!")
        }
    }
   
    func NewSigningKey() (*ecdsa.PrivateKey, error) {
        key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
        return key, err
    }
   
    // Sign signs arbitrary data using ECDSA.
    func Sign(data []byte, privkey *ecdsa.PrivateKey) ([]byte, error) {
        // hash message
        digest := sha256.Sum256(data)
   
        // sign the hash
        r, s, err := ecdsa.Sign(rand.Reader, privkey, digest[:])
        if err != nil {
            return nil, err
        }
   
        // encode the signature {R, S}
        // big.Int.Bytes() will need padding in the case of leading zero bytes
        params := privkey.Curve.Params()
        curveOrderByteSize := params.P.BitLen() / 8
        rBytes, sBytes := r.Bytes(), s.Bytes()
        signature := make([]byte, curveOrderByteSize*2)
        copy(signature[curveOrderByteSize-len(rBytes):], rBytes)
        copy(signature[curveOrderByteSize*2-len(sBytes):], sBytes)
   
        return signature, nil
    }
   
    // Verify checks a raw ECDSA signature.
    // Returns true if it's valid and false if not.
    func Verify(data, signature []byte, pubkey *ecdsa.PublicKey) bool {
        // hash message
        digest := sha256.Sum256(data)
   
        curveOrderByteSize := pubkey.Curve.Params().P.BitLen() / 8
   
        r, s := new(big.Int), new(big.Int)
        r.SetBytes(signature[:curveOrderByteSize])
        s.SetBytes(signature[curveOrderByteSize:])
   
        return ecdsa.Verify(pubkey, digest[:], r, s)
    }



使用特权

评论回复
11
chunyang| | 2022-5-31 16:49 | 只看该作者
不错,多多滴点赞!

使用特权

评论回复
12
keer_zu|  楼主 | 2022-6-2 23:08 | 只看该作者

使用特权

评论回复
13
keer_zu|  楼主 | 2022-6-2 23:10 | 只看该作者
chunyang 发表于 2022-5-31 16:49
不错,多多滴点赞!

test_ecdh.c

/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */

#include "uECC.h"

#include <stdio.h>
#include <string.h>
#include <n32g45x_rng.h>
#include <sys/time.h>

uint64_t getTimeMs()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}


void vli_print(uint8_t *vli, unsigned int size) {
    for(unsigned i=0; i<size; ++i) {
        printf("%02X ", (unsigned)vli[i]);
    }
}

int ecc_rng(uint8_t *dest,unsigned size)
{
        return (int)GetTrueRand_U32((uint32_t *)dest, size/4);
}

int TestEcdh() {
    int i, c;
    uint8_t private1[32] = {0};
    uint8_t private2[32] = {0};
    uint8_t public1[64] = {0};
    uint8_t public2[64] = {0};
    uint8_t secret1[32] = {0};
    uint8_t secret2[32] = {0};
        uECC_set_rng(ecc_rng);
   
    const struct uECC_Curve_t * curves[5];
    int num_curves = 0;
#if uECC_SUPPORTS_secp160r1
    curves[num_curves++] = uECC_secp160r1();
#endif
#if uECC_SUPPORTS_secp192r1
    curves[num_curves++] = uECC_secp192r1();
#endif
#if uECC_SUPPORTS_secp224r1
    curves[num_curves++] = uECC_secp224r1();
#endif
#if uECC_SUPPORTS_secp256r1
    curves[num_curves++] = uECC_secp256r1();
#endif
#if uECC_SUPPORTS_secp256k1
    curves[num_curves++] = uECC_secp256k1();
#endif
   
    printf("Testing 256 random private key pairs\n");

    for (c = 0; c < num_curves; ++c) {
        for (i = 0; i < 256; ++i) {
            printf(".");
            fflush(stdout);
                        getTimeMs();
            if (!uECC_make_key(public1, private1, curves[c]) ||
                !uECC_make_key(public2, private2, curves[c])) {
                printf("uECC_make_key() failed\n");
                return 1;
            }
                        getTimeMs();

                        printf("1===============\n\n");

            if (!uECC_shared_secret(public2, private1, secret1, curves[c])) {
                printf("shared_secret() failed (1)\n");
                return 1;
            }
                        getTimeMs();
            if (!uECC_shared_secret(public1, private2, secret2, curves[c])) {
                printf("shared_secret() failed (2)\n");
                return 1;
            }
                getTimeMs();
                        printf("2===============\n\n");
            if (memcmp(secret1, secret2, sizeof(secret1)) != 0) {
                printf("Shared secrets are not identical!\n");
                printf("Private key 1 = ");
                vli_print(private1, 32);
                printf("\n");
                printf("Private key 2 = ");
                vli_print(private2, 32);
                printf("\n");
                printf("Public key 1 = ");
                vli_print(public1, 64);
                printf("\n");
                printf("Public key 2 = ");
                vli_print(public2, 64);
                printf("\n");
                printf("Shared secret 1 = ");
                vli_print(secret1, 32);
                printf("\n");
                printf("Shared secret 2 = ");
                vli_print(secret2, 32);
                printf("\n");
            }
        }
        printf("\n");
    }
   
    return 0;
}


使用特权

评论回复
14
keer_zu|  楼主 | 2022-6-2 23:11 | 只看该作者
chunyang 发表于 2022-5-31 16:49
不错,多多滴点赞!

test_ecdsa.c
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */

#include "uECC.h"

#include <stdio.h>
#include <string.h>

int ecc_rng(uint8_t *dest,unsigned size);
int TestEcdsa() {
    int i, c;
    uint8_t private[32] = {0};
    uint8_t public[64] = {0};
    uint8_t hash[32] = {0};
    uint8_t sig[64] = {0};
        //unsigned char *plat_public = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFBfm3uQdpKNVVLWO1OQlvC/LEdBG6V68//nzEmeQnL83xWJPs16HBLvxsax2rRICQTTkf4F9fyLG4bjSoYBpkg==";
        //unsigned char *plat_hash[32] = {0};
        //unsigned char *plat_sig = "MEQCIEEgzmiGBWHLYJ1hg0cKi4KCAUX6MLDfHIMfmPlAwSsOAiA4tKnLfab+wVr8M1KEpsCCoDN89mKorzzxez9IZenqpg==";
        uECC_set_rng(ecc_rng);
        uECC_Curve _secp256r1 = uECC_secp256r1();
        uECC_Curve _secp256k1 = uECC_secp256k1();
        uint8_t beigu_public[64] = {
        0x85, 0xC2, 0xDD, 0x2D, 0x2E, 0x52, 0x18, 0x35, 0x9B, 0xA1, 0xDD, 0x25, 0xB3, 0x6F, 0x02, 0xF4, 0xD7, 0x7C, 0x25, 0xF9, 0xD7, 0x4F, 0x49, 0x3C, 0x41, 0x76, 0xCE, 0x08, 0x19, 0x91, 0xCF, 0x0F, 0x7B, 0x2E, 0x28, 0xD0, 0x0E, 0x55, 0x69, 0xAE, 0xC1, 0x11, 0x47, 0x3D, 0xB8, 0x8F, 0x0D, 0x76, 0xE9, 0xF9, 0x65, 0x8C, 0x4A, 0x83, 0x0D, 0xF5, 0xAE, 0x78, 0x69, 0xB4, 0x8D, 0x96, 0x5B, 0x64
        };
        uint8_t beigu_hash[32] = {0x76, 0x29, 0x4f, 0x8e, 0xc5, 0x36, 0xed, 0x41, 0x8f, 0x12, 0x26, 0x0e, 0xea, 0xb3, 0x5f, 0xa5, 0xf9, 0x0a, 0xb5, 0xc3, 0xec, 0xdd, 0xbd, 0xd6, 0x51, 0x57, 0xa9, 0x60, 0xd0, 0x2f, 0xe8, 0x61};
        uint8_t beigu_sig[64] = {0x4F, 0xC8, 0x14, 0xA7, 0x23, 0x47, 0x6C, 0xBC, 0x22, 0x13, 0xE5, 0xB2, 0x92, 0x32, 0xA1, 0x01, 0x71, 0xEB, 0x8B, 0x99, 0x67, 0x93, 0xD7, 0xC2, 0xBC, 0x52, 0x1B, 0xA2, 0xF6, 0x86, 0x34, 0x87, 0x62, 0xA5, 0xCF, 0xC7, 0x6B, 0xF6, 0xF1, 0x48, 0x28, 0x48, 0x02, 0xC2, 0x60, 0x60, 0xF8, 0xDE, 0x9F, 0xD8, 0x4C, 0xDA, 0xF2, 0xE5, 0x52, 0x6A, 0xCF, 0x49, 0x2B, 0xDA, 0x9C, 0xF4, 0x41, 0xD5};

        //memcpy(beigu_hash, beigu_public, sizeof(beigu_hash));

        if (!uECC_verify(beigu_public, beigu_hash, sizeof(beigu_hash), beigu_sig, _secp256r1)) {
       printf("=====1 beigu uECC_verify() failed\n");
        }

        if (!uECC_verify(beigu_public, beigu_hash, sizeof(beigu_hash), beigu_sig, _secp256k1)) {
       printf("=====2 beigu uECC_verify() failed\n");
        }

    const struct uECC_Curve_t * curves[5];
    int num_curves = 0;
#if uECC_SUPPORTS_secp160r1
    curves[num_curves++] = uECC_secp160r1();
#endif
#if uECC_SUPPORTS_secp192r1
    curves[num_curves++] = uECC_secp192r1();
#endif
#if uECC_SUPPORTS_secp224r1
    curves[num_curves++] = uECC_secp224r1();
#endif
#if uECC_SUPPORTS_secp256r1
    curves[num_curves++] = uECC_secp256r1();
#endif
#if uECC_SUPPORTS_secp256k1
    curves[num_curves++] = uECC_secp256k1();
#endif
   
    printf("Testing 256 signatures\n");
    for (c = 0; c < num_curves; ++c) {
        for (i = 0; i < 256; ++i) {
            printf(".");
            fflush(stdout);

            if (!uECC_make_key(public, private, curves[c])) {
                printf("uECC_make_key() failed\n");
                return 1;
            }
            memcpy(hash, public, sizeof(hash));
            
            if (!uECC_sign(private, hash, sizeof(hash), sig, curves[c])) {
                printf("uECC_sign() failed\n");
                return 1;
            }

            if (!uECC_verify(public, hash, sizeof(hash), sig, curves[c])) {
                printf("uECC_verify() failed\n");
                return 1;
            }
        }
        printf("\n");
    }
   
    return 0;
}

使用特权

评论回复
15
chunyang| | 2022-6-10 11:22 | 只看该作者
续上……

使用特权

评论回复
16
keer_zu|  楼主 | 2022-6-11 11:27 | 只看该作者

暂时够用了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1351

主题

12431

帖子

53

粉丝