Python实现希尔加密/解密

希尔加密的原理就不多讲了,直接上代码。

定义一个函数:def fun(s, mod1, mod2, key)

s:要加密/解密的字符串

mod1:加密或解密

mod2:A=0或A=1,目前网络上的希尔加密都不是统一的,两种模式得出的结果是不一样的。

key:密钥,转换为矩阵后必须为方阵且可逆

要有传入的参数,key的长度为平方数,否则return

#边界条件    
    if not s:
        return "请输入密文"
    if not key:
        return "请输入密钥"
    l = int(len(key) ** 0.5)
    if l ** 2 != len(key):
        return "请输入有效密钥"
#统一转成小写字母,便于将字符串转成矩阵
s = s.lower()
key = key.lower()
#确定矩阵的长和宽
if len(s) % l == 0:
    s_w = len(s) // l
else:
    s_w = len(s) // l + 1
s_h = l
#初始化矩阵列表
ss = [[0 for _ in range(s_w)] for _ in range(s_h)]
keys = [[0 for _ in range(l)] for _ in range(l)]

对于上述的处理:不论加密还是解密,都是密钥x密文,或密钥的逆x密文,所以密文的高为密钥的边长,宽为:刚好构成一个矩阵,宽为总长度//l,不够则宽为总长度//l + 1。

下面对A=0和A=1分别处理s和key

#注意,矩阵是按列插入字母,如abcd,放到矩阵里是
#ac
#bd
#这里理解就行,不一定像我这样写    
    if mod_2 == "0":
        for i in range(len(s)):
            x = i // l
            y = i % l
            ss[y][x] += (ord(s[i]) - 97)
        for i in range(len(key)):
            x = i // l
            y = i % l
            keys[y][x] += (ord(key[i]) - 97)
    elif mod_2 == "1":
        for i in range(len(s)):
            x = i // l
            y = i % l
            ss[y][x] += (ord(s[i]) - 96)
        for i in range(len(key)):
            x = i // l
            y = i % l
            keys[y][x] += (ord(key[i]) - 96)
    else:
        pass

用numpy处理刚刚的列表,让他们可以进行乘法运算。

ss = np.array(ss)
keys = np.array(keys)

对于密钥不可逆,直接return,如果为解密,则让他逆

    if mod_1 == "d":
        try:
            keys = np.linalg.inv(keys)
        except Exception:
            return "密钥不可逆QAQ"

结果为

res = np.matmul(keys, ss)

最后将结果转为字符串

注意:

将矩阵的结果先模26,否则可能得不出正确结果

​
    for i in range(s_w):
        for j in range(l):
            if mod_2 == "0":
                it += chr((int(res[j][i]) % 26) + 97)
            else:
                it += chr((int(res[j][i])-1 % 26) + 97)

​

下面是完整代码

​
# 希尔加密/解密
def hill_ed(s, mod_1, mod_2, key):
    if not s:
        return "请输入密文"
    if not key:
        return "请输入密钥"
    l = int(len(key) ** 0.5)
    if l ** 2 != len(key):
        return "请输入有效密钥"
    s = s.lower()
    key = key.lower()
    if len(s) % l == 0:
        s_w = len(s) // l
    else:
        s_w = len(s) // l + 1
    s_h = l
    ss = [[0 for _ in range(s_w)] for _ in range(s_h)]
    keys = [[0 for _ in range(l)] for _ in range(l)]
    if mod_2 == "0":
        for i in range(len(s)):
            x = i // l
            y = i % l
            ss[y][x] += (ord(s[i]) - 97)
        for i in range(len(key)):
            x = i // l
            y = i % l
            keys[y][x] += (ord(key[i]) - 97)
    elif mod_2 == "1":
        for i in range(len(s)):
            x = i // l
            y = i % l
            ss[y][x] += (ord(s[i]) - 96)
        for i in range(len(key)):
            x = i // l
            y = i % l
            keys[y][x] += (ord(key[i]) - 96)
    else:
        pass
    ss = np.array(ss)
    keys = np.array(keys)
    if mod_1 == "d":
        try:
            keys = np.linalg.inv(keys)
        except Exception:
            return "密钥不可逆QAQ"
    res = np.matmul(keys, ss)
    it = ""
    for i in range(s_w):
        for j in range(l):
            if mod_2 == "0":
                it += chr((int(res[j][i]) % 26) + 97)
            else:
                it += chr((int(res[j][i])-1 % 26) + 97)
    return it

​

该工具已收录于https://www.awwwtaaa.net,点击右上角工具即可进入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值