0

What's the best way to create a random alphanumeric string given a key? I am using this

(0...50).map { ('a'..'z').to_a[rand(26)] }.join

but, I want a string based on a string such as "mysecretkey". I don't want to use encryption gems or Cipher, etc. I want to keep it simple like what I have, but adding a key to it.

sawa
  • 165,429
  • 45
  • 277
  • 381
user2974739
  • 619
  • 1
  • 7
  • 20
  • You can use *Caesar's schiffer*. – ndnenkov Aug 30 '15 at 12:58
  • What is the format of the random string? Is is alphanumeric, or alphabet? How long should it be? What is the format of the string key? – sawa Aug 30 '15 at 13:06
  • It should be 10 alphanumeric characters. The key can the any text. – user2974739 Aug 30 '15 at 13:07
  • Please clarify what the purpose of this is. In particular, please explain *how* the output should be based on the input? What does "based on a string" mean to you? For instance, does the same secret key produce the same output string each time? Or perhaps you need it to have some other influence, such as changing the available letters? Does the output need to be reversible? Does the secret need to be really kept secret (if so then despite your desire to not use encryption gems, you really have no choice but to use them). – Neil Slater Aug 30 '15 at 15:20
  • 1
    In what way is a random string generated with a key different than a random string generated without a key? A rose is a rose is a rose. No? – Cary Swoveland Aug 30 '15 at 15:33

2 Answers2

2

What about this?

Random.rand("mysecretkey".hash).to_s(36)[0, 10]
# => "1lc1em343y"
sawa
  • 165,429
  • 45
  • 277
  • 381
  • This does not return the same result each time, which I would expect to be the case from the OP's phrasing (it would help if OP clarified that) – Neil Slater Aug 30 '15 at 13:11
  • Thanks. Is there an easy way to get "mysecretkey" if given the result? – user2974739 Aug 30 '15 at 13:12
  • @NeilSlater That is not a random string. – sawa Aug 30 '15 at 13:12
  • @sawa: Correct, but I am guessing that is in fact what the OP is trying to do. – Neil Slater Aug 30 '15 at 13:12
  • @user2974739 No. You can be relieved that there is no such way. This will give a good random string. – sawa Aug 30 '15 at 13:14
  • @user2974739, actually, you can make a random string with reversible key. For example, you can partition the output character set (alphabet) and the length of the output string. But this reduces randomness. – ndnenkov Aug 30 '15 at 13:16
1

I am assuming from your question that you want for some reason to associate an input string to a random-looking output, and to have it be the same output if the same key is presented.

The code below will generate the same "random" string for the same input secret key, accepting keys up to 8 * 624 = 4992 bytes long. Technically this is not random, but using Ruby's built in random number generator to hash the input string.

def rand_hash secret_key
  int_key = secret_key.unpack("C*").each_with_index.inject(0) do |sum, (byte, index)|
    sum + byte * (256 ** index)
  end
  r = Random.new( int_key )
 (0...50).map { ('a'..'z').to_a[ r.rand(26) ] }.join
end

rand_hash "Hi, how are you today?"
# => "mwerzokwwtlqepizuqimbhxmzexmovzrwgvarjlfbkcqpffhoq"

rand_hash "Hi, how are you today?"
# => "mwerzokwwtlqepizuqimbhxmzexmovzrwgvarjlfbkcqpffhoq"

rand_hash "Hi, how are you today!"
# => "zeudwqltlozjdebamemplwllqftmyhdzapatqhdsbnrzfcrmss"

See How do I unpack a number larger than 64 bits in ruby? for how the secret_key is unpacked from a string into a BigNum called int_key.

We then use that key to seed a Ruby Random object (based on Mersenne Twister)

Then use the new Random object to generate the string, same as you do originally.

Note this is not cryptographically secure. If you want security, such as impossibility to reverse the output and find the secret, then you should use a secure hash mechanism (from an appropriate gem such as openssl), and convert that to the character set you require.

Community
  • 1
  • 1
Neil Slater
  • 26,512
  • 6
  • 76
  • 94
  • How do you add numbers to the result? It only returns characters. – user2974739 Aug 30 '15 at 19:26
  • The answer is about using a secret key as a random seed. It uses the same generator as you supplied. Just change the `('a'..'z').to_a[rand(26)]` part that you wrote in order to generate the character list that you need. There are lots of possibilities for generators in [this question](http://stackoverflow.com/questions/88311/how-best-to-generate-a-random-string-in-ruby) - just remember to replace instances of `rand` with `r.rand` when using them as in this answer. You won't be able to use the SecureRandom or OpenSSL based answers, as those RNGs cannot use a fixed seed. – Neil Slater Aug 30 '15 at 19:33