【问题标题】:Recieving Error from decryption with RSA使用 RSA 解密接收错误
【发布时间】:2016-05-14 03:41:43
【问题描述】:

我正在做一个小型的学校“项目”,它是一个小型聊天程序。您启动服务器,服务器将公钥发送给客户端,以便客户端可以发回加密数据。

问题是当我尝试在服务器端解密它时,我收到一个错误。

javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)

我的服务器等待socket.accept(),当客户端连接时,它会向此套接字发送一个公钥。

(这不是全部代码)

private Client client;
private JSONObject json;

//Connector is used as a listener for messages.
public Connector(Socket socket, ServerBroadCast SBC) throws IOException {
    DIS = new DataInputStream(socket.getInputStream());        
    this.SBC = SBC;
    this.client = SBC.AddClient(socket);        
    //Sending public RSA key to client to use to encrypt their message
    this.client.sendPublicKey(RSA.getPublicKey()); //This is where I am sending RSA public key to client
}

我只是将一条消息发送回服务器,以查看它是否已加密以及服务器是否可以解密它。

使用此类发送给 CLIENT

DataOutputStream DOS;
public Client(Socket s) throws IOException {
    DOS = new DataOutputStream(s.getOutputStream());
}
public void sendPublicKey(PublicKey publicKey) throws IOException {
    JSONObject json = new JSONObject();

    json.put(JSONKeys.TYPE, JSONTypes.PUBLIC_KEY);
    json.put(JSONKeys.MESSAGE, RSA.getEncodedPublicKey());
    this.send(json);
}

public void send(JSONObject json) throws IOException{
    this.DOS.writeUTF(json.toString());
    System.out.println(json);
}

这是我用来加密和解密的 RSA 类

private static PrivateKey privateKey = null;
private static PublicKey publicKey = null;

public static void generateKeyPair() {
    KeyPairGenerator keyPairGenerator = null;
    KeyPair keyPair = null;

    try {
        keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    keyPairGenerator.initialize(1024);
    keyPair = keyPairGenerator.generateKeyPair();

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

public static String getEncodedPublicKey() {
    return (new String(Base64.encode(RSA.getPublicKey().getEncoded())));
}

public static String encrypt(String string) {
    byte[] encrypted = null;

    try {
        Cipher cipher = Cipher.getInstance("RSA");//174 bytes

        cipher.init(Cipher.ENCRYPT_MODE, RSA.getPublicKey());
        encrypted = cipher.doFinal(string.getBytes());
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    }

    return (new String(Base64.encode(encrypted)));
}

public static String decrypt(String string) {
    byte[] decrypted = null;

    try {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

        cipher.init(Cipher.DECRYPT_MODE, RSA.getPrivateKey());
        decrypted = cipher.doFinal(Base64.decode(string));
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (Base64DecodingException e) {
        e.printStackTrace();
    }

    return (new String(decrypted));
}

我知道我的填充有一些“错误”,因为错误说明了这一点,但我不明白是什么。

我从客户端加密消息返回的长度为 174 字节长。我知道它很长,但是为什么它会从我的纯文本中创建如此巨大的加密消息。

private final String MESSAGE = "Hello from client side";

【问题讨论】:

  • 我唯一能想到的是 JSON 可能忽略了一些字节(不适合字符串)..尝试使用 Base64 对字节进行编码和解码。 (Java 通过 Base64.getEncoder() 和 Base64.get decoder() 支持 Base64)。 (我的意思是发送密钥时)
  • @Meguy26 抱歉忘记添加我拥有的另一个功能。我已经在使用 Base64 进行编码和解码。仍然收到此错误
  • 发送密钥的时候呢?
  • @Meguy26 public static String getEncodedPublicKey() { return (new String(Base64.encode(RSA.getPublicKey().getEncoded()))); } 这就是我正在使用的
  • 啊,好吧。我不确定,加密是否必须是 RSA,因为 java 的 SSLSocket 自己进行加密。不过,您可能不得不使用匿名 TSL 协议

标签: java sockets encryption cryptography rsa


【解决方案1】:

看来你有两个问题要回答:

a) 客户端的公钥是否正确?

b) 服务器上的密文是否正确?

尝试分别回答问题。例如,您可以尝试:

  1. 在服务器上获取公钥,并加密消息“hello world”。然后在服务器上获取私钥,并解密消息。它奏效了吗?那么……

  2. 从#1获取密文并在客户端硬编码,这样无论服务器向客户端发送什么,客户端都会将此已知正确的密文发送回服务器.现在,服务器又解密了吗?

如果服务器解密正常,那么你可以:

  1. 从服务器获取公钥并加密一些数据(在客户端)。现在,在客户端使用私钥解密数据。它会解密吗?

  2. 好的,现在,将密文发送到服务器并解密。

限制每一步的未知数。服务器真的可以解密正确的密文吗(可能由于某些错误而无法解密)?客户端真的能收到正确的公钥吗?客户端能否发送正确的密文?

【讨论】:

  • 谢谢.. 我按照你说的做了,结果我没有正确处理接收公钥。
猜你喜欢
  • 1970-01-01
  • 2018-10-27
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 1970-01-01
  • 2011-02-24
  • 2020-11-03
  • 1970-01-01
相关资源
最近更新 更多