加密算法之非对称加密

函数太长
• 阅读 5495
上篇文章介绍了对称加密的原理,但是它的最大问题就是加密和解密的密钥是相同的,并且不能保证密钥能安全的送到双方手里,即使安全的送到双方手里,免不了内部会有"卧底"的存在

非对称加密

既然有对称加密,那么自然会联想到非对称加密。非对称加密的核心在于加密和解密使用的是不同的密钥,如何做到使用不同的密钥呢?
比如我有一个只能用钥匙打开的存钱罐,平时大家只能把零钱放到储钱罐中,但是只有我才有取钱的钥匙。放到储钱罐的硬币可以看成加密后的内容,而只有用钥匙才能将"加密"后的硬币取出来。
这样我们就可以把用来加密的密钥(公钥)给了任何人,我们只要自己保存好解密的密钥(私钥)就可以安全的保护我们的数据。
非对称算法有很多:RSA、Elgamal、背包算法、Rabin、D-H、ECC等,下面我们来简单介绍一下RSA算法。

RSA算法

RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的(啥时候以我名字命名一个呢)。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。

RSA加密&&RSA解密公式

//注意:明文为数字,实际计算过程我们可以通过ASCII码转换
密文 = (明文 ^ E) % N; //其中的E和N就是我们的公钥

明文 = (密文 ^ D) % N; //其中的D和N就是我们的私钥

计算公钥(E)、私钥(D)和数字(N)

公钥和私钥不是随便弄几个数字就可以的,是经过严格的数学公式计算出来的。

1、随机准备两个质数P和Q,计算乘积得到N

N = P * Q;

2、计算L

L = (P - 1) * (Q - 1); //图解密码技术中说需要计算乘积之后的最小公倍数,但是经过代码测试并不准确,哪位大侠了解麻烦留言告知一下~

3、计算E(公钥),用来给加密方使用

//E需要同时满足下面两个条件
1. 1 < E < L
2. E和L的最大公约数为一(欧几里得算法,这些恶魔啊,E和L必须互质,这样才能保证一定可以计算出私钥D)

4、计算D(私钥),用来给解密方使用

//D需要满足下面公式
(E * D) % L = 1; //想要保证结果为1,E和L必须互质!!!

上面就是整个计算过程,为了保证数据的安全现实中,P和Q会选用特别大的数(1024比特或者更大)

RSA的加密和解密

上面已经提到过加密和解密的方法,我们用具体的数字实践一下,加深理解吧。

1、求N(P*Q)

假设:P = 7、Q = 11(均为质数)
那么:N = P * Q = 7 * 11 = 77

2、求L ((P - 1) * (Q - 1))

L = (P - 1) * (Q - 1) = 6 * 10 = 60

3、求E

1 < E < 60
E和L的最大公约数为一,我们假设E=23

4、计算D ((E * D) % L = 1)

(23 * D) % 60 = 1;
D = 47;

那么我就得到了公钥(E=23,N=77),私钥(D=47,N=77)

加密&&解密

我们假设需要加密数字:12
公式:密文 = (明文 ^ E) % N;
12 ^ 23 % 77 = 6624737266949237011120128 % 77 = 45;
这个45就是我们加密后的密文

解密
公式:明文 = (密文 ^ D) % N;
45 ^ 47 % 77 = 502328880013965819626664594350710696732674427522624682751484215259552001953125 % 77 = 12;
得出原文:12

PHP示例

下面是我用PHP实现的加密&解密示例,供大家参考(因为指数运算的结果集会很大,我们必须使用PHP中提供的BC Math系列函数计算)

/**
 * 冒牌RSA算法
 * @author zhjx922
 */

/**
 * 判断数字是否为质数
 * @param $num
 * @return bool
 */
function isPrimeNumber($num) {
    $k = 0;//定义次数变量
    for ($i = 1; $i <= $num; $i++) {
        if (bcmod($num, $i) == 0) {
            $k++;//如果取模等于0,次数k自加
        }
    }

    if ($k == 2) {
        return true;
    }
    return false;
}

