通过套接字使用ObjectStreams传输Java密钥对象

通过套接字使用ObjectStreams传输Java密钥对象,java,sockets,exception,serialization,Java,Sockets,Exception,Serialization,我正在尝试将key类型的公钥对象发送到我的服务器。但我没有让它运行。该协议如下所示: Nov 28, 2012 9:52:59 PM AdminServer.AdminServer run INFO: Get a new request java.io.StreamCorruptedException: invalid stream header: 73720014 at java.io.ObjectInputStream.readStreamHeader(Unknown Source)

我正在尝试将key类型的公钥对象发送到我的服务器。但我没有让它运行。该协议如下所示:

Nov 28, 2012 9:52:59 PM AdminServer.AdminServer run
INFO: Get a new request
java.io.StreamCorruptedException: invalid stream header: 73720014
    at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
    at java.io.ObjectInputStream.<init>(Unknown Source)
    at AdminServer.AdminServer.registerNewKeyEntry(AdminServer.java:115)
    at AdminServer.AdminServer.run(AdminServer.java:65)
    at java.lang.Thread.run(Unknown Source)
Nov 28, 2012 9:52:59 PM AdminServer.AdminServer errorResponse
WARNING: Error: Bad public key format. Use object stream with key object.
[命令]\n[序列化密钥对象]

客户端使用以下代码:

Socket admin;
PrintWriter pw;
OutputStream os;
BufferedReader is; 
for(int tries = 0; tries < MAX_RECONNECT_TRIES_ADMIN_SERVER; tries++)
{
    try 
    {
        admin = new Socket(host,port);
        os = admin.getOutputStream();
        is = new BufferedReader(new InputStreamReader(admin.getInputStream()));
        pw = new PrintWriter(new OutputStreamWriter(os));   

        AdminServerCommand.NODE_REGISTER.writeToPrintWriter(pw);
        pw.flush();

        sendPublicKey(os);

        String resultLine = null;
        resultLine = is.readLine();
        if(AdminServer.Feedback.KEY_REGISTERED.commandMatch(resultLine))
        {
            is.close();
            os.close();
            admin.close();
            return true;
        }
        is.close();
        os.close();
        admin.close();
        registerNodeRetrySleep(1000);
    }
    catch (Exception e) 
    {}
}
return false;

public void sendPublicKey(OutputStream out)
{
    try
    {
        ObjectOutputStream outO = new ObjectOutputStream(out);
        outO.writeObject(cyper.getPublicKey());
        outO.flush();
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
}

public void writeToPrintWriter(PrintWriter os)
{
    if(os == null)
        throw new IllegalArgumentException("Can not write command to null stream.");
    os.println(comm);
    os.flush();
}
例外情况如下所示:

Nov 28, 2012 9:52:59 PM AdminServer.AdminServer run
INFO: Get a new request
java.io.StreamCorruptedException: invalid stream header: 73720014
    at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
    at java.io.ObjectInputStream.<init>(Unknown Source)
    at AdminServer.AdminServer.registerNewKeyEntry(AdminServer.java:115)
    at AdminServer.AdminServer.run(AdminServer.java:65)
    at java.lang.Thread.run(Unknown Source)
Nov 28, 2012 9:52:59 PM AdminServer.AdminServer errorResponse
WARNING: Error: Bad public key format. Use object stream with key object.
2012年11月28日9:52:59 PM AdminServer.AdminServer运行
信息:获取新请求
java.io.StreamCorruptedException:无效的流头:73720014
位于java.io.ObjectInputStream.readStreamHeader(未知源)
位于java.io.ObjectInputStream。(未知源)
在AdminServer.AdminServer.registerNewKeyEntry(AdminServer.java:115)
在AdminServer.AdminServer.run(AdminServer.java:65)
位于java.lang.Thread.run(未知源)
2012年11月28日9:52:59 PM AdminServer.AdminServer错误响应
警告:错误:公钥格式错误。将对象流与键对象一起使用。

现在有人知道我如何解决这个问题了。类型键是一种接口类型,它自身实现接口可序列化。所以序列化这个对象应该不会有问题。我整个晚上都在研究这个问题。希望任何人都能帮我摆脱这个

您的问题中没有足够的代码来完全诊断-但这里有几个观察结果

此代码看起来可疑:

if(client.getInputStream().available() > 2)
com = is.readLine();
假设您有一个缓冲读取器
正在包装客户机输入流。如果if语句不正确,会发生什么情况-跳过这行?现在,这行文本仍在管道中,并将传递给keyIn.readObject方法。这可能会导致损坏的错误

我建议删除整个
if
行。readLine()无论如何都会阻塞,因此不需要进行检查

另外,您是否绝对确定
AdminServerCommand.NODE\u REGISTER.writeToPrintWriter(pw)在换行后只发送一行绝对没有字符的文本

然而,我认为你有一个更大的问题。这种在Java对象序列化和手动文本读/写之间来回切换的设计是一场即将发生的灾难。如果要使用对象序列化,请以独占方式使用它。您可以交替发送一个字符串对象,这样一个键对象和您的流就不会因为发送了太多或一两个换行符而损坏

例如: ObjectOutputStream outO=新的ObjectOutputStream(out)


然后在服务器端,始终使用readObject,知道第一个是命令,第二个是密钥。

您尝试传输的公钥类型是什么?RSA?顺便说一句,请确保通过安全连接传输这些密钥-否则这些密钥不应被信任。抱歉,是的,这是公钥RSA。将保存通道以进行传输。您不使用SSL的原因是什么?或者发送一个证书而不仅仅是它的公钥?是的,有一些原因。该程序用于学术用途,如果可能,应传输公钥。如果您知道算法将是rsa,则可以调用RSAPublicKey的GetPublicModule()和getPublicExponent()方法,并将它们写入OutputStream(序列化或作为文本)。在接收端,您可以使用KeyFactory和RSAPublicKeySpec实例化密钥。
    String command = "whatever";
    outO.writeObject(command);
    outO.writeObject(cyper.getPublicKey());
    outO.flush();