仿射密码实验——Python实现(完整解析版)

文章目录

  • 前言
  • 实验内容
  • 实验操作步骤
    • 1.编写主程序
    • 2.编写加密模块
    • 3.编写解密模块
    • 4.编写文件加解密模块
  • 实验结果
  • 实验心得
  • 实验源码
    • scirpt.py
    • usefile.py


前言

实验目的
1)初步了解古典密码
2)掌握仿射密码的实现

实验方法
根据下图仿射密码(变换)加解密的描述,用所熟悉的语言,完成实验内容、描述实验操作步骤、实验结果与实验心得。

实验环境
计算机语言:Python
开发环境:Pycharm


原理
在这里插入图片描述

实验内容

  1. 编程实现仿射密码,要求有加密步骤和解密步骤。若输入参数a,b不合法,则报错。
  2. 提供两种解密方法,一是掌握密钥破解,而是无密钥的暴力破解
  3. 使用两种加解密的操作,一是命令行的输入输出,而是文件的读取写入生成
  4. 加解密过程中应考虑大小写

实验操作步骤

1.编写主程序

在main主程序里,需要有相应的功能提示

作为菜单栏使用
不同的数字对应实现不同的功能:1加密2解密3文件形式加解密4退出程序
在这里插入图片描述

2.编写加密模块

需求有:提示输入明文和密钥,对明文进行仿射密码方式的加密,最后输出
在这里插入图片描述

m接收用户输入的明文
c作为数组来存储,a和b就是密钥需要用户提供
对于输入的a和b需整形化,然后判断a、b是否互素通过ab的最大公因数是否为1判断
若不互素则提示用户重新输入

达成互素条件后
首先采用正则表达式处理一下用户输入一些特殊符号
(如果不处理的话,那么形成的密文最后也是解密不了的)
接着采用replace去除空格
进入encrypt模块
在这里插入图片描述

在这个模块中,原理就是将之前用户输入的参数m,a,b传入
然后通过先转化成ascii码和进行模运算,这里计算得到的ascii码chr后,得到的是大写的英文字母,为此最后输出的时候提供给用户两种结果:大写和小写

3.编写解密模块

首先提示输入密文,考虑之前我们加密后的结果一般都是只有英文字母的组合
这里我就只有进行大小写的处理
提示用户是否知道密钥,若有则接受参数a和b,同样得判断a,b是否互素来确认密钥的合法性
然后由a计算出k,再传入decrypt模块解密
在这里插入图片描述

解密其实就是加密数学上的逆运算
这里刚刚好相反,通过一系列计算得到的是一串小写英文字母
那与之前一样,我们需要给用户提供大写和小写的结果
在这里插入图片描述

假如选择不知道密钥的话,那么就是采用暴力破解
也就是数字组合一个个试,这里通过对仿射原理的理解便可以缩小点范围
定义的la数组和lb数组分别如图

4.编写文件加解密模块

在这里插入图片描述
这个文件我命名为usefile.py,并且作为库来给之前的脚本代码引用
在这里插入图片描述
这个文件其实和之前的代码以及实现的功能差不多
不过为了代码看起来不那么冗长,就单独再写一个模块了
以下是该代码的展示

密钥的输入
在这里插入图片描述

互素条件的判断
在这里插入图片描述
逆元的求解
在这里插入图片描述
文件加密
在这里插入图片描述

文件解密
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主函数模块
在这里插入图片描述

实验结果

开始使用程序
运行script.py
在这里插入图片描述

输入数字1
在这里插入图片描述
我们用hello作为例子,密钥就为3和4吧
在这里插入图片描述
得到密文为ZQLLU 或 zqllu
在这里插入图片描述
这次试一下特殊符号
输入hell,,!!o
可以看到加密结果与之前一致
在这里插入图片描述
那我们现在试着解密
输入之前的密文zqllu,先按照有密钥解密
在这里插入图片描述
得到hello说明正确
再试一下无密钥暴力破解
在这里插入图片描述
这一次故意输入大写的ZQLLU,然后寻找一下正确的明文
在这里插入图片描述
Ok,与我们之前有密钥解出来结果一致,说明代码可行
好的,我们来看看文件模块运行如何
在这里插入图片描述
出现usefile里特有的菜单模块
事先我创建了一个test.txt,里面内含明文hello
运行功能1看看

在这里插入图片描述
在这里插入图片描述
然后当前目录下多了ciphertext.txt文件,查看该文件
在这里插入图片描述
结果没错
我们再试解密功能
在这里插入图片描述
该目录下多出plaintext.txt文件,查看该文件
在这里插入图片描述

还原成功,是明文hello
这里是提供了密钥,如果暴力破解就是和之前script文件中一致

实验心得

