Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 服务器端加密消息的解密_Java_Encryption_Cryptography_Digital Signature_Encryption Asymmetric - Fatal编程技术网

Java 服务器端加密消息的解密

Java 服务器端加密消息的解密,java,encryption,cryptography,digital-signature,encryption-asymmetric,Java,Encryption,Cryptography,Digital Signature,Encryption Asymmetric,我正在开发一个客户机-服务器应用程序。我必须使用非对称加密技术。客户端对其消息进行加密,并创建数字签名 我将消息和签名存储在一个向量中,然后将这个向量发送到服务器。 服务器接收这个向量 在服务器端,首先我检查签名以查看服务器是否与正确的客户端通信,当签名良好时,我尝试解密消息,但解密的结果不好。 问题只涉及加密/解密,其余代码我没有问题 客户端: private void payActionPerformed(java.awt.event.ActionEvent evt) { Data

我正在开发一个客户机-服务器应用程序。我必须使用非对称加密技术。客户端对其消息进行加密,并创建数字签名

我将消息和签名存储在一个向量中,然后将这个向量发送到服务器。 服务器接收这个向量

在服务器端,首先我检查签名以查看服务器是否与正确的客户端通信,当签名良好时,我尝试解密消息,但解密的结果不好。 问题只涉及加密/解密,其余代码我没有问题

客户端:

private void payActionPerformed(java.awt.event.ActionEvent evt) { 
    DataInputStream dis = new DataInputStream(s.getInputStream()); 
    ObjectOutputStream dos = new ObjectOutputStream(s.getOutputStream());

    Cipher encryptCipher = Cipher.getInstance("RSA");
    encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte[] message = concatMess.getBytes("UTF-8");
    cipherText = encryptCipher.doFinal(message);
    texteCrypteStr= Base64.getEncoder().encodeToString(cipherText);
    System.out.println("MESSAGE: "+cipherText);

    //SIGNATURE DU MESSAGE
    Signature signature = Signature.getInstance("SHA1withRSA","BC");
    System.out.println("Initialisation de la signature");
    signature.initSign(keyPri);
    System.out.println("Hachage du message");
    signature.update(cipherText);
    System.out.println("Generation des bytes");
    bytesign = signature.sign(); 
    String texteSignStr= Base64.getEncoder().encodeToString(bytesign);
    System.out.println("CLIENT SIGNATURE: "+texteSignStr);

    Vector vecByte = new Vector();
    vecByte.add(bytesign);
    vecByte.add(cipherText);
    dos.writeObject(vecByte);
    received = dis.readUTF();
}
                Cipher encryptCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
                encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
                String concatMess="";
                int k = 0;
                while(k<vec.size()){
                    concatMess+=vec.get(k);
                    if(k+1<vec.size())
                        concatMess+="!";
                    k+=1;
                }
                System.out.println("VECTOR:"+concatMess);
                byte[] message = concatMess.getBytes(StandardCharsets.UTF_8);
                cipherText = encryptCipher.doFinal(message);
                System.out.println("MESSAGE byte: "+cipherText);
                cipherTextString = Base64.getEncoder().encodeToString(cipherText);
服务器端:

public class PaiementHandler{
    Vector<byte[]> receivedVec = new Vector<byte[]>();   
    String toreturn; 
    receivedVec = ((Vector)disr.readObject());

    System.out.println("v1 "+receivedVec.get(0));
    System.out.println("v2 "+receivedVec.get(1));
    Vector<String> received = null;

    //RECUPERATION CLE PUBLIQUE
    KeyStore ksv = null;
    ksv = KeyStore.getInstance("PKCS12", "BC");
    ksv.load(new FileInputStream("C:\\Users\\user\\Desktop\\KEYSTORE\\keystore.p12"),"gogo".toCharArray());
    System.out.println("Recuperation du certificat");
    X509Certificate certif = (X509Certificate)ksv.getCertificate("toto");
    System.out.println("Recuperation de la cle publique");
    PublicKey publicKey = certif.getPublicKey(); 

    //VERIFICATION DE LA SIGNATURE

    System.out.println("\nVérification de la signature");
    System.out.println("*** Cle publique recuperee = "+publicKey.toString());
    System.out.println("Debut de verification de la signature construite");
    Signature signature = Signature.getInstance("SHA1withRSA", "BC");
    signature.initVerify(publicKey);
    signature.update(receivedVec.get(1));
    System.out.println("Verification de la signature construite");
    boolean ok = signature.verify(receivedVec.get(0));
    if(ok){
        System.out.println("signature verified with success");
        //DECHIFFREMENT DU MESSAGE
        try{
            Cipher dechiffrement = Cipher.getInstance("RSA", "BC");
            dechiffrement.init(Cipher.DECRYPT_MODE,publicKey);
            System.out.println("AVANT DECH");
            byte[] texteDecode = dechiffrement.doFinal(receivedVec.get(1));
            String texteDecodeStr = new String(texteDecode, "UTF-8");
            System.out.println("Vecteur: "+texteDecodeStr);
     }
}
公共类PaiementHandler{
Vector receivedVec=新向量();
字符串返回;
receivedVec=((Vector)disr.readObject());
System.out.println(“v1”+receivedVec.get(0));
System.out.println(“v2”+receivedVec.get(1));
接收向量=空;
//公共疗养院
密钥库ksv=null;
ksv=KeyStore.getInstance(“PKCS12”、“BC”);
load(新文件输入流(“C:\\Users\\user\\Desktop\\KEYSTORE\\KEYSTORE.p12”),“gogo.tocharray());
系统输出打印(“恢复du证书”);
X509Certificate certif=(X509Certificate)ksv.getCertificate(“toto”);
系统输出打印(“公共疗养”);
PublicKey PublicKey=certif.getPublicKey();
//签名验证
System.out.println(“\nVérification de la signature”);
System.out.println(“***Cle publique recuperee=“+publicKey.toString()”);
System.out.println(“签名构造的首次验证”);
签名签名=Signature.getInstance(“SHA1withRSA”,“BC”);
签名。初始化验证(公钥);
签名。更新(receivedVec.get(1));
System.out.println(“签字确认”);
布尔ok=signature.verify(receivedVec.get(0));
如果(确定){
System.out.println(“签名验证成功”);
//12月12日消息
试一试{
Cipher dechiffrement=Cipher.getInstance(“RSA”、“BC”);
dechiffrement.init(密码解密模式,公钥);
System.out.println(“先锋德奇”);
字节[]texteDecode=dechiffrement.doFinal(receivedVec.get(1));
String texteDecodeStr=新字符串(texteDecode,“UTF-8”);
System.out.println(“Vecteur:+texteDecodeStr”);
}
}
这是客户端发送到服务器的消息:“2222-2222-2222.30 3 1 2019-07-30 2019-07-31 90 40”。因此,此消息经过加密,并以向量形式与客户端签名一起发送到服务器(它们都是字节[])

服务器接收到这个向量,它首先检查签名,确定后再解密消息。 以下是转换为字符串时解密的结果:

�ߩ�U�5.�&�]��{��^��S?u2_��L��我������������b#��fCA�5.�里&�P�T��3.�4.��:���Rm���~�W���危险品��ga��我����虚拟现实

我不明白为什么我会有这个结果。。。
我试图像这个网站那样编写代码,但我不知道问题出在哪里

我找到了解决方案,这要归功于:

我必须在base64中对加密消息的结果进行编码,并在解密之前对其进行解码

客户端:

private void payActionPerformed(java.awt.event.ActionEvent evt) { 
    DataInputStream dis = new DataInputStream(s.getInputStream()); 
    ObjectOutputStream dos = new ObjectOutputStream(s.getOutputStream());

    Cipher encryptCipher = Cipher.getInstance("RSA");
    encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte[] message = concatMess.getBytes("UTF-8");
    cipherText = encryptCipher.doFinal(message);
    texteCrypteStr= Base64.getEncoder().encodeToString(cipherText);
    System.out.println("MESSAGE: "+cipherText);

    //SIGNATURE DU MESSAGE
    Signature signature = Signature.getInstance("SHA1withRSA","BC");
    System.out.println("Initialisation de la signature");
    signature.initSign(keyPri);
    System.out.println("Hachage du message");
    signature.update(cipherText);
    System.out.println("Generation des bytes");
    bytesign = signature.sign(); 
    String texteSignStr= Base64.getEncoder().encodeToString(bytesign);
    System.out.println("CLIENT SIGNATURE: "+texteSignStr);

    Vector vecByte = new Vector();
    vecByte.add(bytesign);
    vecByte.add(cipherText);
    dos.writeObject(vecByte);
    received = dis.readUTF();
}
                Cipher encryptCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
                encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
                String concatMess="";
                int k = 0;
                while(k<vec.size()){
                    concatMess+=vec.get(k);
                    if(k+1<vec.size())
                        concatMess+="!";
                    k+=1;
                }
                System.out.println("VECTOR:"+concatMess);
                byte[] message = concatMess.getBytes(StandardCharsets.UTF_8);
                cipherText = encryptCipher.doFinal(message);
                System.out.println("MESSAGE byte: "+cipherText);
                cipherTextString = Base64.getEncoder().encodeToString(cipherText);
感谢这个解决方案,我得到了正确的信息。
感谢您的建议和解释。

我找到了解决方案,这要归功于:

我必须在base64中对加密消息的结果进行编码,并在解密之前对其进行解码

客户端:

private void payActionPerformed(java.awt.event.ActionEvent evt) { 
    DataInputStream dis = new DataInputStream(s.getInputStream()); 
    ObjectOutputStream dos = new ObjectOutputStream(s.getOutputStream());

    Cipher encryptCipher = Cipher.getInstance("RSA");
    encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte[] message = concatMess.getBytes("UTF-8");
    cipherText = encryptCipher.doFinal(message);
    texteCrypteStr= Base64.getEncoder().encodeToString(cipherText);
    System.out.println("MESSAGE: "+cipherText);

    //SIGNATURE DU MESSAGE
    Signature signature = Signature.getInstance("SHA1withRSA","BC");
    System.out.println("Initialisation de la signature");
    signature.initSign(keyPri);
    System.out.println("Hachage du message");
    signature.update(cipherText);
    System.out.println("Generation des bytes");
    bytesign = signature.sign(); 
    String texteSignStr= Base64.getEncoder().encodeToString(bytesign);
    System.out.println("CLIENT SIGNATURE: "+texteSignStr);

    Vector vecByte = new Vector();
    vecByte.add(bytesign);
    vecByte.add(cipherText);
    dos.writeObject(vecByte);
    received = dis.readUTF();
}
                Cipher encryptCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
                encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
                String concatMess="";
                int k = 0;
                while(k<vec.size()){
                    concatMess+=vec.get(k);
                    if(k+1<vec.size())
                        concatMess+="!";
                    k+=1;
                }
                System.out.println("VECTOR:"+concatMess);
                byte[] message = concatMess.getBytes(StandardCharsets.UTF_8);
                cipherText = encryptCipher.doFinal(message);
                System.out.println("MESSAGE byte: "+cipherText);
                cipherTextString = Base64.getEncoder().encodeToString(cipherText);
感谢这个解决方案,我得到了正确的信息。
感谢您的建议和解释。

您在编码和解码时指定了UTF-8(很好,但您可能希望使用StandardCharsets.UTF_8而不是“UTF-8”),但当您打印出消息时,它将以每个系统上的平台默认字符集打印,并且可能会被您查看结果的终端仿真器解释为不同的编码。您可能需要检查数据的散列,看看它是否真的不同。这有点混乱。核心问题是您正在尝试使用公钥解密。请记住:您使用私钥签名,然后使用收件人的公钥加密。收件人使用您的公钥进行验证,然后使用他的私钥进行解密。您和收件人之间不共享密钥对,这完全违背了非对称加密的目的。在您将该概念应用于此之后,您可以使用你应该对此做很多重要的改进。扔掉它,使用TLS。它比你的方案安全得多。如果你需要数字签名,请使用
SignedObject
@DavidConrad,这样问题就可能来自字符编码/解码?首先,我有一些困难,不要依赖默认值。始终s将完整的算法/模式/填充转换字符串指定为
Cipher.getInstance()
。其次,我不确定您为什么在这里和那里使用“BC”提供程序,而不是在所有地方。除非您有充分的理由指定提供程序,否则不要指定提供程序。我看不到。您在编码和解码时指定UTF-8(很好,但您可能希望使用StandardCharsets.UTF_8而不是“UTF-8”),但当您打印出消息时,它将以每个系统上的平台默认字符集打印,并且可能会被您查看结果的终端仿真器解释为不同的编码。您可能需要检查数据的散列,看看它是否真的不同。这有点混乱。核心问题是您正在尝试使用公钥解密。请记住:您使用私钥进行签名,然后使用收件人的公钥进行加密。收件人使用您的公钥进行验证,然后使用他的私钥进行解密。您和收件人不共享密钥