//求最小公倍数
function minMultiple($a, $b)
{
    if($b==0)     //一定要考虑除数不能为零
    {
        return $b;
    } else {
        $m = bccomp($a, $b) == 1 ? $a : $b;
        $n = bccomp($b, $a) == 1 ? $b : $a;

        for($i=2; ; $i++)
        {
            $mul = bcmul($m, $i);
            if(bcmod($mul, $n) == 0)
            {
                return $mul;
            }
        }
    }
    return bcmul($a, $b);
}

//求最大公约数
function maxDivisor($a,$b)
{
    $n = bccomp($a, $b) == 1 ? $b : $a;
    for($i = $n; $i>1; $i--)
    {
        if(bcmod($a, $i) == 0 && bcmod($b, $i) == 0)
        {
            return $i;   //此处如果用echo $i;则输出结果为432;故应区分echo、return的区别
        }
    }
    return 1;
}


do{
    //随机一个质数P
    $p = mt_rand(101, 197);
} while(!isPrimeNumber($p));

do{
    //随机一个质数Q
    $q = mt_rand(101, 197);
} while(!isPrimeNumber($q));


$n = bcmul($p, $q);

//$l = minMultiple($p - 1, $q - 1); //经测试不可用
$l = bcmul($p - 1, $q - 1);

do {
    $e = mt_rand(2, $l - 1);
}while(maxDivisor($e, $l) != 1);


$d = 1;
while(bcmod(bcmul($e,++$d), $l) != 1) {

}

echo 'p:' . $p . PHP_EOL;
echo 'q:' . $q . PHP_EOL;
echo 'n:' . $n . PHP_EOL;
echo 'l:' . $l . PHP_EOL;
echo 'e:' . $e . PHP_EOL;
echo 'd:' . $d . PHP_EOL;

echo "公钥:e={$e},n={$n}" . PHP_EOL;
echo "私钥:d={$d},n={$n}" . PHP_EOL;

//加密
function encode($e, $n, $string) {
    $enString = '';
    $len = strlen($string);
    for($i = 0; $i < $len; $i++) {
        $pow = bcpow(ord($string{$i}), $e);
        $mod = bcmod($pow, $n);
        $enString .= pack('L', $mod);
    }
    return $enString;
}


//解密
function decode($d, $n, $string) {
    $deString = '';
    $string = unpack('L*', $string);
    $len = count($string);
    for($i = 1; $i <= $len; $i++) {
        $pow = bcpow($string[$i], $d);
        $mod = bcmod($pow, $n);
        $deString .= chr($mod);
    }
    return $deString;
}


$startTime = microtime(true);

$string = '欢迎关注"假装是个程序员"公众号';
echo "原文:" . $string . PHP_EOL;

$encodeString = encode($e, $n, $string);
echo "密文:" . $encodeString . PHP_EOL;

$decodeString = decode($d, $n, $encodeString);
echo "解密后:" . $decodeString . PHP_EOL;


$endTime = microtime(true);

echo "Total:" . ($endTime - $startTime) . 's.' . PHP_EOL;

没有绝对安全的加密方式

没有什么加密方式能一直保持绝对的安全,尤其常用的MD5,如果你的数据库中密码还是使用MD5的哈希结果不要笑话人家直接用明文存密码的人,五十步笑百步而已。。。
最近谷歌宣布破解了SHA-1,随着计算能力的提高,SHA-256,RSA等等也是迟早的事儿。。

关注公众号,一起学习成长~

加密算法之非对称加密

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
4年前
SSH加密原理、RSA非对称加密算法学习与理解
   首先声明一下,这里所说的SSH,并不是Java传统的三大框架,而是一种建立在应用层和传输层基础上的安全外壳协议,熟悉Linux的朋友经常使用到一个SSHSecureShellCilent的工具,本文也是基于此工具加密原理的学习,在SSH的加密原理中,使用到了RSA非对称加密算法,本文也一并做了学习和了解。  非对称加密算法
