I have written this code to read from the file first after hashing the content from the file. It will write the original content plus hash values. But when I try to run the program the program will keep on writing and won't stop. what is the problem with my code?
package Encrypt;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Scanner;
public class Test {
public static void main(String[] args) throws Exception {
File file = new File("C:\\Users\\Tan\\Desktop\\Test.txt");
Scanner scan = new Scanner(file);
FileWriter writer = new FileWriter("C:\\Users\\Tan\\Desktop\\Test.txt", true);
while(scan.hasNextLine()) {
String password = scan.nextLine();
MessageDigest md;
try {
// Select the message digest for the hash computation -> SHA-256
md = MessageDigest.getInstance("SHA-256");
// Generate the random salt
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
// Passing the salt to the digest for the computation
//md.update(salt);
// Generate the salted hash
byte[] hashedPassword = md.digest(password.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hashedPassword)
sb.append(String.format("%02x", b));
//Print output
System.out.println(password + " " + sb.toString());
//write output to text file
writer.write(password + " " + sb + System.getProperty("line.separator"));
writer.flush();
}
catch (NoSuchAlgorithmException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
scan.close();
writer.close();
}
}
You specified true as the append argument of FileWriters constructor. So you are probalby reading what you previously written into the file.
Related
Trying to create java class which will encrypt and decrypt as like C# code in below.
Below is my code for C#, I need to convert it to Java. Can someone help me how to do it?
I've been doing this for almost 2 days yet can't find any solutions on how to convert it. I am new to crypto.
Note - It seems C# code used ACME libraries. But in my java, i should not use ACME jar files.
public static string EncryptBase64(string key, string clearText)
{
if (key.Length > 8)
key = key.Substring(0, 8);
byte[] keyBytes = System.Text.Encoding.ASCII.GetBytes(key);
byte[] clearBytes = GetClearTextBytes(clearText);
// calculate the number of legitimate bytes in the last block
byte lastByte = (byte)(8 - (clearBytes.Length - textEncoding.GetByteCount(clearText)));
MemoryStream ms = new MemoryStream();
DES des = new DESCryptoServiceProvider();
des.Padding = PaddingMode.None;
des.GenerateIV();
System.Security.Cryptography.ICryptoTransform ict = des.CreateEncryptor(keyBytes, des.IV);
CryptoStream cs = new CryptoStream(ms, ict, CryptoStreamMode.Write);
cs.Write(clearBytes, 0, clearBytes.Length);
cs.FlushFinalBlock();
ms.Close();
byte[] cipherBytes = ms.ToArray();
// create a byte output stream for Acme compatibality
MemoryStream acmeCompatStream = new MemoryStream();
// Acme writes the IV to the frist block
acmeCompatStream.Write(des.IV, 0, 8);
for (int i = 0; i < cipherBytes.Length; i = i + 8)
{
// write the next block
acmeCompatStream.Write(cipherBytes, i, 8);
// write the number of valid bytes in the block
if (i == cipherBytes.Length - 8)
acmeCompatStream.WriteByte(lastByte);
else
acmeCompatStream.WriteByte(8);
}
acmeCompatStream.Close();
cipherBytes = acmeCompatStream.ToArray();
return (System.Convert.ToBase64String(cipherBytes));
}
Below is the code which i have tried in java. I have two different encryption function. I have tried both of the encryption method. But both are not giving expected encrypted string to decrypt in acme.
package com.abc.some.common.nativeDES;
import java.io.ByteArrayOutputStream;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.xml.bind.DatatypeConverter;
public class DESEncrypt {
public String keyValue = "123456789";
public static void main(String[] args) {
String text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><SomeRequest><OrderNumber>1564578</OrderNumber></SomeRequest>";
String codedtext ="not encrypted";
try{
codedtext = new DESEncrypt().Encrypt1(text);
//codedtext = new DESEncrypt().encrypt(text);
}catch (Exception e) {
System.out.println("Exception in Encryption.. " + e.getMessage());
}
System.out.println(codedtext);
}
public String Encrypt1(String CXML) {
try {
KeySpec myKey = new DESKeySpec(keyValue.getBytes("UTF8"));
SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(myKey);
Cipher ecipher = Cipher.getInstance("DES");
ecipher.init(Cipher.ENCRYPT_MODE, key);
byte[] data = CXML.getBytes("ASCII");
Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, key);
byte[] crypt = ecipher.doFinal(data);
//String encoded = DatatypeConverter.printBase64Binary(crypt.toString().getBytes("ASCII"));
//String encoded = DatatypeConverter.printBase64Binary(crypt.getBytes("ASCII"));
String encoded = DatatypeConverter.printBase64Binary(crypt).toString();
System.out.println(encoded);
return encoded;
} catch (Exception ex) {
}
return null;
}
}
But I have used below java file to encrypt the string which is using acme jar files. This was working as expected. But as per my project requirement i should not use the external(ACME) jar files.
package com.abc.common.encryption;
import java.io.FileInputStream;
import java.util.Properties;
import Acme.Crypto.SecurityDES;
public class ESBCryptoDES {
public static void main(String args[]){
// DESEncrypt("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><SomeRequest><OrderNumber>1564578</OrderNumber></SomeRequest>"
// ,"D:\\name\\proj\\order\\Encryption\\st.properties");
DESDecrypt("vQ9C7ZrLzjQpHvZjtHvUb0mFCr824/aClY2jKbeciczsRVr+kEETFvDuHgdBS/aLskYV3WX3U5TANSlK3pH80r3xOyn9Q8rTjlB/yXyU7J9MgibJ66jJx0wrqeloAkmQzqj+b5+I/lXANSlK3pH80kT1D+jqWAeV"
,"D:\\name\\proj\\order\\Encryption\\stDecrypt.properties");
}
public static String DESEncrypt(String SourceStrForCrypt,String PropPath) {
String encrypt = "";
String decrypt = "";
// Load the property file.
Properties prop = new Properties();
try {
FileInputStream in = new FileInputStream(PropPath);
prop.load(in);
in.close();
} catch (Exception e) {
System.out.println("Exception in loading property file.. "
+ e.getMessage());
}
// Encrypt the given content.
try {
String keypath = prop.getProperty("proj.sample.DEV");
System.out.println("sample" + keypath);
String SourceToEncrypt = SourceStrForCrypt; //This will provide the xml string to encrypt
// Encryption
encrypt = SecurityDES.DesEncryptBase64(keypath,SourceToEncrypt);
System.out.println(encrypt);
// Decryption
decrypt = SecurityDES.DesDecryptBase64(keypath, encrypt);
System.out.println(decrypt);
} catch (Exception e) {
System.out.println("Exception in Encryption.. " + e.getMessage());
}
return encrypt;
}
public static String DESDecrypt(String SourceStrForCrypt,String PropPath) {
// TODO Auto-generated method stub
String decrypt = "";
Properties prop = new Properties();
try {
FileInputStream in = new FileInputStream(PropPath);
prop.load(in);
in.close();
} catch (Exception e) {
System.out.println("Exception in loading property file.. "+ e.getMessage());
}
try {
String abc_keyPath = prop
.getProperty("proj.abc.DEV");
System.out.println("keypath" + abc_keyPath);
// Decryption
decrypt = SecurityDES.DesDecryptBase64(abc_keyPath, SourceStrForCrypt);
System.out.println("decrypted..."+decrypt);
} catch (Exception e) {
System.out.println("Exception in Encryption.. " + e.getMessage());
}
return decrypt;
}
}
Calling doFinal() twice doesn't make sense.
Printing the value of byte[].toString() doesn't make sense. It doesn't contain the ciphertext.
Converting that to base-64 doesn't make sense. It still doesn't contain the ciphertext.
You need to convert the byte[] array returned by the first doFinal() call directly to base-64, without the round-trip to and from String() caused by calling toString() and then `getBytes().
NB For some reason you have a variable called encrypt in your decrypt method, and for some even stranger reason you are returning it instead of decrypt, which is the only variable that actually contains plaintext.
This is a sample code through which I'm trying to read a file and encrypt/decrypt (if key is known for correct decryption) problem is the code is locked to accept the key of length 8, anything above or below is issuing a runtime error stating :
Exception in thread "main" java.security.InvalidKeyException: Invalid key length: 11 bytes
at com.sun.crypto.provider.DESCipher.engineGetKeySize(DESCipher.java:373)
at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1052)
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1010)
at javax.crypto.Cipher.implInit(Cipher.java:786)
at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
at javax.crypto.Cipher.init(Cipher.java:1213)
at javax.crypto.Cipher.init(Cipher.java:1153)
at custom_enc.Custom_enc.encrypt(Custom_enc.java:50)
at custom_enc.Custom_enc.main(Custom_enc.java:105)
Java Result: 1
Class:
package custom_enc;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Scanner;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.SecretKeySpec;
public class Custom_enc {
String ekey="";
String algorithm="";
String path1="";
File f;
public void Custom_enc()
{
System.out.println("Enter the file name with extension and path : \n");
Scanner s = new Scanner(System.in);
String path1 = s.nextLine();
f = new File(path1);
System.out.println("Enter secret key : \n");
ekey = s.nextLine();
}
public void encrypt() throws Exception
{
Custom_enc();
this.algorithm="DES/ECB/PKCS5Padding";
FileInputStream fis =new FileInputStream(f);
f=new File(f.getAbsolutePath()+"_encrypted_file.txt");
FileOutputStream fos =new FileOutputStream(f);
byte k[] = ekey.getBytes();
SecretKeySpec key = new SecretKeySpec(k,"DES");
Cipher encrypt = Cipher.getInstance(algorithm);
encrypt.init(Cipher.ENCRYPT_MODE, key);
CipherOutputStream cout=new CipherOutputStream(fos, encrypt);
byte[] buf = new byte[1024];
int read;
while((read=fis.read(buf))!=-1) //reading data
cout.write(buf,0,read); //writing encrypted data
fis.close();
cout.flush();
cout.close();
System.out.println("Encryption Done!!");
//exit();
}
public void decrypt() throws Exception
{
Custom_enc();
this.algorithm="DES/ECB/PKCS5Padding";
FileInputStream fis =new FileInputStream(f);
f=new File(f.getAbsolutePath()+"_decrypted_file.txt");
FileOutputStream fos =new FileOutputStream(f);
byte k[] = ekey.getBytes();
SecretKeySpec key = new SecretKeySpec(k,"DES");
Cipher decrypt = Cipher.getInstance(algorithm);
decrypt.init(Cipher.DECRYPT_MODE, key);
CipherInputStream cin=new CipherInputStream(fis, decrypt);
byte[] buf = new byte[1024];
int read=0;
while((read=cin.read(buf))!=-1) //reading encrypted data
{
fos.write(buf,0,read); //writing decrypted data
}
cin.close();
fos.flush();
fos.close();
System.out.println("Encryption Done!!");
//1exit();
}
public static void main(String[] args) throws Exception, java.security.InvalidKeyException {
Custom_enc obj = new Custom_enc();
System.out.println("Enter your choice : \n 1 For Encryption \n 2 For Decryption");
Scanner s1 = new Scanner(System.in);
int choice = s1.nextInt();
if(choice==1)
{
System.out.println("You've chosen to Encrypt\n");
obj.encrypt();
}
else if(choice==2)
{
System.out.println("You've chosen to Decrypt\n");
obj.decrypt();
}
else
{
System.out.println("Invalid Choice, Try again...");
}
}
}
Yes, DES uses a 64-bit key (although the effective key size is only 56-bits). 64-bits is 8 bytes, so that's your key length.
You can for example hashing to shrink a longer password to 64-bits, and go with that.
The problem is that you are confusing a password or pass phrase and a key; a password is not a key.
It is however possible to derive a password from a key. You should use a Password Based Key Derivation Function (PBKDF) to do so. There are a few of them that are safe to use: scrypt, bcrypt and PBKDF2. The latter is also present within the standard Oracle implementation of Java. It is part of the functions to support Password Based Encryption (PBE) in Java, as specified in the PKCS#5 standard.
See for instance the code in this question on how to utilize PBKDF2. Note that you have to create a salt (a secure random value of 64 bits or more) and add store it with your ciphertext.
I'm looking for some help with my program here. This program can encrypt and decrypt a phrase using DES symmetric cipher, based on CBC mode of operation.
What I am trying to do now is it to change it such that it can encrypt and decrypt the content of a text file using DES symmetric cipher using CBC mode of operation.
Can anyone help me out with this please?
Thank you!
import java.security.*;
import javax.crypto.*;
import java.security.spec.*;
import javax.crypto.spec.*;
import javax.crypto.spec.IvParameterSpec;
public class myProgram
{
public static void main (String[] args) throws Exception
{
String text = "Hello World;
SecureRandom sr = new SecureRandom();
byte [] iv = new byte[8];
sr.nextBytes(iv);
IvParameterSpec IV = new IvParameterSpec(iv);
KeyGenerator kg = KeyGenerator.getInstance("DES");
Key mykey = kg.generateKey();
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, mykey,IV);
byte[] plaintext = text.getBytes("UTF8");
byte[] ciphertext = cipher.doFinal(plaintext);
System.out.println("\n\nCiphertext: ");
for (int i=0;i<ciphertext.length;i++) {
if (chkEight(i)) {
System.out.print("\n");
}
System.out.print(ciphertext[i]+" ");
}
So you just want to know how to read and write to a file?
Take a look at apache.commons.io.FileUtils. It offers both methods for reading and writing strings from/to a file. Here are some examples:
// info.txt represents the path to the file
File someFile = new File("info.txt");
// Create String from File
try {
String filecontent = FileUtils.readFileToString(someFile, Charset.defaultCharset());
System.out.println(filecontent);
} catch (IOException e) {
e.printStackTrace();
}
// Encode / Decode string here
// Write String to file
try {
FileUtils.writeStringToFile(someFile, "your new file content string", Charset.defaultCharset());
System.out.println("Success!");
} catch (IOException e) {
e.printStackTrace();
}
You might want to use a different Charset, depending on the charset of your text file.
I implemented this example of jar file which checks it's own checksum:
File currentJavaJarFile = new File(MainApp.class.getProtectionDomain().getCodeSource().getLocation().getPath());
String jarFile = currentJavaJarFile.getAbsolutePath();// + "jarChecksumTest-1.0.jar";
byte[] data = Files.readAllBytes(Paths.get(jarFile));
MessageDigest complete = MessageDigest.getInstance(data);
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(complete.toString().getBytes());
byte byteData[] = md.digest();
// convert the byte to hex format
StringBuilder sb = new StringBuilder();
for (int i = 0; i < byteData.length; i++)
{
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
if ("L9ThxnotKPzthJ7hu3bnORuT6xI=".equals(sb.toString()))
{
System.out.println("Success!!!");
}
But then I run the file I get this message:
Caused by: java.security.NoSuchAlgorithmException: D:\.....\target\jarChecksumTest-1.0.jar MessageDigest not available
How I can solve this issue?
Try this code, it is running fine. You may choose any algorithm whether it is SHA/MD5
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Checksum
{
public static void main(String ar[])
{
File currentJavaJarFile = new File(Checksum.class.getProtectionDomain().getCodeSource().getLocation().getPath());
String filepath = currentJavaJarFile.getAbsolutePath();
StringBuilder sb = new StringBuilder();
try
{
MessageDigest md = MessageDigest.getInstance("SHA-256");// MD5
FileInputStream fis = new FileInputStream(filepath);
byte[] dataBytes = new byte[1024];
int nread = 0;
while((nread = fis.read(dataBytes)) != -1)
md.update(dataBytes, 0, nread);
byte[] mdbytes = md.digest();
for(int i=0; i<mdbytes.length; i++)
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100 , 16).substring(1));
}
catch(NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
System.out.println("Checksum: "+sb);
}
}
MessageDigest.getInstance() takes a string parameter that is the algorithm you wish to use on that message digest, SHA-256 for example. Creating a MessageDigest with a file path makes no sense - Java will try to treat it as a an algorithm, look for an algorithm with the same name as the path, then throw an exception when it can't find one.
Your update makes things worse - you're now passing a stream rather than a String! You're creating the MessageDigest md correctly, but the one called complete is nonsense.
I think what you're trying to do is get the bytes from the file into a byte array? In which case (since Java 7) you can do:
String jarFile = currentJavaJarFile.getAbsolutePath();
byte[] data = Files.readAllBytes(Paths.get(jarFile));
(If you're not running Java 7 see here for a few other ways that can work just as well.) The file's bytes will then be stored in data (so you can then call md.update(data) and then process the digest as before.
i have this java code , its encrypt only a given text witch is already written in the code
how i can edit this code to make the program ask the user to enter the text and then do the encryption for the text and show the final result ? i tried to replace the text ("NagaSakti"); and ("bismillah"); with (System.in); but it did not work !! please help me
import java.io.UnsupportedEncodingException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
public class DesEncrypter {
Cipher ecipher;
// 8-byte Salt
byte[] salt = {
(byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
(byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03
};
// Iteration count
int iterationCount = 19;
public static final DesEncrypter NAGASAKTI = new DesEncrypter("NagaSakti");
private DesEncrypter(String passPhrase) {
try {
// Create the key
KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance(
"PBEWithMD5AndDES").generateSecret(keySpec);
ecipher = Cipher.getInstance(key.getAlgorithm());
// Prepare the parameter to the ciphers
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
// Create the ciphers
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
} catch (java.security.InvalidAlgorithmParameterException e) {
} catch (java.security.spec.InvalidKeySpecException e) {
} catch (javax.crypto.NoSuchPaddingException e) {
} catch (java.security.NoSuchAlgorithmException e) {
} catch (java.security.InvalidKeyException e) {
}
}
public String encrypt(String str) {
try {
// Encode the string into bytes using utf-8
byte[] utf8 = str.getBytes("UTF8");
// Encrypt
byte[] enc = ecipher.doFinal(utf8);
// Encode bytes to base64 to get a string
return new sun.misc.BASE64Encoder().encode(enc);
} catch (javax.crypto.BadPaddingException e) {
} catch (IllegalBlockSizeException e) {
} catch (UnsupportedEncodingException e) {
}
return null;
}
public static void main(String args[]){
String encrypted = DesEncrypter.NAGASAKTI.encrypt("bismillah");
System.out.println("Enter your text");
System.out.println("encrypted text= "+ encrypted);
}
}
Use the Console for reading passwords. Your main method could look like this:
public static void main(String args[])
{
Console console = System.console();
if (console == null)
throw new IllegalStateException("console required");
char[] password = console.readPassword("Enter your text: ");
DesEncrypter encrypter = new DesEncrypter(new String(password));
String encrypted = encrypter.encrypt("bismillah");
System.out.println("encrypted text = " + encrypted);
}
Using the Console class' specialized API has a few advantages.
First, you don't echo the password to the screen. This helps protect it from shoulder-surfing bandits.
Also, the password is returned as a character array, so that the application can fill the array with zeros or random characters when use of the password is complete. This minimizes the chance that it will be written to disk due to paging, or included in a heap dump, etc.
Finally, using the correct high-level API makes it crystal clear what your code is doing, taps into any future improvements to the feature, and simplifies your application.
There are a number of other problems with the encryption used, and I don't recommend anyone use the code as-is, but I have focused on the question posed.
Try something like this:
// open up standard input
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String textFromUser = null;
// read the text from the command-line; need to use try/catch with the
// readLine() method
try {
textFromUser = br.readLine();
} catch (IOException ioe) {
System.out.println("IO error trying to read your text!");
}
You can use the Scanner class.
Add this import:
import java.util.Scanner;
Then in your main method do this:
public static void main(String args[]){
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter your text");
String textToEncrypt = keyboard.next();
String encrypted = DesEncrypter.NAGASAKTI.encrypt(textToEncrypt);
System.out.println("encrypted text= "+ encrypted);
}
If you want to use a passphrase other than NagaSakti then change the line starting with String encrypted... to
System.out.println("Enter your pass phrase");
String passPhrase = keyboard.next();
String encrypted = new DesEncrypter(passPhrase).encrypt(textToEncrypt);
Note you'll also have to change the DesEncrypter constructor to public to do this.