古典密码(1)

1.凯撒密码

明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是3的时候(向左偏移3个字母),所有的字母A将被替换成D,B变成E

恺撒密码的替换方法是通过排列明文和密文字母表,密文字母表示通过将明文字母表向左或向右移动一个固定数目的位置。例如,当偏移量是左移3的时候(解密时的密钥就是3):

明文字母表:ABCDEFGHIJKLMNOPQRSTUVWXYZ ;

密文字母表:DEFGHIJKLMNOPQRSTUVWXYZABC。

使用时,加密者查找明文字母表中需要加密的消息中的每一个字母所在位置,并且写下密文字母表中对应的字母。需要解密的人则根据事先已知的密钥反过来操作,得到原来的明文。例如:

明文:THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG ;

密文:WKH TXLFN EURZQ IRA MXPSV RYHU WKH ODCB GRJ。

恺撒密码的加密、解密方法还能够通过同余的数学方法进行计算。首先将字母用数字代替,A=0,B=1,...,Z=25。此时偏移量为n的加密方法即为:

解密就是:

工具:(1)凯撒密码 加密/解密 - 在线工具 (toolhelper.cn)

(2)利用python代码实现

方法一

加密

str=input("请输入明文:")
n=int(input("请输入密钥:"))
str_encrypt=""
for letter in str:
    if letter==" ":  #遇到空格选择不加密
        letter_encrypt=" "
    else:
        letter_encrypt=chr((ord(letter)-ord("a") +n) %26 +ord("a"))
    str_encrypt += letter_encrypt
print("密文为:",str_encrypt)

解密

str=input("请输入密文:")
n=int(input("请输入密钥:"))
str_decrypt=""
for word in str:
    if word==" ":  #遇到空格选择不解密
        word_decrypt=" "
    else:
        word_decrypt=chr((ord(word)-ord("A") -n) %26 +ord("A"))
    str_decrypt = str_decrypt+word_decrypt
print("明文为:",str_decrypt)

方法二:利用函数 

str = input("请输入一段英文:")
key = int(input("请输入密钥:"))
enc = int(input("0 - 解密\n1 - 加密\n请选择 0 或者 1: "))
str_enc = ""
str_dec = ""

if enc == 1:  #加密
    for i in str:  #用i进行遍历
        if i.isupper():  #isupper函数判断i是否为大写字母
            i_unicode = ord(i)  #找到“i”对应的Unicode码
            i_index = ord(i) - ord("A")  #计算字母“i”到A(起始)的间距
            new_index = (i_index + key) % 26
            new_unicode = new_index + ord("A")
            new_character = chr(new_unicode)  #将Unicode码转换为字符
            str_enc += new_character
        elif i.islower():  #如果“i”为小写字母
            i_unicode = ord(i)
            i_index = ord(i) - ord("a")
            new_index = (i_index + key) % 26
            new_unicode = new_index + ord("a")
            new_character = chr(new_unicode)
            str_enc = str_enc + new_character
        else:  #数字或符号
            str_enc += i  #直接返回“i”
    print("密文为:",str_enc)

else:  #解密
    for k in str:
        if k.isupper():
            k_unicode = ord(k)
            k_index = ord(k) - ord("A")
            new_index = (k_index - key) % 26
            new_unicode = new_index + ord("A")
            new_character = chr(new_unicode)
            str_dec = str_dec + new_character
        elif k.islower():
            k_unicode = ord(k)
            k_index = ord(k) - ord("a")
            new_index = (k_index - key) % 26
            new_unicode = new_index + ord("a")
            new_character = chr(new_unicode)
            str_dec += new_character 
        else:
            str_dec += k
    print("明文为:",str_dec)

2.栅栏密码 

把要加密的明文分成N个一组,然后把每组的第1个字连起来,形成一段无规律的话

加密原理

①把将要传递的信息中的字母交替排成上下两行。

②再将下面一行字母排在上面一行的后边,从而形成一段密码。

