信息安全-古典密码

任务1描述

本关任务:编写一个能实现移位密码的小程序,对输入的明文字符串进行移位加密后打印输出。

相关知识

移位加密是密码学中一种非常经典、也是很重要的加密方法,学好移位加密对后面其他加密方法的学习有着至关重要的作用。

为了完成本关任务,你需要掌握: 1.数论中的模运算; 2.定义模 m 上的运算; 3.移位密码体制。

模运算知识补充 假设a和b均为整数,m是一正整数。若m整除b−a,则可将其表示为: a≡b(mod m) 该式读作“a与b模m同余”,正整数m称为模数。

下面给出计算一组数据中符合指定模数的同余的数字对,具体 C++ 代码示例如下:

 
  1. constexpr int mod=9; // 模数 mod 取值为9
  2. int a[10]= {2,11,12};
  3. for(size_t i=1; i<3; i++) // 循环遍历数组 a 中所有的数字对
  4. if((a[i]-a[i-1])%mod==0) // 判断mod是否可以整除两数之差
  5. cout<<a[i-1]<<"与"<<a[i]<<"模"<<mod<<"同余"<<endl;

输出: 2与11模9同余

上述代码通过遍历数组 a 中的所有数字对,判断模数能否整除数字对中两数之差,从而找出符合条件的数字对。

模上的运算 通俗的理解,模 m 上的运算就是:在模 m 的集合上定义加法和乘法,下面给出具体定义。

Zm​表示集合{0,1,...,m-1},在其上的加法和乘法运算类似于普通实数域上的加法和乘法,所不同的只是所得的值是取模以后的余数。具体运算法则如下:

1.对加法运算封闭:对任意的a,b∈Zm​ ,有a+b∈Zm​

2.加法运算满足交换律:对任意的a,b∈Zm​ ,有a+b=b+a。

3.加法运算满足结合律:对任意的a,b,c∈Zm​,有(a+b)+c=a+(b+c)。

4.0是加法单位元:对任意的a∈Zm​,有a+0=0+a=a。

5.任意a∈Zm​的加法逆元为−a,因为a+(−a)=(−a)+a=0。

6.对乘法运算满足封闭性:对任意的a,b∈Zm​,有ab∈Zm​ 7.乘法运算满足交换律:对任意的a,b∈Zm​,有a×b=b×a。

8.乘法运算满足结合律:对任意的a,b,c∈Zm​,有(a×b)×c=a×(b×c)。

9.1是乘法的单位元:对任意的a,b,c∈Zm​,有a×1=1×a=a。

10.乘法和加法之间存在分配率:对任意的a,b,c∈Zm​,有(a+b)×c=(a×c)+(b×c)。

这里给出判断一组给定数字进行模运算是否满足性质10的 C++ 代码实现示例:

 
  1. constexpr int mod=9; // 模数取值为9
  2. int a=3,b=4,c=5;
  3. if(a*(b+c)%mod==(a*b+a*c)%mod) //判断乘法与加法之间是否存在分配率
  4. cout<<"乘法和加法之间存在分配率"<<endl;

需要注意的是这里最后的结果是取模后的余数。

移位密码体制 通俗的来讲,移位密码体制就是通过一个线性变换,即一次方程,是使得在该变换下,明文和密文是一一对应的。下面给出具体的移位的密码体制。 令P=C=K=Z26​(这里的P表示明文空间,C代表密文空间,K代表密钥空间)。对0<=K<=25,任意x,y属于Z26​,定义: Ek​(x)=(x+K)mod26,这个是加密式子,具体是对每一位明文字符x进行右移K位得到密文。 Dk​(y)=(y−K)mod26,这个是解密式子,具体是对每一位密文字符y进行左移K位得到明文。

另外当K=3的时候,此密码体制叫做凯撒密码。

编程要求

本关的编程任务是,补全右侧编辑器中 Begin-End 区间的代码,实现对只含有小写字母的字符串进行K位加密。具体要求如下:

先读取输入 K,表示移位密码的参数。然后读取输入的一个只含小写字母的字符串。要求你输出该字符串经过 K 位加密之后的密文串,其中串的长度在 100 以内,0<=K<=25。

测试说明

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

测试输入: 1 a 预期输出: b 测试输入: 2 abc 预期输出: cde


开始你的任务吧,祝你成功!

/*
 * shift.cpp
 *  
 */


#include <stdio.h>
#include <string.h>
#include <iostream>

using namespace std;

char S[100];

//在begin和end之间补全代码,对输入的字符串s进行k位移位加密
int main(int argc, char **argv)
{
    int K;
    scanf("%d ",&K);                 //输入移位位数
    cin.getline(S,100);              //输入字符串
    
/*********** Begin ***********/
    size_t i;
    for(i=0;i<strlen(S);i++)
    {
        S[i]='a'+((S[i]-'a'+K)%26);
        printf("%c",S[i]);
    }
    

/*********** End *************/
    return 0;
}

任务2描述

本关任务:编写一个能实现维吉尼亚密码的小程序。

相关知识

为了完成本关任务,你需要掌握:1.多表替代密码,2.vigenere密码。

