将字符串转换为 SecretKey [英] Converting string to SecretKey

查看:19
本文介绍了将字符串转换为 SecretKey的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 java 中实现 AES 算法.我正在将 SecretKey 转换为 String 并通过套接字传递给 server.java.在 server.java 中,我将此字符串转换回 SecretKey.但是,出现错误下面提到.

我尝试了所有可能的解决方案,但没有任何效果.在 client.java 中,我将 secKey 转换为 String

 字符串编码键 =Base64.getEncoder().encodeToString(secKey.getEncoded());System.out.println(secKey);

输出:

<块引用>

de.flexiprovider.core.rijndael.RijndaelKey@714b1429

我已将此字符串转换回 SecretKey

 byte[] decodedKey = Base64.getDecoder().decode(line);SecretKey secKey = new SecretKeySpec(decodedKey, "AES");System.out.println(secKey);`

<块引用>

输出 - de.flexiprovider.api.keys.SecretKeySpec@fffe87c2

这里,两个输出都不相同,我收到以下错误

<块引用>

线程main"中的异常java.security.InvalidKeyException:不支持的类型在de.flexiprovider.api.BlockCipher.engineInit(BlockCipher.java:165)在 de.flexiprovider.api.Cipher.engineInit(Cipher.java:68)在 javax.crypto.Cipher.init(Cipher.java:1246)在 javax.crypto.Cipher.init(Cipher.java:1186)在 server.main(server.java:93)

我该如何纠正这个错误?

server.java

 import java.net.*;导入 java.io.*;导入 java.security.Security;导入 javax.crypto.*;导入 de.flexiprovider.api.keys.SecretKeySpec;导入 de.flexiprovider.core.FlexiCoreProvider;导入 de.flexiprovider.core.rijndael.RijndaelKeyFactory;导入 java.util.Base64;公共类服务器{公共最终静态 int FILE_SIZE = 6022386;私有套接字套接字 = null;私有 ServerSocket 服务器 = null;私有 DataInputStream in = null;int 字节读取;整数电流 = 0;FileOutputStream fos = null;BufferedOutputStream bos = null;静态 SecretKey secKey = null;公共服务器(int 端口){//启动服务器并等待连接尝试{server = new ServerSocket(port);System.out.println("服务器启动");System.out.println("等待客户...");socket = server.accept();System.out.println("客户端接受");//从客户端套接字获取输入in = new DataInputStream(newBufferedInputStream(socket.getInputStream()));字符串行 = in.readUTF();byte[] decodedKey = Base64.getDecoder().decode(line);secKey = new SecretKeySpec(decodedKey, "AES");字节 [] mybytearray = 新字节 [FILE_SIZE];InputStream is = socket.getInputStream();fos = new FileOutputStream("cipher.txt");bos = 新的 BufferedOutputStream(fos);bytesRead = is.read(mybytearray,0,mybytearray.length);当前 = 字节读取;做 {字节读取 =is.read(mybytearray, current, (mybytearray.length-当前的));if(bytesRead >= 0) 当前 += bytesRead;} while(bytesRead > -1);bos.write(mybytearray, 0 , current);bos.flush();System.out.println("文件收到");//关闭连接socket.close();in.close();fos.close();bos.close();}捕获(IOException i){System.out.println(i);}}public static void main(String args[]) 抛出异常{Security.addProvider(new FlexiCoreProvider());Cipher cipher = Cipher.getInstance("AES128_CBC", "FlexiCore");服务器 ser = 新服务器(5003);字节[]块=新字节[8];国际我;String ciphertextFile = "cipher.txt";String cleartextAgainFile = "cleartextAgainSymm.txt";System.out.println(secKey);cipher.init(Cipher.DECRYPT_MODE, secKey);FileInputStream fis = new FileInputStream(ciphertextFile);CipherInputStream cis = new CipherInputStream(fis, cipher);FileOutputStream fos = new FileOutputStream(cleartextAgainFile);而 ((i = cis.read(block)) != -1) {fos.write(block, 0, i);}fos.close();}}

服务器输出

 服务器启动等待客户...客户接受收到文件de.flexiprovider.api.keys.SecretKeySpec@fffe8f6c线程main"中的异常 java.security.InvalidKeyException:不支持的类型在 de.flexiprovider.api.BlockCipher.engineInit(BlockCipher.java:165)在 de.flexiprovider.api.Cipher.engineInit(Cipher.java:68)在 javax.crypto.Cipher.init(Cipher.java:1246)在 javax.crypto.Cipher.init(Cipher.java:1186)

client.java

 import java.net.*;导入 java.io.*;导入 java.security.Security;导入 javax.crypto.Cipher;导入 javax.crypto.CipherInputStream;导入 javax.crypto.CipherOutputStream;导入 javax.crypto.KeyGenerator;导入 javax.crypto.SecretKey;导入 de.flexiprovider.api.keys.SecretKeySpec;导入 de.flexiprovider.core.FlexiCoreProvider;导入 java.util.Arrays;导入 java.util.Base64;公共类客户{静态 SecretKey secKey;//初始化套接字和输入输出流私有套接字套接字 = null;私有数据输入流输入 = null;private DataOutputStream out = null;FileInputStream fis;文件 myFile;BufferedInputStream bis = null;输出流操作系统 = 空;公共客户端(字符串地址,int 端口){//建立连接尝试{套接字=新套接字(地址,端口);System.out.println("已连接");//从终端获取输入input = new DataInputStream(System.in);//将输出发送到套接字out = new DataOutputStream(socket.getOutputStream());String encodingKey = Base64.getEncoder().encodeToString(secKey.getEncoded());out.writeUTF(encodedKey);myFile = new File("ciphertextSymm.txt");字节 [] mybytearray = 新字节 [(int)myFile.length()];fis=new FileInputStream(myFile);bis = new BufferedInputStream(fis);bis.read(mybytearray,0,mybytearray.length);os = socket.getOutputStream();System.out.println("发送中");os.write(mybytearray,0,mybytearray.length);os.flush();System.out.println("完成.");}捕获(未知主机异常你){System.out.println(u);}捕获(IOException i){System.out.println(i);}//关闭连接尝试{input.close();关闭();socket.close();bis.close();os.close();}捕获(IOException x){System.out.println(x);}}public static void main(String args[]) 抛出异常{Security.addProvider(new FlexiCoreProvider());Cipher cipher = Cipher.getInstance("AES128_CBC", "FlexiCore");KeyGenerator keyGen = KeyGenerator.getInstance("AES", "FlexiCore");secKey = keyGen.generateKey();System.out.println(secKey);cipher.init(Cipher.ENCRYPT_MODE, secKey);String cleartextFile = "cleartext.txt";String ciphertextFile = "ciphertextSymm.txt";FileInputStream fis = new FileInputStream(cleartextFile);FileOutputStream fos = new FileOutputStream(ciphertextFile);CipherOutputStream cos = new CipherOutputStream(fos, cipher);字节[]块=新字节[8];国际我;while ((i = fis.read(block)) != -1) {cos.write(block, 0, i);}cos.close();客户端客户端 = 新客户端("127.0.0.1", 5003);}}

客户端输出

 de.flexiprovider.core.rijndael.RijndaelKey@7c226727连接的发送完毕.

解决方案

我建议阅读 Java 256 位 AES 基于密码的加密.但这里有一个快速概述.您必须创建一个 SecretKeyFactory、一个 KeySpec,然后您可以根据 KeySpec 生成您的 SecretKey.从那里,您可以通过 SecretKeySpec 指定您的密钥是 AES.这里有一些神奇的数字,您必须考虑.一个是密码迭代,另一个是密钥大小.对于我在下面创建的示例,我使用的是 128 密钥而不是 256.抱歉,我不是安全主题的专家,所以我使用了一些我拥有的示例.

public static void main(String[] args) {尝试 {//要加密的消息final String message = "这是一条测试消息";最终字符串密码 = "密码";//这里是神奇的数字最终 int pswdIterations = 65536;最终 int keySize = 128;最终字节[] saltBytes = {0, 1, 2, 3, 4, 5, 6};SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, pswdIterations, keySize);SecretKey secretKey = factory.generateSecret(spec);SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");//实例化密码Cipher cipher = Cipher.getInstance("AES");//加密cipher.init(Cipher.ENCRYPT_MODE, 秘密);字节 [] 加密 = cipher.doFinal(message.getBytes());System.out.println("原始字符串:" + message);System.out.println("加密字符串:" + Arrays.toString(encrypted));//解密cipher.init(Cipher.DECRYPT_MODE, 秘密);字节[]decrypt_original = cipher.doFinal(加密);字符串decrypt_originalString = new String(decrypt_original);System.out.println("解密字符串:" +decrypt_originalString);} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex) {Logger.getLogger(Sandbox.class.getName()).log(Level.SEVERE, null, ex);}}

希望这对您有所帮助.

I am implementing AES algorithm in java.I am converting SecretKey to String and passing to server.java through sockets. In server.java, I am converting this string back to SecretKey.However, I am getting the error mentioned below.

I have tried all possible solutions but nothing worked for me. In client.java, I am converting secKey to String

 String encodedKey = 
 Base64.getEncoder().encodeToString(secKey.getEncoded());
 System.out.println(secKey);

Output:

de.flexiprovider.core.rijndael.RijndaelKey@714b1429

I have converted this string back to SecretKey

 byte[] decodedKey = Base64.getDecoder().decode(line);
 SecretKey secKey = new SecretKeySpec(decodedKey, "AES");
 System.out.println(secKey);`

