首页 文章

使用ObjectOutputStream发送公钥的字节数组,加密某些内容,然后发回加密版本

提问于
浏览
0

所以我有一个服务器端公钥和私钥,我的目的是向客户端发送公钥,客户端将使用密钥加密字符串,然后通过流发送字节,服务器将解密字节数组 .

例外:

javax.crypto.BadPaddingException:解密错误

码:

发送编码密钥 .

handler.getOos().writeObject(publicKey.getEncoded());
                    handler.getOos().flush();

接收字节数组(编码密钥):

Object o = ois.readObject();
                        if (o instanceof byte[]) {
                            JChat.get().setServerPublicKey(KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec((byte[]) o)));
                            JChat.get().go();
                        }

go()方法(这里我使用DataOutputStream来发送字节数组):

public void go() {
    String text = "hello darkness my old friend";
    byte[] encrypted = encrypt(text, serverPublicKey);
    try {
        handler.getDos().write(encrypted);
        handler.getDos().flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

在服务器端读取字节数组:

int count = dis.available();
                        byte[] in = new byte[count];
                        dis.readFully(in);
                        System.out.println(Server.decrypt(in, Server.get().getPrivateKey()));

解密方法抛出此异常:

javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at com.archiepking.Server.decrypt(Server.java:97)
at com.archiepking.net.ClientHandler$1.run(ClientHandler.java:44)
at java.lang.Thread.run(Thread.java:745)

关于我做错了什么的任何建议?请注意:

Dos = DataOutputStream Dis = DataInputStream Oos = ObjectOutputStream Ois = ObjectInputStream

我使用两个不同的套接字,一个用于发送对象,一个用于数据类型(因为我的聊天应用程序将需要两个) .

我该怎么做才能解决这个错误?

更多信息:密钥生成:

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        FileOutputStream fosPublic = new FileOutputStream("public");
        fosPublic.write(publicKeyBytes);
        fosPublic.close();

        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        FileOutputStream fosPrivate = new FileOutputStream("private");
        fosPrivate.write(privateKeyBytes);
        fosPrivate.close();

        publicKey = keyPair.getPublic();
        privateKey = keyPair.getPrivate();

2 回答

  • 0

    如果您正在使用ObjectOutputStream,为什么还要使用getEncoded将公钥转换为字节数组呢?您可以直接序列化对象 . 例如 . handler.getOos()的writeObject(公钥);或者,如果必须使用编码版本,则删除ObjectOutputStream并使用ByteArrayOutputStream .

  • 1

    问题是您使用 DataInputStream.available() 来确定要读取的字节数 . 那种方法没有做你明显认为它做的事情 .

    从这个方法的Javadoc:

    返回可以从此输入流中读取(或跳过)的字节数的估计值,而不会被此输入流的方法的下一个调用方阻塞 . 下一个调用者可能是同一个线程或另一个线程 . 单个读取或跳过这么多字节不会阻塞,但可以读取或跳过更少的字节 .

    它只返回可以读取的字节数 without blocking ,它可以远远小于您发送的实际字节数,特别是如果您使用网络套接字发送/接收该数据 .

    解决方案:

    • 在写入字节之前,使用包含您正在编写的字节数的 writeInt 方法写入 int

    • 在读取字节之前,调用 readInt 以读取将跟随的字节数,并从该数字构造一个正确长度的字节数组 .

相关问题