Generate random string WITHOUT time? - string

I know how to generate a random string in go using Runes & seeding rand.Init with time.UnixNano(). My question is, is it possible (with the stdlib) to seed rand without using the current timestamp (secure)?
Furthermore, I ask because isn't just relying on time to generate a random string for a sensitive operation insecure/a vulnerability?

For sensitive operations use crypto/rand instead of math/rand:
Package [crypto/] rand implements a cryptographically secure random number generator.
Note that you don't need (you can't) seed crypto/rand.

You can seed it with anything, it just takes an integer. Time is commonly used because it changes and there aren't a lot of sources for good random seeds that aren't constant - if you use the same seed, you'll get the same sequence of values, so typically you want something that changes.
Is it insecure? Absolutely! If you need secure random number generation, you must use crypto/rand instead: https://golang.org/pkg/crypto/rand/
crypto/rand does not offer a way to seed it because it's seeded using the system's cryptographically-strong random number generator.

Related

How to make Golang seed init stronger

I will see people use this method to random seed init for Go to make random!
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}
I am 100% sure this method is not safe,
guess time.Now().UTC().UnixNano() is 1000X> easy then find real generated random password
Does any one have an idea, also call windows api to generate random seed is good idea I think?
If security is important to begin with, then you should "drop" math/rand and use crypto/rand in the first place.
If security is "not" important, then seeding with time.Now().UnixNano() is perfectly fine. (Note that it is needless to call Time.UTC() because Time.UnixNano() returns the Unix time which is specified to be in UTC.)
Note that there are 2592000000000000 nanoseconds in 24 hours, so even if the day is known, theoretically there are 2.592*1015 different seed combinations, perfectly enough for non-secure scenarios.
rand.Seed() is to seed the global Rand of the math/rand package. You don't have to (you can't) seed the crypto/rand package.
See possible duplicate: Generate random string WITHOUT time?
See related questions:
Generating a random, fixed-length byte array in Go
How to get a sample of random numbers in golang?

Is it better to use a 128-bit long (uuid) or a 7-bit long (shortid) unique ID generator in Node?

I'm currently using uuid npm package to generate unique IDs for the elements of my graph database in my node.js app.
It generates RFC-compliant 128-bit long IDs, like
6e228580-1cb5-11e8-8271-891867c15336
I'm currently thinking to shift to shortid npm package, which does a similar job but generates 7-bit long IDs:
PPBqWA9
My database requests are already long and I want to shorten them, so I'm considering the switch from uuid to shortid.
However, the question: I understand that the 128-bit long compliant UUID generator guarantees that it's going to be unique. What about the 7-bit one? I understand it can provide about 78364164096 unique possibilities which is not bad, but I already have about 50M unique objects in my DB, each of which has a unique index, so I'm just curious if that algorithm would really be able to generate a unique ID considering that 78364164096 is only 1350 times more than 50000.
Any ideas? Should I use a 7-bit identifier or a 128-bit one?
I will assume the shorter ids provided by the shortid package to be full 56 bit long. But most likely they take 56-bit long space (7 bytes) but only something like 42-bit long payload.
Both 56-bit and 128-bit ids are subject to collision. The difference is the probability of having a collision. I think the 56-bit one REQUIRE you to be able to handle collisions, so you'll end up having a more complex code. The 128-bit is quite unlikely to produce collisions to the point of generally not being considered.
For the sake of simplicity and safety, I would choose the time proven 128-bit.

How random is crypto#randomBytes?

How random is crypto.randomBytes(20).toString('hex')?
Easy as that, all I need to know.
How random is crypto.randomBytes()? Usually, random enough for whatever purpose you need.
crypto.randomBytes() generates cryptographically secure random data:
crypto.randomBytes(size[, callback])
Generates cryptographically strong pseudo-random data. The size argument is a number indicating the number of bytes to generate.
This means that the random data is secure enough to use for encryption purposes. In fact, the function is just a wrapper around OpenSSL's RAND_bytes() function. This part of their documentation states:
RAND_bytes will fetch cryptographically strong random bytes. Cryptographically strong bytes are suitable for high integrity needs, such as long term key generation. If your generator is using a software algorithm, then the bytes will be pseudo-random (but still cryptographically strong).
Unless you have a hardware random number generator, the bytes will be pseudo-random—generated predictably from a seed value. The seed is generated from an OS-specific source (/dev/urandom on Unix-like systems, CryptGenRandom on Windows). As long as your seed is relatively random and not known to an attacker, the data produced will appear totally random.
If you like, you could perform the test described here:
Given any arbitrary sequence of binary digits it is possible to examine it using statistical techniques. There are various suites of statistical tests available such as STS (Statistical Test Suite) available from NIST's RANDOM NUMBER GENERATION page. This suite provides a number of different tests including:
The Frequency (Monobit) Test: Checks whether the proportion of 0s and 1s in a given sequence are approximately as one would expect
The Runs Test: Tests whether the number of runs of consecutive identical digits of varying lengths within a given sequence is as expected
The Longest Run of Ones in a block: Confirms whether the longest single run of ones within a sequence is as would be expected
That would give you a very good indication on how random your generator is on your system. Rest assured, though, that it's likely to be virtually indistinguishable from a truly random source, so it should be sufficiently random for nearly any application.