vigenere密码

vigenere密码是一种典型的多表替代密码,它选择一个词组作为密钥,密钥中每个字母用来确定一个代换表,每个密钥字母用来加密一个明文字母。 例如密钥字母为a,明文字母为c,则密文字母为0+2(mod26)=2,也就是c。直到所有的密钥字母用完,后再从头开始,使用第一个密钥字母加密。也就是说,密钥循环使用。 例1: 密钥k =cipher,明文消息appliedcryptosystem, 则: 由密钥k=cipher,得n=6,密钥对应的数字序列为 (2,8,15,7,4,17)。然后将明文按每6个字母进行分组,并转换这些明文字母为相应的数字,再用模26加上对应密钥数字,其加密过程如表所示。
表 密钥为cipher的维吉尼亚密码加密过程

密文为:cxtsmvfkgftkqanzxvo。 例2: 明文为attack begins at five,密钥为cipher, attack begins at five 明文 + cipher cipher ci pher 密钥 ---------------------------------------------- = cbihgb dmvprj cb upzv 密文 去除空格后为cbihgbdmvprjcbupzv 解密使用相同的密钥,但用模26的减法代替模26加法,这里不再赘述

编程要求

根据提示,在右侧编辑器补充代码,对输入的字符串进行维吉尼亚加密。要求输入密钥字符串和明文字符串(输入的字符串若为大写字母需将其转换为小写字母),输出经过维吉尼亚加密后的密文字符串。

测试说明

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

测试输入:aaa qwert 预期输出:qwert

测试输入:abc aaaaaaa 预期输出:abcabca


开始你的任务吧,祝你成功!

// vigenere.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <cstring>
#include <bits/stdc++.h>
using namespace std;
char A[103], B[103];
//在下面Begin和End之间补全代码,对输入的字符串进行维吉尼亚加密
int main()
{
    cin >> A;   //输入密钥字符串
    cin >> B;   //输入明文字符串
    /*********** Begin ***********/
   int i,j,k;
   j=strlen(A);
   for(k=0;k<j;k++)
   {
       if(A[k]>='A'&&A[k]<='Z')
          A[k]='a'+(A[k]-'A');
   }
   int lm=strlen(B);
   for(i=0;i<lm;i++)
   {
       if(B[i]>='A'&&B[i]<='Z')
          B[i]=B[i]-'A'+'a';
   }
   for(i=0;i<lm;i++)
   {
       B[i]=((B[i]-'a')+(A[i%j]-'a'))%26;
       printf("%c",B[i]+'a');
   }
   

       
    /*********** End ***********/
}




任务3描述

本关任务:编写一个能周期置换密码的小程序。

相关知识

为了完成本关任务,你需要掌握:1.置换密码,2.置换矩阵。

周期置换密码

前面讨论的密码体制都是代换密码:明文字母被不同的字母所代替。置换密码的特点是保持明文的所有字母不变,只是利用置换打乱了明文字母的位置和次序。 置换密码的使用已经有数百年的历史,最早在1563年 Porta 就给出了置换密码和代换密码的具体区别。 下面给出置换密码的定义: 令 m 为一正整数 K由所有定义在集合1,2,...,m上的置换组成。对任意的密钥π,定义加密变换: 相应的解密变换为: 上式中π−1 为置换π的解密变换。 下面给出一个例子: 设m=6,密钥为置换π=(3 5 1 6 4 2),置换表可表示为:

给定明文cryptography,按照下面方法进行周期置换: 密钥长度是6,所以按周期长度6对明文分组。明文分组为:crypto∣graphy,再利用置换密钥π进行加密变换,得: E(crypto)=(ytcopr) E(graphy)=(ahgypr) 即密文消息为ytcoprahgypr。 显然由加密置换可求出逆置换,π−1 =(3 6 1 5 2 4), 根据密文和逆置换π−1, 即可直接求出明文。

编程要求

根据提示,在右侧编辑器补充代码,输入密钥长度、置换密钥和明文,输出密文。

测试说明

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

测试输入:3 3 2 1 qwerty 预期输出:ewqytr

测试输入:4 4 1 3 2 abcdefghi 预期输出:dacbhegfi


开始你的任务吧,祝你成功!

#include<bits/stdc++.h>
using namespace std;
#define mod 26
char A[100];
int K1[100],K2[100];
int n;
//在begin和end之间补充代码
/*********** Begin ***********/
struct node
{
    int x;
    char p;
}N[100];
int main()
{
    cin>>n;
    for(int i=0;i<n;++i)
    {
        cin>>K1[i];
        K2[K1[i]-1]=i;
    }
    cin>>A;
    for(size_t i=0;i<strlen(A);++i)
    {
        N[i].x=i;
        N[i].p=A[i];
    }
    for(size_t i=0;i<strlen(A);i+=n)
    {
        sort(N+i,N+i+n,[&](node X,node Y)
        {
            return K2[X.x%n]<K2[Y.x%n];
        });
        for(size_t j=i;j<i+n;j++)
        {
            cout<<N[j].p;
        }

    }



 /*********** End ***********/
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值