即使使用一个char数据,PyCrypto Cyphertext的长度也不正确

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

我想加密/解密包含在.csv文件中的一组数据。我使用以下代码生成我的RSA公钥/私钥:

import Crypto
from Crypto.PublicKey import RSA

key = RSA.generate(2048)

k = key.exportKey('PEM')
p = key.publickey().exportKey('PEM')

with open('private.pem', 'w') as kf:
    kf.write(k.decode())
    kf.close()

with open('public.pem', 'w') as pf:
    pf.write(p.decode())
    pf.close()

with open('private.pem','r') as fk:
    priv = fk.read()
    fk.close()

with open('public.pem','r') as fp:
    pub = fp.read()
    fp.close()

privat = RSA.importKey(priv)
public = RSA.importKey(pub)

if key == privat:
    print('Private key has been successfuly write')
if key.publickey() == public:
    print('Public key has been successfuly write')

然后我用这个代码加密没有任何问题:

import Crypto
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

with open('public.pem','r') as fp:
    pub = fp.read()
    fp.close()

public = RSA.importKey(pub)

#stockage du fichier dans une variable rep
fichier = open('test.csv', 'r')
rep = fichier.read()
fichier.close()

#eliminations des spaces
rep = rep.replace(' ', '')

#encodage pour type bytes
rep = rep.encode()

#decoupage en mot de 10 chars
rep = [rep[i:i+10] for i in range(0, len(rep), 10)]

cipher = PKCS1_OAEP.new(public)

fichier2 = open('encrypted.csv', 'a')
for i in rep:
    encrypted_line = cipher.encrypt(i)
    fichier2.write(str(encrypted_line))
    fichier2.write('\n')

fichier2.close()

我可以通过修改此行来修改我的数据分离方式:

rep = [rep [i:i + n] for i in range(0,len(rep),n)]

这一行用n个字符组分隔我的数据

这里我的代码解密数据,它提出:

ValueError:长度不正确的密文。

import Crypto
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

with open('private.pem','r') as fk:
    priv = fk.read()
    fk.close()

private = RSA.importKey(priv)

fichier = open('encrypted.csv', 'r')
rep = fichier.read().splitlines()
fichier.close()

cipher = PKCS1_OAEP.new(private)

fichier2 = open('decrypted.csv', 'a')
for i in rep:
    decrypted_line = cipher.decrypt(i)
    decrypted_line = decrypted_line.decode('utf-8')
    fichier2.write(str(encrypted_line))

fichier2.close()

我试图编码一个示例文件,并引发了这个ValueError。然后我尝试使用一个直接在Python解释器上只包含一个char的文件。加密效果很好,但解密破坏了与上面相同的错误。

python python-3.x encryption pycrypto pycryptodome
1个回答
1
投票

代码的主要问题是使用换行符来分隔加密数据块。加密数据可能已包含换行符,因此尝试将加密数据拆分为行可能会产生部分块,这会提高解密时看到的ValueError

第二个问题是加密文件是以文本模式打开的。处理加密数据时以二进制模式打开文件。加密的bytes不太可能对str进行解码,因此使用文本模式将导致编码或解码错误。

此版本的代码有效:

import functools

from Crypto.PublicKey import RSA 
from Crypto.Cipher import PKCS1_OAEP

if __name__ == '__main__':

    # Encrypt

    with open('public.pem', 'r') as fp: 
        pub = fp.read()
        fp.close()

    public = RSA.importKey(pub)

    # tockage du fichier dans une variable rep
    with open('test.csv', 'r') as fichier:
        rep = fichier.read()

    # liminations des spaces
    rep = rep.replace(' ', '') 

    # ncodage pour type bytes
    rep = rep.encode()

    cipher = PKCS1_OAEP.new(public)

    # decoupage en mot de 10 chars
    rep = [rep[i:i+10] for i in range(0, len(rep), 10)]

    # Open the file in binary mode so we can write bytes.
    with open('encrypted.csv', 'wb') as fichier2:
        for i in rep:
            fichier2.write(cipher.encrypt(i))

    # Decrypt
    with open('private.pem', 'r') as fk: 
        priv = fk.read()

    private = RSA.importKey(priv)

    CHUNK_SIZE = 256 
    # Open the file in binary mode so we can read bytes.
    with open('encrypted.csv', 'rb') as fichier:
        # Create an iterator that will return chunks of the correct size.
        chunker = iter(functools.partial(fichier.read, CHUNK_SIZE), b'')
        rep = list(chunker)

    cipher = PKCS1_OAEP.new(private)

    with open('decrypted.csv', 'w') as fichier2:
        for i in rep:
            decrypted_line = cipher.decrypt(i)
            fichier2.write(decrypted_line.decode())

此代码不是将加密数据拆分为换行符,而是从256字节的块中读取文件,因为加密过程似乎为每个输入块生成256个字节。我不是密码学家,所以有可能并非总是如此。在这种情况下,最好在一个步骤中加密(或解密)所有数据。

© www.soinside.com 2019 - 2024. All rights reserved.