Java string encryption/decryption

Discussion in 'Java' started by dj_uncas, Nov 20, 2008.

  1. dj_uncas

    dj_uncas Guest

    Hello group,

    I have a problem, and I hope you can help me. I'm building an RMI
    client/server solution, which requires encrypted parameters. I'm
    mostly sending objects with String-type parameters, and therefore just
    need to be able to encrypt and decrypt a String.

    I have been looking at Java Cryptographic Extension, and had a running
    sample that worked, however in the sample, I did not convert the
    encrypted byte-array to a String before decrypting it. When I try
    that, I get different exceptions regarding the length of the String
    I'm trying to decrypt. For example, with the Triple DES algorithm I
    get:
    "javax.crypto.IllegalBlockSizeException: Input length must be multiple
    of 8 when decrypting with padded cipher"

    Some other algorithms just tell me, that the incomming string is not
    padded correctly...

    I think my issue is in converting the encrypted byte-array to a
    String, and back - and this is where I fall short. Can you give me
    some pointers on this?


    Regards,

    Mads
    dj_uncas, Nov 20, 2008
    #1
    1. Advertising

  2. dj_uncas

    Tom Anderson Guest

    On Thu, 20 Nov 2008, dj_uncas wrote:

    > I have a problem, and I hope you can help me. I'm building an RMI
    > client/server solution, which requires encrypted parameters. I'm mostly
    > sending objects with String-type parameters, and therefore just need to
    > be able to encrypt and decrypt a String.


    Have you thought about doing RMI over SSL? Would that do what you need?
    Have a look:

    http://today.java.net/pub/a/today/2005/10/06/the-new-rmi.html

    tom

    --
    skin thinking
    Tom Anderson, Nov 20, 2008
    #2
    1. Advertising

  3. dj_uncas

    dj_uncas Guest

    On Nov 20, 5:24 pm, rossum <> wrote:
    > On Thu, 20 Nov 2008 06:49:55 -0800 (PST), dj_uncas <>
    > wrote:
    >
    > >Hello group,

    >
    > >I have a problem, and I hope you can help me. I'm building an RMI
    > >client/server solution, which requires encrypted parameters. I'm
    > >mostly sending objects with String-type parameters, and therefore just
    > >need to be able to encrypt and decrypt a String.

    >
    > >I have been looking at Java Cryptographic Extension, and had a running
    > >sample that worked, however in the sample, I did not convert the
    > >encrypted byte-array to a String before decrypting it.

    >
    > You probably need to convert the cyphertext to Base64 rather than to a
    > String.  Cyphertext will contain all bytes from -128 to 127 which will
    > make for a very strange string if you convert it directly.  Base64 is
    > a form of armouring so you can effectively transmit raw bytes over a
    > text stream.
    >
    > >When I try
    > >that, I get different exceptions regarding the length of the String
    > >I'm trying to decrypt. For example, with the Triple DES algorithm I
    > >get:
    > >"javax.crypto.IllegalBlockSizeException: Input length must be multiple
    > >of 8 when decrypting with padded cipher"

    >
    > 3DES is obsolescent.  Unless you are using it for backwards
    > compatibility you should change to AES.  The blocksize for AES is 128
    > bits (16 bytes).  What padding did you specify?  The JCE default is no
    > padding so you will get a blocksize error if your plaintext is not a
    > multiple of 8 bytes (DES) or 16 bytes (AES).  Also if you are using
    > ECB mode, do not because it is not safe.  Use CBC or CTR instead.
    >
    >
    >
    > >Some other algorithms just tell me, that the incomming string is not
    > >padded correctly...

    >
    > Check what padding you are specifying at both ends.  They must be the
    > same.
    >
    >
    >
    > >I think my issue is in converting the encrypted byte-array to a
    > >String, and back - and this is where I fall short. Can you give me
    > >some pointers on this?

    >
    > The cyphertext will not make sense as a String and should not be
    > converted to a String as such.  If you need to be able to transmit the
    > cyphertext over a text stream or similar then you will need to use
    > something like Base64 to enable this.  Of course you will need to
    > change from Base64 back into a byte array before decrypting.
    >
    >
    >
    > >Regards,

    >
    > >Mads

    >
    > Start with your plaintext as a String.
    > Convert the plaintext to a byte array.
    > Encrypt the byte array to produce the cyphertext as a byte array.
    > Convert the cyphertext byte array into a Base64 String for
    > transmission.
    > After transmission convert the Base64 String back into the cyphertext
    > byte array.
    > Decrypt the cyphertext byte array to give the plaintext byte array.
    > Convert the plaintext byte array back into a String.
    >
    > Remember to specify the same padding at both ends.
    >
    > rossum



    Well, it makes perfect sense. And Base64 was probably the step i
    missed. I still get a "Given final block not properly padded"
    exception though. I get a cipher instance like this:

    Cipher c = Cipher.getInstance( "AES" );

    What do I do to specify the padding? I'm a total Java crypto novice :-(
    dj_uncas, Nov 20, 2008
    #3
  4. dj_uncas

    dj_uncas Guest

    >
    >   Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");


    Just one more thing: Which JCE provider can I use for the above
    Cipher? I had com.sun.crypto.provider.SunJCE (dynamically) installed,
    but it cannot find the algorithm.
    dj_uncas, Nov 20, 2008
    #4
  5. dj_uncas

    Arne Vajhøj Guest

    dj_uncas wrote:
    > I have a problem, and I hope you can help me. I'm building an RMI
    > client/server solution, which requires encrypted parameters. I'm
    > mostly sending objects with String-type parameters, and therefore just
    > need to be able to encrypt and decrypt a String.
    >
    > I have been looking at Java Cryptographic Extension, and had a running
    > sample that worked, however in the sample, I did not convert the
    > encrypted byte-array to a String before decrypting it. When I try
    > that, I get different exceptions regarding the length of the String
    > I'm trying to decrypt. For example, with the Triple DES algorithm I
    > get:
    > "javax.crypto.IllegalBlockSizeException: Input length must be multiple
    > of 8 when decrypting with padded cipher"
    >
    > Some other algorithms just tell me, that the incomming string is not
    > padded correctly...
    >
    > I think my issue is in converting the encrypted byte-array to a
    > String, and back - and this is where I fall short. Can you give me
    > some pointers on this?


    Hex:

    private static String toHex(byte[] ba) {
    StringBuffer sb = new StringBuffer("");
    for (int i = 0; i < ba.length; i++) {
    sb.append(Integer.toHexString((ba >> 4) & 0x0F));
    sb.append(Integer.toHexString(ba & 0x0F));
    }
    return sb.toString();
    }
    private static byte[] fromHex(String s) {
    int n = s.length() / 2;
    byte[] res = new byte[n];
    for(int i = 0; i < n; i++) {
    res = (byte)(Integer.parseInt(s.substring(2 * i, 2 * i +
    2), 16));
    }
    return res;
    }


    Base64:

    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;
    }

    Arne
    Arne Vajhøj, Nov 21, 2008
    #5
  6. dj_uncas

    Arne Vajhøj Guest

    dj_uncas wrote:
    >> Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");

    >
    > Just one more thing: Which JCE provider can I use for the above
    > Cipher? I had com.sun.crypto.provider.SunJCE (dynamically) installed,
    > but it cannot find the algorithm.


    All SUN Java versions >= 1.4.2 should have it.

    Arne
    Arne Vajhøj, Nov 21, 2008
    #6
  7. dj_uncas

    Arne Vajhøj Guest

    rossum wrote:

    [a ton of good advice that I will not comment on]

    > You probably need to convert the cyphertext to Base64 rather than to a
    > String. Cyphertext will contain all bytes from -128 to 127 which will
    > make for a very strange string if you convert it directly.


    (new String(b, cs)).getBytes(cs) will even return b for all
    character sets.

    Arne
    Arne Vajhøj, Nov 21, 2008
    #7
  8. dj_uncas

    Roedy Green Guest

    On Thu, 20 Nov 2008 06:49:55 -0800 (PST), dj_uncas <>
    wrote, quoted or indirectly quoted someone who said :

    >I have a problem, and I hope you can help me. I'm building an RMI
    >client/server solution, which requires encrypted parameters. I'm
    >mostly sending objects with String-type parameters, and therefore just
    >need to be able to encrypt and decrypt a String.


    Encryption works with bytes. So you must first encode your string as
    byte[] to encrypt it, e.g. to UTF-8. see
    http://mindprod.com/jgloss/encoding.

    You will get a mishmash of bytes once encrypted. You can't simply
    decode this as a UTF-8 string since it will include bytes that are not
    legit UTF-8 sequences. You must "armour" it to convert it to String,
    usually a string of limited character set, so it won't be mangled by
    email. There are many ways to armour. BASE64 is common.

    See http://mindprod.com/jgloss/armouring.html

    Code provided.

    At the other end, you string the armour, and get back the bytes. Then
    you decrypt. You get back bytes. Then you decode the UTF-8. Whew!

    For code to do all this without JCE see:
    http://mindprod.com/products1.html#TRANSPORTER

    For code to do it with JCE see:
    http://mindprod.com/jgloss/cipher.html
    --
    Roedy Green Canadian Mind Products
    http://mindprod.com
    Your old road is
    Rapidly agin'.
    Please get out of the new one
    If you can't lend your hand
    For the times they are a-changin'.
    Roedy Green, Nov 21, 2008
    #8
  9. dj_uncas

    Roedy Green Guest

    On Thu, 20 Nov 2008 10:12:37 -0800 (PST), dj_uncas <>
    wrote, quoted or indirectly quoted someone who said :

    >Just one more thing: Which JCE provider can I use for the above
    >Cipher? I had com.sun.crypto.provider.SunJCE (dynamically) installed,
    >but it cannot find the algorithm.


    To see which algorithms are available with your default provider, see
    http://mindprod.com/jgloss/jce.html
    which has the code
    ..
    --
    Roedy Green Canadian Mind Products
    http://mindprod.com
    Your old road is
    Rapidly agin'.
    Please get out of the new one
    If you can't lend your hand
    For the times they are a-changin'.
    Roedy Green, Nov 21, 2008
    #9
  10. dj_uncas

    Roedy Green Guest

    On Fri, 21 Nov 2008 07:43:23 -0800, Roedy Green
    <> wrote, quoted or indirectly quoted
    someone who said :

    > Encryption works with bytes. So you must first encode your string as
    >byte[] to encrypt it, e.g. to UTF-8. see
    >http://mindprod.com/jgloss/encoding.


    that should read
    http://mindprod.com/jgloss/encoding.html
    --
    Roedy Green Canadian Mind Products
    http://mindprod.com
    Your old road is
    Rapidly agin'.
    Please get out of the new one
    If you can't lend your hand
    For the times they are a-changin'.
    Roedy Green, Nov 21, 2008
    #10
  11. dj_uncas

    dj_uncas Guest

    > If that doesn't work then show more code.

    It didn't... I found that it isn't the Cipher that throws the
    NoSuchAlgorithmException, but the KeyGenerator.getInstance(). My code
    looks like this:

    KeyGenerator kg = KeyGenerator.getInstance( "AES/CBC/PKCS5Padding" );
    System.out.println( kg.getProvider().getName() );
    SecretKey key = kg.generateKey();

    Cipher c = Cipher.getInstance( "AES/CBC/PKCS5Padding" );
    c.init( mode, key );

    byte[] result = c.doFinal( input );


    Can you spot something?
    dj_uncas, Nov 22, 2008
    #11
  12. dj_uncas

    dj_uncas Guest


    > Are you retrieving the generated key?
    >
    >    AlgorithmParameters ap = c.getParameters();
    >
    > Without it you will not be able to decrypt.  The same key is needed on
    > the decrypting machine.


    I don't think I am, no. I've added the following to the method:

    AlgorithmParameters parameters = c.getParameters();
    c.init( mode, key, parameters );

    But decrypting throws a
    "java.security.InvalidAlgorithmParameterException: Parameters missing"

    I'm sure it's just that I don't get it.

    > Without it you will not be able to decrypt. The same key is needed on
    > the decrypting machine.


    I'm not quite sure what you mean by this? The previously posted code
    is used for both encrypting and decrypting - just with different
    Cipher modes.
    dj_uncas, Nov 22, 2008
    #12
  13. dj_uncas

    dj_uncas Guest


    > <Lots of code>


    Awesome dude! It's working for me now :)

    That is, until I implement it in my application. It's an RMI
    application, which means everything I send has to be serialized.
    AlgorithmParameters is not serializable. I've experimented with
    serializing it manually, but it seems pretty weird, especially when
    deserializing it. Have you tried it before?

    The particular code that is failing is this:

    String algorithm = in.readUTF();
    Provider provider = (Provider)in.readObject();
    _parameters = AlgorithmParameters.getInstance( algorithm, provider );

    The last line throws this exception:
    java.security.NoSuchAlgorithmException: no such algorithm: AES for
    provider SunJCE
    dj_uncas, Nov 24, 2008
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Srinivasa Reddy K Ganji

    database connection string encryption and decryption

    Srinivasa Reddy K Ganji, Jul 18, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    688
    Gary Varga
    Jul 18, 2003
  2. Replies:
    2
    Views:
    1,597
    Sushant Bhatia
    May 3, 2005
  3. Replies:
    6
    Views:
    651
    DishanF
    Jan 12, 2005
  4. Aidan Diffey
    Replies:
    11
    Views:
    9,461
    Chris Uppal
    Oct 24, 2005
  5. schw
    Replies:
    1
    Views:
    1,150
    rossum
    May 10, 2007
Loading...

Share This Page