4

I am struggling due to my incomplete knowledge of Java to convert this encryption code to Python code. The two should have the exact same results. Help would be greatly appreciated.

Java Function

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 Equivalent

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)

Results

Java Function: "??¾ô"

Python Function: "Ë4A-¾`*ã"

Hunter Larco
  • 785
  • 5
  • 17
  • I think your PKCS5Padding is wrong in the case when `packingLength == 8`. See [RFC 2898, section 6.1](http://tools.ietf.org/html/rfc2898#section-6.1) – President James K. Polk Jun 16 '13 at 14:49
  • Thank you, i have made the appropriate changes – Hunter Larco Jun 16 '13 at 21:19
  • Those outputs are meaningless. You should probably print hex-encoded outputs. Using binascii.hexlify in python, in Java it is not quite as trivial but you'll find plenty of examples online. – President James K. Polk Jun 16 '13 at 23:27
  • Yes, but even when converted to hex, they aren't equal. I need an exact replica for the third party extension to read. A third party receives the encryption and thus they must be equal. It is intended for Java, but for the purposes of my project, Python is more convenient. – Hunter Larco Jun 16 '13 at 23:55

3 Answers3

6

I get the same output for both python and Java using your example.

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))

In both cases the output is 223950ff19fbea872fce0ee543692ba7

President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
  • yes, as i figured out an hour ago, when both are converted to hex they are in fact equivalent, clearly i dont know much about java, thank you! – Hunter Larco Jun 17 '13 at 02:40
3
def PKCS5Padding(string):
    byteNum = len(string)
    packingLength = 8 - byteNum % 8
    appendage = chr(packingLength) * packingLength
    return string + appendage

Use chr instead of str.

>>> chr(1)
'\x01'
>>> str(1)
'1'

str * int -> repeated str

>>> '!' * 5
'!!!!!'
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • @JoachimIsaksson, `packingLength` become 0 when the length of `string` is multiplier of 8. – falsetru Jun 16 '13 at 16:54
  • 1
    Ah, I missed that you changed the calculation. It should actually still be `packingLength = 8 - byteNum % 8` or it'll not pad correctly. An empty string for example should get 8 bytes with value 8 as padding. – Joachim Isaksson Jun 16 '13 at 16:54
  • thanks for the help, though regardless the program does not work. I have updated the question with sample results from each function – Hunter Larco Jun 16 '13 at 21:18
  • @HunterLarco, Try `System.out.write(enc_bytes);` in java code instead of `..println`. – falsetru Jun 17 '13 at 01:59
1

https://stackoverflow.com/a/17139643/1645017 answer correct for python2.

For 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'

`

yv84_
  • 101
  • 2
  • 10
  • This worked for me. Had to replace the return statement in PKCS5Padding method to: "return string.encode() + appendage" – Sonal Dubey Jul 06 '23 at 06:32