ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

应用密码学基础部分一

2021-03-06 04:32:26  阅读:205  来源: 互联网

标签:std 26 gcd int 基础 算法 应用 using 密码学


单表代换密码 (上)

单表代还密码是一种很常见也很简单的密码, 著名的凯撒密码就是其中之一

恺撒密码

恺撒密码 : 实质上可以看成是一种哈希算法, 将字母进行移位来进行加密.

恺撒密码的数学表示 :

\[c\ =\ E_3(m)\ ≡\ m\ +\ 3\ (mod\ 26),\ 0\ ≤\ m\ ≤\ 26 \]

解密算法 :

\[m\ =\ D_3(c)\ ≡\ c\ -\ 3\ (mod\ 26),\ 0\ ≤\ m\ ≤\ 26 \]

其中 3 是密钥, m 是明文, c 是加密后的密文, E是加密, D是解密. 下面用 C++ 来进行描述

加密

#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

string words("abcdefghijklmnopqrstuvwxyz");     /*列出26个字母*/

void Ceasar(string m)
{

    for (int i = 0; i < m.size(); i++)		/*从字符串的第一个字母开始遍历更换*/
    {
        int temp = m[i] - 'a';              /*将字母改成数组的索引值*/
        m[i] = words[(temp + 3) % 26];		/*恺撒加密算法*/
    }

    cout << m << endl;
}

int main(void)
{
    string m;

    cin >> m;
    Ceasar(m);

    return 0;
}

解密

#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

string words("abcdefghijklmnopqrstuvwxyz");     /*列出26个字母*/

void Ceasar(string m)
{

    for (int i = 0; i < m.size(); i++)		/*从字符串的第一个字母开始遍历更换*/
    {
        int temp = m[i] - 'a';              /*将字母改成数组的索引值*/
        m[i] = words[(temp - 3) % 26];		/*恺撒加密算法*/
    }

    cout << m << endl;
}

int main(void)
{
    string m;

    cin >> m;
    Ceasar(m);

    return 0;
}


仿射变换

上述的恺撒密码是移位变换, 一般形式为

\[c\ =\ E_k(m)\ ≡\ m\ +\ k\ (mod\ 26),\ 0\ ≤\ m\ ,\ k\ ≤\ 25 \]

\[m\ =\ D_k(c)\ ≡\ c\ -\ k\ (mod\ 26),\ 0\ ≤\ c\ ,\ k\ ≤\ 25 \]

仿射变换的一般形式是

\[c\ =\ E_{a,b}(m)\ ≡\ am\ +\ b\ (mod\ 26) \]

\[m\ =\ D_{a,b}(C)\ ≡\ a^{-1}(m-b)\ (mod\ 26) \]

仿射变换中的 a, b 是密钥. 为满足 \(0 ≤ a\), \(b<=26\) 和 \(gcd(a,\ 26)=1\) 的整数. ( 这意味着如果要使用仿射变换密码的话, a 与 26必须互素. )

这个密码的破解关键点在于求 a 的逆元, 求逆元有两种方法 :

  1. 暴力枚举
  2. 广义欧几里得算法

暴力枚举很简单, 但是如果数字较大的情况下会比较麻烦. 这里介绍一种在大数求值时相对简便的广义欧几里得算法

广义欧几里得算法

在介绍广义欧几里得之前, 我们先来看看高中数学课上讲的欧几里得算法 (即辗转相除法)

欧几里得算法的思想就是 : 用一个数除以另外一个数, 如果没有余数则除数为这两个数的最大公约数, 否则的话就用除数和余数继续相除, 直到没有余数为止. 下面是 C++ 算法描述

#include <iostream>
#include <algorithm>

using std::cin;
using std::cout;
using std::endl;

int gcd(int a, int b)
{
    if (b == 0)
        return a;       /*如果余数为0, 则除数为最大公约数*/

    else
        return gcd(b, a % b);
}

int main(void)
{
    int a, b;

    cin >> a >> b;
    cout << gcd(a, b) << endl;

    return 0;
}

这是最简单的欧几里得算法, 一般情况下已知 a, b 的值就可以直接求出. 而广义欧几里得算法则是逆向相求, 通过结果去反推出 x, y.

它的一般形式是 :

\[ax\ +\ by\ =\ gcd(a,\ b) \]

从这个公式上看, 大概可以看做是如果在原 \(a\ +\ b\ =\ gcd(a,\ b)\) 的前提下, 为 a 和 b 分别乘 x 和 y 原式依然成立. 我们通过上面的算法可以看出, 算法结束时 a 的值即为最大公约数 gcd, 而 b 的值则为 0. 那么显然 x = 1, y = 0.

在计算 \(gcd (a, b)\)时, 有 \(a_{x1}+b_{y1}=gcd\) 成立, 在下一步计算时, \(a\ =\ b,\ b\ =\ a\ \%\ b\). 那么就有 \(b_{x2}\ +\ (a\ \%\ b)\ y_{y2}\ =\ gcd\) 成立, 因此 \(ax_{x1}\ +\ b_{y1}\ =\ b_{x2}\ +\ (a\ \%\ b)\ y_2\) 成立. 而 \(a\ \%\ b\ =\ a\ -\ (a\ /\ b)\ ×\ b\) 成立 ( 注意这里的\(a/b\) 不能被约分. ) 则代换一下就是 \(a_{x1}\ +\ b{y1}\ =\ a_{y2}\ +\ b(x_2\ -\ (a\ /\ b)y_2)\) . 根据对应项系数相等原则, 我们可以得到下面这个公式

\[\begin{cases} x_1\ =\ y_2\\ y_1\ =\ x_2\ -\ (a\ /\ b)\ y_2 \end{cases} \]

