I am trying to generate a RSA key pair and store RSA public key in a text file so I can open it later. I have my text file but after I run my saveRSApublicKey function, it does not write anything to my pubkey.txt file. Please help.
public class Server {
static KeyPair keys;
static byte[] RSAencrypted;
File file;
FileOutputStream fop = null;
public Receiver() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException{
keys = KeyPairGenerator.getInstance("RSA").generateKeyPair();
}
public void saveRSApublicKey() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException{
byte[] pubKeyBytes = keys.getPublic().getEncoded();
file = new File("pubkey.txt");
fop = new FileOutputStream(file);
fop.write(publicKeyBytes);
fop.close();
}
}
Notice pubKeyBytes and publicKeyBytes are not same.
You are getting the public key content in pubKeyBytes, but writing streams from publicKeyBytes. It should be:
byte[] pubKeyBytes = keys.getPublic().getEncoded();
file = new File("pubkey.txt");
fop = new FileOutputStream(file);
fop.write( pubKeyBytes );
fop.close();
How did your code compiled anyway?
Related
I am doing a project to learn about encryption and decryption. I encrypt a file (input file) and encrypt the symmetric key using RSA public. Then I decrypt the symmetric key using RSA private key and then decrypt the file(output file).
here below is the code:
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
public class Main {
public static SecretKey generateKey(int n) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(n);
SecretKey key = keyGenerator.generateKey();
return key;
}
public static IvParameterSpec generateIv() {
byte[] iv = new byte[128/8];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
public static void encryptFile(String algorithm, SecretKey key, IvParameterSpec iv,
File inputFile, File outputFile) throws IOException, NoSuchPaddingException,
NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile);
byte[] buffer = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byte[] output = cipher.update(buffer, 0, bytesRead);
if (output != null) {
outputStream.write(output);
}
}
byte[] outputBytes = cipher.doFinal();
if (outputBytes != null) {
outputStream.write(outputBytes);
}
inputStream.close();
outputStream.close();
}
public static void decryptFile(String algorithm, SecretKey key, IvParameterSpec iv,
File inputFile, File outputFile) throws IOException, NoSuchPaddingException,
NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile);
byte[] buffer = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byte[] output = cipher.update(buffer, 0, bytesRead);
if (output != null) {
outputStream.write(output);
}
}
byte[] outputBytes = cipher.doFinal();
if (outputBytes != null) {
outputStream.write(outputBytes);
}
inputStream.close();
outputStream.close();
}
public static byte[] encryptSymmetricKey(SecretKey secKey) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
byte[] key = Files.readAllBytes(Paths.get("publicKey.key"));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.PUBLIC_KEY, publicKey);
byte[] encryptedKey = cipher.doFinal(secKey.getEncoded());
return encryptedKey;
}
public static SecretKey decryptSymmetricKey(SecretKey secKey) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
byte[] encryptedKey= encryptSymmetricKey(secKey);
byte[] key = Files.readAllBytes(Paths.get("publicKey.key"));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.PRIVATE_KEY, privateKey);
byte[] decryptedKey = cipher.doFinal(encryptedKey);
SecretKey originalKey = new SecretKeySpec(decryptedKey , 0, decryptedKey .length, "AES");
return originalKey;
}
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, RuntimeException, InvalidKeySpecException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException, InvalidAlgorithmParameterException {
SecretKey secKey=generateKey(128);
IvParameterSpec iv=generateIv();
File inputFile=new File("C:/Users/nm-ca/IdeaProjects/RSA/src/inputFile.txt");
File outputFile=new File("C:/Users/nm-ca/IdeaProjects/RSA/src/outputFile.txt");
encryptFile("AES/CBC/PKCS5Padding",secKey,iv,inputFile,outputFile);
//Decrypt the cipher text using decrypted symmetric key
decryptFile("AES/CBC/PKCS5Padding", decryptSymmetricKey(secKey),iv,outputFile,inputFile);
}
}
The Error:
Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
When I encrypt the symmetric key and then decrypt it, I produce an invalid key I guess. How can I solve this problem?
I am writing java program to encrypt video files,with small video files it performs as expected however when i try on a huge file approximately 800 Megabyte,it throws an exception
java.lang.OutOfMemoryError: Java heap space.
I have researched on the topic getting more information about the garbage collector from here and reviewing similar problems here. According to the best chosen answer how can you "Encrypt a byte at a time": With block ciphers encryption is by the block (AES: 16-bytes)`.
The contents of my source code
main.java
public static void main(String[] args) {
String key = "Mary has one cat";
File inputFile = new File("C:\\Users\\xyz\\Music\\test\\-.mp4");
File encryptedFile = new File("C:\\Users\\xyz\\Music\\test\\-.mp4.encrypted");
File decryptedFile = new File("C:\\Users\\xyz\\Music\\test\\decrypted.mp4");
try {
CryptoUtils.encrypt(key, inputFile, encryptedFile);
CryptoUtils.decrypt(key, encryptedFile, decryptedFile);
} catch (CryptoException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
}
}
CryptoUtils.java
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES";
public static void encrypt(String key, File inputFile, File outputFile)
throws CryptoException {
doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
}
public static void decrypt(String key, File inputFile, File outputFile)
throws CryptoException {
doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
}
private static void doCrypto(int cipherMode, String key, File inputFile,
File outputFile) throws CryptoException {
try {
Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(cipherMode, secretKey);
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
} catch (NoSuchPaddingException | NoSuchAlgorithmException
| InvalidKeyException | BadPaddingException
| IllegalBlockSizeException | IOException ex) {
throw new CryptoException("Error encrypting/decrypting file", ex);
}
}
CryptoException.java
public class CryptoException extends Exception {
public CryptoException() {
}
public CryptoException(String message, Throwable throwable) {
super(message, throwable);
}}
I think you should look into using CipherOutputStream. This way you won't need to load the file into memory:
https://docs.oracle.com/javase/9/docs/api/javax/crypto/CipherOutputStream.html
Don't process the whole file at once: use a buffer:
try (FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile)) {
byte[] inputBytes = new byte[4096];
for (int n = inputStream.read(inputBytes); n > 0; n = inputStream.read(inputBytes)) {
byte[] outputBytes = cipher.update(inputBytes, 0, n);
outputStream.write(outputBytes);
}
byte[] outputBytes = cipher.doFinal();
outputStream.write(outputBytes);
}
PROBLEM: Upload method is working the problem I'm presenting is **encrypt(inputFile, new File("Users/myname/Desktop/example.txt"),key);** instead of writing to my desktop I want it to be stored as a file or var I can use so I can upload to dropbox server. I just do not know how to code this part and do not know what to put so this will execute appropriately.
private byte[] getKeyBytes(final byte[] key) throws Exception {
byte[] keyBytes = new byte[16];
System.arraycopy(key, 0, keyBytes, 0, Math.min(key.length, keyBytes.length));
return keyBytes;
}
public Cipher getCipherEncrypt(final byte[] key) throws Exception {
byte[] keyBytes = getKeyBytes(key);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
return cipher;
}
public void encrypt(File in, File output, byte[] key) throws Exception {
Cipher cipher = getCipherEncrypt(key);
FileOutputStream fos = null;
CipherOutputStream cos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(in);
fos = new FileOutputStream(output);
cos = new CipherOutputStream(fos, cipher);
byte[] data = new byte[1024];
int read = fis.read(data);
while (read != -1) {
cos.write(data, 0, read);
read = fis.read(data);
System.out.println(new String(data, "UTF-8").trim());
}
cos.flush();
System.out.println("name"+ output);
} finally {
System.out.println("performed encrypt method now closing streams");
cos.close();
fos.close();
fis.close();
}
}
// Working Upload Method To DropBox Cloud
public void uploadFile () throws DbxException, IOException, FileLoadException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException, InvalidParameterSpecException, ClassNotFoundException, NoSuchProviderException, InvalidAlgorithmParameterException, UnsupportedAudioFileException, LineUnavailableException, InterruptedException, ShortBufferException, Exception {
// autheticate if there is a accessToken here if not prompt to login by activating the drop method re-auth..
try{
phoneHome();
}catch(IOException e){
System.out.println("not saving accessToken");
JOptionPane.showMessageDialog(null, "Your Access Information Does Not Exist,\n Please Login"+
"Please Login By Clicking 'OK'");
drop(); // will run auth method for user to login
}
// user picks file to upload with JFileChooser
fc = new JFileChooser();
fc.setMultiSelectionEnabled(true);
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
int dialog = fc.showSaveDialog(this);
if (dialog == JFileChooser.APPROVE_OPTION) {
inputFile = fc.getSelectedFile();
inputFile.getName();
inputFile.getAbsoluteFile();
String nameOf = inputFile.getName();
System.out.println(" File: " + inputFile);
/* calling out inputFIle from out JFileChooser and now passing it into
our method and encrytping and outputing it.
*/
encrypt(inputFile, new File("Users/myname/Desktop/example.txt"),key);
File selected = new File ("?");
inputStream = new FileInputStream (selected);
uploadedFile = client.uploadFile( "/" +selected ,DbxWriteMode.add(), inputFile.length(), inputStream);
/*
Original works without encryption
File selectedFile = new File(nameOf+inputFile);
inputStream = new FileInputStream(inputFile);
*/
// Original uploadedFile = client.uploadFile( "/" +selectedFile ,DbxWriteMode.add(), inputFile.length(), inputStream);
setTitle("Uploading File..");
System.out.println("Uploaded: " + uploadedFile.toString());
JOptionPane.showMessageDialog(null,"File Upload:" + uploadedFile.toString(),
"Success!", JOptionPane.WARNING_MESSAGE);
}
}
Solved... all it was is simply over complicating something that didn't need to be complicated furthermore and have settled for a more simplicit way.
ORIGINAL: encrypt(inputFile, new File("Users/myname/Desktop/example.txt"),key);
WORKING: encrypt(inputFile, new File(inputFile.getName),key);
Eazy Peezy... if anyone has any other suggestions I would like to hear them, thanks.
I am using the following code to encrypt/decrypt:
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class CryptoUtils {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES";
public static void encrypt(String key, File inputFile, File outputFile)
throws CryptoException {
doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
}
public static void decrypt(String key, File inputFile, File outputFile)
throws CryptoException {
doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
}
private static void doCrypto(int cipherMode, String key, File inputFile,
File outputFile) throws CryptoException {
try {
Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PAdding");
cipher.init(cipherMode, secretKey);
FileInputStream inputStream = new FileInputStream(inputFile);
byte[] inputBytes = new byte[(int) inputFile.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes);
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException
| InvalidKeyException | BadPaddingException
| IllegalBlockSizeException | IOException ex) {
throw new CryptoException("Error encrypting/decrypting file", ex);
}
}
public static class CryptoException extends Exception {
public CryptoException() {
}
public CryptoException(String message, Throwable throwable) {
super(message, throwable);
}
}
}
I can both encrypt and decrypt a video file.
However, I am not able to play the decrypted file, encrypted by the same code.
The original file: http://www.megafileupload.com/hSTZ/a.mp4
The encrypted file: http://www.megafileupload.com/hSU2/encrypted-a.mp4
The decrypted file: http://www.megafileupload.com/hSU1/decrypted-final-a.mp4
The first 16 bytes of the decrypted file are different from the original file. The length is the same.
You're assuming that:
The file fits into memory.
The file size fits into an int.
read() fills the buffer.
The result of encryption or decryption fits into memory along with the source content.
There's no need for any of these assumptions.
FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile);
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
byte[] output = cipher.update(buffer, 0, count);
outputStream.write(output);
}
outputStream.write(cipher.doFinal());
outputStream.close();
inputStream.close();
E&OE but you get the idea. You could make your life even simpler by using CipherInput/OutputStreams, but you lose touch with the crypto exceptions a bit that way.
I want to cipher a file, and keep the key in the file, like a ciphered text key.
Then I want to take the key from the file, and decipher the file using that key.
I have the code below,
public class JavaApplication8 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, FileNotFoundException, ClassNotFoundException {
// TODO code application logic here
cifrarFicheiro();
decifrarFicheiro();
}
public static void cifrarFicheiro() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
File t1 = new File("t1.txt");
FileInputStream Fin= new FileInputStream(t1);
byte[] texto= new byte[(int)t1.length()];
Fin.read(texto);
Fin.close();
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
Cipher cifra = Cipher.getInstance("DES/ECB/PKCS5Padding");
cifra.init(Cipher.ENCRYPT_MODE, key);
byte[] chave = key.getEncoded();
byte[] texto_cifrado = cifra.doFinal(texto);
FileOutputStream fout = new FileOutputStream("t1_t.txt");
ObjectOutputStream obj = new ObjectOutputStream(fout);
fout.write(texto_cifrado);
obj.writeObject(chave);
obj.close();
fout.close();
}
public static void decifrarFicheiro() throws FileNotFoundException, IOException, ClassNotFoundException{
FileInputStream fin = new FileInputStream("t1_t.txt");
ObjectInputStream obj = new ObjectInputStream(fin);
SecretKey chave = (javax.crypto.SecretKey)obj.readObject();
byte []keyCifrada = chave.getEncoded();
obj.close();
FileOutputStream fout = new FileOutputStream("t1_chave.txt");
ObjectOutputStream obj1 = new ObjectOutputStream(fout);
obj1.writeObject(keyCifrada);
byte [] text = new byte[fin.available()];
fin.read(text);
}
}
But I am getting the Exception below:
Exception in thread "main" java.io.StreamCorruptedException: invalid type code: F9
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1377)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at javaapplication8.JavaApplication8.decifrarFicheiro(JavaApplication8.java:59)
at javaapplication8.JavaApplication8.main(JavaApplication8.java:31)
Java Result: 1
Can anyone help me? :)
First of all the cipher and decipher methods should be symmetric. You are calling two write operations and only reading once. If you have an ObjectOutputStream wrapping the fileoutputstream the calls should both be made on the ObjectOutputStream. StreamCorruptedException is launched when the metadata on the stream is damaged. Call the flush method to prevent that (i think). Either way you should: writeObject(texto_cifrado), writeObject(key), flush. Then read_Object(texto_cifrado), read_object(key). Acho que assim funciona lol
public class JavaApplication8 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, FileNotFoundException, ClassNotFoundException {
// TODO code application logic here
cifrarFicheiro();
decifrarFicheiro();
}
public static void cifrarFicheiro() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
File t1 = new File("t1.txt");
FileInputStream Fin= new FileInputStream(t1);
byte[] texto= new byte[(int)t1.length()];
Fin.read(texto);
Fin.close();
SecretKey key = KeyGenerator.getInstance("DES").generateKey();
Cipher cifra = Cipher.getInstance("DES/ECB/PKCS5Padding");
cifra.init(Cipher.ENCRYPT_MODE, key);
byte[] chave = key.getEncoded();
byte[] texto_cifrado = cifra.doFinal(texto);
FileOutputStream fout = new FileOutputStream("t1_t.txt");
ObjectOutputStream obj = new ObjectOutputStream(fout);
obj.writeObject(texto_cifrado);
obj.writeObject(chave);
obj.close();
fout.close();
}
public static void decifrarFicheiro() throws FileNotFoundException, IOException, ClassNotFoundException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
FileInputStream fin = new FileInputStream("t1_t.txt");
ObjectInputStream obj = new ObjectInputStream(fin);
byte[] texto = (byte[]) obj.readObject();
byte[] chave = (byte[]) obj.readObject();
obj.close();
FileOutputStream fout = new FileOutputStream("t1_chave.txt");
ObjectOutputStream obj1 = new ObjectOutputStream(fout);
obj1.writeObject(chave);
FileOutputStream fout1 = new FileOutputStream("t1_texto.txt");
ObjectOutputStream obj2 = new ObjectOutputStream(fout1);
obj2.writeObject(texto);
SecretKey sks = new SecretKeySpec(chave, "DES");
Cipher c= Cipher.getInstance("DES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE,sks);
byte[] aux=c.doFinal(texto);
FileOutputStream fout2 = new FileOutputStream("t1_final.txt");
fout2.write(aux);
}
}
I was able to solve it. If you use Objects, you can write it in the file and the read it in the same order. In the cifrarFicheiro() function, I use the ObjectInputStream and write the text followed by the key. And then in the decifrarFicheiro() function I use de ObjectOutputStream, and I now that the first object is the text and the second is the key.