将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
基于欧拉定理和费马小定理,下面公式成立:
\(密文=明文^E\ mod\ N\)
\(明文=密文^D\ mod\ N\)
公钥 \((E, N)\),私钥 \((D, N)\)。
名称 | 说明 |
---|---|
$N$ | $N=p\times q$,且 $p$ 与 $q$ 互质 |
$L$ | $p−1$ 与 $q−1$ 的最小公倍数 |
$E$ | $E<L$,并与 $L$ 互质 |
$D$ | $D<L$,$(E\times D)\ mod\ L=1$ |
运行结果:
RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。
RSA 所需要的大素数怎样生成的呢?简单说来是这样的:
随机构造一个满足最终大素数长度的奇数。
判断这个奇数是不是素数。如果是,ok,结束;否则,加 2,然后再检验,…,再加 2 再检验,总会遇到一个素数的。
这里面有两个难点需要解决:
一个快算法 miller-rabin,但是不准,一个慢算法 AKS,但是准确。
循环“迭代”(非常规迭代,因为每轮之间是独立的)。“迭代”过程中,如果某步断定是一个合数【断定方式是:有某几个公式,质素一定成立,合数可能成立。所以只要不成立,那么一定是合数。而分明是合数,却成立的概率小于 1/4】,那么一定是合数。否则,每一步都能以 1/4 概率的误判率断定是一个素数。如果需要更高的概率精度,那么就多做几轮【承上面括号中内容。如果一次误判的概率小于 1/4,那么没有理由做了 n 多次,每次都撞中了小概率】。这样概率可以任意提高。wikipedia:https://en.wikipedia.org/wiki/Miller%e2%80%93Rabin_primality_test。
2002 年几个印度人发明的 AKS 方式,则是给出了一个多项式可解的判别法!
这个有赖于素数的概率分布情况。对于整数 n,n 处的连续两个素数的平均间隔大概是 $ln(n)$,而 $ln(n)$ 往往很小了,所以从 $n$ 开始不用做多少次(几百位的一个数,也就是只需要几十几百次而已),就往往发现了一个素数了。而且因为这个平均间隔是比较小的,如果不是要找比 n 大最接近 n 的素数,那么这时候都可以在 +2 好多次(比如几万几十万)都没有找到一个素数的情况下,一下加一个较大的数字然后再次尝试。不可能每次总是需要 +2 好多好多次。
RSA 算法本身没什么问题,因为只要你的密钥是真正随机产生的,猜对这个密钥就如同大海捞针一般难,现有计算机肯定无法在密码更换周期内攻破你的加密档案。但是,如果这个随机算法是假的呢?如果它仅仅是在一个很小的集合中产生的密钥呢?你的加密档案瞬间就被查看了,这就是 NSA 干的事情。