作为古典密码的一种,仿射密码的原理其实挺简单的,所以这次使用python来实现关于仿射密码的加解密难度不大,中间遇到的一些问题还是让我收获不少:加解密时要注意英文字母大小写、特殊符号需要处理、chr和ord的配合使用、编写不同的函数模块和文件来实现CLI版的功能等等,让我对于python的使用更加的得心应手。

很喜欢python的话语:人生苦短,我用python。
希望之后继续使用python解决有关密码学的问题。

实验源码

scirpt.py

# 暴力破解
import usefile as u
import re

la = [1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25]
lb = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
      14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]

# 最大公约数
def gcd(a, b):
    while b != 0:
        tem = a % b
        a = b
        b = tem
    return a

# 加密
def encrypt(m, c, a, b):
    for i in range(len(m)):
        # 加密成相应的大写字母
        c.append(chr(((ord(m[i]) - 97) * a + b) % 26 + 65))
    d = ''.join(c)
    print(d,"或 {}".format(d.lower()))

# 求逆元
def niyuan(a, b):
    ny = 1
    while (a * ny) % b != 1:
        ny += 1
    return ny

# 解密
def decrypt(c, k, b):
    mw = []
    for i in range(len(c)):
        tem = ord(c[i]) - 65 - b
        if tem < 0:
            tem += 26
        mw.append(chr((k * tem) % 26 + 97))
    print("k=" + str(k) + ", b=" + str(b) + "时,解密后的明文为:")
    res = ''.join(mw)
    print(res,"或 {}".format(res.upper()))

def jiami():
    m = input("请输入明文:")
    c = []
    x, y = input("请输入a和b: ").split()
    a = int(x)
    b = int(y)
    while gcd(a, b) != 1:
        x, y = input("a和b不互素,请重新输入a和b: ").split()
        a = int(x)
        b = int(y)
    print("明文内容为:")
    print(m)
    r = "[!!+-=——,,。??、]"
    m = re.sub(r, ' ', m)
    m = m.replace(' ', '')
    print("加密后的密文为:")
    encrypt(m, c, a, b)


def jiemi():
    m = input("请输入密文:")
    c = []
    q = input("是否有密钥,有请输入1,无则输入0:")
    print("密文内容为:")
    print(m)
    if int(q)==1:
        x, y = input("请输入a和b: ").split()
        a = int(x)
        b = int(y)
        while gcd(a, b) != 1:
            x, y = input("a和b不互素,请重新输入a和b: ").split()
            a = int(x)
            b = int(y)
        m = m.upper()
        for i in range(len(m)):
            # 加密成相应的大写字母
            c.append(m[i])
        print("知道密钥破解:")
        k = niyuan(a, 26)
        decrypt(c, k, b)

    elif int(q)==0:
        m = m.upper()
        # 加密成相应的大写字母
        for i in range(len(m)):
            c.append(chr(ord(m[i])))
        print("不知道秘钥破解,暴力破解如下: ")
        for i in range(0, 12):
            for j in range(0, 26):
                decrypt(c, la[i], lb[j])

#实现
if __name__ == "__main__":
    # 明文
    while True:
        print("-------------------------")
        print("1.仿射密码加密")
        print("2.仿射密码解密")
        print("3.文件仿射加解密")
        print("4.程序退出")
        n = input("请输入功能对应的数字:")
        print("-------------------------")
        if int(n)==1:
            jiami()
        elif int(n)==2:
            jiemi()
        elif int(n)==3:
            u.main()
        elif int(n)==4:
            print("感谢使用!")
            break
        else:
            print("输入有误,请重新输入!")

usefile.py

#仿射密码加密与解密实现算法
# -*- coding=utf-8 -*-

#输入密钥
def accept():
	k1,k2 = map(int,input('请输入两个密钥(以空格隔开):').split())
	while gcd(k1, 26) !=1:
		k1,k2 = map(int,input('k1和26不互素,请重新输入密钥:').split())
	return k1,k2

#判断互素
def gcd(k1,m):
	t = 0
	while m!=0:
		t = m
		m = k1%m
		k1 = t
	return k1

#求逆元
def niyuan(k1):
	n = 1
	while (k1 * n) % 26 != 1:
		n += 1
	return n

#加密算法
def encrypt():
	#输入密钥
	k1,k2 = accept()
	n = input("请输入当前目录下需要加密文件名:")
	f = open(n)
	plain = f.read()
	#print(plain)
	c = []
	for i in range(len(plain)):
		#小写字母
		if plain[i].islower():
			c.append(chr(((ord(plain[i])-97)*k1+k2)%26+97))
		#大写字母
		elif plain[i].isupper():
			c.append(chr(((ord(plain[i])-65)*k1+k2)%26+65))
		#其他
		else :
			c.append(plain[i])

	cipher = ''.join(c)
	w = open('ciphertext.txt','w')
	w.write(cipher)
	print('加密完成!')
	f.close()
	w.close()

