在Java中使用rsa时发生解密错误。

时间:2018-10-22 07:32:18

标签: java encryption rsa public-key-encryption

我的目的是接受包含挑战和起源的信息。收到此消息后,必须生成一个rsa密钥对,然后将其用于操作数据,如下所示。数据的某些部分使用生成的公共密钥加密。授权期间,必须使用私钥解密该数据。但是,当我尝试解密时,显示解密错误。我什至已经打印了代码的不同部分,只是为了检查是否实现了所需的输出,这就是为什么我知道从文件中获取的私钥是正确的。我无法解决解密错误。该任务的规范要求使用rsa,而不是混合加密。我曾尝试填充,但这并没有帮助。请提供有关如何解决此问题的建议

package pam;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.xml.bind.DatatypeConverter;
import com.sun.jersey.core.util.Base64;

class Test 
{
  public static void kpgen(int numBits, String s) throws Exception
  {
    if(s.length()!=64)
    {
        System.out.println("invalid entry");
    }
    else
    {
        KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
        KeyPair keyPair = keygen.genKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        System.out.println("pk: "+privateKey);
        System.out.println("pubk: "+publicKey);

        String fileBase = "f:\\tempKey";        //WRITING PVT KEY TO FILE
        try (FileOutputStream out = new FileOutputStream(fileBase + ".key")) 
        {
            out.write(keyPair.getPrivate().getEncoded());
        }
        try (FileOutputStream out = new FileOutputStream(fileBase + ".pub")) 
{
            out.write(keyPair.getPublic().getEncoded());
        }

        System.out.println("Key pair : " + Base64.encode(String.valueOf(keyPair)));
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] digest = md.digest(keyPair.toString().getBytes(StandardCharsets.UTF_8));
        String sha256 = DatatypeConverter.printHexBinary(digest).toLowerCase();
        System.out.println("Hash value: "+sha256);

        String ch = s.substring(0,32);
        String or = s.substring(32,64);
        System.out.println("Challenge: "+ch);
        System.out.println("Origin: "+or);

        MessageDigest md1 = MessageDigest.getInstance("SHA-256");
        byte[] digest1 = md1.digest(privateKey.toString().getBytes(StandardCharsets.UTF_8));
        String sha = DatatypeConverter.printHexBinary(digest1).toLowerCase();
        or = or + sha;
        System.out.println("String kh: "+or);

        Cipher cipher = Cipher.getInstance("RSA");  
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] keyHandle = cipher.doFinal(or.getBytes());
        System.out.println("Key Handle: "+keyHandle);

        String f = "f:\\keyList.pub";
        Key pub = getKeyFromFile(f);
        System.out.println("Attestation Public Key: "+pub);

        PrivateKey pk = (PrivateKey) getPvtKey("f:\\keyList.key");
        Signature rsa = Signature.getInstance("SHA1withRSA"); 
        rsa.initSign(pk);
        rsa.update(ch.getBytes());
        byte[] sc = rsa.sign();
        System.out.println("Signed challenge: "+sc);

        String rm = publicKey.toString() + pub + sc + keyHandle;
        System.out.println("Response Msg: " +rm);
    }
}
public static Key getKeyFromFile(String fileName) throws Exception
{
    byte[] bytes = Files.readAllBytes(Paths.get(fileName));
    X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PublicKey pub = kf.generatePublic(ks);
    return pub;
}
public static PrivateKey getPvtKey(String s) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException
{
    byte[] bytes = Files.readAllBytes(Paths.get(s));
    PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PrivateKey pvt = kf.generatePrivate(ks);
    return pvt;
}
public static void auth(String s) throws NoSuchAlgorithmException, Exception, IOException
{   
    String chal = s.substring(0, 32);
    String origin = s.substring(32,64);
    String kh = s.substring(64);
    byte[] kh1 = kh.getBytes();

    PrivateKey pvtKey = getPvtKey("f:\\tempKey.key"); //READING THE PRIVATE KEY MADE IN KPGEN
    System.out.println("pk: "+pvtKey);
    Cipher cipher = Cipher.getInstance("RSA");  
    cipher.init(Cipher.DECRYPT_MODE, pvtKey);
    byte[] keyHandle = cipher.doFinal(kh1);

    String or = keyHandle.toString().substring(0, (kh.length()/2));
    String pk = keyHandle.toString().substring(kh.length()/2);

    int c = 0;
    if(or.equals(origin))
    {
        c++;
    }
    else
    {
        System.out.println("Bad Key Handle: Invalid Origin");
    }
    if(pk.equals(pvtKey.toString()))
    {
        c++;
    }
    else
    {
        System.out.println("Bad Key Handle: invalid private key");
    }
    if(c==2)
    {
        Signature rsa = Signature.getInstance("SHA1withRSA"); 
        rsa.initSign((PrivateKey) pvtKey);
        rsa.update(chal.getBytes());
        byte[] sc = rsa.sign();
        System.out.println("Signed Challenge: "+sc);
    }
    else
        System.out.println("error");
}

}

1 个答案:

答案 0 :(得分:2)

您的代码中存在多个加密问题(很多)

首先-正确编码您的数据,Java中的String表示可打印字符。一旦进行了加密(在byte []级别上工作),就需要对值进行编码或解码。

示例-您的代码将打印“ keyHandle”,它是一个字节数组对象哈希,不是真正的加密数据本身

byte[] keyHandle = cipher.doFinal(or.getBytes());
System.out.println("Key Handle: "+keyHandle);
...
String rm = publicKey.toString() + pub + sc + keyHandle;

以十六进制或base64编码使用以打印输出。签名也是如此。

  

我无法解决解密错误。

String kh = s.substring(64);
byte[] kh1 = kh.getBytes();
..  
byte[] keyHandle = cipher.doFinal(kh1);

您只是假设您可以解密一些随机子字符串?使用RSA加密将产生密钥大小(例如2048位)的输出,并且您必须整体存储和解密,而不是任何子字符串。

作为学习练习-尝试简单地加密和解密,编码,解码,以学习可以(重用)的基元。