将任意长度的数据映射到有限长度的域上。直观解释起来,就是对一串数据 m 进行杂糅,输出另一段固定长度的数据 h,作为这段数据的特征(指纹)
md4 md5遭遇碰撞破解,在商业领域应用较少
sha-2 sha-3使用较多
ETH 使用SHAKE256 (不满足标准的版本)
银行中存储密码都是hash的value,通过value对比来判断密码正确性
数字签名是一个带有密钥的消息摘要算法,这个密钥包括了公钥和私
钥,用于验证数据完整性、认证数据来源和抗否认。
常见的数字签名 算法主要有 RSA、DSA、ECDSA
三种
发送方通过哈希函数从内容中生成摘要,用私钥加密后,生成的摘要作为内容的数字签名和内容一起合并发给接收方
接收方先用发送方一样的哈希函数从原始内容计算出摘要,然后再用发送方的公钥来对数字签名进行解密,获得另一份摘要,对比两次摘要的结果来确认合法性。
RSA 既能用于数据加密也能用于数字签名 RSA 的算法涉及三个参数,
n、e1、e2。
其中,n 是两个大质数 p、q 的积,即n=p*q
欧拉函数
$$
fn = (p-1)(q-1)
$$
公钥e 为 1<e< fn 之间的数,e和fn互质
私钥d,
$$
(e*d)/fn 要求余数为1
$$
加密方式
$$
m^e / n 求余c
$$
解密方式
$$
c^d / n 求余m
$$
若e地d,必须求fn,要求p q,质因数分解n=pq,这里的质因数分解是大数,非常困难
n 的二进制表示时所占用的位数, 就是所谓的密钥长度。e1 和 e2 是一对相关的值,e1 可以任意取,但 要求 e1 与 (p − 1) ∗ (q − 1) 互质;再选择 e2,要求
$$
(e2 × e1) ≡ 1 (mod((p − 1) × (q − 1)))
$$
(n, e1),(n, e2) 就是密钥对。其中 (n, e1) 为公钥,(n, e2) 为私钥。RSA 加解密的算法完全相同,设 A 为明文,B 为密文,则:
$$
A ≡ Be2 (mod n);B ≡ Ae1 (mod n)
$$
(公钥加密体制中,一般用公钥 加密,私钥解密)e1 和 e2 可以互换使用,即:
$$
A ≡ B (mod ); B ≡ A (mod n)
$$
这里n分解成p q是很困难的
椭圆曲线数字签名加密算法 (Elliptic Curve Digital Signature Algorithm,ECDSA) 的基础是椭圆曲线密码学,给定参数 a, b, 我们选 取如下的椭圆曲线:
$$
y^2 = x^3 + ax + b
$$
红色曲线有4个点,PQTR。PQ连线延长与曲线相交为T,以X轴坐垂直线相交曲线另一点为R,因此椭圆曲线点相加
$$
P + Q = R
$$
代数上即可以通过PQ坐标解到R。
定义一组共同接受的椭圆曲线参数:
$$
(C, tt, n)
$$
其中,C 表示椭圆曲线点域和几何方程;tt 是所有点倍积运算的基点;
n 是该椭圆曲线的可倍积阶数。
签名者需要创建一对匙:即一个私钥和一个公钥,其中私匙 d 是一个 小于 n 的标量,公匙是
$$
Q = d × tt
$$
计算 e = Hash(m), 并截取二进制下其前 n 位为 z
选择一个随机数 k (比较重要,要随机)
计算椭圆曲线上的点 (x1, y1) = k × tt
计 算 r ≡ x1 (mod n)
计算 s = k−1(z + rd) (mod n)
生成的数字签名就是 (r, s).
计算 e = Hash(m),验证前 n 位是否为 z
计 算 w = s^−1 (mod n)
计 算 两 个 参 数 u1 = zw mod n 和 u2 = rw mod n
计算 (x1, y − 1),如果 (x1, y1) 不是椭圆曲线上一个点,验证失败
验证 r ≡ x1 (mod n)
环签名是一种特殊的群签名,当中只有环成员,没有管理者。
签名者利用其他人的公钥临时组建一个集合,被加入到这个集合的其他人都 不一定知道自己被“加”进来了。
monero 通过环签名隐藏交易者和发送者
是一类具有某种功能的函数,这类函数正向计算很容易, 但是在不知道密钥的情况下求逆的概率可以忽略。例如 RSA 就是一种 陷门置换,假设有公钥 (n, e1) 和私钥 (n, e2),在已知公钥的情况下, 任何人都可以从明文 A 计算密文 B,B ≡ Ae1 (mod n),但是如果不 知道私钥,从 B 计算出 A 的概率是可以忽略的;而如果知道私钥,那 么就可以计算 A ≡ Be2 (mod n),是很容易的。
我们用g(x) 来表示正向计算,g−1(x) 来表示求逆。
输入一个密钥 k,一个初始值 v,以及一系列随机数
y1, y2, · · · , yn,对于每一个参数都使用一个对称加密函数 Ek,最终输 出一个值 z ∈ {0, 1}b。我们构造如下函数:
$$
Ck,v (y1, y2, ..., yn) = Ek(y1 + Ek(y2 + Ek(...Ek(yn + v))))
$$
实际使用的时候令 Ck,v (y1, y2, , yn) = v,也就是令初始值和结果相等, 这样就相当于将等式构成了一个环,再缺少其中任何一项时都可以用 其他项算出缺少的那一项。
签名者随机选择一个公钥集合 P1, P2, , Pn 作为混淆公钥,其中签名者 自己的公钥对应的下标为 s,按照如下方式来产生对消息 m 最终的环 签名:
计 算 k = Hash(m)
选择一个随机数 v ∈ {0, 1}b
接着为所有公钥选择一个随机 xi ∈ {0, 1}b, 1 ≤ i ≤ n, i ≠ s 然后 计 算 yi = gi(xi)
签名者可以求解组合函数方程 Ck,v (y1, y2, , yn) = v 的解 ys, 签名者使陷门置换由 ys 算出 xs, 即 xs = gs−1(ys)
输出最终的环签名,σ = (x1, x2, · · · , xn, v)
验证者收到对于消息 m 的签名 (x1, x2, , xn, v) 后,按照如下步骤来进 行验证:
对于所有的 i = 1, 2, · · · , r,计算 yi = gi(xi)
验 证 k = Hash(m)
验证 Ck,v (y1, y2, , yn) = v
它指的是证明者能够在不向验证者提供任何有用的信息的情况下,使验证者相信某个论断是正确的。
零知识证明实质上是一种涉及两方或 更多方的协议,即两方或更多方完成一项任务所需采取的一系列步骤。
证明者向验证者证明并使其相信自己知道或拥有某一消息,但证明过程不能向验证者泄漏任何关于被证明消息的信息。
编码成一个多项式问题: 把需要验证的程序编写成一个二次的多项式方程:
$$
t(x)h(x) = w(x)v(x)
$$
当且仅当程序的计算结果正确时这个等式才成立。证明者需要说服验 证者这个等式成立。
简单随机抽样:
验证者会选择一个私密评估点 s 来将多项式乘法和验证多项式函数相 等的问题简化成简单乘法和验证等式 t(s)h(s) = w(s)v(s) 的问题。这 样做不但可以减少证明量,还可以大量的减小验证所需的时间。
同态编码加密:
我们使用一个拥有一些同态属性的(并不是完全同态的,至少在实际 使用中有一些不是同态的) 加密函数 E。这个函数允许证明者在不知 道 s 的情况下计算 E(t(s)), E(h(s)), E(w(s)), E(v(s)),她只知道 E(s) 和一些其他有用的加密信息。
零知识:
证明者通过乘以一个数来替换 E(t(s)), E(h(s)), E(w(s)), E(v(s)) 的 值,这样验证者就可以在不知道真实的编码值的情况下验证他们正确 的结构了。
有一个粗糙的想法是这样的,因为校验 t(s)h(s) = w(s)v(s) 和校验
t(s)h(s)k = w(s)v(s)k(对于一个不等于 0 的私密的随机数 k 来说) 几乎是完全一样的,而不同的地方在于如果你只接收到了 (t(s)h(s)k) 和 (w(s)v(s)k) 那么从中获取到 t(s)h(s) 或者 w(s)v(s) 的值就几乎是 不可能了。
https://www.amazon.com/Introduction-Modern-Cryptography-Principles-Protocols/dp/1584885513
随机生成比较大的数, 其次是可不可以通过素性测试
素性测试一种是通过费马素性测试,另一种是
https://gist.github.com/atoponce/07d8d4c833873be2f68c34f9afc5a78a