Output - de.flexiprovider.api.keys.SecretKeySpec@fffe87c2

Here, both outputs are not same and I am getting the following error

Exception in thread "main" java.security.InvalidKeyException: 
unsupported type
   at 
de.flexiprovider.api.BlockCipher.engineInit(BlockCipher.java:165)
   at de.flexiprovider.api.Cipher.engineInit(Cipher.java:68)
   at javax.crypto.Cipher.init(Cipher.java:1246)
   at javax.crypto.Cipher.init(Cipher.java:1186)
   at server.main(server.java:93)

How can I correct this error?

server.java

 import java.net.*;
   import java.io.*;
   import java.security.Security;
   import javax.crypto.*;
   import de.flexiprovider.api.keys.SecretKeySpec;
   import de.flexiprovider.core.FlexiCoreProvider;
   import de.flexiprovider.core.rijndael.RijndaelKeyFactory;
   import java.util.Base64;
   public class server {
    public final static int FILE_SIZE = 6022386; 
    private Socket          socket   = null;
    private ServerSocket    server   = null;
    private DataInputStream in       =  null;
    int bytesRead;
    int current = 0;
    FileOutputStream fos = null;
    BufferedOutputStream bos = null;
    static SecretKey secKey = null;


    public server(int port)
    {
        // starts server and waits for a connection
        try
        {
               server = new ServerSocket(port);
            System.out.println("Server started");
            System.out.println("Waiting for a client ...");
            socket = server.accept();
            System.out.println("Client accepted");



            // takes input from the client socket
            in = new DataInputStream(new 
      BufferedInputStream(socket.getInputStream()));
            String line = in.readUTF();

          byte[] decodedKey = Base64.getDecoder().decode(line);
            secKey = new SecretKeySpec(decodedKey, "AES"); 





            byte [] mybytearray  = new byte [FILE_SIZE];
            InputStream is = socket.getInputStream();
            fos = new FileOutputStream("cipher.txt");
            bos = new BufferedOutputStream(fos);
            bytesRead = is.read(mybytearray,0,mybytearray.length);
            current = bytesRead;
            do {
                bytesRead =
                   is.read(mybytearray, current, (mybytearray.length-
         current));
                if(bytesRead >= 0) current += bytesRead;
             } while(bytesRead > -1);
            bos.write(mybytearray, 0 , current);
            bos.flush();
            System.out.println("File Received" );

            // close connection
            socket.close();
            in.close();fos.close();bos.close();
        }
        catch(IOException i)
        {
            System.out.println(i);
        }
        }
       public static void main(String args[]) throws Exception
       {
        Security.addProvider(new FlexiCoreProvider());
        Cipher cipher = Cipher.getInstance("AES128_CBC", "FlexiCore");
        server ser = new server(5003);

        byte[] block = new byte[8];
        int i;

        String ciphertextFile = "cipher.txt";
        String cleartextAgainFile = "cleartextAgainSymm.txt";

        System.out.println(secKey);
        cipher.init(Cipher.DECRYPT_MODE, secKey);
        FileInputStream fis  = new FileInputStream(ciphertextFile);
        CipherInputStream cis = new CipherInputStream(fis, cipher);


    FileOutputStream  fos = new FileOutputStream(cleartextAgainFile);

            while ((i = cis.read(block)) != -1) {
                fos.write(block, 0, i);
            }
            fos.close();
           }
         }