Entropy for Nonce creation

In OAuth, a Nonce is used to prevent replay-attacks. In addition to the nonce, a timestamp is also used (and can be considered a second nonce, as, when strictly sticking with the specification, there is no timeframe in which requests are consideed valid - servers MAY, not MUST limit the range).
The question that came into my mind when implementing a OAuth-Client is: Do Nonces have to be cryptographcally secure?
Two points are important to me here:
Is it ok to use /dev/urandom instead of /dev/random and risk predictable values if the system is running low on entropy when many nonces are created in little time?
(For those not familiar with random/urandom: This would have an advantage in performance, as /dev/urandom doesn't block calls when little entropy is available at the cost of security, as, of course, values are less random).
As nonces have to be encoded to be sent if they contain non-ASCII-characters, it's the easiest thing to create them only out of those ASCII chars that can be sent as-is ([0-9A-Za-z_-+~] AFAIR). Of course this limits entropy again, so the nonce has t be longer to be equally strong. In your oppinion, what's a reasonable length for nonce that only consist of those characters and is it worth the advantage of not having to encode?
Normally it is hardly ever useful to use /dev/random instead of /dev/urandom. You can make a point of using it to seed other PRNG's if you don't want to have those PRNG's rely on /dev/urandom. For nonce's, you should certainly be better off using /dev/urandom. Or you can use a well seeded, thread local cryptographically secure PRNG implemented in your app or library of course.
If you want to send a nonce (or most binary data) over ASCII then you can use hexadecimals or base 64. For the best readability of the value itself, use hex, for efficiency use base64. Now by default base 64 uses numbers, upper and lowercase letters, plus the characters +, / and = but if you want to use other values you can always URLencode the base64, replace the characters you do not want, or use one of the variants.

How (if at all) does a predictable random number generator get more secure after SHA-1ing its output?

This article states that
Despite the fact that the Mersenne Twister is an extremely good pseudo-random number generator, it is not cryptographically secure by itself for a very simple reason. It is possible to determine all future states of the generator from the state the generator has at any given time, and either 624 32-bit outputs, or 19,937 one-bit outputs are sufficient to provide that state. Using a cryptographically-secure hash function, such as SHA-1, on the output of the Mersenne Twister has been recommended as one way of obtaining a keystream useful in cryptography.
But there are no references on why digesting the output would make it any more secure. And honestly, I don't see why this should be the case. The Mersenne Twister has a period of 2^19937-1, but I think my reasoning would also apply to any periodic PRNG, e.g. Linear Congruential Generators as well. Due to the properties of a secure one-way function h, one could think of h as an injective function (otherwise we could produce collisions), thus simply mapping the values from its domain into its range in a one-to-one manner.
With this thought in mind I would argue that the hashed values will produce exactly the same periodical behaviour as the original Mersenne Twister did. This means if you observe all values of one period and the values start to recur, then you are perfectly able to predict all future values.
I assume this to be related to the same principle that is applied in password-based encryption (PKCS#5) - because the domain of passwords does not provide enough entropy, simply hashing passwords doesn't add any additional entropy - that's why you need to salt passwords before you hash them. I think that exactly the same principle applies here.
One simple example that finally convinced me: Suppose you have a very bad PRNG that will always produce a "random number" of 1. Then even if SHA-1 would be a perfect one-way function, applying SHA-1 to the output will always yield the same value, thus making the output no less predictable than previously.
Still, I'd like to believe there is some truth to that article, so surely I must have overlooked something. Can you help me out? To a large part, I have left out the seed value from my arguments - maybe this is where the magic happens?
The state of the mersenne twister is defined by the previous n outputs, where n is the degree of recurrence (a constant). As such, if you give the attacker n outputs straight from a mersenne twister, they will immediately be able to predict all future values.
Passing the values through SHA-1 makes it more difficult, as now the attacker must try to reverse the RNG. However, for a 32-bit word size, this is unlikely to be a severe impediment to a determined attacker; they can build a rainbow table or use some other standard approach for reversing SHA-1s, and in the event of collisions, filter candidates by whether they produce the RNG stream observed. As such, the mersenne twister should not be used for cryptographically sensitive applications, SHA-1 masking or no. There are a number of standard CSPRNGs that may be used instead.
An attacker is able to predict the output of MT based on relatively few outputs not because it repeats over such a short period (it doesn't), but because the output leaks information about the internal state of the PRNG. Hashing the output obscures that leaked information. As #bdonlan points out, though, if the output size is small (32 bits, for instance), this doesn't help, as the attacker can easily enumerate all valid plaintexts and precalculate their hashes.
Using more than 32 bits of PRNG output as an input to the hash would make this impractical, but a cryptographically secure PRNG is still a much better choice if you need this property.

Resources