Wesley13 Wesley13
4年前
RSA加密、解密、签名、验签的原理及方法
一、RSA加密简介  RSA加密是一种非对称加密。可以在不直接传递密钥的情况下,完成解密。这能够确保信息的安全性,避免了直接传递密钥所造成的被破解的风险。是由一对密钥来进行加解密的过程,分别称为公钥和私钥。两者之间有数学相关,该加密算法的原理就是对一极大整数做因数分解的困难性来保证安全性。通常个人保存私钥,公钥是公开的(可能同时多人持有)。
Wesley13 Wesley13
4年前
java实现非对称加密
对称加密:加密和解密的过程使用的是相同的密钥!这里写图片描述(https://oscimg.oschina.net/oscnet/42e81282a912d5abcf561e846c2b997914e.png)非对称加密与对称加密不同,非对称加密算法的加密和解密使用不同的两个密钥.这两个密钥就是我们经常听到的”公开密钥”(公钥
Wesley13 Wesley13
4年前
RSA —— 典型非对称加密算法
RSA——JAVA代码(toc_0)RSA——加密过程图解(toc_1)(图1)构建RSA算法密匙对(toc_2)(图2)甲方向乙方发送RSA加密数据(toc_3)(图3)乙方向甲方发送RSA加密数据(toc_4)RSA——简述(
Wesley13 Wesley13
4年前
DES与RSA加解密
加密,是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容。大体上分为双向加密 和单向加密 ,而双向加密又分为对称加密 和非对称加密(有些资料将加密直接分为对称加密和非对称加密)。 双向加密大体意思就是明文加密后形成密文,可以通过算法还原成明文。而
Stella981 Stella981
4年前
OpenSSL和Python实现RSA Key公钥加密私钥解密
基于非对称算法的RSAKey主要有两个用途,数字签名和验证(私钥签名,公钥验证),以及非对称加解密(公钥加密,私钥解密)。本文提供一个基于OpenSSL和Python进行非对称加解密的例子。1\.OpenSSL实现非对称加解密1.1生成私钥,并导出公钥生成2048bit的PEM格式的RSAKey:Key.pem$openssl
Stella981 Stella981
4年前
Openssl生成RSA公私钥以及将公钥转换成C#支持的格式
Openssl生成RSA公私钥以及将公钥转换成C支持的格式1.RSA算法介绍RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。RSA的算法涉及三个参数,n、e、d。其中,n是两个大质数p、q的积,n被称为模数,n的二进
Wesley13 Wesley13
4年前
JAVA_RSA_的加解密
RSA为非对称加密算法。数字签名的过程:1、对明文数据进行HASH加密,不可逆;2、对加密后的数据再用RSA的私钥进行二次加密。数字签名的验证过程:1、对明文数据进行HASH加密,不可逆;2、用RSA的公钥对数字签名后的数据进行解密;3、把1的结果和2的结果进行比较是否相等。RSA加密的过程和解密的过程都需要三步:加/解密、分组、填充。这三部分每
Wesley13 Wesley13
4年前
Go加密解密之DES
一、DES简介DES(DataEncryptionStandard)是对称加密算法,也就是加密和解密用相同的密钥。其入口参数有三个:key、data、mode。key为加密解密使用的密钥,data为加密解密的数据,mode为其工作模式。当模式为加密模式时,明文按照64位进行分组,形成明文组,key用于对数据加密,当模式为解密模式时,key用于对数据解
Easter79 Easter79
4年前
SpringCloud配置中心内容加密
从配置获取的配置默认是明文的,有些像数据源这样的配置需要加密的话,需要对配置中心进行加密处理。下面使用对称性加密来加密配置,需要配置一个密钥,当然也可以使用RSA非对称性加密,但对称加密比较方便也够用了,这里就以对称加密来配置即可。1、安装JCEJDK下的JCR默认是有长度限制的,需要替换没有长度限制的JCE版本。htt