③例如:

明文:THE LONGEST DAY MUST HAVE AN END

加密:

1、把将要传递的信息中的字母交替排成上下两行。

T E O G S D Y U T A E N N

H L N E T A M S H V A E D

2、 密文:

将下面一行字母排在上面一行的后边。

TEOGSDYUTAENN HLNETAMSHVAED

解密:

先将密文分为两行

T E O G S D Y U T A E N N

H L N E T A M S H V A E D

再按上下上下的顺序组合成一句话

明文:THE LONGEST DAY MUST HAVE AN END

工具:(1)栅栏密码在线加密解密 - 千千秀字 (qqxiuzi.cn)

 (2)python代码实现

import math

def fun_deCrypto(string_M, Ek):
    Dk = int(len(string_M) / Ek)
    string_C = ''
    yushu = len(string_M) % Ek
    steps = []
 
    if len(string_M) % Ek == 0:
        print('不存在余数')
        step = Dk
        for i in range(Ek):
            steps.append(step)
        print(steps)
 
    else:
        print('存在余数')
 
        big_step = math.ceil(len(string_M) / Ek)
        small_step = int(len(string_M) / Ek)
        for p in range(yushu):
            steps.append(big_step)
        for q in range(Ek - yushu):
            steps.append(small_step)
        print(steps)
 
    n_column = 0
    while n_column < math.ceil(len(string_M) / Ek):
        count_steps = 0
        for one_step in steps:
            if len(string_C) == len(string_M):
                break
            else:
                string_C += string_M[n_column + count_steps]
                count_steps += one_step
        n_column += 1
    return string_C

string_M = input("请输入密文:")
Ek = int(input("请输入加密分组中的字符个数:"))

plaintext = fun_deCrypto(string_M, Ek)
print("明文为:", plaintext)

3.维吉尼亚密码

是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。

在一个凯撒密码中,字母表中的每一字母都会作一定的偏移,例如偏移量为3时,A就转换为了D、B转换为了E……而维吉尼亚密码则是由一些偏移量不同的恺撒密码组成。

图1.表格法

为了生成密码,需要使用表格法。这一表格(如图1所示)包括了26行字母表,每一行都由前一行向左偏移一位得到。具体使用哪一行字母表进行编译是基于密钥进行的,在过程中会不断地变换。

例如,假设明文为:

ATTACKATDAWN

选择某一关键词并重复而得到密钥,如关键词为LEMON时,密钥为:

LEMONLEMONLE

对于明文的第一个字母A,对应密钥的第一个字母L,于是使用表格中L行字母表进行加密,得到密文第一个字母L。类似地,明文第二个字母为T,在表格中使用对应的E行进行加密,得到密文第二个字母X。以此类推,可以得到:

明文:ATTACKATDAWN密钥:LEMONLEMONLE密文:LXFOPVEFRNHR

解密的过程则与加密相反。例如:根据密钥第一个字母L所对应的L行字母表,发现密文第一个字母L位于A列,因而明文第一个字母为A。密钥第二个字母E对应E行字母表,而密文第二个字母X位于此行T列,因而明文第二个字母为T。以此类推便可得到明文。

用数字0-25代替字母A-Z,维吉尼亚密码的加密文法可以写成同余的形式:

解密方法则能写成:

工具:

在线维吉尼亚密码加密解密 (lddgo.net)

4.培根密码

培根所用的密码是一种本质上用二进制数设计的,没有用通常的0和1来表示,而是采用a和b

 

加密者需使用两种不同字体,分别代表A和B。准备好一篇包含相同AB字数的假信息后,按照密文格式化假信息,即依密文中每个字母是A还是B分别套用两种字体。

解密时,将上述方法倒转。所有字体一转回A,字体二转回B,以后再按上表拼回字母

import re

alphabet = ['a', 'b']

