If there's anyone who knows a thing or two about this, your help would be much appreciated. This is a code I'm working on:

try {
			//ask user for short password
			System.out.print("Enter a password: ");
			
			//read in a character at a time, putting them into the buffer
			while((buf[bufPos++] = (char)System.in.read()) != '\n') {}
			
			//convert buffer into password char array
			//remove the trailing \n character
			char[] password = new char[--bufPos];
			System.arraycopy(buf, 0, password, 0, bufPos);
			
			//create a PBE Key specification
			//provide the password, salt and iteration count
			PBEKeySpec pbeKeySpec = new PBEKeySpec(password,salt,iterations);
			
			//locate PBE secret key factory
			SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
			
			//generate the secret key from the PBEKeySpec
			SecretKey key = factory.generateSecret(pbeKeySpec);
			
			//locate a PBE cipher
			Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
			
			//initialise the cipher for encryption and give it the key it should use
			cipher.init(Cipher.ENCRYPT_MODE, key);
			
			//encrypt our command line sentence
			byte[] cipherText = cipher.doFinal(args[0].getBytes());
			
			//send encrypted data to target, e.g file
			FileOutputStream passText = new FileOutputStream(new File("password.txt"));
			passText.write(cipherText);
			
			//clear out all password references from memory
			for(int i = 0; i < password.length; i++) {
				buf[i] = password[i] = 0;
			}
		} catch  (etc...)

I keept getting this message: java.security.spec.InvalidKeySpecException: Password is not ASCII. It occurs at this line of code:

SecretKey key = factory.generateSecret(pbeKeySpec);

I honestly don't know what else to do. I've looked at everything, and nothing seems wrong.

Please, help

Can you try to print the pbeKeySpec value and see what it has?
Also is there any specific reason that you need to read the input character by character and then copy it to another array? Can you just use the Scanner class to read the whole line and get the password?

Hi, JavaAddict,

pbeKeySpec has three methods: getPassword(), getSalt(), and getIterationCount(), all of which print out the password inputed the reader, the salt set above as an array (byte[] salt), and the int iterations, respectively.

So if you run the codes, it asks the user for a password, and whatever the user enters, pbeKeySpec.getPassword() will print it, getSalt() will print out the byte[] salt, and getIterationCount() will print out the int iterations.

As for your question, The answer I can provide is, from what I read, reading a password char by char is a lot safer, security wise, than reading the entire thing as a string. To further prove the point, pbeKeySpec, does not accept a string as a parameter. It accepts a char array. That's the way it was designed.

Well the error says that Password is not ASCII. So maybe if you could print the values of the password array one by one and see what it has.
Perhaps the problem is that the last element of the array is the \n new line.

Edited 6 Years Ago by javaAddict: n/a

Hi javaAddict, I followed your suggestion and did this:

System.out.print("Enter a password: ");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String passW = in.readLine();
char[] password = passW.toCharArray();

I pretty much took the string and then converted it to a char array. You were right. That's what was causing the problem!

Cheers :D

Hi javaAddict, I followed your suggestion and did this:

System.out.print("Enter a password: ");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String passW = in.readLine();
char[] password = passW.toCharArray();

I pretty much took the string and then converted it to a char array. You were right. That's what was causing the problem!

Cheers :D

I think that the problem was that when you were reading char by char the input, you were stopping when the new line was read. That means that you were trying to generate a key from a password that contained the \n character.

Can you please verify that? Can you use your previous code and print all the elements of the buf array:

System.arraycopy(buf, 0, password, 0, bufPos);
for (int i=0;i<password.length;i++) {
  System.out.println(">"+password[i]+"<");
}

If the last elements prints nothing but only changes lines means that that was the problem.
You can use a loop to copy the elements of the buf to password:

char[] password = new char[bufPos-2];
for (int i=0;i<password.length;i++) {
  password[i] = buf[i];
}

I think that the problem was that when you were reading char by char the input, you were stopping when the new line was read. That means that you were trying to generate a key from a password that contained the \n character.

Can you please verify that? Can you use your previous code and print all the elements of the buf array:

System.arraycopy(buf, 0, password, 0, bufPos);
for (int i=0;i<password.length;i++) {
  System.out.println(">"+password[i]+"<");
}

If the last elements prints nothing but only changes lines means that that was the problem.
You can use a loop to copy the elements of the buf to password:

char[] password = new char[bufPos-2];
for (int i=0;i<password.length;i++) {
  password[i] = buf[i];
}

Hey! I tested this and you're right! That's the problem! It takes in the "\n". Man, I thought I had taken care of that. Cheers, mate!

You stop when the \n is read, but with this code: while((buf[bufPos++] = (char)System.in.read()) != '\n') {} First you assign the new line in the array:
buf[bufPos++] = (char)System.in.read()
And then you check for the new line.

This question has already been answered. Start a new discussion instead.