I tried convert it to byte[] and store it on a bytea but it didn't work, i don't receive the same secretkey that i stored. Using type String didn't work as well
if you're interested in more details, my application is to crypt and decrypt pictures using AES and these are methods to crypt and decrypt
public void crypt() throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IOException{
Cipher cipher = Cipher.getInstance("AES");
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
SecretKey secKey = keyGen.generateKey();
byte[] encoded = secKey.getEncoded();
this.setCodeCrypt(encoded);
cipher.init(Cipher.ENCRYPT_MODE, secKey);
String cleartextFile = this.lien;
String ciphertextFile = "crypted img.jpg";
FileInputStream fis = new FileInputStream(cleartextFile);
FileOutputStream fos = new FileOutputStream(ciphertextFile);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
int i;
while ((i = fis.read()) != -1) {
cos.write(i);
}
cos.close();
}
// Decrypt
public void decrypt() throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IOException{
try {
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:5432/papiersadmin";
String user = "postgres";
String passwd = "postgresql";
java.sql.Connection conn = DriverManager.getConnection(url, user,passwd);
Statement state = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
// loading a picture knowing its path (lien)
ResultSet result = state.executeQuery("SELECT * FROM image WHERE lien = '"+this.lien+"'");
while(result.next()){
setCodeCrypt(result.getObject(6).toString().getBytes());}
state.close();
} catch (Exception e) {
e.printStackTrace();
}
Cipher cipher = Cipher.getInstance("AES");
SecretKey originalKey = new SecretKeySpec(codeCrypt, 0, codeCrypt.length, "AES");
cipher.init(Cipher.DECRYPT_MODE, originalKey);
String cleartextFile = "decrypted img.jpg";
String ciphertextFile = this.lien;
FileInputStream fis = new FileInputStream(ciphertextFile);
FileOutputStream fos = new FileOutputStream(cleartextFile);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
int i;
while ((i = fis.read()) != -1) {
cos.write(i);
}
cos.close();
}
Converting a byte[] to a String using toString() and then calling getBytes() will not do anything useful. I would suggest starting with ResultSet.getBytes().
Related
I am trying to decrypt files by Java and below codes work. However it will have OutOfMemory exception when decrypting large files. I tried to change to cipher.update but the program will freeze without any responding.
How can I change this from doFinal to update?
public File decryptDataFile(File inputFile, File outputFile, File keyFile, String correlationId) {
try {
Security.addProvider(new BouncyCastleProvider());
String key = new String(Files.readAllBytes(keyFile.toPath())).trim();
byte[] byteInput = this.getFileInBytes(inputFile);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
byte[] salt = new byte[8];
System.arraycopy(byteInput, 8, salt, 0, 8);
SecretKeyFactory fact = SecretKeyFactory.getInstance("PBEWITHMD5AND256BITAES-CBC-OPENSSL", "BC");
cipher.init(Cipher.DECRYPT_MODE, fact.generateSecret(new PBEKeySpec(key.toCharArray(), salt, 100)));
byte[] data = cipher.doFinal(byteInput, 16, byteInput.length-16);
OutputStream os = new FileOutputStream(outputFile);
os.write(data);
os.close();
if(outputFile.exists()) {
return outputFile;
} else {
return null;
}
} catch (IOException | NoSuchAlgorithmException | NoSuchProviderException | NoSuchPaddingException | InvalidKeyException | InvalidKeySpecException | IllegalBlockSizeException | BadPaddingException e) {
logger.WriteLog(appConfig.getPlatform(), "INFO", alsConfig.getProjectCode(), correlationId, alsConfig.getFunctionId(), "SCAN_DECRYPT", e.getClass().getCanonicalName() + " - " + e.getMessage() );
return null;
}
}
My non-working version:
Security.addProvider(new BouncyCastleProvider());
String key = new String(Files.readAllBytes(keyFile.toPath())).trim();
byte[] byteInput = this.getFileInBytes(inputFile);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
byte[] salt = new byte[8];
System.arraycopy(byteInput, 8, salt, 0, 8);
SecretKeyFactory fact = SecretKeyFactory.getInstance("PBEWITHMD5AND256BITAES-CBC-OPENSSL", "BC");
cipher.init(Cipher.DECRYPT_MODE, fact.generateSecret(new PBEKeySpec(key.toCharArray(), salt, 100)));
FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
if(outputFile.exists()) {
return outputFile;
} else {
return null;
}
Foreword: I couldn't decrypt with your original method a file that was encrypted with your openssl-command
openssl enc -aes-256-cbc -e -salt -in ${tarFile} -out ${encTarFile} -pass file:./${KEY_RANDOM}
but the following method should decode even large files similar to your original method - I tested files up to 1 GB size.
Edit: Regarding the OpenSSL statement, it's worth mentioning that since v1.1.0 the default digest has changed from MD5 to SHA256,
so for higher versions the -md MD5 option must be set explicitly for compatibility with the Java code. (thanks to #Topaco).
Please keep in mind that I don't care about correct file paths for
new FileInputStream(inputFile.toPath().toString())
and
new FileOutputStream(outputFile.toPath().toString())
as I'm working locally and with my folder, maybe you have to change the code to "find" your files. As well there is no exception handling in this example.
The code line
byte[] ibuf = new byte[8096];
is defining the buffer that is used - a larger buffer makes the decryption faster but consumes more memory (8096 means 8096 byte compared to 1 Gbyte when reading the complete file into memory and causing the out of memory error).
public static File decryptDataFileBuffered(File inputFile, File outputFile, File keyFile, String correlationId) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
Security.addProvider(new BouncyCastleProvider());
String key = new String(Files.readAllBytes(keyFile.toPath())).trim();
byte[] salt = new byte[8];
byte[] salted = new byte[8]; // text SALTED__
try (FileInputStream in = new FileInputStream(inputFile.toPath().toString()); // i don't care about the path as all is lokal
FileOutputStream out = new FileOutputStream(outputFile.toPath().toString())) // i don't care about the path as all is lokal
{
byte[] ibuf = new byte[8096]; // thats the buffer used - larger is faster
int len;
in.read(salted);
in.read(salt);
SecretKeyFactory fact = SecretKeyFactory.getInstance("PBEWITHMD5AND256BITAES-CBC-OPENSSL", "BC");
SecretKey secretKey = fact.generateSecret(new PBEKeySpec(key.toCharArray(), salt, 100));
System.out.println("secretKey length: " + secretKey.getEncoded().length + " data: " + bytesToHex(secretKey.getEncoded()));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
while ((len = in.read(ibuf)) != -1) {
byte[] obuf = cipher.update(ibuf, 0, len);
if (obuf != null)
out.write(obuf);
}
byte[] obuf = cipher.doFinal();
if (obuf != null)
out.write(obuf);
} catch (IOException | BadPaddingException | IllegalBlockSizeException e) {
e.printStackTrace();
}
if (outputFile.exists()) {
return outputFile;
} else {
return null;
}
}
Edit2: As commented by #Topaco the usage of CipherInput/OutputStream shortens the code and makes it better readable, so here is the code:
public static File decryptDataFileBufferedCipherInputStream (File inputFile, File outputFile, File keyFile, String correlationId) throws
IOException, NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, InvalidKeyException
{
Security.addProvider(new BouncyCastleProvider());
String key = new String(Files.readAllBytes(keyFile.toPath())).trim();
byte[] salt = new byte[8];
byte[] salted = new byte[8]; // text SALTED__
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try (FileInputStream in = new FileInputStream(inputFile.toPath().toString()); // i don't care about the path as all is lokal
CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
FileOutputStream out = new FileOutputStream(outputFile.toPath().toString())) // i don't care about the path as all is lokal
{
byte[] buffer = new byte[8192];
in.read(salted);
in.read(salt);
SecretKeyFactory fact = SecretKeyFactory.getInstance("PBEWITHMD5AND256BITAES-CBC-OPENSSL", "BC");
SecretKey secretKey = fact.generateSecret(new PBEKeySpec(key.toCharArray(), salt, 100));
System.out.println("secretKey length: " + secretKey.getEncoded().length + " data: " + bytesToHex(secretKey.getEncoded()));
cipher.init(Cipher.DECRYPT_MODE, secretKey);
int nread;
while ((nread = cipherInputStream.read(buffer)) > 0) {
out.write(buffer, 0, nread);
}
out.flush();
}
if (outputFile.exists()) {
return outputFile;
} else {
return null;
}
}
I am trying to encrypt and decrypt files with BouncyCastle 3DES. But the files are corrupted after encrypting and decrypting. For example a simple text-file or a jpg-image-file. This is my Code:
ZipUnzipBouncyCastle()
{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
}
public void encrypt3DES(String password, String file)
throws IOException, DataLengthException, IllegalStateException,
InvalidCipherTextException, NoSuchAlgorithmException
{
byte[] data = Files.readAllBytes(new File(file).toPath());
SecureRandom random = new SecureRandom(data);
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
keyGenerator.init(168, random);
SecretKey secreteKey = keyGenerator.generateKey();
BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
new CBCBlockCipher(new DESedeEngine()));
cipher.init(true, new KeyParameter(secreteKey.getEncoded()));
byte[] result = new byte[cipher.getOutputSize(data.length)];
int tam = cipher.processBytes(data, 0, data.length, result, 0);
cipher.doFinal(result, tam);
byte[] encodedData = Base64.getEncoder().encode(result);
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(encodedData);
fileOutputStream.flush();
fileOutputStream.close();
}
public void decrypt3DES(String password, String file)
throws NoSuchAlgorithmException, DataLengthException,
IllegalStateException, InvalidCipherTextException, IOException
{
byte[] data = Files.readAllBytes(new File(file).toPath());
byte[] decodedData = Base64.getDecoder().decode(data);
SecureRandom random = new SecureRandom(decodedData);
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
keyGenerator.init(168, random);
SecretKey secreteKey = keyGenerator.generateKey();
BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
new CBCBlockCipher(new DESedeEngine()));
cipher.init(true, new KeyParameter(secreteKey.getEncoded()));
byte[] result = new byte[cipher.getOutputSize(decodedData.length)];
int tam = cipher.processBytes(decodedData, 0, decodedData.length, result, 0);
cipher.doFinal(result, tam);
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(result);
fileOutputStream.flush();
fileOutputStream.close();
}
I looked all over the Internet but could not find any explanation. What am I doing wrong?
I am trying to create a signature then verify for a message of 40 bytes using the SHA-256 algorithm. I thought I did everything correctly, but it is giving me false for verification, and I cannot find out what I did wrong. I double and triple and quadruple checked, but couldn't find out. Any help would be appreciated.
here are the two functions I have created to sign and verify signature for a message.
public static byte[] sigAuth(byte[] message, File file, PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, IOException{
SecretKeySpec secretKey = new SecretKeySpec(sharedKey, "hmacSHA256");
Mac macHMAC = Mac.getInstance("HmacSHA256");
macHMAC.init(secretKey);
byte[] authMessageInHMACC = macHMAC.doFinal(message);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(authMessageInHMACC);
byte[] finalSignature = signature.sign();
FileOutputStream fos = new FileOutputStream(file);
fos.write(message);
fos.write(finalSignature);
fos.close();
return finalSignature;
}
public static boolean verify(File file, PublicKey pubKey) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, IOException{
byte fileContent[] = new byte[(int)sharedKeyFile.length()];
FileInputStream fos = new FileInputStream(file);
fos.read(fileContent);
fos.close();
/Split message from signed hash
byte[] messageOnly = new byte[40];
byte[] hash = new byte[256];
//messageauthmessage
int j = 0;
int k = 0;
for (int i = 0; i < fileContent.length;i++){
if(i < 40){
messageOnly[i] = fileContent[i];
j++;
} else {
hash[k] = fileContent[j+1];
k++;
}
}
SecretKeySpec secretKey = new SecretKeySpec(sharedKey, "hmacSHA256");
Mac macHMAC = Mac.getInstance("HmacSHA256");
macHMAC.init(secretKey);
byte[] authMessageInHMACC = macHMAC.doFinal(messageOnly);
Signature pubSignature = Signature.getInstance("SHA256withRSA");
pubSignature.initVerify(pubKey);
pubSignature.update(authMessageInHMACC);
boolean verified = pubSignature.verify(hash);
return verified;
}
messageOnly[i] = fileContent[i];
should be
messageOnly[j] = fileContent[i];
and
hash[k] = fileContent[j+1];
should be
hash[k] = fileContent[i];
I've been trying to write an encrypted file in AES and decrypt it subsequently by using Cipher Streams provided in JCA. However, I'm having problems while reading the file, as the decryption is going haywire.
public class CipherStreams {
public static void main(String[] args) {
try {
KeyGenerator keygen = KeyGenerator.getInstance("AES");
Key k = keygen.generateKey();
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes.init(Cipher.ENCRYPT_MODE, k);
FileOutputStream fs = new FileOutputStream("Encrypyed.txt");
CipherOutputStream out = new CipherOutputStream(fs, aes);
out.write("[Hello:Okay]\nOkay".getBytes());
out.close();
Cipher aes2 = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes2.init(Cipher.DECRYPT_MODE, k);
FileInputStream fis = new FileInputStream("Encrypyed.txt");
CipherInputStream in = new CipherInputStream(fis,aes2);
byte[] b = new byte[8];
int i = in.read(b);
while(i!=-1) {
System.out.print((char)i);
i = in.read(b);
}
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IOException ex) {
Logger.getLogger(CipherStreams.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I'm receiving a single byte output as 5. Can anyone please help point out the problem?
You're not writing the bytes read, you're writing the number of bytes being read.
You're also assuming that the default platform encoding just transforms each character to a byte.
Just do the reverse of what you did when writing: read everything, and transform the read byte array to a String, then print that string:
public class CipherStreams {
public static void main(String[] args) {
try {
KeyGenerator keygen = KeyGenerator.getInstance("AES");
Key k = keygen.generateKey();
Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes.init(Cipher.ENCRYPT_MODE, k);
String fileName = "Encrypted.txt";
FileOutputStream fs = new FileOutputStream(fileName);
CipherOutputStream out = new CipherOutputStream(fs, aes);
out.write("[Hello:Okay]\nOkay".getBytes());
out.flush();
out.close();
Cipher aes2 = Cipher.getInstance("AES/ECB/PKCS5Padding");
aes2.init(Cipher.DECRYPT_MODE, k);
FileInputStream fis = new FileInputStream(fileName);
CipherInputStream in = new CipherInputStream(fis, aes2);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int numberOfBytedRead;
while ((numberOfBytedRead = in.read(b)) >= 0) {
baos.write(b, 0, numberOfBytedRead);
}
System.out.println(new String(baos.toByteArray()));
}
catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IOException ex) {
ex.printStackTrace();
;
}
}
}
I am trying to make a encryption and decryption app but in decryption method I got javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
byte[] key = ("Sh").getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16);
secretKeySpec = new SecretKeySpec(key, "AES");
cipher = Cipher.getInstance("AES");
public void dec (String dir)
{
try{
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
String cleartextFile = dir;
FileInputStream fis = new FileInputStream(cleartextFile);
CipherInputStream cis = new CipherInputStream(fis, cipher);
FileOutputStream fos = new FileOutputStream(dir);
block = new byte[6];
while ((i = cis.read(block)) != -1) {
fos.write(block, 0, i);
}
fos.close();
}
catch(Exception ex)
{
Toast.makeText(MainActivity.this, "Chiper Error"+ex, Toast.LENGTH_LONG).show();
}
}