RSA算法的简单实现——PHP

RSA算法的简单实现

前言

加密算法有两大类:对称加密和非对称加密

而非对称加密中应用最广泛的就是RSA算法,非对称加密可以用来解决互联网中的非接触式加密问题,即用以加密的密钥需要通过不安全的链路来传输,因此需要一种算法使中间人即使得到加密的密钥也无法解密,更无法伪造信息

算法逻辑

算法步骤

RSA算法安全性源于大数拆解因子的复杂度,公钥私钥加解密的实现和同余原理有关,算法实现的具体步骤如下:

  1. 产生两个大素数p,q

  1. 求N = p * q,和N的欧拉函数: Z = (p - 1) * (q - 1)

  1. 求公钥E,满足两个条件:1 < E < Z, gcd( E, Z) = 1

    1. gcd表示欧几里得算法,用来求两个整数的最大公约数

    2. gcd( E, Z) = 1,即E和Z的最大公约数为1,两者互质,例如3和17

  1. 求私钥D,满足两个条件:1 < D < Z, (E * D) mod Z = 1

    1. 简单实现可以用遍历来求,实际使用扩展欧几里得算法求

  1. 公钥和私钥满足:ED = 1(mod Z )

  1. 加解密表达式:

    1. 密文 =(明文 ^ E) mod N

    2. 明文 =(密文 ^ D) mod N

欧拉函数φ(n)

https://baike.baidu.com/item/%E6%AC%A7%E6%8B%89%E5%87%BD%E6%95%B0/1944850

φ(n) = 小于等于n的正整数中与n互质的数的个数

欧拉函数还有几个特性:

  1. 乘积的欧拉函数等于欧拉函数的乘积,即:φ(pq)=φ(p) * φ(q)

  2. 质数的欧拉函数是其自身减一,即:φ(p)=p-1

  3. 因此n= p*q有:φ(n)=φ(p) * φ(q)=(p-1) * (q-1)

如φ(7) = 6,φ(35)=φ(5) * φ(7)=(5-1) * (7-1) = 24

欧几里得和扩展欧几里得算法

https://blog.csdn.net/u014634338/article/details/40210435

欧几里得算法也叫辗转相除法,用来求两个数的最大公约数

function gcd(int $a, int $b): int
{
    if ($b === 0)
        return $a;
    return gcd($b, $a % $b);
}

而扩展欧几里得算法主要用来:

  1. 求解不定方程;

  1. 求解模的逆元;

  1. 求解模线性方程(线性同余方程);

在RSA中的应用是求解模的逆元,选出公钥e后使用扩展欧几里得算法求出私钥d


/**
 * 扩展欧几里得算法,用来求模的逆元;密钥符合(E * D) mod Z = 1
 * 计算 ax + by = gcd(a,b) = 1中x,y的整数解(a与b互质)
 */
function extGcd(int $a, int $b): array
{
    if ($b === 0) 
        // 返回[x,y]
        return [1, 0];
    }
    [$x1, $y1] =  extGcd($b, $a % $b);
    $x = $y1;
    $y = $x1 - intdiv($a, $b) * $y1;
    return [$x, $y];
}

简单实现的话可以通过遍历求私钥d,其中$e和$z互质

function getSecretKey($p, $q, $e)
{
    $z = ($p - 1) * ($q - 1);
    $i = intdiv($z, $e);
    while (($i * $e) % $z !== 1) {
        $i++;
    }
    return $i;
}

注意要点:

  1. 由于加解密的表达式取决于指数,因此可以使用公钥加密私钥解密,或者私钥加密公钥解密两种方式

  2. 取幂次方和取余时,如果数很大不应直接计算,如 10240000^65537 mod 1553679,可以参考蒙哥马利算法求解大整数幂求模

  3. 生产环境中公钥指数e常取e=65537(费马数)

  4. 明文要求小于密钥n,因为加解密时需要mod n;如下例中的密钥n=35,则明文 m < 35(若长度表示bit也成立)

代码实现

简单版

https://blog.csdn.net/a745233700/article/details/102341542

https://blog.csdn.net/bian_h_f612701198412/article/details/79358771

https://www.zhihu.com/question/304030251/answer/543201982

<?php

declare(strict_types=1);
/**
 * 扩展欧几里得算法,用来求模的逆元
 * 计算 ax + by = gcd(a,b) = 1中x,y的整数解(a与b互质)
 */
function extGcd(int $a, int $b): array
{
    if ($b === 0) {
        // 返回[x,y]
        return [1, 0];
    }
    [$x1, $y1] =  extGcd($b, $a % $b);
    $x = $y1;
    $y = $x1 - intdiv($a, $b) * $y1;
    return [$x, $y];
}
/**
 * 获取密钥对,(n, e, d)
 */
function getKey(int $p, int $q): array
{
    // 公钥,这里为简便取5,实际生产环境中常用65537(费马数)
    $e = 5;
    $n = $p * $q;
    // n的欧拉函数,φ(n) = 小于等于n的正整数中与n互质的数的个数;可以由下式得出
    $z = ($p - 1) * ($q - 1);
    [$x, $y] = extGcd($e, $z);
    $d = ($x < 0) ? ($x + $z) : $x;
    return [$n, $e, $d];
}

/**
 * RSA加密解密;当指数为公钥时定义为加密,私钥时定义为解密
 * 先求指数再取余的方式有很大局限性,指数运算后很容易超出整型范围
 */
function RSA(int $m, int $n, int $exponent): int
{
    return pow($m, $exponent) % $n;
}
[$n, $e, $d] = getKey(5, 7);
print_r([$n, $e, $d]);
for ($i = 0; $i < 12; $i++) {
    $secret[$i] = RSA($i, $n, $d);
    $message[$i] = RSA($secret[$i], $n, $d);
}
var_dump($secret, $message);
// 输出
Array
(
    [0] => 35
    [1] => 5
    [2] => 5
)
(
    [0] => 0
    [1] => 1
    [2] => 32
    [3] => 33
    [4] => 9
    [5] => 10
    [6] => 6
    [7] => 7
    [8] => 8
    [9] => 4
    [10] => 5
    [11] => 16
)
Array
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
    [6] => 6
    [7] => 7
    [8] => 8
    [9] => 9
    [10] => 10
    [11] => 11
)

小结

  1. 以上就是RSA算法的原理以及简单实现,而实际应用RSA算法时,密钥长度n往往较大,取1024bit以上,因为太短的密钥不够安全

  2. 我们常说的签名和加密其实本质运算是一样的,根据指数用公钥e还是私钥d来决定;

  3. 加密指的是使用对方的公钥进行RSA运算,保证只有对方的私钥能够解密,确保信息不会泄露

  4. 签名指的是使用自身的私钥进行RSA运算,保证只有自己的公钥能够解密,确保信息不被伪造

  5. 我们平时使用的RSA密钥都是转码成base64格式保存的,这是为了方便传输和阅读,可以使用以下命令查看RSA私钥的格式,如下图所示的私钥,采用的是ASN.1格式保存,密钥文本保存的格式将在下一篇中讲解

openssl rsa -text -noout < ~/.ssh/id_rsa

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值