get hexadecimal hash string for a number

Discussion in 'Java' started by Magnus Warker, Sep 18, 2012.

  1. Hi,

    I want users to register on a site and send confirmation emails to them.
    These emails should contain a link like this:

    http://myurl?registration=E4AC4BD4

    Here, "E4AC4BD4" should be a unique string. My idea for such a string is
    just to hash an integer, i. e. the internal database key for the
    registration record.

    However, I actually don't know how to get such a hash. I tried BCrypt,
    but this produces hashes built out of characters that I would not want
    to be in a URL, e. g. commatas and that.

    I would like to have a string like this:

    - hexadecimal only
    - fixed size, e. g. always n characters, independend of the integer

    Can you help?

    Thank you!

    Magnus
     
    Magnus Warker, Sep 18, 2012
    #1
    1. Advertising

  2. Magnus Warker

    markspace Guest

    On 9/18/2012 9:25 AM, Magnus Warker wrote:
    > Hi,
    >
    > I want users to register on a site and send confirmation emails to them.
    > These emails should contain a link like this:
    >
    > http://myurl?registration=E4AC4BD4
    >
    > Here, "E4AC4BD4" should be a unique string.



    <http://docs.oracle.com/javase/7/docs/api/java/util/UUID.html>

    I think UUID is better, as it is more random than just an integer, and
    I'm pretty sure it uses a hexadecimal representation, so you can just
    use it as-is. Make a new one, call toString, and you're ready to go.
     
    markspace, Sep 18, 2012
    #2
    1. Advertising

  3. Magnus Warker

    Lew Guest

    Magnus Warker wrote:
    > I want users to register on a site and send confirmation emails to them.
    > These emails should contain a link like this:
    >
    > http://myurl?registration=E4AC4BD4
    >
    > Here, "E4AC4BD4" should be a unique string. My idea for such a string is
    > just to hash an integer, i. e. the internal database key for the
    > registration record.
    >
    > However, I actually don't know how to get such a hash. I tried BCrypt,
    > but this produces hashes built out of characters that I would not want
    > to be in a URL, e. g. commatas and that.
    >
    > I would like to have a string like this:
    >
    > - hexadecimal only
    > - fixed size, e. g. always n characters, independend of the integer
    >
    > Can you help?


    First of all, hashing a unique integer is silly. It's already unique!

    If you have a reliably unique, stable integer ID, you don't need to hash it!

    Just use the value.

    Got that? Good, because an internal database ID is not reliable.
    It's *internal*! It's not meant to be used externally!

    Got that? Good, because the database record has (or you're not doing it
    right) an external unique key, one based on visible attributes. You could
    hash that key.

    Or you could perhaps use
    http://docs.oracle.com/javase/7/docs/api/java/rmi/server/UID.html

    You'll want to store that UID with the registration record.

    First and foremost google around for hash codes and how to use them.
    Your lack of understanding will screw you otherwise.

    --
    Lew
     
    Lew, Sep 18, 2012
    #3
  4. Magnus Warker

    Lew Guest

    markspace wrote:
    > Magnus Warker wrote:
    >> I want users to register on a site and send confirmation emails to them.
    >> These emails should contain a link like this:
    >>
    >> http://myurl?registration=E4AC4BD4
    >>
    >> Here, "E4AC4BD4" should be a unique string.

    >
    > <http://docs.oracle.com/javase/7/docs/api/java/util/UUID.html>
    > I think UUID is better, as it is more random than just an integer, and
    > I'm pretty sure it uses a hexadecimal representation, so you can just
    > use it as-is. Make a new one, call toString, and you're ready to go.


    It's better than UID that I suggested, too.

    --
    Lew
     
    Lew, Sep 18, 2012
    #4
  5. Magnus Warker

    Roedy Green Guest

    Roedy Green, Sep 18, 2012
    #5
  6. Magnus Warker

    Arne Vajhøj Guest

    On 9/18/2012 1:08 PM, markspace wrote:
    > On 9/18/2012 9:25 AM, Magnus Warker wrote:
    >> I want users to register on a site and send confirmation emails to them.
    >> These emails should contain a link like this:
    >>
    >> http://myurl?registration=E4AC4BD4
    >>
    >> Here, "E4AC4BD4" should be a unique string.

    >
    >
    > <http://docs.oracle.com/javase/7/docs/api/java/util/UUID.html>
    >
    > I think UUID is better, as it is more random than just an integer, and
    > I'm pretty sure it uses a hexadecimal representation, so you can just
    > use it as-is. Make a new one, call toString, and you're ready to go.


    It meets the stated requirements of being unique.

    But the original poster most likely have a requirement he
    forgot to mention: that it should be hard to guess as well.

    The point of emailing a confirmation link is to ensure that the
    registrant indeed own the email address.

    If the link is guessable then there is no point.

    UUID's are not intended to be cryptographic secure, so they
    are not the right toll for the job.

    The correct approach is to use a cryptographic secure
    RNG to generate a number of random bytes.

    Being slightly paranoid I will recommend generating
    maybe 100 bytes and do a SHA-256 of that just to
    protect against weaknesses.

    It does not cost much coding or many resources runtime, so
    I can not see any reason to not do it the right way.

    Arne
     
    Arne Vajhøj, Sep 19, 2012
    #6
  7. Magnus Warker

    Arne Vajhøj Guest

    Arne Vajhøj, Sep 19, 2012
    #7
  8. Magnus Warker

    Arne Vajhøj Guest

    On 9/18/2012 1:10 PM, Lew wrote:
    > Magnus Warker wrote:
    >> I want users to register on a site and send confirmation emails to them.
    >> These emails should contain a link like this:
    >>
    >> http://myurl?registration=E4AC4BD4
    >>
    >> Here, "E4AC4BD4" should be a unique string. My idea for such a string is
    >> just to hash an integer, i. e. the internal database key for the
    >> registration record.
    >>
    >> However, I actually don't know how to get such a hash. I tried BCrypt,
    >> but this produces hashes built out of characters that I would not want
    >> to be in a URL, e. g. commatas and that.
    >>
    >> I would like to have a string like this:
    >>
    >> - hexadecimal only
    >> - fixed size, e. g. always n characters, independend of the integer
    >>
    >> Can you help?

    >
    > First of all, hashing a unique integer is silly. It's already unique!
    >
    > If you have a reliably unique, stable integer ID, you don't need to hash it!
    >
    > Just use the value.


    The real issue for the confirmation link problem is not
    uniqueness but that it has to be hard to guess.

    Which changes the solution quite a bit.

    Arne
     
    Arne Vajhøj, Sep 19, 2012
    #8
  9. Magnus Warker

    Arne Vajhøj Guest

    On 9/18/2012 12:25 PM, Magnus Warker wrote:
    > I want users to register on a site and send confirmation emails to them.
    > These emails should contain a link like this:
    >
    > http://myurl?registration=E4AC4BD4
    >
    > Here, "E4AC4BD4" should be a unique string. My idea for such a string is
    > just to hash an integer, i. e. the internal database key for the
    > registration record.
    >
    > However, I actually don't know how to get such a hash. I tried BCrypt,
    > but this produces hashes built out of characters that I would not want
    > to be in a URL, e. g. commatas and that.
    >
    > I would like to have a string like this:
    >
    > - hexadecimal only
    > - fixed size, e. g. always n characters, independend of the integer


    Use a secure RNG (java.security.SecureRandom) to generate 100 random bytes.

    Convert it to 32 bytes with SHA-256 (java.security.MessageDigest).

    And convert it to 64 hex characters.

    Done.

    Arne
     
    Arne Vajhøj, Sep 19, 2012
    #9
  10. Magnus Warker

    markspace Guest

    On 9/18/2012 4:58 PM, Arne Vajhøj wrote:

    > The correct approach is to use a cryptographic secure
    > RNG to generate a number of random bytes.
    >



    I looked up"cryptographic secure" on Wikipedia, and I have to disagree.
    The key he's sending is going out as plain text. Cryptographically
    secure RNGs are used to generate keys, you never reveal your seed value
    or there's no point to the keys either. The UUID is plenty hard to
    guess; using a hard-to-guess value that you then send out as plain text
    isn't going to improve your security.

    Also, there's human factors to consider as well. "Fake" but valid email
    addresses are plenty easy to generate. If someone really wants to use a
    bogus address, they just make one, get the link you send them, and then
    ignore the email address after that. This whole process is easy to
    automate. Hundreds or thousands of fake ID per day can be generated
    this way. "Cryptographically secure" doesn't mean much when Alice and
    Mallory are the same person. In this case the human factor is a coder
    who thinks "cryptographically secure" is going to solve some problem
    when it won't.

    If you can show me how UUIDs are "easy to guess," I might retract my
    statements somewhat.
     
    markspace, Sep 19, 2012
    #10
  11. Magnus Warker

    markspace Guest

    On 9/18/2012 5:06 PM, Arne Vajhøj wrote:

    > Use a secure RNG (java.security.SecureRandom) to generate 100 random
    > bytes.



    And UUID uses SecureRandom internally to generate its values, so this is
    bogus advice. Sorry, Arne, but you really should have checked before
    you posted.
     
    markspace, Sep 19, 2012
    #11
  12. Magnus Warker

    Arne Vajhøj Guest

    On 9/18/2012 8:30 PM, markspace wrote:
    > On 9/18/2012 5:06 PM, Arne Vajhøj wrote:
    >> Use a secure RNG (java.security.SecureRandom) to generate 100 random
    >> bytes.

    >
    > And UUID uses SecureRandom internally to generate its values,


    In that case UUID is good.
    so this is
    > bogus advice. Sorry, Arne, but you really should have checked before
    > you posted.


    Maybe.

    But UUID is not a Java specific concept and in general UUID's are
    not guaranteed to be hard to guess values.

    It turns out that Java UUID support two types of UUID's - of which
    one of them per Java doc is using a "cryptographically strong
    pseudo random number generator".

    I was not aware.

    Arne
     
    Arne Vajhøj, Sep 19, 2012
    #12
  13. Magnus Warker

    Arne Vajhøj Guest

    On 9/18/2012 8:27 PM, markspace wrote:
    > On 9/18/2012 4:58 PM, Arne Vajhøj wrote:
    >> The correct approach is to use a cryptographic secure
    >> RNG to generate a number of random bytes.

    >
    > I looked up"cryptographic secure" on Wikipedia, and I have to disagree.
    > The key he's sending is going out as plain text. Cryptographically
    > secure RNGs are used to generate keys,


    Yes and no.

    A cryptographic secure RNG is really just an RNG that produces
    values that are hard/impossible to predict.

    It has an obvious usage for generating cryptography keys.

    But it also has other usages.

    Hard to guess id's are one of the other.

    > you never reveal your seed value
    > or there's no point to the keys either. The UUID is plenty hard to
    > guess; using a hard-to-guess value that you then send out as plain text
    > isn't going to improve your security.


    It solves the problem it is intended to solve.

    The purpose of a confirmation email with a link with such an
    id is to verify that the owner of the email account is indeed
    the one registering.

    You can not ensure that if it is possible for the registering
    person to guess the id.

    It need to be hard to guess.

    Which is what a cryptographic secure RNG provide.

    > Also, there's human factors to consider as well. "Fake" but valid email
    > addresses are plenty easy to generate. If someone really wants to use a
    > bogus address, they just make one, get the link you send them, and then
    > ignore the email address after that. This whole process is easy to
    > automate. Hundreds or thousands of fake ID per day can be generated
    > this way. "Cryptographically secure" doesn't mean much when Alice and
    > Mallory are the same person. In this case the human factor is a coder
    > who thinks "cryptographically secure" is going to solve some problem
    > when it won't.


    That is not relevant for what we are discussing.

    We are discussing how to send out confirmation emails with links.

    Whether that idea brings value or not is another question.

    Arne
     
    Arne Vajhøj, Sep 19, 2012
    #13
  14. Magnus Warker

    Arne Vajhøj Guest

    On 9/18/2012 8:27 PM, markspace wrote:
    > If you can show me how UUIDs are "easy to guess," I might retract my
    > statements somewhat.


    UUID's type 1, 2 and 3 are not random at all.

    UUID's type 4 is random but if it is not a cryptographic
    secure RNG then it is vulnerable. And if it is something
    trivial like a 32 bit LCG then it is trivial to break.

    Arne
     
    Arne Vajhøj, Sep 19, 2012
    #14
  15. In article <k3a74r$u3s$-online.net>,
    Magnus Warker <> wrote:

    > Hi,
    >
    > I want users to register on a site and send confirmation emails to them.
    > These emails should contain a link like this:
    >
    > http://myurl?registration=E4AC4BD4
    >
    > Here, "E4AC4BD4" should be a unique string. My idea for such a string is
    > just to hash an integer, i. e. the internal database key for the
    > registration record.
    >
    > However, I actually don't know how to get such a hash. I tried BCrypt,
    > but this produces hashes built out of characters that I would not want
    > to be in a URL, e. g. commatas and that.
    >
    > I would like to have a string like this:
    >
    > - hexadecimal only
    > - fixed size, e. g. always n characters, independend of the integer
    >
    > Can you help?
    >
    > Thank you!
    >
    > Magnus


    You can't use a 32 bit integer here. Valid values would quickly become
    easier to guess as you add users.

    1) Use SecureRandom to generate a string of link-safe characters.
    2) Insert the key into the database
    3) Send the link


    Base64 will work well for step one. Base 64 encodes sets of 3 bytes
    into sets of 4 characters. You'll want 9 SecureRandom bytes generating
    a 12 character id.


    Should step two give you a unique key violation, buy a lottery ticket
    using the numbers. If you don't retire on the winnings, make sure that
    SecureRandom doesn't have a stupid implementation in your JVM. You can
    find it with the debugger.
    --
    I will not see posts from Google because I must filter them as spam
     
    Kevin McMurtrie, Sep 19, 2012
    #15
  16. On 09/18/2012 07:10 PM, Lew wrote:
    > Magnus Warker wrote:


    > First of all, hashing a unique integer is silly. It's already unique!


    > First and foremost google around for hash codes and how to use them.
    > Your lack of understanding will screw you otherwise.


    As Arne guessed, I should have said "encrypt" instead of "hash". You
    could also guess this, but I think you didn't want to.

    Magnus

    --
    This is Unix-Land. In quiet nights, you can hear the Windows machines
    reboot.
     
    Magnus Warker, Sep 19, 2012
    #16
  17. Hi Arne!

    On 09/19/2012 01:58 AM, Arne Vajhøj wrote:

    > The correct approach is to use a cryptographic secure
    > RNG to generate a number of random bytes.


    What about encrypting the database key?

    > Being slightly paranoid I will recommend generating
    > maybe 100 bytes and do a SHA-256 of that just to
    > protect against weaknesses.


    If we are paranoid, we should also remember the uniqueness requirement.
    "Random" could be a problem here.

    > It does not cost much coding or many resources runtime, so
    > I can not see any reason to not do it the right way.


    I am sure that your approach will do the job. Thanks!

    But I would like to know if encrypting the database key would also be
    ok. Can we encrypt it and also ensure a fixed-length hex value?

    Magnus

    --
    This is Unix-Land. In quiet nights, you can hear the Windows machines
    reboot.
     
    Magnus Warker, Sep 19, 2012
    #17
  18. Magnus Warker

    Arne Vajhøj Guest

    On 9/19/2012 2:27 AM, Magnus Warker wrote:
    > On 09/19/2012 01:58 AM, Arne Vajhøj wrote:
    >> The correct approach is to use a cryptographic secure
    >> RNG to generate a number of random bytes.

    >
    > What about encrypting the database key?


    That relies on the key being kept secret.

    In many cases this is a necessary requirement, but not
    in this case, so I would say that it is second best option.

    And since Java UUID do provide a way to generate using
    a cryptographic secure RNG as markspace pointed out, then it
    it is even simpler to code than I expected (not that SecureRandom
    is that hard to use in the first place).

    >> Being slightly paranoid I will recommend generating
    >> maybe 100 bytes and do a SHA-256 of that just to
    >> protect against weaknesses.

    >
    > If we are paranoid, we should also remember the uniqueness requirement.
    > "Random" could be a problem here.


    If you make the column unique in the database then you will get an error
    inserting and can then just pick another.

    It will happen at average 1 out of some billion/trillion years, so
    I think you can live with that.

    >> It does not cost much coding or many resources runtime, so
    >> I can not see any reason to not do it the right way.

    >
    > I am sure that your approach will do the job. Thanks!
    >
    > But I would like to know if encrypting the database key would also be
    > ok. Can we encrypt it and also ensure a fixed-length hex value?


    You can sure pad and encrypt.

    But as explained above then I think it is just the second best
    option.

    Arne
     
    Arne Vajhøj, Sep 19, 2012
    #18
  19. In article <k3bonl$ta1$>,
    Magnus Warker <> wrote:

    > Hi Arne!
    >
    > On 09/19/2012 01:58 AM, Arne Vajhøj wrote:
    >
    > > The correct approach is to use a cryptographic secure
    > > RNG to generate a number of random bytes.

    >
    > What about encrypting the database key?
    >
    > > Being slightly paranoid I will recommend generating
    > > maybe 100 bytes and do a SHA-256 of that just to
    > > protect against weaknesses.

    >
    > If we are paranoid, we should also remember the uniqueness requirement.
    > "Random" could be a problem here.
    >
    > > It does not cost much coding or many resources runtime, so
    > > I can not see any reason to not do it the right way.

    >
    > I am sure that your approach will do the job. Thanks!
    >
    > But I would like to know if encrypting the database key would also be
    > ok. Can we encrypt it and also ensure a fixed-length hex value?
    >
    > Magnus


    What is your database key?

    If it's 1, 2, 3, 4, ... then encrypting it will simply reveal your
    encryption key. If characters aren't efficient for your keys, simply use
    a translation table between the random and sequential values. Use the
    randomized value as a database key on all traffic leaving and entering
    your server. It prevents the public from guessing new database keys.

    create table urlparams
    {
    param char(16) primary key,
    id integer unique not null references main_table (id)
    }
    -- param is the outside database key made of random characters
    -- id is the local primary key

    create table main_table
    {
    id integer primary key,
    ...
    }

    create table other_table
    {
    id integer primary key references main_table (id),
    ...
    }

    create table more_table
    {
    id integer primary key references main_table (id),
    ...
    }

    You fetch all your table data together efficiently in one join:

    select ... from main_table, other_table, more_table, urlparams
    where
    urlparams.param=?
    and urlparams.id=main_table.id
    and urlparams.id=other_table.id
    and urlparams.id=more_table.id
    --
    I will not see posts from Google because I must filter them as spam
     
    Kevin McMurtrie, Sep 20, 2012
    #19
  20. > As has been pointed out, integers are already unique. Just decide on
    > a large enough fixed size and zero pad the small numbers:
    > 0000000000001


    > If you want to disguise the actual number you are using, which is what
    > I take your mention of "hash" to mean, then you need an encryption.
    > Each unique input gives a unique output. It has to be unique,
    > otherwise you couldn't decrypt it reliably.


    What about Kevin's posting? He noted that encrypting sequential numbers
    would reveal the encryption key?

    > For 64 bit numbers, just use DES and encrypt the numbers 0, 1, 2, 3,
    > ... n in turn. For 128 bits use AES.


    Could you please explain this? I haven't used encryption in Java, but I
    would expect that the encryption method should be independend of the
    size of the data to encrypt?

    > Again, you will need to be sure that your chosen bit size will
    > acommodate enough users, with plenty to spare for keeping the gaps
    > numerous enough.


    Well, I would simply choose the size of SQL standard integer (64)...

    Magnus

    --
    This is Unix-Land. In quiet nights, you can hear the Windows machines
    reboot.
     
    Magnus Warker, Sep 20, 2012
    #20
    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. Shivani
    Replies:
    3
    Views:
    310
    Joe Wright
    Sep 7, 2005
  2. muss
    Replies:
    13
    Views:
    728
    Vladimir S. Oka
    Mar 27, 2006
  3. Replies:
    14
    Views:
    1,069
    Simon Biber
    Nov 16, 2006
  4. rp
    Replies:
    1
    Views:
    580
    red floyd
    Nov 10, 2011
  5. Bob Sanders
    Replies:
    5
    Views:
    243
    Ryan Lewis
    May 30, 2008
Loading...

Share This Page