server output

   Server started
Waiting for a client ...
Client accepted
File Received
de.flexiprovider.api.keys.SecretKeySpec@fffe8f6c
Exception in thread "main" java.security.InvalidKeyException: unsupported type
    at de.flexiprovider.api.BlockCipher.engineInit(BlockCipher.java:165)
    at de.flexiprovider.api.Cipher.engineInit(Cipher.java:68)
    at javax.crypto.Cipher.init(Cipher.java:1246)
    at javax.crypto.Cipher.init(Cipher.java:1186)

client.java

   import java.net.*;
import java.io.*;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import de.flexiprovider.api.keys.SecretKeySpec;
import de.flexiprovider.core.FlexiCoreProvider;

import java.util.Arrays;
import java.util.Base64;

public class Client {

    static SecretKey secKey;
    // initialize socket and input output streams
    private Socket socket            = null;
    private DataInputStream  input   = null;
    private DataOutputStream out     = null;
    FileInputStream fis;
    File myFile;
    BufferedInputStream bis = null;
    OutputStream os = null;

    public Client(String address, int port)
    {

        // establish a connection
        try
        {
            socket = new Socket(address, port);
            System.out.println("Connected");

            // takes input from terminal
            input  = new DataInputStream(System.in);

            // sends output to the socket
            out    = new DataOutputStream(socket.getOutputStream());


            String encodedKey = Base64.getEncoder().encodeToString(secKey.getEncoded());
            out.writeUTF(encodedKey);

             myFile = new File ("ciphertextSymm.txt");
             byte [] mybytearray  = new byte [(int)myFile.length()];
             fis=new FileInputStream(myFile);
             bis = new BufferedInputStream(fis);
             bis.read(mybytearray,0,mybytearray.length);
             os = socket.getOutputStream();
             System.out.println("Sending ");
             os.write(mybytearray,0,mybytearray.length);
             os.flush();
             System.out.println("Done.");

        }
        catch(UnknownHostException u)
        {
            System.out.println(u);
        }
        catch(IOException i)
        {
            System.out.println(i);
        }

        // close the connection
        try
        {
            input.close();
            out.close();
            socket.close();
            bis.close();
            os.close();
        }
        catch(IOException x)
        {
            System.out.println(x);
        }
    }
    public static void main(String args[]) throws Exception
    {
        Security.addProvider(new FlexiCoreProvider());
        Cipher cipher = Cipher.getInstance("AES128_CBC", "FlexiCore");
        KeyGenerator keyGen = KeyGenerator.getInstance("AES", "FlexiCore");
        secKey = keyGen.generateKey();


        System.out.println(secKey);
        cipher.init(Cipher.ENCRYPT_MODE, secKey);
        String cleartextFile = "cleartext.txt";
        String ciphertextFile = "ciphertextSymm.txt";

        FileInputStream fis = new FileInputStream(cleartextFile);
        FileOutputStream fos = new FileOutputStream(ciphertextFile);
        CipherOutputStream cos = new CipherOutputStream(fos, cipher);

        byte[] block = new byte[8];
        int i;
        while ((i = fis.read(block)) != -1) {
            cos.write(block, 0, i);
        }
        cos.close();

        Client client = new Client("127.0.0.1", 5003);
    }
}

