Simple encryption/decryption

A

angelochen960

I'm looking for a simple solution: a way to encrypt a string into a
alphanumeric string, and can be decrypted back to its original form,
using a string as the key, say 'password123', any idea how to achieve
this? Thanks.
 
J

Joshua Cranmer

I'm looking for a simple solution: a way to encrypt a string into a
alphanumeric string, and can be decrypted back to its original form,
using a string as the key, say 'password123', any idea how to achieve
this? Thanks.

Well, there's always ROT-13. For extra security, you might want to
perform it twice. :p

If you're trying to store passwords, it's generally advisable to store a
hash of the password. For example, my Linux password is stored as the
following:
$1$exPy4JWs$Fp5p5vjY6b0P0m1HzSTxu.

The $1 indicates that this is an MD5-encrypted password
The $exPy4JWs$ indicates that exPy4JWs is the salt
The rest is the actual hash, in base64-form.

P.S., if you could tell me what the password is, please do! I've
forgotten what I made it...
 
M

Mark Space

I'm looking for a simple solution: a way to encrypt a string into a
alphanumeric string, and can be decrypted back to its original form,
using a string as the key, say 'password123', any idea how to achieve
this? Thanks.


I'm not seeing a good answer to this. In particular, the
SecretKeyFactory.getInstance( "ARCFOUR" ) method returns an error. I
don't see a simple way to use RC4 without this call succeeding. Anyone
got a solution?

Anyway, to the OP, check out the code below. It will at least get you
going. Sorry for the lack of Javadoc comments, I just had this laying
around on the hard drive. You can compare this code to the description
of RC4 at Wikipedia. It's the exact same algorithm. Note the test vectors.

<http://en.wikipedia.org/wiki/RC4>


package local;

/**

COPYRIGHT 2009 Brenden Towey

This code is donated to the public domain but is unsupported and has no
warranty whatsoever. Use at your own risk.

*
* @author Brenden
*/
public class Rc4
{
private byte[] state = new byte[256];
int x, y;

public Rc4( byte[] key )
{
// if( key.length<5||key.length>16 )
// {
// throw new IllegalArgumentException( "Key: "+key+
// " must be between 40 and 128 bits. (key length is "+
// key.length+".)" );
// }
for( int i = 0; i < state.length; i++ ) {
state = (byte) i;
}
for( int i = 0; i < state.length; i++ ) {
x = (x + key[i % key.length] + state) & 0xFF;
byte swap = state;
state = state[x];
state[x] = swap;
}
x = 0;
}

public byte[] crypt( byte[] input )
{
byte[] output = new byte[input.length];
for( int i = 0; i < input.length; i++ ) {
x = (x + 1) % 256;
y = (state[x] + y) & 0xFF;
byte swap = state[x];
state[x] = state[y];
state[y] = swap;
byte r = state[(state[x] + state[y]) & 0xFF];
output = (byte) (input ^ r);
}
return output;
}

public static void main( final String... args )
{
String[][] testVectors = {{"Key", "Plaintext"},
{"Wiki", "pedia"}, {"Secret", "Attack at dawn"}
};
for( String[] s : testVectors ) {
System.out.printf( "RC4( \"%s\", \"%s\" ) == ", s[0], s[1] );
System.out.println( hexString( new Rc4( s[0].getBytes()
).crypt( s[1].
getBytes() ) ) );
}
}

private static String hexString( byte[] bytes )
{
StringBuilder sb = new StringBuilder( bytes.length *2 );
for( int i = 0; i < bytes.length; i++ ) {
sb.append( String.format( "%02X", bytes ));
}
return sb.toString();
// return local.utils.ArrayUtils.toFormattedString( "%02X",
//bytes, null );
}
}
 
R

Roedy Green

I'm looking for a simple solution: a way to encrypt a string into a
alphanumeric string, and can be decrypted back to its original form,
using a string as the key, say 'password123', any idea how to achieve
this? Thanks.

Sample code for a JCE solution is posted at
http://mindprod.com/jgloss/aes.html
Follow the links for others.


Sample code for a non-JCE solution, using public encryption is posted
at http://mindprod.com/jgloss/products1.html#TRANSPORTER
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Nature provides a free lunch, but only if we control our appetites."
~ William Ruckelshaus, America’s first head of the EPA
 
A

Arne Vajhøj

rossum said:
IIRC, Base-64 is not part of standard Java, though there is an
undocumented version in sun.misc. There are a lot of implementations
floating about on the internet; I use Bouncy Castle, which has Base-64
as part of their general crypto package.

Base64 is part of the Java EE spec. It is under the mail stuff.

Arne
 
A

Arne Vajhøj

Lew said:
Apache commons-codec has it also. Besides, as

The code is simple:

public static String b64encode(byte[] b) throws MessagingException,
IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream b64os = MimeUtility.encode(baos, "base64");
b64os.write(b);
b64os.close();
return new String(baos.toByteArray());
}
public static byte[] b64decode(String s) throws
MessagingException, IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes());
InputStream b64is = MimeUtility.decode(bais, "Base64");
byte[] tmp = new byte[s.length()];
int n = b64is.read(tmp);
byte[] res = new byte[n];
System.arraycopy(tmp, 0, res, 0, n);
return res;
}

