3

https://raw.github.com/usefulfor/usefulfor/master/security/JBoss.javaにあるコードを使用して、次のことを行いました。

bash-3.2$ java -cp . JBoss -e testpython
-27038292d345798947e2852756afcf0a
bash-3.2$ java -cp . JBoss -d -27038292d345798947e2852756afcf0a
testpython

ただし、Pythonでpycryptoを使用して文字列「27038292d345798947e2852756afcf0a」を復号化する方法を理解することはできません。私の理解では、Java コードは Blowfish を使用しており、「jaas is the way」というフレーズが暗号のキーとして使用されています。しかし、Pythonでこれを行う方法がわかりません。次の結果は、ほとんど印刷できないガベージになります。

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 

何が欠けていますか?

ありがとう。

4

2 に答える 2

5

まず第一に、その Java サンプル コードは非常に悪いものです。暗号文は整数として出力されますが、暗号文はバイナリ文字列のままでなければなりません。その理由は、整数は無限の数のバイナリ エンコーディングで表現できるからです。たとえば、1 は '0x01' (1 バイト)、'0x0001' (2 バイト) などになります。暗号化機能を扱うときは、表現を非常に正確にする必要があります。

さらに、この例ではjavax.cryptoAPI のデフォルト値を使用していますが、これについてはどこにも記載されていません。だから本当に試行錯誤です。

解決するには、Python で負の整数を 16 進文字列に変換する方法を知っている必要があります。この場合、16 進文字列は必要ありませんが、そのバイト表現は必要です。コンセプトは同じだけど。PyCrypto を使用long_to_bytesして、(任意の長さの) 正の整数をバイト文字列に変換します。

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)

出力は次のとおりです。

'testpython\x06\x06\x06\x06\x06\x06'

javax.cryptoそこから、自分で削除する必要がある PKCS#5 パディングも追加されていることがわかります。しかし、それは簡単なことです。

ただし、問題の本当の解決策は、Java 暗号化をより適切な方法で行うことです。Python コードは大幅に簡素化されます。

于 2012-06-01T08:22:27.437 に答える
0

これは私を助けます

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());
}

これがあなたにとって役立つことを願っています

于 2013-08-02T13:20:05.293 に答える