如何在保留字母数字文本格式的情况下进行加密

问题描述 投票:0回答:1

如何对像“A123456”这样的文本进行FPE(格式保留加密),如果加密保留了格式,我应该得到一个字符长度超过6位的字符串,例如“Z655432”,我使用了python库FF3,所以我将字符串“A123456”拆分为“A”和“123456”,并将 FF3cipher 应用于每个字符串,在这里我发现最小字符数问题,所以我必须对“A”进行一些填充,问题是当你这样做时填充你丢失了格式,你不会得到你想要的格式。

我尝试了填充,但格式没有保留,我尝试了没有最低字符要求的 pyffx 库,但显然它不安全,它没有 NIST 要求

from ff3 import FF3Cipher

key = "2DE79D232DF5585D68CE47882AE256D8"
tweak = "CB92D080979564"
alphabet = "AZERTYUIOPQSDFGHJKLMWXCVBN"
cipher = FF3Cipher.withCustomAlphabet(key, tweak, alphabet)
def pad_to_min_length_alp(text, min_len):
    pad_char = 'A'
    if len(text) < min_len:
        return text + pad_char * (min_len - len(text))
    return text
plaintext = 'A'
padded_plaintext = pad_to_min_length_alp(plaintext, cipher.minLen)
ciphertext = cipher.encrypt(padded_plaintext)
print(f"Encrypted value: {ciphertext}")

结果:加密值:SPVVY
所以A已被加密为5个字符的字符串
格式未保留

python encryption cryptography lets-encrypt encryption-symmetric
1个回答
0
投票

我注意到对于某些用户来说,在原始消息(1 个字母 + 6 个十进制数字)、[0, 26000000) 中的数字和基数为 72 的 4 位数字的字符串之间进行转换并不简单。这激励我回答这个问题。

消息空间的大小为26000000,所以需要加密[0, 26000000)中的一个整数。但这不是整数的幂,您需要循环行走,而不是分裂。我建议使用基数 72,因为 724 接近且大于 26000000。

因为

ff3
库不支持数字作为输入,所以你应该将原始消息转换为数字,然后将其转换为基数为72的4位数字的字符串。设基数72的数字为
''.join(chr(e) for e in range(72))
。例如,在加密
'Z123456'
时,它会先转换为
25123456 = 67*72**3 + 22*72**2 + 24*72 + 64
,然后再转换为
'\x43\x16\x18\x40'
。您需要使用
ff3
加密该字符串,并将输出密文转换为数字。如果解码后的数字大于
26000000 - 1
,则需要重新加密。这就是循环行走。

以下是一个实现示例。

import math
import ff3

RADIX = 72
MAX_NUM = 26*1000000
N_DIGITS = math.ceil(math.log(MAX_NUM) / math.log(RADIX))
DIGITS = ''.join(chr(e) for e in range(RADIX))

def msg_to_num(msg):
    return (ord(msg[0]) - ord('A')) * 1000000 + int(msg[1:])

def num_to_msg(num):
    q, r = divmod(num, 1000000)
    return '%c%06d' % (q + ord('A'), r)


def num_to_digits(num):
    digits = [None] * N_DIGITS
    for i in range(N_DIGITS):
        num, r = divmod(num, RADIX)
        digits[N_DIGITS-1 - i] = DIGITS[r]
    return ''.join(digits)

def digits_to_num(digits):
    num = 0
    for i in range(N_DIGITS):
        num = num * RADIX + DIGITS.index(digits[i])
    return num


cipher = ff3.FF3Cipher.withCustomAlphabet(
    b'key0123456789012'.hex(), b'tweak012'.hex(), DIGITS)
def encrypt(pt):
    num = msg_to_num(pt)
    i = 0
    while True:
        num = digits_to_num(cipher.encrypt(num_to_digits(num)))
        i += 1
        if num < MAX_NUM:
            break
    return num_to_msg(num)

def decrypt(ct):
    num = msg_to_num(ct)
    i = 0
    while True:
        num = digits_to_num(cipher.decrypt(num_to_digits(num)))
        i += 1
        if num < MAX_NUM:
            break
    return num_to_msg(num)

pt = 'Z123456'
ct = encrypt(pt)
print('ct:', ct)
pt2 = decrypt(ct)
print('pt2:', pt2)
© www.soinside.com 2019 - 2024. All rights reserved.