and if it is in Java EE context the classes are there - if it is in
pure Java SE context then getting JavaMail and put that jar in classpath
is enough.

Arne
 
A

Arne Vajhøj

Mark said:
I'm not seeing a good answer to this. In particular, the
SecretKeyFactory.getInstance( "ARCFOUR" ) method returns an error. I
don't see a simple way to use RC4 without this call succeeding. Anyone
got a solution?

private Cipher rc4;
private SecretKey rc4key;
public RC4(String key) {
try {
rc4 = Cipher.getInstance("RC4");
rc4key = new SecretKeySpec(key.getBytes(), "RC4");
} catch(Exception e) {
e.printStackTrace();
}
}

works fine for me.

Arne
 
R

Roedy Green

Others have talked about encryption - RC4 etc. Using a cypher will
produce an array, or stream, of bytes. In order to get those bytes
into alphanumeric form you will need to use Base-64 (or similar) to
code those bytes as alphanumeric characters.

see http://mindprod.com/jgloss/base64.html
and
http://mindprod.com/jgloss/armouring.html

The Transporter code I pointed you to does armouring using Base64
..
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Nature provides a free lunch, but only if we control our appetites."
~ William Ruckelshaus, America’s first head of the EPA
 
M

Mark Space

Arne said:
private Cipher rc4;
private SecretKey rc4key;
public RC4(String key) {
try {
rc4 = Cipher.getInstance("RC4");
rc4key = new SecretKeySpec(key.getBytes(), "RC4");
} catch(Exception e) {
e.printStackTrace();
}
}

works fine for me.


Thanks for that, I'll play around with it. I read the docs and thought
I was supposed to use a SecretKeyFactory. The SecretKeySpec class
looked like something else (a "specification" for the key).

Just for reference, the following fails on line 34 (marked):


public class Encryption {

Cipher c;
public Encryption( String password )
throws NoSuchAlgorithmException,
NoSuchPaddingException,
InvalidKeySpecException,
InvalidKeyException
{
c = Cipher.getInstance( "RC4" );
char[] passChars = new char[password.length()];
password.getChars( 0, passChars.length, passChars, 0 );
// line 34 below
SecretKeyFactory skf = SecretKeyFactory.getInstance( "ARCFOUR" );
SecretKey sk = skf.generateSecret( new PBEKeySpec( passChars ) );
c.init( Cipher.ENCRYPT_MODE, sk );
}

public static void main ( String... args )
throws Exception
{
System.out.println( new Encryption("password1234") );
}
}
 
M

Mark Space

Seems to work:

package fubar;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class Encryption {

Cipher rc4;
SecretKey rc4Key;

public Encryption( String password )
throws NoSuchAlgorithmException,
NoSuchPaddingException,
InvalidKeySpecException,
InvalidKeyException
{
rc4 = Cipher.getInstance( "RC4" );
rc4Key = new SecretKeySpec( password.getBytes(), "RC4" );
rc4.init( Cipher.ENCRYPT_MODE, rc4Key );
}

public byte[] crypt( byte[] input )
throws IllegalBlockSizeException,
BadPaddingException
{
return rc4.doFinal( input );
}

public static void main ( String... args )
throws Exception
{
// RC4 test vectors from Wikipedia
// Only "Secret" is long enough to supply the required
// 40 bits.

String [][] testVectors = { { "Secret", "Attack at dawn"} };

for( String[] s : testVectors ) {
Encryption encryption = new Encryption( s[0] );
System.out.println( hexBytes( encryption.crypt(
s[1].getBytes() ) ) );
}
}

private static String hexBytes( byte[] bytes ) {
StringBuilder sb = new StringBuilder( bytes.length *2 );
for( int i = 0; i < bytes.length; i++ ) {
sb.append( String.format( "%02X", bytes ) );
}
return sb.toString();
}

}
 
A

Arne Vajhøj

Mark said:
Thanks for that, I'll play around with it. I read the docs and thought
I was supposed to use a SecretKeyFactory. The SecretKeySpec class
looked like something else (a "specification" for the key).

If the constructor works, then I would have expected the factory to
work as well.

But apparently not.

Arne
 
A

Angelo Chen

I'm looking for a simple solution:  a way to encrypt a string into a
alphanumeric string, and can be decrypted back to its original form,
using a string as the key, say 'password123', any idea how to achieve
this? Thanks.

I'm not seeing a good answer to this.  In particular, the
SecretKeyFactory.getInstance( "ARCFOUR" ) method returns an error.  I
don't see a simple way to use RC4 without this call succeeding.  Anyone
got a solution?

Anyway, to the OP, check out the code below.  It will at least get you
going.  Sorry for the lack of Javadoc comments, I just had this laying
around on the hard drive.  You can compare this code to the description
of RC4 at Wikipedia.  It's the exact same algorithm.  Note the test vectors.

<http://en.wikipedia.org/wiki/RC4>

package local;

