Home > Archive > Java Security > July 2004 > encrypt - decrypt
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
|
| I have a password (text - about 4 to 15 chars long) and a text.
How can I encrypt text with password and how can I restore from encrypted?
Is there a class which does this?
(I am newbie)
| |
| Roedy Green 2004-07-17, 3:58 pm |
| On Sat, 17 Jul 2004 18:55:29 +0300, "<- Chameleon ->"
<cham_gss@hotmail.NOSPAM.com> wrote or quoted :
>I have a password (text - about 4 to 15 chars long) and a text.
>
>How can I encrypt text with password and how can I restore from encrypted?
A very simple to code but easy to crack scheme is just to convert your
password to a byte[] and your data to hide to byte[]. You can do that
with a ByteArrayStream ObjectOutputStream GZIP etc.
then xOR the password with the data, repeating the password over and
over as needed. This discourages amateur cracking, but of course is
duck simple for a pro to crack.
Something tougher to crack is to take an MD-5 or SHA-1 digest of your
password and use it as a AES key.
The XOR scheme with SHA-1 prestep to grow the password will keep even
a pro guessing, but it won't stop the CIA.
--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
| |
| Roedy Green 2004-07-17, 3:58 pm |
| On Sat, 17 Jul 2004 17:10:06 GMT, Roedy Green
<look-on@mindprod.com.invalid> wrote or quoted :
>then xOR the password with the data, repeating the password over and
>over as needed. This discourages amateur cracking, but of course is
>duck simple for a pro to crack.
and to decode, you just XOR again with the password.
--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
| |
|
| -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
- - Chameleon - wrote:
> I have a password (text - about 4 to 15 chars long) and a text.
>
> How can I encrypt text with password and how can I restore from
> encrypted?
>
> Is there a class which does this?
>
> (I am newbie)
Hi,
The XOR encryption system works, but it's really not very secure (as
Mr. Green pointed out). If you want a system that's rather more
secure than any of those, you can use what I've got pasted below. It
uses the Java Cryptography API to provide good encryption.
All the tweakable parameters are in the static final variables near
the top of the file: ITERATION_COUNT is the key-generation iteration
count, SALT_LENGTH is the length of the salt (which must be set
properly depending on the algorithm in use, otherwise an exception
will be thrown), ALGORITHM (which defines the name of the algorithm
you want to use), EXTRA_PROVIDER (which defines the classname of an
additional JCE provider class to add, if not null), input (which
defines the plaintext to test), and password. The file is also
liberally commented, especially in encrypt() (much of the code is
almost duplicated in decrypt()).
The provider that comes with the Java Runtime only implements, for
password-based-encryption, PBEWithMD5AndDES, which is actually pretty
weak for today. If you want much stronger encryption (to the point
that, well, nobody's exactly sure how long it would take the CIA to
break), you need a better algorithm. First, go to
http://www.bouncycastle.org/
Go to the Latest Releases page, and choose the appropriate download
link in the "Signed JAR files" section for your JDK version under the
Provider column (i.e. bcprov-jdk<something>-<something>.jar).
Download this file into your jre/lib/ext directory in your JDK
install directory.
You can now modify the code as followed to get a better algorithm
going:
1. Change the PROVIDER variable to
"org.bouncycastle.jce.provider.BouncyCastleProvider".
2. Change the ALGORITHM variable to "PBEWithSHAAndTwofish-CBC".
3. To really get good security, you might also want to increase
SALT_LENGTH from 8 to 32. It appears that PBEWithSHAAndTwofish-CBC
works with either of these values (possibly with any value), but
PBEWithMD5AndDES only works with 8.
4. If you feel like it, increase ITERATION_COUNT. It's probably fine
at 1000, and anything above 10000 is probably vast overkill.
As a final note, to really improve security, you might also try *not*
using "abcd" as a password. <G>
And now, for the code.
This code doesn't do proper error checking, and you really might want
to copy it into a text editor and clean up the formatting a bit
before trying to understand it; it's a bit ugly here due to newsgroup
formatting.
- --- BEGIN FILE Test.java ---
import java.io.*;
import java.security.*;
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class Test {
/* The "iteration count" for the key generation algorithm.
Basically, this means that the processing that is done to generate
the key happens 1000
times. You won't even notice the difference while encrypting or
decrypting text, but an
attacker will notice a *big* difference when brute forcing keys! */
static final int ITERATION_COUNT = 1000;
/* Length of the salt (see below for details on what the salt is) */
static final int SALT_LENGTH = 8;
/* Which encryption algorithm we're using. */
static final String ALGORITHM = "PBEWithMD5AndDES";
/* The name of a provider class to add to the system before running,
if using a provider that's
not permanently installed. */
static final String EXTRA_PROVIDER = null;
/* Our input text and password. */
static final String input = "Hello World!";
static final String password = "abcd";
public static byte[] encrypt(byte[] input, char[] password) throws
Exception {
/* Get ourselves a random number generator, needed in a number of
places for encrypting. */
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
/* A "salt" is considered an essential part of password-based
encryption. The salt is
selected at random for each encryption. It is not considered
"sensitive", so it is
tacked onto the generated ciphertext without any special
processing. It doesn't
matter if an attacker actually gets the salt. The salt is used as
part of the key,
with the very useful result that if you encrypt the same plaintext
with the same
password twice, you get *different* ciphertexts. There are lots of
pages on the 'net
with information about salts and password-based encryption, so read
them if you
want more details. Suffice to say salt=good, no salt=bad. */
byte[] salt = new byte[SALT_LENGTH];
sr.nextBytes(salt);
/* We've now got enough information to build the actual key. We do
this by encapsulating
the variables in a PBEKeySpec and using a SecretKeyFactory to
transform the spec into
a key. */
PBEKeySpec keyspec = new PBEKeySpec(password, salt,
ITERATION_COUNT);
SecretKeyFactory skf = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey key = skf.generateSecret(keyspec);
/* We'll use a ByteArrayOutputStream to conveniently gather up data
as it's encrypted. */
ByteArrayOutputStream baos = new ByteArrayOutputStream();
/* We've to a key, but to actually encrypt something, we need a
"cipher". The cipher is
created, then initialized with the key, salt, and iteration count.
We use a
PBEParameterSpec to hold the salt and iteration count needed by the
Cipher object. */
PBEParameterSpec paramspec = new PBEParameterSpec(salt,
ITERATION_COUNT);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key, paramspec, sr);
/* First, in our output, we need to save the salt in plain
unencrypted form. */
baos.write(salt);
/* Next, encrypt our plaintext using the Cipher object, and write it
into
our output buffer. */
baos.write(cipher.doFinal(input));
/* We're done. For security reasons, we probably want the PBEKeySpec
object to clear
its internal copy of the password, so it can't be stolen later. */
keyspec.clearPassword();
return baos.toByteArray();
}
public static byte[] decrypt(final byte[] input, final char[]
password) throws Exception {
/* The first SALT_LENGTH bytes of the input ciphertext are actually
the salt,
not the ciphertext. */
byte[] salt = new byte[SALT_LENGTH];
System.arraycopy(input, 0, salt, 0, SALT_LENGTH);
/* We can now create a key from our salt (extracted just above),
password, and
iteration count. Same procedure to create the key as in encrypt().
*/
PBEKeySpec keyspec = new PBEKeySpec(password, salt,
ITERATION_COUNT);
SecretKeyFactory skf = SecretKeyFactory.getInstance(ALGORITHM);
SecretKey key = skf.generateSecret(keyspec);
/* Once again, create a PBEParameterSpec object and a Cipher object.
*/
PBEParameterSpec paramspec = new PBEParameterSpec(salt,
ITERATION_COUNT);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key, paramspec);
/* Decrypt the data.
The parameters we pass into doFinal() instruct it to skip the first
SALT_LENGTH bytes
of input (which are actually the salt), and then to encrypt the
next
(length - SALT_LENGTH) bytes, which are the real ciphertext. */
byte[] output = cipher.doFinal(input, SALT_LENGTH, input.length -
SALT_LENGTH);
/* Clear the password and return the generated plaintext. */
keyspec.clearPassword();
return output;
}
public static void main(final String[] args) throws Exception {
/* If we're configured to use a third-party cryptography provider,
where that provider is not permanently installed, then we need
to install it first. */
if (EXTRA_PROVIDER != null) {
Provider prov = (Provider)
Class.forName(EXTRA_PROVIDER).newInstance();
Security.addProvider(prov);
}
/* The encrypt() function above uses a byte[] as input, so it's more
general (it can encrypt anything, not just a String), as well as
using a char[] for the password, because it can be overwritten
once it's finished. Strings are immutable, so to purge them from
RAM you have to hope they get garbage collected and then the RAM
gets reused. For char[]s you can simply fill up the array with
junk to erase the password from RAM. Anyway, use char[] if you're
concerned about security, but for a test case, a String works fine.
*/
byte[] inputBytes = input.getBytes();
char[] passwordChars = password.toCharArray();
/* Encrypt the data. */
byte[] ciphertext = encrypt(inputBytes, passwordChars);
System.out.println("Ciphertext:");
/* This is just a little loop I made up which displays the
encrypted data in hexadecimal, 30 bytes to a line. Obviously, the
ciphertext won't necessarily be a recognizable String, and it'll
probably
have control characters and such in it. We don't even want to
convert it
to a String, let alone display it onscreen. If you need text,
investigate
some kind of encoding at this point on top of the encryption, like
Base64.
It's not that hard to implement and it'll give you text to carry
from place
to place. Just remember to *de*code the text before calling
decrypt(). */
int i;
for (i = 0; i < ciphertext.length; i++) {
String s = Integer.toHexString(((int) ciphertext[i]) & 0xFF);
if (s.length() == 1)
s = "0" + s;
System.out.print(s);
if (i % 30 == 29)
System.out.println();
}
if ((ciphertext.length - 1) % 30 != 29)
System.out.println();
/* Now, decrypt the data. Note that all we need is the password and
the ciphertext. */
byte[] output = decrypt(ciphertext, passwordChars);
/* Transform the output into a string. */
String sOutput = new String(output);
/* Display it. */
System.out.println("Plaintext:\n" + sOutput);
}
}
- --- END FILE ---
Have fun.
Chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
iD8DBQFA/ waCnwjA8LryK2IRAqCyAKDJstsnHPQUeyuA7yzxe
gxah64ZEgCeKKvB
WwKi511R4lVDJd1eNFX7yhU=
=NaEf
-----END PGP SIGNATURE-----
| |
| Roedy Green 2004-07-22, 3:57 am |
| On Thu, 22 Jul 2004 00:12:09 GMT, Chris <chris2k01@hotmail.com> wrote
or quoted :
>If you need text,
>investigate
> some kind of encoding at this point on top of the encryption, like
>Base64.
> It's not that hard to implement and it'll give you text to carry
>from place
> to place. Just remember to *de*code the text before calling
>decrypt(). */
see http://mindprod.com/jgloss/base64.html
or http://mindprod.com/jgloss/base64u.html
which is like base64, but URL-encoder friendly not needing
URL-encoding.
--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
|
|
|
|
|