#解密算法
def decrypt():
	#输入密钥
	k1,k2 = accept()
	#逆元
	ny = niyuan(k1)
	str = input("请输入当前目录下需要解密文件名:")
	f = open(str)
	cipher = f.read()
	p = []
	for i in range(len(cipher)):
		#小写字母
		if cipher[i].islower():
			t1 = ord(cipher[i])-97-k2
			if t1 < 0:
				t1 +=26
			p.append(chr((ny * t1)%26+97))
		#大写字母
		elif cipher[i].isupper():
			t2 = ord(cipher[i])-65-k2
			if t2 < 0:
				t2 +=26
			p.append(chr((ny * t2)%26+65))
		#其他
		else :
			p.append(cipher[i])

	plain = ''.join(p)
	w = open('plaintext.txt','w')
	w.write(plain)
	print('解密完成!')
	f.close()
	w.close()

def main():
	while True:
		print("--------文件加解密操作--------")
		print("加密【1】:")
		print("解密【2】:")
		print("退出【3】:")
		ch = int(input("请输入对应功能数字:"))
		if ch == 1:
			encrypt()
		elif ch == 2:
			decrypt()
		elif ch == 3:
			print("感谢使用!")
			exit()
		else:
			print("请输入1或2")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955216.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在 QNAP NAS中使用 Container Station 运行 Docker 的完整指南

QNAP 为用户提供了一个名为 Container Station 的应用&#xff0c;它在 QNAP NAS 上将 Docker 和 LXC 结合在一起&#xff0c;通过图形化界面&#xff0c;让用户更轻松地在 NAS 上管理容器。本文将带你一步步了解如何在 QNAP NAS 上安装和使用 Container Station&#xff0c;以…

基于vite+vue3+mapbox-gl从零搭建一个项目

下面是基于 Vite、Vue 3 和 Mapbox GL 从零搭建一个项目的完整步骤&#xff0c;包括环境搭建、依赖安装、配置和代码示例。 文章目录 1. 初始化项目2. 安装 mapbox-gl 依赖3. 配置 Mapbox Access Token4. 实现地图组件5. 在 App.vue 中使用地图组件6. 启动开发服务器7. 添加自定…

运维作业一

1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容&#xff0c;不存在则创建一个文件将创建时间写入。 2、写一个 shel1 脚本,实现批量添加 20个用户,用户名为user01-20,密码为user 后面跟5个随机字符。 首先&#xff0c;获得随机字符&#xff0c;需下载pwgen&am…

【拒绝算法PUA】3065. 超过阈值的最少操作数 I

系列文章目录 【拒绝算法PUA】0x00-位运算 【拒绝算法PUA】0x01- 区间比较技巧 【拒绝算法PUA】0x02- 区间合并技巧 【拒绝算法PUA】0x03 - LeetCode 排序类型刷题 【拒绝算法PUA】LeetCode每日一题系列刷题汇总-2025年持续刷新中 C刷题技巧总结&#xff1a; [温习C/C]0x04 刷…

SSE部署后无法连接问题解决

1. 问题现象 通过域名访问 https://api-uat.sfxs.com/sse/subscribe?tokenBearer%20eyJUxMiJ9.eyJhY2NvdW50IjoiYWRtaWZ0NvZGUiOiIwMDEiLCJyb2xidXNlcm5hbWUiOiLotoXnuqfnrqHnkIblkZgifQ.tlz9N61Y4 一直无法正常连接 2. 问题解决 nginx.conf进行配置 server {location /ss…

JS宏进阶: 工厂函数与构造函数

一、构造函数 在JavaScript中&#xff0c;构造函数是一种用于创建和初始化对象的特殊函数。构造函数的名字通常以大写字母开头&#xff0c;以区分于普通函数。通过new关键字调用构造函数&#xff0c;可以创建一个新的实例对象&#xff0c;并自动执行构造函数内部的代码来初始化…

编译pytorch——cuda-toolkit-nvcc

链接 https://blog.csdn.net/wjinjie/article/details/108997692https://docs.nvidia.com/cuda/cuda-installation-guide-linux/#switching-between-driver-module-flavorshttps://forums.developer.nvidia.com/t/can-not-load-nvidia-drivers-on-ubuntu-22-10/239750https://…

光谱相机的光谱分辨率可以达到多少?

多光谱相机 多光谱相机的光谱分辨率相对较低&#xff0c;波段数一般在 10 到 20 个左右&#xff0c;光谱分辨率通常在几十纳米到几百纳米之间&#xff0c;如常见的多光谱相机光谱分辨率为 100nm 左右。 高光谱相机 一般的高光谱相机光谱分辨率可达 2.5nm 到 10nm 左右&#x…

案例 —— 怪物出水

