发布
社区首页 >问答首页 >RSA在Qt/C++中用OpenSSL加密,在Java中解密:坏的填充异常

RSA在Qt/C++中用OpenSSL加密,在Java中解密:坏的填充异常
EN

Stack Overflow用户
提问于 2021-05-19 17:29:29
回答 1查看 617关注 0票数 0

我正在试用一个示例程序,在这个示例程序中,我在C++ Qt框架中用RSA公钥加密字符串(使用静态链接的OpenSSL C++库),并使用javax.crypto库解密相同的密文。我是发送这个密文通过套接字连接使用我的电脑上的自由端口到本地主机。

以下是守则:

我的Qt/C++代码:

main.cpp:

代码语言:javascript
代码运行次数:0
复制
#include "cipher.h"
#include "assert.h"
#include "string.h"
#include <QApplication>
#include <QTcpSocket>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Cipher *cipher=new Cipher();

    QTcpSocket *qts=new QTcpSocket();
    qts->connectToHost("localhost",11111);

    QByteArray message, enc_key,enc_message;

    message="Elephant";
   
    enc_message=cipher->encryptRSA(cipher->getPublicKey("publickey.pem"),message);

    qDebug()<<message;
    qDebug()<<enc_message;

    if(qts->waitForConnected(300)){
        qts->write(QString::fromStdString(enc_message.toStdString()).toUtf8().constData());
        qts->write("\n");
        qts->flush();
    }

    return a.exec();
}

对于encryptRSA函数,我使用了VoidRealms教程中的示例。以下是GitHub链接:https://github.com/voidrealms/Qt-154

从上面的链接中,我使用了cipher.hcipher.cpp,没有做任何更改。

Java代码:

代码语言:javascript
代码运行次数:0
复制
package servertest;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.io.FileUtils;

public class ServerTest {
    static int port=11111;
    static ServerSocket ss;
    static Socket s;
    
    public static void main(String[] args) {
        System.out.println("Server Started!");
        try {
            ss = new ServerSocket(port);
            s=ss.accept();
            
            InputStreamReader isr = new InputStreamReader(new BufferedInputStream(s.getInputStream()));
            BufferedReader br = new BufferedReader(isr);
            
            String str=br.readLine();
            
            System.out.println("Received: "+str);
            byte[] encrypted = str.getBytes("UTF-8");
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            PrivateKey privateKey = loadPrivateKey();
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] decrypted = cipher.doFinal(encrypted); 
            
            System.out.println("Decrypted: "+new String(decrypted));
            
        } catch (IOException ex) {
            Logger.getLogger(ServerTest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidKeyException ex) {
            Logger.getLogger(ServerTest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(ServerTest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchPaddingException ex) {
            Logger.getLogger(ServerTest.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(ServerTest.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public static PrivateKey loadPrivateKey() throws Exception {
        String privateKeyPEM = FileUtils.readFileToString(new File("privatekey-pkcs8.pem"), StandardCharsets.UTF_8);

        // strip off header, footer, newlines, whitespaces
        privateKeyPEM = privateKeyPEM
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replace("-----BEGIN RSA PRIVATE KEY-----", "")
                .replace("-----END RSA PRIVATE KEY-----", "")
                .replaceAll("\\s", "");
        
        //System.out.println(privateKeyPEM);
        
        // decode to get the binary DER representation
        byte[] privateKeyDER = Base64.getDecoder().decode(privateKeyPEM.getBytes("UTF-8"));

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyDER));
        return privateKey;
    }
    
}

另外,我使用标准的OpenSSL命令生成了这些键。我尝试使用不同的键,不同的位长度,但我得到相同的错误。我已将privatekey.pem转换为PKCS8 ( privatekey-pkcs8.pem)。为了生成和使用密钥,我遵循了下面的链接:

https://adangel.org/2016/08/29/openssl-rsa-java/

问题:

我正在用Java获得javax.crypto.BadPaddingException: Decryption error。我做错了什么?

我已经试过了

  • 我对加密很陌生,我不知道是否应该将这些密文编码成类似于base64或十六进制的东西。当我尝试使用QString::fromUtf8 8()和QString::know 8bit()时,
  • 在qts-> when ()阶段尝试在几种数据类型和格式之间进行转换,包括const char*、char[]、QByteArray、toUtf8().toconstData()、:string,使用QString::fromUtf8 8()和QString::know 8bit()。我应该试试Utf16和Latin1吗?

请帮我拿这个。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-19 18:28:48

好的,我在发帖后20分钟内解决了这个问题,方法是将密文转换成Base64,并通过套接字传递它,当然,在接收端,我需要将它解码回字节。

以前,当我尝试这样做时,我忘记将Base64文本解码回字节。抱歉我浪费了别人的时间。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67608129

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档