Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Saving encrypted string in java?

Options
  • 08-08-2005 3:06pm
    #1
    Registered Users Posts: 21,264 ✭✭✭✭


    I have a string, I want to store it to a property file encrypted. I want to be able to read it back and compare it to another string but I don't want the code have to decode the string.

    Anyone any pointers what to look at? Is there an easy way in java libraries?


Comments

  • Closed Accounts Posts: 1,502 ✭✭✭MrPinK


    What you want to do is store the hash (or message digest) of the string. Sample code here

    Generate the hash of the original String and save it in the props file. Then to check if another String is equal to it, you hash that String and compare this with the original hash.


  • Registered Users Posts: 4,003 ✭✭✭rsynnott


    Java has builtin MD5, I seem to remember...


  • Registered Users Posts: 20,994 ✭✭✭✭Stark


    Yup. MessageDigest object.

    I believe the code was
    MessageDigest md = MessageDigest.getInstance("MD5");
    

    MessageDigest can only accept byte arrays, not strings, but that's no problem as you can just do
    stringObject.getBytes()
    
    to get a byte array from a string.

    To do a simple digest on a short string do.
    byte[] hashedValue = md.digest(yourString.getBytes());
    

    or
    md.update(stringPiece1.getBytes());
    md.update(stringPiece2.getBytes());
    ...
    byte[] hashedValue = md.digest();
    
    for large values.

    The resultant bytes won't be in convenient format for most storage purposes as they'll contain ASCII control characters and the like, so you need to encode them in BASE64 format. There's a BASE64Encoder class, but I can't seem to find it in the javadocs right now.

    Edit: it's
    String hashedString = new sun.misc.BASE64Encoder().encode(hasedValue);
    

    You'll need to repeat the above steps when you go to compare another string.


  • Registered Users Posts: 4,003 ✭✭✭rsynnott


    Stark wrote:
    The resultant bytes won't be in convenient format for most storage purposes as they'll contain ASCII control characters and the like, so you need to encode them in BASE64 format. There's a BASE64Encoder class, but I can't seem to find it in the javadocs right now.

    There is in Sun java, but it's a Sun specific one, and isn't available everywhere. You'd be better find a free one with no usage restrictions (they're pretty simple) and put it in.


  • Closed Accounts Posts: 1,502 ✭✭✭MrPinK


    rsynnott wrote:
    Java has builtin MD5, I seem to remember...
    It has all the major hashing functions, including the superior SHA-1.

    For converting the byte array to a String, I'd usually write my own small method to convert it to hex.
        public static String bytesToHex(byte[] b)
        {
            String values = "0123456789ABCDEF";
            String result = "";
            for(int i = 0; i < b.length; i++)
            {
                int firstCharPos = (int)((b[i] & 0xf0) >>> 4);
                int secondCharPos = (int)(b[i] & 0x0f);
                result +=  "" + values.charAt(firstCharPos) + values.charAt(secondCharPos);
            }
            return result;
        }
    


  • Advertisement
  • Registered Users Posts: 4,003 ✭✭✭rsynnott


    MrPinK wrote:
    It has all the major hashing functions, including the superior SHA-1.

    For converting the byte array to a String, I'd usually write my own small method to convert it to hex.
        public static String bytesToHex(byte[] b)
        {
            String values = "0123456789ABCDEF";
            String result = "";
            for(int i = 0; i < b.length; i++)
            {
                int firstCharPos = (int)((b[i] & 0xf0) >>> 4);
                int secondCharPos = (int)(b[i] & 0x0f);
                result +=  "" + values.charAt(firstCharPos) + values.charAt(secondCharPos);
            }
            return result;
        }
    

    What?! Why on earth would you do that, and by that cripplingly inefficient method? :S


  • Registered Users Posts: 20,994 ✭✭✭✭Stark


    More portable than BASE64 I guess.

    And yes, horribly inefficient :) For a start, use a stringbuffer, and give it an advance size because you know how big it will be to begin with.


  • Closed Accounts Posts: 1,502 ✭✭✭MrPinK


    *sigh* Everyone's a critic.

    I find it nice for sample code to be as reader friendly as possible, but those extra few nanoseconds are important to you then here you go.
    public static String byteToHex(byte[] b)
    {
        char[] hexDigit = {'0', '1', '2', '3', '4', '5', '6', '7',
                           '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        char[] result = new char[b.length * 2];
        for(int i = 0; i < b.length; i++)
        {
            result[i * 2] = hexDigit[(b[i] & 0xf0) >>> 4]; 
            result[i * 2 + 1] = hexDigit[b[i] & 0x0f] };
        }
       
        return new String(result);
    }
    
    What?! Why on earth would you do that
    BASE64Encoder is not part of the Java API. AFAIK there's nothing in the API for converting bytes to hex.


  • Registered Users Posts: 4,003 ✭✭✭rsynnott


    I'd have been very much inclined to just use Integer.toString with the radix parameter, but yep, the second mechanism is of comparable efficiency.

    Of course, if you're going with this strategy, you may as well make the most of available space and go for base 36.


  • Registered Users Posts: 20,994 ✭✭✭✭Stark


    Mr. Pink wrote:
    I find it nice for sample code to be as reader friendly as possible, but those extra few nanoseconds are important to you then here you go.

    Well it was just you used
    (b[i] & 0xf0) >>> 4) and (b[i] & 0x0f)
    
    instead of
    b[i]/16 and b[i]%16
    
    , I would have thought you were valuing the latter :)


  • Advertisement
  • Registered Users Posts: 20,994 ✭✭✭✭Stark


    By the way, why isn't there a free-for-all BASE64Encoder in the Java API? Is it patented or something?


  • Registered Users Posts: 4,003 ✭✭✭rsynnott


    Stark wrote:
    By the way, why isn't there a free-for-all BASE64Encoder in the Java API? Is it patented or something?

    It never got added to the spec, and feature requests have been ignored. There's one in the Sun Java API, but it's not standard.


  • Closed Accounts Posts: 1,502 ✭✭✭MrPinK


    rsynnott wrote:
    I'd have been very much inclined to just use Integer.toString with the radix parameter
    Which requires an int, and the hash is 128 bits too big to be an int.
    I would have thought you were valuing the latter
    True, but I so rarely get the opportunity to use bitwise operations in java. I like to throw them in where ever I can :)

    As to BASE64Encoder being patented, tbh I'd never heard of it before you mentioned it. A quick google just returned lots of API references for third party packages. The only time I've ever had to work with bits and hex is in cryptography, and all the java examples I've seen have used their own bytesToHex method.


  • Registered Users Posts: 4,003 ✭✭✭rsynnott


    Do on a per-byte level, just as you did.

    No, there is no question of Base64 being patented; fortunately, the American run-away patent fixation has SOME shame. It's just an oversight... (People tend to use the sun one, which is a Bad Thing)


  • Registered Users Posts: 20,994 ✭✭✭✭Stark


    rsynnott wrote:
    Do on a per-byte level, just as you did.

    Then you're creating a massive load of String objects for a menial task which isn't good. The char array solution was far, far more efficient :)


  • Registered Users Posts: 1,996 ✭✭✭lynchie


    Stark wrote:
    By the way, why isn't there a free-for-all BASE64Encoder in the Java API? Is it patented or something?

    The JDK does ship with a base 64 encoder/decoder. But it is not in the standard java api packages. Its included in rt.jar under sun's packages
    import sun.misc.Base64Encoder;
    ...
    ...
    ...
        /**
         * Displays a byte array in base 64 format
         * 
         * @param b The data in byte array format
         * @return The data in base64 format
         */
        public static String toBase64(byte[] b)
        {
            BASE64Encoder encoder=new BASE64Encoder();
            return encoder.encodeBuffer(b);
        }
    


  • Registered Users Posts: 21,264 ✭✭✭✭Hobbes


    I'm using IBM JVM not suns. thanks for the replies though.


  • Registered Users Posts: 20,994 ✭✭✭✭Stark


    Sorry, we did go very off-topic there :)

    IBM JVM also has a BASE64Encoder class, it's com.ibm.misc.BASE64Encoder


Advertisement