client output

    de.flexiprovider.core.rijndael.RijndaelKey@7c226727
Connected
Sending 
Done.

解决方案

I would recommend to read Java 256-bit AES Password-Based Encryption. But here a quick overview. You will have to create a SecretKeyFactory, a KeySpec and then you can generate your SecretKey based on the KeySpec. From there, you can specify that your key is an AES through SecretKeySpec. There are some magic numbers here that you will have to consider. One is the password iterations, and the other the key sizes. For the example that I created below, I am using a 128 key instead of a 256. Sorry, I am not an expert in security topics so I used some examples that I have.

public static void main(String[] args) {
    try {
        //message to be encrypted
        final String message = "This is a test message";  
        final String password = "password";

        // Here the magic numbers
        final int pswdIterations = 65536;
        final int keySize = 128;

        final byte[] saltBytes = {0, 1, 2, 3, 4, 5, 6};

        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, pswdIterations, keySize);
        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        // Instantiate the cipher
        Cipher cipher = Cipher.getInstance("AES");

        // Encrypt
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        byte[] encrypted = cipher.doFinal(message.getBytes());
        System.out.println("Original string: " + message);
        System.out.println("Encrypted string: " + Arrays.toString(encrypted));

        // Decrypt
        cipher.init(Cipher.DECRYPT_MODE, secret);
        byte[] decrypt_original = cipher.doFinal(encrypted);
        String decrypt_originalString = new String(decrypt_original);
        System.out.println("Decrypt string: " + decrypt_originalString);
    } catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex) {
        Logger.getLogger(Sandbox.class.getName()).log(Level.SEVERE, null, ex);
    }
}

Hopefully, this will help you.

这篇关于将字符串转换为 SecretKey的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