first_cipher = ["aaaaa", "aaaab", "aaaba", "aaabb", "aabaa", "aabab", "aabba", "aabbb", "abaaa", "abaab", "ababa", "ababb", "abbaa", "abbab", "abbba", "abbbb", "baaaa", "baaab", "baaba", "baabb", "babaa", "babab", "babba", "babbb", "bbaaa", "bbaab"]

second_cipher = ["aaaaa", "aaaab", "aaaba", "aaabb", "aabaa", "aabab", "aabba", "aabbb", "abaaa", "abaaa", "abaab", "ababa", "ababb", "abbaa", "abbab", "abbba", "abbbb", "baaaa", "baaab", "baaba", "baabb", "baabb", "babaa", "babab", "babba", "babbb"]

def encode():
    string = input("Please input string to encode:\n")
    e_string1 = ""
    e_string2 = ""
    for index in string:
        if index in alphabet:
            i = alphabet.index(index)
            e_string1 += first_cipher[i]
            e_string2 += second_cipher[i]
    print("First encode method result is:\n" + e_string1)
    print("Second encode method result is:\n" + e_string2)

def decode():
    e_string = input("Please input string to decode:\n")
    e_array = re.findall(".{5}", e_string)
    d_string1 = ""
    d_string2 = ""
    for index in e_array:
        if index in first_cipher:
            i = first_cipher.index(index)
            d_string1 += alphabet[i]
        if index in second_cipher:
            i = second_cipher.index(index)
            d_string2 += alphabet[i]
    print("First decode method result is:\n" + d_string1)
    print("Second decode method result is:\n" + d_string2)

if __name__ == '__main__':
    while True:
        print("\t******* Bacon Encode_Decode System *******")
        print("Input should be lowercase, cipher should only include 'a' and 'b'.")
        print("1. Encode\n2. Decode\n3. Exit")
        s_number = input("Please input the number to choose:\n")
        if s_number == "1":
            encode()
            input()
        elif s_number == "2":
            decode()
            input()
        elif s_number == "3":
            break
        else:
            continue

5.仿射密码

1.仿射密码结合了移位密码和乘数密码的特点,是移位密码和乘数密码的组合。
2.仿射密码的加密算法就是一个线性变化,即对明文字符x,对应的密文字符为y=ax+b(mod26)其中,a, b属于Z26gcd(a,b)=1
3.实现过程:

  • 选取a,b两个参数,其中gcd(a, 26)=1
  • 加密变换: c= a∗𝑚+b 𝑚𝑜𝑑 26
    a=1时,移位密码
    b=1时,乘数密码
  • 解密变换: 𝑚= (c−b)∗a^(−1) 𝑚𝑜𝑑 26
# 暴力破解
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)

# 求逆元
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)

#实现
if __name__ == "__main__":
    # 明文
    m = 'ifnottothesunforsmilingwarmisstillinthesuntherebutwewilllaughmoreconfidentcalmifturnedtofoundhisownshadowappropriateescapethesunwillbethroughtheheartwarmeachplacebehindthecornerifanoutstretchedpalmcannotfallbutterflythenclenchedwavingarmsgivenpowerificanthavebrightsmileitwillfacetothesunshineandsunshinesmiletogetherinfullbloom'
    # 密文
    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)
    print("加密后的密文为:")
    encrypt(m, c, a, b)
    print("知道密钥破解:")
    k = niyuan(a, 26)
    decrypt(c, k, b)
    print("不知道秘钥破解,暴力破解如下: ")
    for i in range(0, 12):
        for j in range(0, 26):
            decrypt(c, la[i], lb[j])

 刷题记录

1.[AFCTF 2018]Vigenère

下载附件,得到一个c文件和txt文件

 打开txt文件,根据题目提示可知是维吉尼亚密码,利用工具进行解密,将明文复制到一个空白文档,搜索flag即可获得flag

2. [HGAME 2022 week3]Multi Prime RSA

打开附件,是变形的RSA加密,变形处为 n = p ** 2 * q ** 3 * r ** 5 * s ** 7:

