Reputation: 81
Using the code found at https://raw.github.com/usefulfor/usefulfor/master/security/JBoss.java, I did thefollowing:
bash-3.2$ java -cp . JBoss -e testpython
-27038292d345798947e2852756afcf0a
bash-3.2$ java -cp . JBoss -d -27038292d345798947e2852756afcf0a
testpython
However, I can't for the life of me, figure out how to decrypt the string '27038292d345798947e2852756afcf0a' using pycrypto in python. My understanding is that the Java code is using Blowfish, and the phrase 'jaas is the way' as the key for the cipher. But I can't make any sense of how to do this in python. The following results in mostly unprintable garbage:
import Crypto
from Crypto.Cipher import Blowfish
from base64 import b64encode, b64decode
bs = Blowfish.block_size
key = 'jaas is the way'
plaintext = b'27038292d345798947e2852756afcf0a'
iv = '\0' * 8
c1 = Blowfish.new(key, Blowfish.MODE_ECB)
c2 = Blowfish.new(key, Blowfish.MODE_CBC, iv)
c3 = Blowfish.new(key, Blowfish.MODE_CFB, iv)
c4 = Blowfish.new(key, Blowfish.MODE_OFB, iv)
msg1 = c1.decrypt(plaintext)
msg2 = c2.decrypt(plaintext)
msg3 = c3.decrypt(plaintext)
msg4 = c4.decrypt(plaintext)
print "msg1 = %s\n" % msg1
print "msg2 = %s\n" % msg2
print "msg3 = %s\n" % msg3
print "msg4 = %s\n" % msg4
What am I missing ?
thanks.
Upvotes: 3
Views: 4392
Reputation: 478
This helps me
private byte[] encrypt(String key, String plainText) throws GeneralSecurityException {
SecretKey secret_key = new SecretKeySpec(key.getBytes(), ALGORITM);
Cipher cipher = Cipher.getInstance(ALGORITM);
cipher.init(Cipher.ENCRYPT_MODE, secret_key);
return cipher.doFinal(plainText.getBytes());
}
hope this will be useful for you, more http://dexxtr.com/post/57145943236/blowfish-encrypt-and-decrypt-in-java-android
Upvotes: 0
Reputation: 7776
First of all, that Java example code is very bad. It outputs the ciphertext as an integer, whereas ciphertext should remain a binary string. The reason is that an integer can be represented in an infinite number of binary encodings. For instance, the number one can be '0x01' (1 byte), '0x0001' (2 bytes), and so forth. When you are dealing with cryptographic functions, you must be extremely precise with the representation.
Additionally, the example uses the default values of the javax.crypto
API, which are not described anywhere. So it is really trial and error.
For the solution, you must know how to convert negative integers to hex strings in Python. In this case, you don't need a hex string, but its byte representation. The concept is the same though. I use PyCrypto's long_to_bytes
to convert a positive integer (of arbitrary length) to a byte string.
from Crypto.Cipher import Blowfish
from Crypto.Util.number import long_to_bytes
def tobytestring(val, nbits):
"""Convert an integer (val, even negative) to its byte string representation.
Parameter nbits is the length of the desired byte string (in bits).
"""
return long_to_bytes((val + (1 << nbits)) % (1 << nbits), nbits/8)
key = b'jaas is the way'
c1 = Blowfish.new(key, Blowfish.MODE_ECB)
fromjava = b"-27038292d345798947e2852756afcf0a"
# We don't know the real length of the ciphertext, assume it is 16 bytes
ciphertext = tobytestring(int(fromjava, 16), 16*8)
print c1.decrypt(ciphertext)
The output is:
'testpython\x06\x06\x06\x06\x06\x06'
From that you see that javax.crypto
also adds PKCS#5 padding, which you need to remove by yourself. That is trivial to do though.
However, the real solution to your problem is to do Java encryption in a better way. The Python code will be greatly simplified.
Upvotes: 5