Python Blowfish加密

4

由于我对Java知识不完整,我无法将此加密代码转换为Python代码。这两个代码应该具有完全相同的结果。非常感谢您的帮助。

Java函数

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;


class Main
{
    public static void main (String[] args) throws java.lang.Exception
    {
        String s = "testings";
        Cipher cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
        Key key = new SecretKeySpec("6#26FRL$ZWD".getBytes(), "Blowfish");
        cipher.init(1, key);
        byte[] enc_bytes = cipher.doFinal(s.getBytes());
        System.out.println(enc_bytes);
    }
}

Python等效语法

def PKCS5Padding(string):
    byteNum = len(string)
    packingLength = 8 - byteNum % 8
    if packingLength == 8:
        return string
    else:
        appendage = chr(packingLength) * packingLength
        return string + appendage

def PandoraEncrypt(string):
    from Crypto.Cipher import Blowfish
    key = b'6#26FRL$ZWD'
    c1  = Blowfish.new(key, Blowfish.MODE_ECB)
    packedString = PKCS5Padding(string)
    return c1.encrypt(packedString)

结果

Java函数:"??¾ô"

Python函数:"Ë4A-¾`*ã"


我认为在 packingLength == 8 的情况下,您的 PKCS5Padding 是错误的。请参阅 RFC 2898,第6.1节 - President James K. Polk
谢谢,我已经做出了适当的更改。 - Hunter Larco
这些输出毫无意义。你应该打印十六进制编码的输出。在Python中使用binascii.hexlify很容易,虽然在Java中不那么简单,但你可以在网上找到大量的例子。 - President James K. Polk
是的,但即使转换为十六进制,它们也不相等。我需要一个精确的副本让第三方扩展程序能够读取。第三方收到加密内容,因此它们必须相等。这是为Java设计的,但出于我的项目目的,Python更方便。 - Hunter Larco
3个回答

6
使用您提供的示例,我在Python和Java中获得了相同的输出。
Java代码:
import java.math.BigInteger;
import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class Blowfish1 {

    public static void main(String[] args) throws Exception {
        String s = "testings";
        Cipher cipher = Cipher.getInstance("Blowfish/ECB/PKCS5Padding");
        Key key = new SecretKeySpec("6#26FRL$ZWD".getBytes(), "Blowfish");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] enc_bytes = cipher.doFinal(s.getBytes());
        System.out.printf("%x%n", new BigInteger(1, enc_bytes));
    }

}

Python:

from Crypto.Cipher import Blowfish
import binascii

# See @falsetru answer for the following method
#
def PKCS5Padding(string):
    byteNum = len(string)
    packingLength = 8 - byteNum % 8
    appendage = chr(packingLength) * packingLength
    return string + appendage

def PandoraEncrypt(string):
    key = b'6#26FRL$ZWD'
    c1  = Blowfish.new(key, Blowfish.MODE_ECB)
    packedString = PKCS5Padding(string)
    return c1.encrypt(packedString)

if __name__ == '__main__':
    s = 'testings'
    c = PandoraEncrypt(s)
    print(binascii.hexlify(c))

在这两种情况下,输出结果都是223950ff19fbea872fce0ee543692ba7

是的,正如我一个小时前发现的那样,当两者都转换为十六进制时,它们实际上是等价的。显然我对Java不是很了解,谢谢! - Hunter Larco

3
def PKCS5Padding(string):
    byteNum = len(string)
    packingLength = 8 - byteNum % 8
    appendage = chr(packingLength) * packingLength
    return string + appendage

请使用 chr 而非 str 。
>>> chr(1)
'\x01'
>>> str(1)
'1'

str * int -> 重复的 str

>>> '!' * 5
'!!!!!'

@JoachimIsaksson,当string的长度是8的倍数时,packingLength会变为0。 - falsetru
1
啊,我没注意到你改了计算方法。实际上应该还是 packingLength = 8 - byteNum % 8,否则就填充不正确了。例如,一个空字符串应该用值为8的字节填充8个字节。 - Joachim Isaksson
谢谢您的帮助,但是无论如何程序都无法运行。我已经更新了问题,并提供了每个函数的样本结果。 - Hunter Larco
@HunterLarco,在 Java 代码中尝试使用 System.out.write(enc_bytes); 而不是 ..println - falsetru

1

https://dev59.com/1nPYa4cB1Zd3GeqPiF8w#17139643 答案适用于 Python2。

对于 Python 3,https://pycryptodome.readthedocs.io/en/latest/index.html `

from Crypto.Cipher import Blowfish
import binascii

# See @falsetru answer for the following method
#
def PKCS5Padding(string):
    byteNum = len(string)
    packingLength = 8 - byteNum % 8
    appendage = chr(packingLength).encode() * packingLength
    return string + appendage

def PandoraEncrypt(string):
    key = b'6#26FRL$ZWD'
    c1  = Blowfish.new(key, Blowfish.MODE_ECB)
    packedString = PKCS5Padding(string)
    return c1.encrypt(packedString)

def PandoraDecrypt(string):
    key = b'6#26FRL$ZWD'
    c1  = Blowfish.new(key, Blowfish.MODE_ECB)
    decrypted = c1.decrypt(string)
    last_byte = decrypted[-1]
    decrypted_without_padding = decrypted[:-last_byte]
    return decrypted_without_padding

if __name__ == '__main__':
    s = b'testings'
    c = PandoraEncrypt(s)
    d = PandoraDecrypt(c)
    print(binascii.hexlify(c)) # b'223950ff19fbea872fce0ee543692ba7'
    print(d) # b'testings'

`


这对我有用。不得不在PKCS5Padding方法中替换返回语句为:"return string.encode() + appendage" - Sonal Dubey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接