phi=p ** (2 - 1) * (p - 1) * q ** 2 * (q - 1) * r ** 4 * (r - 1) * s ** 6 * (s - 1)

phi是欧拉函数值,phi(ϕ)被计算为五个因子的乘积,每个因子都是通过对相应的素数进行操作得到的

import gmpy2
import binascii

p = 61789932148719477384027458333380568978056286136137829092952317307711908353477
q = 91207969353355763685633284378833506319794714507027332929290701748727534193861
r = 105471299607375388622347272479207944509670502835651250945203397530010861809367
s = 83153238748903772448138307505579799277162652151244477391465130504267171881437
e = 65537
n = 1039344372165087100001063920598151812324151064684841845250974758525265148567706103784958424873181721352440209284812493753972556519482026327282644619091466886523804841248277210353173383407944598453848113815866908595335619458549486958764490103808475329598085842184963065068499489886467911087295087163762599284622055185456905774507245781667293199205317692029829495961487347944813874415423771980660778986211145841712412631156369129146470119135136378158203459576596246169191419488560832734046076107673091995860021863239882608638458149930255944184863801278386551031980146460231515747754411678651752698881001464973981424240781413084941947261875289725538959720572496329348499870580057997540844488309111059240745081048324762866572948371222839278718034435739827677190025500802453626872356208612718417249649474571197167076916403582394186357812640566250930361276229969553128128312736245440129556020108188835966131425956431796417720436474093381770796431629523054378258497546013222494974549262140415585158985940966415459478150722832119691308697510189026447359189994055885090735411738332296254011208547676914004864732327863884217733456287369771087094514708468685641820375220835485053482570852619363091173324203334503461823983610886849930944250553928855506012684504211525542998575275626784129736345142772399109273619522445919
c = 844677395496466411520394190869787261209960246734415406217975986418865760680024542119231873259131861208878522030009923057991526761346423130242121884493257732067700857897379859545356609151834223804262174935191718271211809221730601602827122249238086030580971376104724987801049500689134122609834321586609223761140538079460830213824674361601046367637227094018381901291488659642720549583856812747877519600804325570421770575999289389175021646347371879234023647657507178519047236746071420327155188213839293382288787853777540226192644761028822256165706787395891134765908229036044468473519166141610604791485071702808854944672418124203289328124793348198048601338476086482318248264508789781967910205393740835345086784345145351367491197717933757414967811594913692588314161669333147733048171044386546892346475181197482702164468542430187885074163177843285948999943328049159021873821254267471067523609151007885131921896462161216356454116929796355815756642621369974260365378070336290542971599886325232821981080341858950609157813769416455337935096696635623426418166316737131174435618543058086342714723330814586496030805366321181723292731710369013923285787724941830672247377301048663929453294620044701627159066468762709113137517559435822623284148112827473010030736329596829357275518641576798298066541516764673029908084962144713

phi=p ** (2 - 1) * (p - 1) * q ** 2 * (q - 1) * r ** 4 * (r - 1) * s ** 6 * (s - 1)
d=gmpy2.invert(e,phi)

m=pow(c,d,n)

print(binascii.unhexlify(hex(m)[2:]))

#b'hgame{EulEr:fUNcTIon;iS.So*IMpORTaNt*In&RsA}'

这里 使用了libnum.invmod函数来计算模逆,gmpy2是一个用于高精度计算的Python库,它提供了一系列高效的函数和算法。它支持大整数运算、模逆计算等操作,适用于处理大素数和大数值的情况。

要使用gmpy2库,您需要首先安装它。可以使用以下命令进行安装:

pip install gmpy2

 

安装完成后,您可以使用以下代码来计算模逆:

import gmpy2

d = gmpy2.invert(e, phi)

在这段代码中,gmpy2.invert函数用于计算e的模逆,其中e是公钥指数,phi是欧拉函数值。

运行得到结果

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值