/**

COPYRIGHT 2009 Brenden Towey

This code is donated to the public domain but is unsupported and has no
warranty whatsoever. Use at your own risk.

  *
  * @author Brenden
  */
public class Rc4
{
     private byte[] state = new byte[256];
     int x, y;

     public Rc4( byte[] key )
     {
//        if( key.length<5||key.length>16 )
//        {
//            throw new IllegalArgumentException( "Key: "+key+
//             " must be between 40 and 128 bits. (key length is "+
//               key.length+".)" );
//        }
         for( int i = 0; i < state.length; i++ ) {
             state = (byte) i;
         }
         for( int i = 0; i < state.length; i++ ) {
             x = (x + key[i % key.length] + state) & 0xFF;
             byte swap = state;
             state = state[x];
             state[x] = swap;
         }
         x = 0;
     }

     public byte[] crypt( byte[] input )
     {
         byte[] output = new byte[input.length];
         for( int i = 0; i < input.length; i++ ) {
             x = (x + 1) % 256;
             y = (state[x] + y) & 0xFF;
             byte swap = state[x];
             state[x] = state[y];
             state[y] = swap;
             byte r = state[(state[x] + state[y]) & 0xFF];
             output = (byte) (input ^ r);
         }
         return output;
     }

     public static void main( final String... args )
     {
         String[][] testVectors = {{"Key", "Plaintext"},
             {"Wiki", "pedia"}, {"Secret", "Attack at dawn"}
         };
         for( String[] s : testVectors ) {
             System.out.printf( "RC4( \"%s\", \"%s\" ) == ", s[0], s[1] );
             System.out.println( hexString( new Rc4( s[0].getBytes()
).crypt( s[1].
                     getBytes() ) ) );
         }
     }

     private static String hexString( byte[] bytes )
     {
         StringBuilder sb = new StringBuilder( bytes.length *2 );
         for( int i = 0; i < bytes.length; i++ ) {
             sb.append(  String.format( "%02X", bytes ));
         }
         return sb.toString();
//        return local.utils.ArrayUtils.toFormattedString( "%02X",
//bytes, null );
     }

}


This seems enough, with that I can:

Key
Plaintext
A2B93E8F6F023A078E

now how to decode the string "A2B93E8F6F023A078E" back to "Plaintext"?
thanks
 
M

Mark Space

Angelo said:
This seems enough, with that I can:

Key
Plaintext
A2B93E8F6F023A078E

now how to decode the string "A2B93E8F6F023A078E" back to "Plaintext"?


That's not what I get. Check your tests with Wikipedia. The
cipher-text for Key and Plaintext is "BBF316E8D940AF0AD3", which is what
the program I posted prints.

But for how to decrypt, RC4 is symmetric. That means you decrypt with
the same key and algorithm you encrypt with.

package local;

public class Rc4
{
private byte[] state = new byte[256];
int x, y;

public Rc4( byte[] key )
{
// if( key.length<5||key.length>16 )
// {
// throw new IllegalArgumentException( "Key: "+key+
// " must be between 40 and 128 bits. (key length is //"+
// key.length+".)" );
// }
for( int i = 0; i < state.length; i++ ) {
state = (byte) i;
}
for( int i = 0; i < state.length; i++ ) {
x = (x + key[i % key.length] + state) & 0xFF;
byte swap = state;
state = state[x];
state[x] = swap;
}
x = 0;
}

public byte[] crypt( byte[] input )
{
byte[] output = new byte[input.length];
for( int i = 0; i < input.length; i++ ) {
x = (x + 1) % 256;
y = (state[x] + y) & 0xFF;
byte swap = state[x];
state[x] = state[y];
state[y] = swap;
byte r = state[(state[x] + state[y]) & 0xFF];
output = (byte) (input ^ r);
}
return output;
}

public static void main( final String... args )
{
String[][] testVectors = {{"Key", "Plaintext"},
{"Wiki", "pedia"}, {"Secret", "Attack at dawn"},
};
for( String[] s : testVectors ) {
System.out.printf( "RC4( \"%s\", \"%s\" ) => ",
s[0], s[1] );
System.out.println( hexString( new Rc4( s[0].getBytes() )
.crypt( s[1].getBytes() ) ) );
}
String [][] reverseVectors = {
{"Key", "BBF316E8D940AF0AD3" },
{"Wiki", "1021BF0420" },
{"Secret", "45A01F645FC35B383552544B9BF5" }
};
for( String[] s : reverseVectors ) {
System.out.printf( "RC4( \"%s\", \"%s\" ) => ",
s[0], s[1] );
byte[] bytes = new byte[s[1].length()/2];
for( int i = 0; i < bytes.length; i++ ) {
bytes = (byte)Integer.parseInt( s[1]
.substring( i*2, i*2+2), 16 );
}
System.out.println( new String( new Rc4( s[0].getBytes() )
.crypt( bytes ) ) );
}
}

private static String hexString( byte[] bytes )
{
StringBuilder sb = new StringBuilder( bytes.length *2 );
for( int i = 0; i < bytes.length; i++ ) {
sb.append( String.format( "%02X", bytes ));
}
return sb.toString();
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top