目录 一&#xff0c;Ocean Setup 二&#xff0c;Water Setup 解算前设置 解算设置 解算后设置 三&#xff0c;Meshing Setup Meshing 剔除外围边界mesh 应用低频频谱变形并添加变形速度 为whitewater创建自定义的surface、vel 清理属性和组并缓存 四&#xff0c;Wh…

怎么在iPhone手机上使用便签进行记录?

宝子们&#xff0c;在这个快节奏的时代&#xff0c;灵感的火花总是一闪而过&#xff0c;待办事项也常常让人应接不暇。好在咱们的 iPhone手机便签超给力&#xff0c;能满足各种记录需求&#xff01;今天就来给大家分享一下&#xff0c;如何在 iPhone 手机上巧用便签&#xff0c…

2025宝塔API一键建站系统PHP源码

源码介绍 2025宝塔API一键建站系统PHP源码&#xff0c;对接自己的支付&#xff0c;虚拟主机也能搭建&#xff0c;小白式建站系统&#xff0c;基于宝塔面板搭建的建站系统&#xff0c;功能丰富&#xff0c;多款模板&#xff0c;每日更新 上传源码到服务器&#xff0c;浏览器访问…

【C++】拷贝构造函数与运算符重载

写在前面 拷贝构造函数、赋值运算符重载、取地址运算符都是属于类的默认成员函数&#xff01; 默认成员函数是程序猿不显示声明定义&#xff0c;编译器会中生成。 在程序编写中&#xff0c;我们也经常使用拷贝的方式来获取到对应的值&#xff0c;例如整形变量拷贝int a 0; i…

Linux:SystemV通信

目录 一、System V通信 二、共享内存 代码板块 总结 三、信号量 信号量理论 信号量接口 一、System V通信 System V IPC&#xff08;inter-process communication&#xff09;&#xff0c;是一种进程间通信方式。其实现的方法有共享内存、消息队列、信号量这三种机制。 …

2025.1.15——七、cookie注入

题目来源&#xff1a;ctfhub技能树 目录 一、打开靶机&#xff0c;整理已知信息 二、解题步骤 step 1&#xff1a;按F12查看cookie信息&#xff0c;见上 step 2&#xff1a;bp抓包修改cookie信息&#xff0c;确认注入类型 step 3&#xff1a;查看字段数 step 4&#xff…

【简博士统计学习方法】第2章:3. 感知机——学习算法之原始形式:算法解说

3. 感知机——学习算法之原始形式&#xff1a;算法解说 3.1 学习问题 给定训练数据集&#xff1a; T { ( x 1 , y 1 ) , ( x 2 , y 2 ) ⋯ , ( x N , y N ) } T\left\{\left(x_{1}, y_{1}\right),\left(x_{2}, y_{2}\right) \cdots,\left(x_{N}, y_{N}\right)\right\} T{(x…

【Flink系列】10. Flink SQL

10. Flink SQL Table API和SQL是最上层的API&#xff0c;在Flink中这两种API被集成在一起&#xff0c;SQL执行的对象也是Flink中的表&#xff08;Table&#xff09;&#xff0c;所以我们一般会认为它们是一体的。Flink是批流统一的处理框架&#xff0c;无论是批处理&#xff08…

web漏洞扫描有什么作用?web漏洞扫描原理

Web漏洞扫描在网络安全领域中扮演着至关重要的角色&#xff0c;web漏洞扫描有什么作用&#xff1f;Web漏洞扫描能够自动化地检测Web应用中的潜在安全漏洞&#xff0c;包括但不限于SQL注入、跨站脚本&#xff08;XSS&#xff09;、跨站请求伪造&#xff08;CSRF&#xff09;、文…

【Idea启动项目报错NegativeArraySizeException】

项目场景&#xff1a; Idea启动项目报错&#xff08;打包不报错&#xff09;&#xff0c;项目在服务器部署运行没有问题&#xff0c;尝试了重启idea、重启电脑、maven clean/install 都不行 maven-resources-production:sample: java.lang.NegativeArraySizeException: -5833…

小程序组件 —— 31 事件系统 - 事件绑定和事件对象

小程序中绑定事件和网页开发中绑定事件几乎一致&#xff0c;只不过在小程序不能通过 on 的方式绑定事件&#xff0c;也没有 click 等事件&#xff0c;小程序中绑定事件使用 bind 方法&#xff0c;click 事件也需要使用 tap 事件来进行代替&#xff0c;绑定事件的方式有两种&…

sparkSQL练习

1.前期准备 &#xff08;1&#xff09;建议先把这两篇文章都看一下吧&#xff0c;然后把这个项目也搞下来 &#xff08;2&#xff09;看看这个任务 &#xff08;3&#xff09;score.txt student_id,course_code,score 108,3-105,99 105,3-105,88 107,3-105,77 105,3-245,87 1…