这样就可以通过 \(x_2\ 和\ y_2\) 求出 \(x_1\ 和\ x_2\)了, 只需反复的递推即可. C++算法描述如下

#include <iostream>
#include <algorithm>

using std::cin;
using std::cout;
using std::endl;

int exgcd(int a, int b, int &x, int &y)
{
    if (b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }

    int g = exgcd(b, a % b, x, y);      /*求出 a 和 b 的最大公约数 gcd */
    int temp = x;                   /*临时存放 x, 下面就是对公式的运用*/
    x = y;
    y = temp - (a / b) * y;

    return g;
}

int main(void)
{
    int a, b, x, y;
    int gcd;

    cin >> a >> b >> x >> y;
    gcd = exgcd(a, b, x, y);
    cout << gcd << endl;
    cout << x << ' ' << y << endl;

    return 0;
}

我们用这个算法求一下 \(47x\ +\ 30y\ =\ 1\) 中的 x 和 y. 将 47, 30, 1, 0 带入后的结果为 -7 和 11. 结果正确

这里注意一点的是, if 中的判断条件是 b == 0. 原因是因为不管欧几里得算法怎么执行, 到最后一步 b 永远为 0.

而这只是一个解, 如果想得到所有解的话该怎么办呢 ? 我们可以设其中一组解为 \(x_0\ +\ s_1\), \(y_0\ -\ s_2\). ( 关于为什么 \(y_0\ -\ s_2\). 因为欧几里得算法需要被除数大于除数才能进行, 如果被除数小于除数则会通过计算转换过来. 同时也是为了方便) 可得到

\(a\ ×\ (x_0\ +\ s_1) + b\ (y_0\ -\ s_2)\ =\ gcd\).

然后将 \(ax_0\ +\ by_0\ =\ gcd\) 带入可得到 \(as_1\ =\ bs_2\), 整理后可得 \(\frac{s_1}{s_2}\ =\ \frac{b}{a}\). 为了让 \(s_1\) 和 \(s_2\) 更贴近 \(ax_0\ +\ by_0\ =\ gcd\), 我们需要让 \(s_1\) 和 \(s_2\) 越小越好, 同时也必须是整数, 那么可以尝试让它们同时去除以较大的数去满足这个条件. 很明显 gcd 最符合条件. 因此\(\frac{s_1}{s_2} = \frac{b}{a} = \frac{b/gcd}{a/gcd}\).

由此, 我们就能总结出下面这个公式 :

\[\begin{cases} x'\ =\ x\ +\ \frac{b}{gcd}\ ×\ K\\ y'\ =\ y\ -\ \frac{a}{gcd}\ ×\ K\\ K \in Z \end{cases} \]

在了解完广义欧几里得算法后, 我们就可以去求解逆元

逆元的求解

逆元的一般形式为 \(aa^{-1}\ ≡\ 1\ (mod\ m)\). 其中要求 a 与 m 互素. 而且 \(m整除aa^{-1}-1\) (即\((aa^{-1}-1)\ \%\ m\ ==\ 0\)).

我们来看一道题 : 求解 \(5x ≡ 1(mod\ 3)\)

由于 5 与 3互素, 因此根据广义欧几里得算法可以得到 \(ax+by=1\), 在这里 a = 5, b = 3.

于是就有 \(5x+3y=1\), 根据公式

\[\begin{cases} x_1\ =\ y_2\\ y_1\ =\ x_2\ -\ (a\ /\ b)\ y_2 \end{cases} \]

先经过欧几里得算法得到 5 和 3 计算的步骤数. 然后再套用公式逆向求出, 直到逆向所用的步数与欧几里得算法所用的步数相等时, 即可求出逆元. 这里逆元 \(x_1=-1\), \(x_2=2\)

**注意这里不能直接将最开始的 x = 1 和 y = 0 代入公式 : **

\[\begin{cases} x'\ =\ x\ +\ \frac{b}{gcd}\ ×\ K\\ y'\ =\ y\ -\ \frac{a}{gcd}\ ×\ K \end{cases} \]

如果这样代入就认为 x = 1 与 y = 0 是 \(5x+3y=1\)的一组解, 但很明显并不是.


公式总结 :

恺撒密码

加密 :

\[c\ =\ E_3(m)\ ≡\ m\ +\ 3\ (mod\ 26),\ 0\ ≤\ m\ ≤\ 26 \]

解密 :

\[m\ =\ D_3(c)\ ≡\ c\ -\ 3\ (mod\ 26),\ 0\ ≤\ m\ ≤\ 26 \]

仿射变换密码

加密 :

\[c\ =\ E_k(m)\ ≡\ m\ +\ k\ (mod\ 26),\ 0\ ≤\ m\ ,\ k\ ≤\ 25 \]

解密 :

\[m\ =\ D_3(c)\ ≡\ c\ -\ 3\ (mod\ 26),\ 0\ ≤\ m\ ≤\ 26 \]

广义欧几里得算法

一般形式 :

\[ax\ +\ by\ =\ gcd(a,\ b) \]

求单个解 :

\[\begin{cases} x_1\ =\ y_2\\ y_1\ =\ x_2\ -\ (a\ /\ b)\ y_2 \end{cases}\]

求所有解 :

\[\begin{cases} x'\ =\ x\ +\ \frac{b}{gcd}\ ×\ K\\\ y'\ =\ y\ -\ \frac{a}{gcd}\ ×\ K\\K \in Z\end{cases}\]


参考 :

《算法笔记》—— 胡凡,曾磊

百度百科 —— 扩展欧几里得算法

标签:std,26,gcd,int,基础,算法,应用,using,密码学
来源: https://www.cnblogs.com/ICeVe/p/14489310.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有