【问题标题】:Python Blowfish EncryptionPython河豚加密
【发布时间】:2013-06-17 10:26:56
【问题描述】:

由于我对 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-¾`*ã”

【问题讨论】:

  • 我认为您的 PKCS5Padding 在packingLength == 8 的情况下是错误的。见RFC 2898, section 6.1
  • 谢谢,我已经做了相应的修改
  • 那些输出毫无意义。您可能应该打印十六进制编码的输出。在 python 中使用 binascii.hexlify,在 Java 中它不是那么简单,但是你会在网上找到很多例子。
  • 是的,但即使转换为十六进制,它们也不相等。我需要一个精确的副本供第三方扩展读取。第三方接收加密,因此他们必须是平等的。它是为 Java 设计的,但就我的项目而言,Python 更方便。

标签: java python encryption blowfish ecb


【解决方案1】:

使用您的示例,我得到了 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 不太了解,谢谢!
【解决方案2】:
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, packingLengthstring 的长度是 8 的倍数时变为 0。
  • 啊,我错过了你改变了计算。它实际上应该仍然是packingLength = 8 - byteNum % 8,否则它不会正确填充。例如,一个空字符串应该得到 8 个字节,值为 8 作为填充。
  • 感谢您的帮助,尽管该程序无法正常工作。我已经用每个函数的示例结果更新了问题
  • @HunterLarco,在 Java 代码中尝试使用 System.out.write(enc_bytes); 而不是 ..println
猜你喜欢
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-30
  • 1970-01-01
  • 2015-09-24
  • 1970-01-01
相关资源
最近更新 更多