将密码与套接字 java 一起使用,不起作用
Posted
技术标签:
【中文标题】将密码与套接字 java 一起使用,不起作用【英文标题】:Using cipher with a socket java, not working 【发布时间】:2014-08-26 17:36:44 【问题描述】:我有以下问题 我有两个程序,一个客户端 android 和一个服务器 java 在程序点中,客户端必须使用 java 的实例化密码 AES 发送加密信息,但我不知道它必须如何发送到服务器。 在前面的代码中,我使用 ObjectInputStream 和 ObjectOutputStream 作为套接字 java 上的流,它正在工作,但现在我不知道。 这是一段感兴趣的代码。
[客户] [代码]
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivparameters = new IvParameterSpec(IV);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), ivparameters);
//and here I have to sent a string(the string is the SHA512 of a password
byte[] encryptedText = cipher.doFinal(passwordHash.getBytes());
oos.writeObject(new String(encryptedText));
oos.flush();
[\代码]
[服务器] [代码]
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivparameters = new IvParameterSpec(IV);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), ivparameters);
//and here I have to read a string sent from client
String textToRead = (String) ois.readObject();
String decryptedText = new String(cipher.doFinal(textToRead.getBytes()));
[\代码]
我在两个程序中使用 ObjectInputStream 和 ObjectOutputStream 我也尝试使用 ObjectOutputStream 的 writeObject 方法,但我不知道如何使用 cipher java 加密对象。帮帮我!!!!
我修改了代码,但出现了这个错误
javax.crypto.IllegalBlockSizeException:使用填充密码解密时,输入长度必须是 16 的倍数 在 com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:913) 在 com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824) 在 com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436) 在 javax.crypto.Cipher.doFinal(Cipher.java:2121)
【问题讨论】:
在 ObjectOutputStream 和套接字之间使用 CipherOutputStream,在输入上也是如此。 我也尝试了 CipherOutputStream 和 CipherInputStream,但是我该如何写对象呢?你能告诉我这个解决方案的代码吗? new ObjectOutoutStream(new CipherOutputStream(...)) 的代码?真的有那么神秘吗? 不,但我还有一个用于套接字的全局 ObjectOutputStream。如果我创建另一个 ObjectOutputStream 所以我有两个流,它可能会产生问题。我尝试使用 ObjectOutputStream 作为参数创建一个新的 CipherOutputStream 所以放到全局ObjectOutputStream下。我没有说要使用其中两个。 【参考方案1】:您需要加密,保存在可序列化的对象中,从套接字获取输出流,并使用套接字的输出流创建一个 ObjectOutputstream。这是一个例子。 希望对您有所帮助。
package test.cipher;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class CipherTest
public void runTest() throws Exception
KeyGenerator generator=KeyGenerator.getInstance("AES");
generator.init(256);
SecretKey key=generator.generateKey();
byte[] bytes=new byte[16];
(new Random()).nextBytes(bytes);
IvParameterSpec spec=new IvParameterSpec(bytes);
Server s=new Server(key,spec);
Client c=new Client(key,spec);
s.startListening();
c.sendMessage("Hi there");
c.sendMessage("this is a test");
c.sendMessage("The rain in Spain stays mainly on the plains.");
MessageDigest md=MessageDigest.getInstance("SHA-512");
md.update("The rain in Spain stays mainly on the plains. The rain in Spain stays mainly on the plains. The rain in Spain stays mainly on the plains. The rain in Spain stays mainly on the plains. The rain in Spain stays mainly on the plains. ".getBytes());
byte[] digest=md.digest();
c.sendHash(digest);
s.stopServer();
public static void main(String[] args) throws Exception
CipherTest t=new CipherTest();
t.runTest();
class Message implements Serializable
byte[] message;
public static Message createMessageFromHash(byte[] hash)
StringBuilder sb=new StringBuilder();
for (byte b:hash)
sb.append(String.format("%02x", b));
return new Message(sb.toString().getBytes());
public Message(byte[] bytes)
message=bytes;
class Server implements Runnable
Cipher cipher;
ServerSocket server;
boolean wasStopped=false;
Thread serverThread;
public Server(SecretKey key,IvParameterSpec spec)
try
cipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key,spec);
catch (Exception e)
e.printStackTrace();
public void startListening() throws IOException
server=new ServerSocket(9189);
Thread t=new Thread(this);
t.start();
@Override
public void run()
serverThread=Thread.currentThread();
try
if (server!=null)
while (!wasStopped)
Socket clientSocket=server.accept();
ObjectInputStream ois=new ObjectInputStream(clientSocket.getInputStream());
Message message=(Message)ois.readObject();
System.out.println( new String(cipher.doFinal(message.message)) );
ois.close();
catch (Exception e)
e.printStackTrace();
public void stopServer()
serverThread.interrupt();
wasStopped=true;
try
serverThread.join(1000);
catch (InterruptedException e)
e.printStackTrace();
serverThread=null;
server=null;
class Client
Cipher cipher;
public Client(SecretKey key, IvParameterSpec spec)
try
cipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
catch (Exception e)
e.printStackTrace();
public void sendHash(byte[] hash) throws Exception
Socket server=new Socket("localhost", 9189);
Message message=Message.createMessageFromHash(hash);
System.out.println(new String(message.message));
byte[] ciphertext=cipher.doFinal(message.message);
ObjectOutputStream oos=new ObjectOutputStream(server.getOutputStream());
oos.writeObject(new Message(ciphertext));
oos.close();
public void sendMessage(String message) throws Exception
Socket server=new Socket("localhost", 9189);
byte[] ciphertext=cipher.doFinal(message.getBytes());
ObjectOutputStream oos=new ObjectOutputStream(server.getOutputStream());
oos.writeObject(new Message(ciphertext));
oos.close();
【讨论】:
我也尝试对 apache commons 编解码器库的 base64 进行编码和解码,但我有填充错误 您是否将 IV 设置为长度 16? 是IV是16字节,cipherKey是32字节 现在的问题是:javax.crypto.IllegalBlockSizeException:在 com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:913) 使用填充密码解密时,输入长度必须是 16 的倍数在 com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824) 在 com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436) 在 javax.crypto.Cipher.doFinal(Cipher.java :2121) 你能发送一个十六进制字符串吗?如果我获取摘要并将其转换为十六进制字符串,我可以发送 SHA-512 消息摘要。 see an example。当然,你必须像任何其他字符串一样获取字节。以上是关于将密码与套接字 java 一起使用,不起作用的主要内容,如果未能解决你的问题,请参考以下文章
当 Statement 与 Java 和 Oracle 一起使用时,Prepared Statement 不起作用
为啥将 LIKE 与 TIMESTAMPS 一起使用在 DB2 中不起作用
尝试将 maven 与 android eclipse 项目一起使用不起作用?