Python 2 和 Java 1.6 之间的 BadPaddingException AES 128 CBC
我有一个 Python 服务器脚本和一个 Java 客户端应用程序,目标是通过套接字加密数据。数据始终是字符串。 (我是 Java 新手)
应该发生什么:
Python 脚本创建一个套接字并侦听连接,接受新连接,以纯文本形式发送 AES CBC PKCS5Padding 的 IV,设置密码,然后从 Java 应用程序接收加密数据(解密,然后在终端中打印出来) ,然后将加密数据发送到 Java 应用程序,然后关闭连接。
Java 应用程序连接到 python 套接字,接收 IV,设置相同的密码,加密一个简单的填充字符串,将其发送到 python 服务器,然后等待回复,解密回复并将其打印到屏幕上。然后连接关闭。
实际发生的情况
服务器建立套接字,java客户端连接并接收IV,两者设置相同的加密/解密密码,然后java客户端发送加密的填充字符串。 Python服务器成功接收密文,对字符串进行解密并解密,字符串正确显示。然后,服务器将加密的填充字符串发送到 java 客户端,客户端接收该字符串,然后在解密时由于 BadPaddingException 而失败。
我已经根据 RFC 验证了 python 端的 PKCS5 填充是正确的。我尝试过其他填充方法(零填充等),但没有任何效果。我还在字符串上尝试了几种不同的编码,我还尝试了 M2Crypto (现在使用 pycrypto)等。我尝试在客户端的套接字上使用 CipherInputStream ,并得到相同的结果。
什么都不起作用。我仍然认为 Python 和 Java 之间可能存在编码问题,但对于 Java 客户端解密失败的原因,我陷入了困境。
Python 服务器:
#!/usr/bin/env python
import os, time, threading, json
from socket import *
import sys, base64
from Crypto.Cipher import AES
from socket import *
### Settings
serverHost = '' # localhost
serverPort = 5555 # non-reserved
masterkey = 'mysecretpassword'
BLOCK_SIZE = 16 # Block-size for cipher (16, 24 or 32 for AES)
#PADDING = '{' # block padding for AES
# PKCS5 Padding
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s : s[0:-ord(s[-1])]
# generate new IV's - why you ask? ... just look at WEP
def createCipher(key):
iv = os.urandom(16)
return (AES.new(key, AES.MODE_CBC, iv), iv)
class IRCTalkServer(threading.Thread):
def __init__(self, masterkey, host='', port=5555):
try:
self.sockobj = socket(AF_INET, SOCK_STREAM) # create TCP socket obj
self.sockobj.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # make port reusable
self.sockobj.bind((host, port)) # bind socket to port
self.sockobj.listen(5) # listen, allow 5 pending connects
if host == '': host='localhost'
print "Started server on %s:%d" % (host, port)
except:
print "Error starting server"
sys.exit(0)
threading.Thread.__init__(self)
self.die = False # loop killer
self.masterkey = masterkey
self.host = host
self.port = port
def run(self):
try:
while True and not self.die: # infinite loop unless called to quit
connection, address = self.sockobj.accept()
print 'Server connected by ', address
# generate cipher and get first IV - prevent same WEP hacks
#paddedKey = keypad(masterkey)
#print "master key:", masterkey, " - padded key:", paddedKey, " - diff key:", keypad('test')
self.cipher, self.iv = createCipher(masterkey)
print "IV:", self.iv.encode('hex'), "Sending IV: ", repr(self.iv)
connection.send("%s%s" % (self.iv.encode('hex'),'\n')) # send iv first
while True and not self.die: # read from client
print "waiting for client"
data = connection.recv(10485760)
print "recieved from client:", repr(data.rstrip())
if not data:
print "NO DATA"
break
dataCheck, JSON = self.decryptData(data.rstrip())
print 'Recieved from Client:', repr(JSON)
#print 'Recieved from Client:', repr(data)
#if dataCheck:
#senddata = self.encryptData('SUCCESS')
#print "Size of compresseddata:", len(senddata)
#connection.send(senddata)
#morestuff = 'abc123def456'*int(10000/9)
#senddata = self.encryptData(['test', morestuff, 'test1', {'key': 'value'}, 2223])
#print "Size of compresseddata:", len(senddata)
#connection.send(senddata)
print "Sending reply to client..."
senddata = self.encryptData('test')
print "reply data:", repr("%s%s" % (senddata, "\n"))
connection.send("%s%s" % (senddata, "\n"))
#connection.send("Hello back mr android!")
#successReply = connection.recv(256) # only for "END REQUEST"
break
print "Closing connection... \n\n"
connection.close()
except:
print "exception on try loop"
pass # an error occurred, just drop it, the client will try again later
def encryptData(self, plaintext):
# convert to json string, pad the string, then encrypt, then compress
#JSON = json.dumps(plaintext, separators=(',',':'))
JSON = plaintext
#print "Size of JSON:", len(JSON)
ciphertext = pad(unicode(JSON))
print "padded text:", repr(ciphertext)
ciphertext = self.cipher.encrypt(ciphertext)
print "ciphertext:", repr(ciphertext), "|", len(ciphertext), "|", ciphertext
ciphertext = ciphertext.encode('hex').upper()
print "hexified text:", repr(ciphertext)
#ciphertext = self.cipher.encrypt(pad(JSON)).encode('hex').upper()
print "Size of ciphertext:", len(ciphertext)
return ciphertext
def decryptData(self, ciphertext):
try:
# decompress data to ciphertext, decrypt, convert to json
print "length of ciphertext:", len(ciphertext)
ptext = ciphertext.decode('hex')
print "unhexifed:", repr(ptext)
ptext = self.cipher.decrypt(ptext)
print "decrypted:", repr(ptext)
ptext = unpad(ptext)
print "unpadded:", repr(ptext)
#ptext = unpad(self.cipher.decrypt(ciphertext.decode('hex')))
print "ptext: ", repr(ptext)
JSON = ptext
#plaintext = unpad(self.cipher.decrypt(ciphertext))
##JSON = json.loads(plaintext)
#JSON = plaintext
except:
print "Error on decryption"
JSON = None
return (True, JSON)
def addToQueue(self, data):
pass
def getFromQueue(self):
pass
testserver =IRCTalkServer(masterkey)
testserver.start()
testserver.join()
Java 客户端:(此代码的部分内容仍需要正确注明 - [我只是还没有完成])
import java.io.*;
import java.util.*;
import java.net.*;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
//import javax.crypto.CipherInputStream;
//import javax.crypto.CipherOutputStream;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.spec.SecretKeySpec;
class clientHandler {
/*
* This class sets up AES CBC encryption for the socket,
* new instance for every connection since the IV changes
*/
// Declare variables
private Cipher ecipher;
private Cipher dcipher;
Socket testSocket = null;
//DataOutputStream out = null;
//DataInputStream in = null;
PrintWriter out = null;
BufferedReader in = null;
String masterkey = "mysecretpassword";
static final String HEXES = "0123456789ABCDEF";
public static String byteToHex( byte [] raw ) {
if ( raw == null ) {
return null;
}
final StringBuilder hex = new StringBuilder( 2 * raw.length );
for ( final byte b : raw ) {
hex.append(HEXES.charAt((b & 0xF0) >> 4))
.append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
public static byte[] hexToByte(String hexString) {
int len = hexString.length();
byte[] ba = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
ba[i/2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i+1), 16));
}
return ba;
}
public String encrypt(String plaintext) {
// encrypt string
try {
byte[] cipherbyte = ecipher.doFinal(plaintext.getBytes("UTF-8"));
//String ciphertext = new String(ecipher.doFinal(plaintext.getBytes("UTF8")));
return byteToHex(cipherbyte);
} catch (Exception e){
e.printStackTrace();
return null;
}
}
public String decrypt(String ciphertext) {
// decrypt hex string
try {
System.out.println("decrypt byte length: " + hexToByte(ciphertext).length);
String tp = new String(hexToByte(ciphertext), "UTF-8");
System.out.println("toString(): " + tp);
String plaintext = new String(dcipher.doFinal(hexToByte(ciphertext.trim())), "UTF-8");
//String plaintext = new String(dcipher.doFinal(ciphertext.getBytes("UTF8")), "UTF-8");
return plaintext;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void setupCrypto(byte[] iv, String key) {
// setup AES CBC encryption
// convert IV and key to byte array for crypto
try {
System.out.println("Setting up Crypto...");
//byte[] ivb = iv.getBytes("UTF8");
byte[] keyb = key.getBytes("UTF8");
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
SecretKeySpec skey = new SecretKeySpec(keyb, "AES");
ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
ecipher.init(Cipher.ENCRYPT_MODE, skey, paramSpec);
dcipher.init(Cipher.DECRYPT_MODE, skey, paramSpec);
} catch (Exception e) {
System.err.println("Error:" + e);
}
}
public void startServer() {
// starts server
try {
System.out.println("Connecting to Server");
testSocket = new Socket("localhost", 5555);
//out = new DataOutputStream(testSocket.getOutputStream());
//in = new DataInputStream(testSocket.getInputStream());
out = new PrintWriter(testSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(testSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Uknown Host");
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection");
}
}
public void androidClientHandler() {
// actual communication
if (testSocket != null && out != null && in != null) {
try {
System.out.println("Waiting for IV..");
String iv;
iv = in.readLine();
byte [] ivb = hexToByte(iv);
System.out.println("Got IV..." + iv);
setupCrypto(ivb, masterkey);
String ciphertext;
String plaintext;
System.out.println("Sending \"test\" to server");
//out.writeBytes("test\n");
ciphertext = encrypt("test");
System.out.println("Sent: " + ciphertext);
out.println(ciphertext);
System.out.println("Waiting for Server to reply");
String responseLine;
responseLine = in.readLine().replaceAll("\\\\n", "");
System.out.println("Recieved from Server: " + responseLine + " - length: " + responseLine.length());
plaintext = decrypt(responseLine);
System.out.println("Recieved from Server: " + plaintext);
System.out.println("Closing Connection");
out.close();
in.close();
testSocket.close();
} catch (UnknownHostException e) {
System.err.println("Trying to connect to unknown host:" + e);
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
public void javaIsGay() {
startServer();
androidClientHandler();
}
public static void main(String[] args) {
System.setProperty("file.encoding", "UTF-8");
clientHandler c = new clientHandler();
c.javaIsGay();
}
}
Python 服务器的输出:
Started server on localhost:5555
Server connected by ('127.0.0.1', 59683)
IV: c54aae0a5c43f547f0355ee7a0ee38c1 Sending IV: '\xc5J\xae\n\\C\xf5G\xf05^\xe7\xa0\xee8\xc1'
waiting for client
recieved from client: 'BBE7E09093625204CD3F7B755066419D'
length of ciphertext: 32
unhexifed: '\xbb\xe7\xe0\x90\x93bR\x04\xcd?{uPfA\x9d'
decrypted: 'test\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c'
unpadded: 'test'
ptext: 'test'
Recieved from Client: 'test'
Sending reply to client...
padded text: u'test\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c'
ciphertext: '\x9fT\xfc\xf0\xa8\xc2\xd3N*\x8f\x8e~\xc7\x8a\xbfR' | 16 | �T�����N*~NJ�R
hexified text: '9F54FCF0A8C2D34E2A8F8E7EC78ABF52'
Size of ciphertext: 32
reply data: '9F54FCF0A8C2D34E2A8F8E7EC78ABF52\n'
Closing connection...
Java客户端的输出:
Connecting to Server
Waiting for IV..
Got IV...c54aae0a5c43f547f0355ee7a0ee38c1
Setting up Crypto...
Sending "test" to server
Sent: BBE7E09093625204CD3F7B755066419D
Waiting for Server to reply
Recieved from Server: 9F54FCF0A8C2D34E2A8F8E7EC78ABF52 - length: 32
decrypt byte length: 16
toString(): �T����N*��~NJ�R
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:317)
at javax.crypto.Cipher.doFinal(Cipher.java:1813)
at clientHandler.decrypt(SocketClient.java:70)
at clientHandler.androidClientHandler(SocketClient.java:134)
at clientHandler.javaIsGay(SocketClient.java:151)
at clientHandler.main(SocketClient.java:157)
Recieved from Server: null
Closing Connection
I have a Python server script and a Java client application and the goal is to encrypt the data over the socket. The data will always be a string. (I am new to Java)
What is supposed to happen:
The Python script creates a socket and listens for connections, accepts new connections, sends the IV in plain-text for AES CBC PKCS5Padding, sets up the ciphers, then receives encrypted data from the Java application (decrypts, then prints out in the terminal), then sends encrypted data to the Java application, then closes the connection.
The Java application connects to the python socket, receives the IV, sets up the same ciphers, encrypts a simple padded string, sends it to the python server, then waits for a reply, decrypts the reply and prints it out to the screen. The connection then closes.
What is actually happening
Server sets up socket, java client connects and recieves IV, both setup the same encryption/decryption ciphers, then the java client sends an encrypted padded string. the Python server succesfully receives the ciphertext, decrypts the string and unpads, and the string shows correctly. The server then sends an encrypted padded string to the java client, the client receives the string, then on decryption it fails due a BadPaddingException.
I have verified that the PKCS5 Padding on the python side is correct according to the RFC. I have tried other padding methods (zero-padding, etc), and nothing is working. I have also tried several different encodings on the strings, I have also tried M2Crypto (using pycrypto now), etc. I have tried using CipherInputStream over the socket for the client, and the same result.
Nothing works. I am still thinking there might be an encoding problem between Python and Java, but I am stuck in a rut as to only why the Java client is failing at decrypting.
Python Server:
#!/usr/bin/env python
import os, time, threading, json
from socket import *
import sys, base64
from Crypto.Cipher import AES
from socket import *
### Settings
serverHost = '' # localhost
serverPort = 5555 # non-reserved
masterkey = 'mysecretpassword'
BLOCK_SIZE = 16 # Block-size for cipher (16, 24 or 32 for AES)
#PADDING = '{' # block padding for AES
# PKCS5 Padding
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s : s[0:-ord(s[-1])]
# generate new IV's - why you ask? ... just look at WEP
def createCipher(key):
iv = os.urandom(16)
return (AES.new(key, AES.MODE_CBC, iv), iv)
class IRCTalkServer(threading.Thread):
def __init__(self, masterkey, host='', port=5555):
try:
self.sockobj = socket(AF_INET, SOCK_STREAM) # create TCP socket obj
self.sockobj.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # make port reusable
self.sockobj.bind((host, port)) # bind socket to port
self.sockobj.listen(5) # listen, allow 5 pending connects
if host == '': host='localhost'
print "Started server on %s:%d" % (host, port)
except:
print "Error starting server"
sys.exit(0)
threading.Thread.__init__(self)
self.die = False # loop killer
self.masterkey = masterkey
self.host = host
self.port = port
def run(self):
try:
while True and not self.die: # infinite loop unless called to quit
connection, address = self.sockobj.accept()
print 'Server connected by ', address
# generate cipher and get first IV - prevent same WEP hacks
#paddedKey = keypad(masterkey)
#print "master key:", masterkey, " - padded key:", paddedKey, " - diff key:", keypad('test')
self.cipher, self.iv = createCipher(masterkey)
print "IV:", self.iv.encode('hex'), "Sending IV: ", repr(self.iv)
connection.send("%s%s" % (self.iv.encode('hex'),'\n')) # send iv first
while True and not self.die: # read from client
print "waiting for client"
data = connection.recv(10485760)
print "recieved from client:", repr(data.rstrip())
if not data:
print "NO DATA"
break
dataCheck, JSON = self.decryptData(data.rstrip())
print 'Recieved from Client:', repr(JSON)
#print 'Recieved from Client:', repr(data)
#if dataCheck:
#senddata = self.encryptData('SUCCESS')
#print "Size of compresseddata:", len(senddata)
#connection.send(senddata)
#morestuff = 'abc123def456'*int(10000/9)
#senddata = self.encryptData(['test', morestuff, 'test1', {'key': 'value'}, 2223])
#print "Size of compresseddata:", len(senddata)
#connection.send(senddata)
print "Sending reply to client..."
senddata = self.encryptData('test')
print "reply data:", repr("%s%s" % (senddata, "\n"))
connection.send("%s%s" % (senddata, "\n"))
#connection.send("Hello back mr android!")
#successReply = connection.recv(256) # only for "END REQUEST"
break
print "Closing connection... \n\n"
connection.close()
except:
print "exception on try loop"
pass # an error occurred, just drop it, the client will try again later
def encryptData(self, plaintext):
# convert to json string, pad the string, then encrypt, then compress
#JSON = json.dumps(plaintext, separators=(',',':'))
JSON = plaintext
#print "Size of JSON:", len(JSON)
ciphertext = pad(unicode(JSON))
print "padded text:", repr(ciphertext)
ciphertext = self.cipher.encrypt(ciphertext)
print "ciphertext:", repr(ciphertext), "|", len(ciphertext), "|", ciphertext
ciphertext = ciphertext.encode('hex').upper()
print "hexified text:", repr(ciphertext)
#ciphertext = self.cipher.encrypt(pad(JSON)).encode('hex').upper()
print "Size of ciphertext:", len(ciphertext)
return ciphertext
def decryptData(self, ciphertext):
try:
# decompress data to ciphertext, decrypt, convert to json
print "length of ciphertext:", len(ciphertext)
ptext = ciphertext.decode('hex')
print "unhexifed:", repr(ptext)
ptext = self.cipher.decrypt(ptext)
print "decrypted:", repr(ptext)
ptext = unpad(ptext)
print "unpadded:", repr(ptext)
#ptext = unpad(self.cipher.decrypt(ciphertext.decode('hex')))
print "ptext: ", repr(ptext)
JSON = ptext
#plaintext = unpad(self.cipher.decrypt(ciphertext))
##JSON = json.loads(plaintext)
#JSON = plaintext
except:
print "Error on decryption"
JSON = None
return (True, JSON)
def addToQueue(self, data):
pass
def getFromQueue(self):
pass
testserver =IRCTalkServer(masterkey)
testserver.start()
testserver.join()
Java Client: (parts of this code still needs to be properly credited - [i just haven't done it yet])
import java.io.*;
import java.util.*;
import java.net.*;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
//import javax.crypto.CipherInputStream;
//import javax.crypto.CipherOutputStream;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.spec.SecretKeySpec;
class clientHandler {
/*
* This class sets up AES CBC encryption for the socket,
* new instance for every connection since the IV changes
*/
// Declare variables
private Cipher ecipher;
private Cipher dcipher;
Socket testSocket = null;
//DataOutputStream out = null;
//DataInputStream in = null;
PrintWriter out = null;
BufferedReader in = null;
String masterkey = "mysecretpassword";
static final String HEXES = "0123456789ABCDEF";
public static String byteToHex( byte [] raw ) {
if ( raw == null ) {
return null;
}
final StringBuilder hex = new StringBuilder( 2 * raw.length );
for ( final byte b : raw ) {
hex.append(HEXES.charAt((b & 0xF0) >> 4))
.append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
public static byte[] hexToByte(String hexString) {
int len = hexString.length();
byte[] ba = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
ba[i/2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i+1), 16));
}
return ba;
}
public String encrypt(String plaintext) {
// encrypt string
try {
byte[] cipherbyte = ecipher.doFinal(plaintext.getBytes("UTF-8"));
//String ciphertext = new String(ecipher.doFinal(plaintext.getBytes("UTF8")));
return byteToHex(cipherbyte);
} catch (Exception e){
e.printStackTrace();
return null;
}
}
public String decrypt(String ciphertext) {
// decrypt hex string
try {
System.out.println("decrypt byte length: " + hexToByte(ciphertext).length);
String tp = new String(hexToByte(ciphertext), "UTF-8");
System.out.println("toString(): " + tp);
String plaintext = new String(dcipher.doFinal(hexToByte(ciphertext.trim())), "UTF-8");
//String plaintext = new String(dcipher.doFinal(ciphertext.getBytes("UTF8")), "UTF-8");
return plaintext;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void setupCrypto(byte[] iv, String key) {
// setup AES CBC encryption
// convert IV and key to byte array for crypto
try {
System.out.println("Setting up Crypto...");
//byte[] ivb = iv.getBytes("UTF8");
byte[] keyb = key.getBytes("UTF8");
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
SecretKeySpec skey = new SecretKeySpec(keyb, "AES");
ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
ecipher.init(Cipher.ENCRYPT_MODE, skey, paramSpec);
dcipher.init(Cipher.DECRYPT_MODE, skey, paramSpec);
} catch (Exception e) {
System.err.println("Error:" + e);
}
}
public void startServer() {
// starts server
try {
System.out.println("Connecting to Server");
testSocket = new Socket("localhost", 5555);
//out = new DataOutputStream(testSocket.getOutputStream());
//in = new DataInputStream(testSocket.getInputStream());
out = new PrintWriter(testSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(testSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Uknown Host");
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection");
}
}
public void androidClientHandler() {
// actual communication
if (testSocket != null && out != null && in != null) {
try {
System.out.println("Waiting for IV..");
String iv;
iv = in.readLine();
byte [] ivb = hexToByte(iv);
System.out.println("Got IV..." + iv);
setupCrypto(ivb, masterkey);
String ciphertext;
String plaintext;
System.out.println("Sending \"test\" to server");
//out.writeBytes("test\n");
ciphertext = encrypt("test");
System.out.println("Sent: " + ciphertext);
out.println(ciphertext);
System.out.println("Waiting for Server to reply");
String responseLine;
responseLine = in.readLine().replaceAll("\\\\n", "");
System.out.println("Recieved from Server: " + responseLine + " - length: " + responseLine.length());
plaintext = decrypt(responseLine);
System.out.println("Recieved from Server: " + plaintext);
System.out.println("Closing Connection");
out.close();
in.close();
testSocket.close();
} catch (UnknownHostException e) {
System.err.println("Trying to connect to unknown host:" + e);
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
public void javaIsGay() {
startServer();
androidClientHandler();
}
public static void main(String[] args) {
System.setProperty("file.encoding", "UTF-8");
clientHandler c = new clientHandler();
c.javaIsGay();
}
}
Output of Python Server:
Started server on localhost:5555
Server connected by ('127.0.0.1', 59683)
IV: c54aae0a5c43f547f0355ee7a0ee38c1 Sending IV: '\xc5J\xae\n\\C\xf5G\xf05^\xe7\xa0\xee8\xc1'
waiting for client
recieved from client: 'BBE7E09093625204CD3F7B755066419D'
length of ciphertext: 32
unhexifed: '\xbb\xe7\xe0\x90\x93bR\x04\xcd?{uPfA\x9d'
decrypted: 'test\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c'
unpadded: 'test'
ptext: 'test'
Recieved from Client: 'test'
Sending reply to client...
padded text: u'test\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c'
ciphertext: '\x9fT\xfc\xf0\xa8\xc2\xd3N*\x8f\x8e~\xc7\x8a\xbfR' | 16 | �T�����N*~NJ�R
hexified text: '9F54FCF0A8C2D34E2A8F8E7EC78ABF52'
Size of ciphertext: 32
reply data: '9F54FCF0A8C2D34E2A8F8E7EC78ABF52\n'
Closing connection...
Output of Java Client:
Connecting to Server
Waiting for IV..
Got IV...c54aae0a5c43f547f0355ee7a0ee38c1
Setting up Crypto...
Sending "test" to server
Sent: BBE7E09093625204CD3F7B755066419D
Waiting for Server to reply
Recieved from Server: 9F54FCF0A8C2D34E2A8F8E7EC78ABF52 - length: 32
decrypt byte length: 16
toString(): �T����N*��~NJ�R
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:317)
at javax.crypto.Cipher.doFinal(Cipher.java:1813)
at clientHandler.decrypt(SocketClient.java:70)
at clientHandler.androidClientHandler(SocketClient.java:134)
at clientHandler.javaIsGay(SocketClient.java:151)
at clientHandler.main(SocketClient.java:157)
Recieved from Server: null
Closing Connection
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我可能来得太晚了,但这就是我得到的:
您的 python 填充例程存在问题。如果明文的大小是 16 的倍数,则不会添加填充,而 Java 期望 16 '\x10'。
这当然可能无法解决您在运输过程中的腐败问题。最好的办法是检查问题是否来自密码或传输:如何将编码文本写入文件并让 Java 从中读取,只是为了确定?
I may be too late, but here's what I got:
There is a problem in your python padding routine. If the cleartext's size is a multiple of 16, no padding will be added, while Java expects 16 '\x10'.
This may of course not solve your corruption problem during transport. Your best bet would be to check whether the problem comes from the cipher or the transport: how about writing the encoded text in a file and have Java read from it, just to be sure?
您提到尝试 nopadding,您是否尝试切换密码模式?对于您的应用程序来说,CTR 应该与 CBC 一样安全,并且不需要填充。
You mentioned trying nopadding, did you try switching the cipher mode? CTR should be just as secure as CBC for your application and doesn't require padding.
在 Java 程序中,您使用 2 个 Cipher 实例进行加密和解密,它们都使用相同的 IV 进行初始化;在 python 代码中,您使用相同的对象进行解密和加密。我不熟悉 pycrypto 库(也不熟悉 python),但加密对象很可能包含内部状态,尤其是在 CBC 模式下。如果您在初始解密后没有重置密码,我不确定您是否使用预期的 IV 加密回复,这可以解释该异常。
In the Java program you are using 2
Cipher
instances for encryption and decryption both initialize with the same IV; in the python code you are using the same object for both decryption and encryption. I am not familiar with the pycrypto library (and not fluent in python neither) but it is more than likely that the encryption object contains an internal state, especially in CBC mode. And if you don't reset the cipher after the initial decryption I'm not sure that you are encrypting the reply with the expected IV, which could explain the exception.当我使用 Java JDK 的扩展安全功能(特别是 AES 加密和解密)时,我也遇到了同样的异常。完成这项工作的关键是为我的生产 JDK 安装扩展安全策略文件。您也可以尝试这样做。
您可以在此处下载它们 http://www.oracle.com/technetwork/ java/javase/downloads/index.html(在页面底部搜索 Java Cryptography Extension)。下载后,您必须将两个 *.jar 文件复制到 JDK_HOME/jre/lib/security 并覆盖以前的文件。
希望这有帮助,问候。
I was having the same exception being thrown, when I was using extended security features of Java JDK (particularly - AES encryption and decryption). The key to making this work, was to install extended security policy files for my production JDK. You might try doing this as well.
You can download them here http://www.oracle.com/technetwork/java/javase/downloads/index.html (search for Java Cryptography Extension at the bottom of the page). After downloading, you'll have to copy both *.jar files into JDK_HOME/jre/lib/security and overwrite previous files.
Hope this helps, regards.
我和你有类似的问题,我不确定下面的代码是否能给你一个想法。
python代码
//java代码
I have the similar problem with you, I am not sure whether the code following will give you an idea.
python code
//java code