将字符串转换为 SecretKey
Converting string to SecretKey
我正在 java.I 中实现 AES 算法,正在将 SecretKey 转换为字符串并通过套接字传递给 server.java。在 server.java 中,我将此字符串转换回 SecretKey.However,但出现错误
下面提到。
我已经尝试了所有可能的解决方案,但没有任何效果。
在 client.java 中,我将 secKey 转换为 String
String encodedKey =
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);`
Output - de.flexiprovider.api.keys.SecretKeySpec@fffe87c2
这里,两个输出不一样,我收到以下错误
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)
我该如何纠正这个错误?
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 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);
}
}
客户端输出
de.flexiprovider.core.rijndael.RijndaelKey@7c226727
Connected
Sending
Done.
我建议阅读 Java 256-bit AES Password-Based Encryption。但这里有一个快速概述。您将必须创建一个 SecretKeyFactory、一个 KeySpec 然后您可以生成您的 SecretKey关键规范。从那里,您可以通过 SecretKeySpec 指定您的密钥是 AES。这里有一些你必须考虑的神奇数字。一个是密码迭代,另一个是密钥大小。对于我在下面创建的示例,我使用的是 128 密钥而不是 256 密钥。抱歉,我不是安全主题方面的专家,所以我使用了一些我已有的示例。
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);
}
}
希望这对您有所帮助。
对于 Java 7 或以下:
字符串的密钥:
stringKey = Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT);
字符串到密钥:
byte[] encodedKey = Base64.decode(stringKey, Base64.DEFAULT);
SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
对于Java8:
字符串的密钥:
String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
字符串到密钥:
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
摘自参考资料:
我正在 java.I 中实现 AES 算法,正在将 SecretKey 转换为字符串并通过套接字传递给 server.java。在 server.java 中,我将此字符串转换回 SecretKey.However,但出现错误 下面提到。
我已经尝试了所有可能的解决方案,但没有任何效果。 在 client.java 中,我将 secKey 转换为 String
String encodedKey =
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);`
Output - de.flexiprovider.api.keys.SecretKeySpec@fffe87c2
这里,两个输出不一样,我收到以下错误
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)
我该如何纠正这个错误?
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 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);
}
}
客户端输出
de.flexiprovider.core.rijndael.RijndaelKey@7c226727
Connected
Sending
Done.
我建议阅读 Java 256-bit AES Password-Based Encryption。但这里有一个快速概述。您将必须创建一个 SecretKeyFactory、一个 KeySpec 然后您可以生成您的 SecretKey关键规范。从那里,您可以通过 SecretKeySpec 指定您的密钥是 AES。这里有一些你必须考虑的神奇数字。一个是密码迭代,另一个是密钥大小。对于我在下面创建的示例,我使用的是 128 密钥而不是 256 密钥。抱歉,我不是安全主题方面的专家,所以我使用了一些我已有的示例。
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);
}
}
希望这对您有所帮助。
对于 Java 7 或以下:
字符串的密钥:
stringKey = Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT);
字符串到密钥:
byte[] encodedKey = Base64.decode(stringKey, Base64.DEFAULT);
SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
对于Java8:
字符串的密钥:
String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
字符串到密钥:
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
摘自参考资料: