I apologize to ask your skills in the question asked so many times. I have a problem with RSA cryptography. I already checked other topics on this issue, but I did not find a useful answer. I hope you can help me.
I want to read a file, crypt to contain it, and then decrypt it and put these decrypted bytes in a new file.
I really can: - get bytes of a file - crypt it
I have an exception: javax.crypto.BadPaddingException: data must start from scratch.
Here is my code:
package com.bodom.ghosty; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.io.*; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import java.util.Scanner; public class EncryptionUtil { private final PrivateKey privateKey; private final PublicKey publicKey; public EncryptionUtil (KeyPair keyPair) { this.privateKey = keyPair.getPrivate(); this.publicKey = keyPair.getPublic(); } private static KeyPair keyGenerate() throws NoSuchAlgorithmException { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(2048); return keyGen.genKeyPair(); } private static byte[] rsaEncryption(byte[] data, EncryptionUtil encryptionUtil) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, encryptionUtil.publicKey); return cipher.doFinal(data); } private static byte[] readBytesInFile (Path file) throws IOException { byte[] result = new byte[(int)Files.size(file)]; try { try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file.getFileName().toString()))) { int bytesRead = 0; while (bytesRead < result.length) { int bytesLeft = result.length - bytesRead; int bytesGet = inputStream.read(result, bytesRead, bytesLeft); if (bytesGet > 0) { bytesRead += bytesGet; } } } } catch (IOException e) { System.out.println(e); } return result; } public static byte[] encryption (Path file, EncryptionUtil encryptionUtil) throws IOException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException { byte[] datatocrypt = readBytesInFile(file); int offset = 0; byte[] cryptedfile = null; while (offset < datatocrypt.length) { byte[] outputBytes; byte[] tmp; if(datatocrypt.length - offset < 200 ) { outputBytes = new byte[datatocrypt.length - offset]; System.arraycopy(datatocrypt, offset, outputBytes, 0, datatocrypt.length - offset); byte[] crypt = rsaEncryption(outputBytes, encryptionUtil); tmp = cryptedfile; if (tmp != null) { cryptedfile = new byte[tmp.length + crypt.length]; } else cryptedfile = new byte[crypt.length]; if (tmp != null) { System.arraycopy(tmp, 0, cryptedfile, 0, tmp.length); System.arraycopy(crypt, 0, cryptedfile, tmp.length, crypt.length); } else { System.arraycopy(crypt, 0, cryptedfile, 0, crypt.length); } break; } outputBytes = new byte[200]; System.arraycopy(datatocrypt, offset, outputBytes, 0, 200); byte[] crypt = rsaEncryption(outputBytes, encryptionUtil); tmp = cryptedfile; if (tmp != null) { cryptedfile = new byte[tmp.length + crypt.length]; } else cryptedfile = new byte[crypt.length]; if (tmp != null) { System.arraycopy(tmp, 0, cryptedfile, 0, tmp.length); System.arraycopy(crypt, 0, cryptedfile, tmp.length, crypt.length); } else { System.arraycopy(crypt, 0, cryptedfile, 0, crypt.length); } offset += 200 ; } return cryptedfile; } private static byte[] rsaDecryption(byte[] crypteddata, EncryptionUtil encryptionUtil) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, encryptionUtil.privateKey); return cipher.doFinal(crypteddata); } public static byte[] decryption(Path file, EncryptionUtil encryptionUtil) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException { byte[] crypteddata = readBytesInFile(file); int offset = 0; byte[] decryptedfile = null; while (offset < crypteddata.length) { byte[] outputBytes; byte[] tmp; if(crypteddata.length - offset < 200 ) { outputBytes = new byte[crypteddata.length - offset]; System.arraycopy(crypteddata, offset, outputBytes, 0, crypteddata.length - offset); byte[] decrypt = rsaDecryption(outputBytes, encryptionUtil); tmp = decryptedfile; if (tmp != null) { decryptedfile = new byte[tmp.length + decrypt.length]; } else decryptedfile = new byte[decrypt.length]; if (tmp != null) { System.arraycopy(tmp, 0, decryptedfile, 0, tmp.length); System.arraycopy(decrypt, 0, decryptedfile, tmp.length, decrypt.length); } else { System.arraycopy(decrypt, 0, decryptedfile, 0, decrypt.length); } break; } outputBytes = new byte[200]; System.arraycopy(crypteddata, offset, outputBytes, 0, 200); byte[] decrypt = rsaDecryption(outputBytes, encryptionUtil); tmp = decryptedfile; if (tmp != null) { decryptedfile = new byte[decrypt.length + tmp.length]; } else decryptedfile = new byte[decrypt.length]; if (tmp != null) { System.arraycopy(tmp, 0, decryptedfile, 0, tmp.length); System.arraycopy(decrypt, 0, decryptedfile, tmp.length, decrypt.length); } else { System.arraycopy(decrypt, 0, decryptedfile, 0, decrypt.length); } offset +=200 ; } return decryptedfile; } private static void saveKeyToFile (BigInteger modulus, BigInteger exponent, String filename) throws IOException, NoSuchAlgorithmException { Path path = Paths.get(filename); if(!Files.exists(path)) { Files.createFile(path); } try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filename))) { objectOutputStream.writeObject(modulus); objectOutputStream.writeObject(exponent); } } public static void saveKeyPair(EncryptionUtil encryptionUtil, String directorypath) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec rsaPublicKeySpec = keyFactory.getKeySpec(encryptionUtil.publicKey, RSAPublicKeySpec.class); saveKeyToFile(rsaPublicKeySpec.getModulus(), rsaPublicKeySpec.getPublicExponent(), directorypath + "/public.key"); RSAPrivateKeySpec rsaPrivateKeySpec = keyFactory.getKeySpec(encryptionUtil.privateKey, RSAPrivateKeySpec.class); saveKeyToFile(rsaPrivateKeySpec.getModulus(), rsaPrivateKeySpec.getPrivateExponent(), directorypath + "/private.key"); } private static PublicKey getPublicKeyFromFile (String filename) throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException { try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename))) { BigInteger modulus = (BigInteger) objectInputStream.readObject(); BigInteger exponent = (BigInteger) objectInputStream.readObject(); RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, exponent); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(rsaPublicKeySpec); } } private static PrivateKey getPrivateKeyFromFile (String filename) throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException { try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename))) { BigInteger modulus = (BigInteger) objectInputStream.readObject(); BigInteger exponent = (BigInteger) objectInputStream.readObject(); RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulus, exponent); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(rsaPrivateKeySpec); } } public static KeyPair getKeysFromFiles (String directorypath) throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException{ PublicKey publicKey = getPublicKeyFromFile(directorypath + "/public.key"); PrivateKey privateKey = getPrivateKeyFromFile(directorypath + "/private.key"); return new KeyPair(publicKey, privateKey); } public static void main(String[] args) { EncryptionUtil encryptionUtil = null; Scanner scanner = new Scanner(System.in); System.out.println("Path of the keys :"); String path = scanner.nextLine(); try { encryptionUtil = new EncryptionUtil(EncryptionUtil.keyGenerate()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } Path directorypath = Paths.get(path); try { Files.createDirectories(directorypath); } catch (IOException e) { e.printStackTrace(); } try { saveKeyPair(encryptionUtil, path); } catch (NoSuchAlgorithmException | InvalidKeySpecException| IOException e) { System.out.println("Error during the storage of the keys : " + e); }
I read that the problem often occurs when the wrong private key is used for decryption or Cypher is used incorrectly. But I do not think this is the case, or I did not see this ... I do not know what is wrong with my code. To run this code, you will need a file called "filetocrypt". I use bytes [], and I broke them up by gluing and decrypting files to avoid RSA byte size. This splitting works fine (I tried files with strings without using RSA algorithm)
Thank you for your help!