经典密码体制(上)

本文介绍了仿射密码的工作原理,包括其加密函数、解密方法以及如何利用欧拉函数、逆元和费马小定理确保单射性。并通过C++代码示例展示了如何实现密钥生成、加密和解密过程,以及快速幂算法在求解逆元中的应用。
摘要由CSDN通过智能技术生成

第3关:仿射密码:
 

任务描述

仿射密码为单表加密的一种,字母系统中所有字母都利用一个简单数学方程加密,对应至数值或转回字母。

本关任务:用 c++ 实现仿射密码,然后对输入的密文字符串进行仿射解密后打印输出。

相关知识

为了完成本关任务,你需要掌握: 1.同余方程; 2.欧拉函数; 3.逆元; 4.仿射密码的密码体制; 5.费马小定理; 在仿射密码中,加密函数定义成为: e(x)=(ax+b)(mod 26) 我们知道,密码体制需要满足单射性,在当前密码体制下,一个明文只能对应一个密文,所以为了保证上面加密的式子的单射性,我们需要加一些限制条件,这些限制条件由一些定理来支撑,下面给出这些定理。

同余方程

定义 设a∈Zm​,对任意的b∈Zm​,同余方程ax≡b(mod m)有唯一解x∈Zm​的充分必要条件是gcd(a,m)=1(这里的gcd的意思是最大公约数的意思)。

下面我们会看到只有am互质,a才会有关于m的逆元,才会有唯一解。 假设m=26,因为26=2×13,故所有的与26互质的数为a=1,3,5,7,9,11,15,17,19,21,23,25b的取值可以是Z26​中的任何数。因此仿射密码的密钥空间为12×26=312。 下面是代码实现:

 
  1. constexpr int m=26; // 模数 mod 取值为26
  2. cout<<"a=";
  3. for(int i=1; i<m; i++)
  4. if(m%i!=0) //判断m是否可以整除i
  5. cout<<i<<' '; //输出与m互质的数

输出结果:

 
  1. a=1 3 5 7 9 11 15 17 19 21 23 25
欧拉函数

定义 设a≥1,m≥2且均为整数。如果gcd(a,m)=1,则称a与 m 互质。Zm​中所有的与 m互质的个数使用ϕ(m)来表示(这个函数称为欧拉函数)。 定义 假定 m=∏i=1n​piei​​ 这里的pi​均为素数且互不相同,且ei​>0,1≤i≤n。则 ϕ(m)=∏i=1n​(piei​​−piei−1​​)

根据上面关于欧拉函数ϕ(m)的公式,可推出来在仿射密码中密钥空间的大小为m∗ϕ(m)。例如,如果m=60ϕ(60)=2×2×2=16,那么此仿射密码的密钥空间大小为60×16=960。 但是想要解同余方程y≡ax+b(mod 26),还需要有效的方法来实现。下面给出逆元的概念。

逆元

定义:设a∈Zm​,若存在a′∈Zm​,使得aa′≡a′a≡1(mod m),则a′称为aZm​上的乘法逆,将其记为a−1(mod m)。在m是固定的情形下,一般也可以将其简记为a−1。 当gcd(a,m)=1时,aZm​上存在乘法逆元,并且如果逆元存在,那么该逆元在(mod m)下是唯一的。另外还可以发现如果b≡a−1(mod m),那么a≡b−1(mod m)。 下面给出在Z26​的情况下的逆元 1−1=1 3−1=9 5−1=21 7−1=15 11−1=19 17−1=23 25−1=25 说到这里,就可以给出解密函数了, y≡ax+b(mod 26) 等价于 ax≡y−b(mod 26) 因为gc(a,26)=1,所以 a 在Z26​上存在逆元,那么在两边同时乘上a−1,有: (a−1)ax≡a−1(y−b)(mod 26) 根据之前的乘法结合律有 x≡a−1(y−b)(mod 26) 那么相应的解密变换为: d(y)≡a−1(y−b)(mod 26)

仿射密码体制

P=C=Z26​K=(a,b)∈Z26​×Z26​:gcd(a,26)=1,对任意的K=(a,b)∈K,x,y∈Z26​,定义加密变换为: ek​(x)=(ax+b)(mod 26)

相应的解密变换为: dk​(y)=a−1(y−b)(mod 26) 下面给出一个例子: 设密钥K=(7,3),由前所得,有7−1(mod 26)=15。加密函数为ek​=7x+3(mod 26),因为7×15≡1(mod 26),相应的解密变换为: dk​(y)=15(y−3)(mod 26)=15y−45(mod 26) 上面的运算均是在Z26​上完成的。下面来验证对于任意的x∈Z26​,都有dk​(ek​(x))=x,下面是验证过程: dk​(ek​(x))=dk​(7x+3) =15(7x+3)−45 =x+45−45 =x 验证完毕。

费马小定理

经过前面的学习,相信你对仿射的密码的体系结构已经有了深刻的理解,但是你有没有发现对于逆元的求解,依旧是一团迷雾,下面给出一种逆元的求法。 在gcd(a,m)==1的条件下,根据费马小定理有 aϕ(m)≡1(mod m) 那么两边同时除以a可得aϕ(m)−1≡a−1(mod m),那么a−1≡aϕ(m)−1(mod m),这里就把a−1(mod m)给求出来了。但是这里还有一个问题就是aϕ(m)−1怎么快速求出来,这里给出快速幂的板子,供大家学习。

 
  1. 求x^y(modm)
  2. constexpr int mod=26; // 模数取值为26
  3. size_t quick(size_t x,size_t y)
  4. {
  5. size_t ans=x; //设置初始值
  6. while(y)
  7. {
  8. if(y&1) //判断y是不是奇数
  9. ans=ans*x%mod; //计算答案贡献
  10. x=x*x%mod; //每次都乘方
  11. y>>=1; //每次除以2
  12. }
  13. return ans; //返回结果
  14. }
编程要求

本关的编程任务是,补全右侧编辑器中 Begin-End 区间的代码,实现给定字符串的解密功能,具体要求如下:

  • 对于给定的密钥对以及密文串,要求计算并打印出解密后的明文串。
测试说明

平台会对你编写的代码进行测试:

测试输入:

 
  1. 2 3
  2. qwercvzzxx

预期输出:

 
  1. asqqkcooii

测试输入:

 
  1. 5 10
  2. qwercvzzxx

预期输出:

 
  1. gmuhslppnn

代码:
 

#include<bits/stdc++.h>
using namespace std;
char A[103];
constexpr int mod=26;
//在下面Begin和End之间补全代码,对输入的字符串进行仿射密码解密
/*********** Begin ***********/
size_t quick(size_t x,size_t y)
{
    size_t ans=x;
    while(y)
    {
        if(y&1)
            ans=ans*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return ans;
}
int main()
{
    int a,b;
    cin>>a>>b;
    cin>>A;
    int x=quick(a,15);
    for(int i=0; i<strlen(A); i++)
        printf("%c",'a'+(x*((A[i]-'a'-b+mod)%mod)%mod));
    return  0;
}
/*********** End ***********/

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值