java java程序中的java.security.spec.InvalidKeySpecException和不适当的密钥规范错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26867840/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:47:30  来源:igfitidea点击:

java.security.spec.InvalidKeySpecException and Inappropriate key specification error in java program

javaencryptioncryptographydsa

提问by user123

As a part of project implementation,I have done: 1. Generete DSA keys 2. Encrypt the private key using AES 3. Save into the file 4. Open the file and read the encrypted private key 5. I tried to convert the read value into primary key format

作为项目实施的一部分,我做了: 1.Generete DSA 密钥 2. 使用 AES 加密私钥 3. 保存到文件 4. 打开文件并读取加密的私钥 5. 我尝试转换读取值成主键格式

import java.security.spec.EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.Security;
import java.io.File;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.io.*;
import java.security.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class Pgm {
    public static void main(String[] args) {
        try {
            KeyPairGenerator dsa = KeyPairGenerator.getInstance("DSA");
            SecureRandom random = new SecureRandom();
            dsa.initialize(1024, random);
            KeyPair keypair = dsa.generateKeyPair();
            PrivateKey privateKey = (PrivateKey) keypair.getPrivate();
            byte[] key = "?u???1ù?iw&a".getBytes();
            Key aesKey = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            String currentDir = System.getProperty("user.dir");
            // encrypt the text
            cipher.init(Cipher.ENCRYPT_MODE, aesKey);
            byte[] abc = privateKey.getEncoded();

            byte[] encrypted = cipher.doFinal(abc);
            // System.out.println("len="+encrypted.length());
            File dir = new File(currentDir);
            File private_file = new File(dir, "privatekey.txt");
            if (!private_file.exists()) {
                private_file.createNewFile();
            }
            FileOutputStream fileos = new FileOutputStream(private_file);
            ObjectOutputStream objectos = new ObjectOutputStream(fileos);
            objectos.writeObject(encrypted);
            objectos.close();
            fileos.close();

            File file_private = new File(dir, "privatekey.txt");
            FileInputStream fileo = new FileInputStream(file_private);
            ObjectInputStream objos = new ObjectInputStream(fileo);
            Object obj = objos.readObject();
            byte[] encrypted1 = (byte[]) obj;
            cipher.init(Cipher.DECRYPT_MODE, aesKey);
            String decrypted = new String(cipher.doFinal(encrypted1));
            if (decrypted.equals(new String(abc)))
                System.out.println("true");
            else
                System.out.println("false");
            Signature tosign = Signature.getInstance("DSA");
            byte[] val = decrypted.getBytes();

            KeyFactory generator = KeyFactory.getInstance("DSA");
            EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(val);
            PrivateKey privatekey1 = generator.generatePrivate(privateKeySpec);
            tosign.initSign(privatekey1);

        } catch (Exception e) {
            System.out.println("failed");
            e.printStackTrace();

        }

    }
}

While I am trying to execute the above code, it shows the following error!

当我尝试执行上面的代码时,它显示以下错误!

screen shot of output screen

输出屏幕的屏幕截图

回答by Maarten Bodewes

Ciphertext and keys should both consist of random bytes. Neither one of them can be represented 1:1 with a string. Not all bytes may represent valid encodings for a specific character-encoding.

密文和密钥都应该由随机字节组成。它们中的任何一个都不能用字符串 1:1 表示。并非所有字节都可以表示特定字符编码的有效编码

Instead you should use byte arrays directly. If you require actual text, use either hexadecimals or base 64 encoding.

相反,您应该直接使用字节数组。如果您需要实际文本,请使用十六进制或 base 64编码

Your code using ciphertext as bytes and a key specified in hexadecimals:

您的代码使用密文作为字节和以十六进制指定的密钥:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import codec.Hex;

public class Pgm {
    public static void main(String[] args) {
        try {
            KeyPairGenerator dsa = KeyPairGenerator.getInstance("DSA");
            SecureRandom random = new SecureRandom();
            dsa.initialize(1024, random);
            KeyPair keypair = dsa.generateKeyPair();
            PrivateKey privateKey = (PrivateKey) keypair.getPrivate();
            byte[] key = Hex.decode("000102030405060708090A0B0C0D0E0F");
            Key aesKey = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            String currentDir = System.getProperty("user.dir");
            // encrypt the text
            cipher.init(Cipher.ENCRYPT_MODE, aesKey);
            byte[] abc = privateKey.getEncoded();

            byte[] encrypted = cipher.doFinal(abc);
            // System.out.println("len="+encrypted.length());
            File dir = new File(currentDir);
            File private_file = new File(dir, "privatekey.txt");
            if (!private_file.exists()) {
                private_file.createNewFile();
            }
            FileOutputStream fileos = new FileOutputStream(private_file);
            ObjectOutputStream objectos = new ObjectOutputStream(fileos);
            objectos.writeObject(encrypted);
            objectos.close();
            fileos.close();

            File file_private = new File(dir, "privatekey.txt");
            FileInputStream fileo = new FileInputStream(file_private);
            ObjectInputStream objos = new ObjectInputStream(fileo);
            Object obj = objos.readObject();
            byte[] encrypted1 = (byte[]) obj;
            cipher.init(Cipher.DECRYPT_MODE, aesKey);
            byte[] decrypted = cipher.doFinal(encrypted1);
            if (Arrays.equals(decrypted, abc))
                System.out.println("true");
            else
                System.out.println("false");
            Signature tosign = Signature.getInstance("DSA");

            KeyFactory generator = KeyFactory.getInstance("DSA");
            EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(decrypted);
            PrivateKey privatekey1 = generator.generatePrivate(privateKeySpec);
            tosign.initSign(privatekey1);

        } catch (Exception e) {
            System.out.println("failed");
            e.printStackTrace();
        }
    }
}