-5

I know this kind of question has been already discussed here: How to generate a random number in C?

But I wanted to share the way I implemented it just to know what people may think about it.

#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>

long int getNanoSecs(){
    struct timespec unixtimespec;
    clock_gettime(CLOCK_REALTIME_COARSE, &unixtimespec);
    return unixtimespec.tv_nsec;
}

. . .

unsigned char personal_final_token[PERSONAL_FINAL_TOKEN_SIZE_SIZE];
                unsigned char pwd_ptr_ctr;
                srandom(getNanoSecs()*(getNanoSecs()&0xFF));
                for(pwd_ptr_ctr=0;pwd_ptr_ctr<PERSONAL_FINAL_TOKEN_SIZE_SIZE;pwd_ptr_ctr++){
                    memset(personal_final_token+pwd_ptr_ctr,(random()^getNanoSecs())&0xFF,1);
                }

just define PERSONAL_FINAL_TOKEN_SIZE_SIZE and you can generate a quite random token of the size you want.

Community
  • 1
  • 1
Whitefield
  • 31
  • 6
  • 10
    Maybe you should go to http://codereview.stackexchange.com/ – cpplearner Feb 15 '16 at 13:49
  • It's probably a poor approach. – Jabberwocky Feb 15 '16 at 13:50
  • Trying to make a random generator more random is quite counterproductive. – Karoly Horvath Feb 15 '16 at 13:54
  • 2
    I don't see the point of xor-ing random() with getNanoSecs(). What's worse: you are taking the least significant bits of the random number (&0xFF). These are usually less random than the most significant bits. – Frank Puffer Feb 15 '16 at 13:57
  • Maybe I was unclear, I would like to hear a technical objection to this method to generate an array of random number. It involves simple bitwise operations and it only reads nanosec from SO so it should be efficient and quite unpredictive. If you think it's not in this way please answer in a detailed way. – Whitefield Feb 15 '16 at 13:58
  • Xorig it's needed, let's say that each call to getNanoSecs() will generate maybe near or however increasing numbers, so it reduces the randomness, BUT xoring with a random value, whose first seed is getNanoSecs(), solves this problem. Thanx to Frank for the technical approach – Whitefield Feb 15 '16 at 14:00
  • @Revolver_Ocelot please put back c++ flag, this solution is suitable for C++ too – Whitefield Feb 15 '16 at 14:04
  • @Whitefield: your title and description contradict. Update your question. – Karoly Horvath Feb 15 '16 at 14:06
  • @MichaelWalz Thanx for the clear and precise explanation. – Whitefield Feb 15 '16 at 14:07
  • XOR ing with nano seconds is a sure way to break any cryptographic properties the underlying random generator might have. – Daniel Jour Feb 15 '16 at 14:08
  • @KarolyHorvath Can you be more explicit please ? I don't get in which sense you see a contradiction – Whitefield Feb 15 '16 at 14:09
  • it depends. If your PRNG is for some cryptographic code then no, it's a poor approach (very very likely). If this is for some game, not critical code then it could be fine. What about using rand() or mersenne twister or whatever pre-made? The fact is, independently on how much effort you put in it, it's gonna be a poor PRNG. That's why we have PRNGs out there ready to be used :-) – Gianluca Ghettini Feb 15 '16 at 14:11
  • @Whitefield: you specifically only mention C. – Karoly Horvath Feb 15 '16 at 14:11
  • @DanielJour really?! if you are able to tell me how I'll listen very carefully to your explanation – Whitefield Feb 15 '16 at 14:11
  • Possible duplicate of [How to generate a random number in C?](http://stackoverflow.com/questions/822323/how-to-generate-a-random-number-in-c) – too honest for this site Feb 15 '16 at 14:11
  • 1
    http://security.stackexchange.com/questions/79344/is-it-possible-to-make-a-more-secure-random-number-generator-algorithm-by-xoring – Karoly Horvath Feb 15 '16 at 14:16
  • @GianlucaGhettini Hi, My goal is to generate a random byte array, the thing which it is really not clear to me is, how is it possibile to predict the number of nano sec that have passed??? you should consider a lot of uncertanty (so shchedule of different process, interrupts and so on). While using only random() or rand() your randomness depends only on the seed I think this way is 'even more random' as there is noway to predict the value of getNanoSecs() exept for the fact that 2 near calls will probably produce two near values. But Xoring with random solves this problem for sure. – Whitefield Feb 15 '16 at 14:18
  • You say "for sure", but you're asking a lot of questions in response to others' comments, so I don't think you're so sure... – underscore_d Feb 15 '16 at 14:21
  • @Whitefield I see what you want to do. You could use /dev/rand which collects entropy from the machine behavior – Gianluca Ghettini Feb 15 '16 at 14:22
  • @Whitefield It's more than likely that the clock source doesn't have actual nanosecond precision and your multiplication in `srandom` will always multiply by 0 on some systems and you'll have the exact same seed all the time. If you want numbers that are actually unpredictable you need to use a proper cryptographic PRNG. (I'm using the word "unpredictable" because the word "random" in programming tends to mean "perfectly predictable and repeatable"). – Art Feb 15 '16 at 14:22
  • @Whitefield You don't need to collect entropy along the way. If you manage to capture a very strong seed at startup and if you use a good PRNG you are pretty much done. How to get a really strong seed? cat /dev/rand – Gianluca Ghettini Feb 15 '16 at 14:24
  • @KarolyHorvath thanks for the article, I'm reading it but the hypothesis are not matched in this case I think, I'm xoring them to solve a specific problem, not just to encrease the entropy. let me better explain, If I had to call just once getNanoSecs() it would be fine as random generator I think. But since I call it to generate a byte array, I need to call it more than once in a raw , there could be a problem. A simpler version could make use only of random & 0xFF seeded with getNanoSecs() – Whitefield Feb 15 '16 at 14:29
  • No, it's still totally unclear. What's the problem? What's wrong with just a plain `random()`? – Karoly Horvath Feb 15 '16 at 14:32
  • @GianlucaGhettini thanks for your advice, it may be of interest http://askubuntu.com/questions/192203/how-to-use-dev-urandom too – Whitefield Feb 15 '16 at 14:32
  • @KarolyHorvath I just didn't like the idea of having an entire byte sequence depending on a single initial seed. – Whitefield Feb 15 '16 at 14:34
  • @FrankPuffer I don't agree with what you said please check the result of unsigned long long int test = 1000000001; printf("test %llu\n", test & 0xFF); – Whitefield Feb 15 '16 at 15:05
  • @Whitefield your PRNG *should* depend only on a initial value! If the PRNG is strong you actually don't have to feed the PRNG itself along the way – Gianluca Ghettini Feb 15 '16 at 15:37
  • @Whitefield, I think your initial seed is the source of the problem here. An attacker who has a reasonable idea when you ran this will be able to find the correct seed quickly. https://www.cs.berkeley.edu/~daw/papers/ddj-netscape.html. I would suggest focusing on seeding the PRNG well, and then you can reseed with time + PRNG output occasionally if you like. Tinkering with the PRNG algorithm itself is very likely to weaken it. – tbroberg Feb 15 '16 at 19:18
  • @tbroberg Hi, the number of nanoseconds is not a unix timestamp with nano seconds, on the contrary it varies from 0 to 10^9-1 every second of the internal clock of the machine so I think that it should be very difficult for an attacker knowing exactly this value. – Whitefield Feb 16 '16 at 08:47
  • @whitefield Recommend that you don't take for granted that the clock is sampled every time you call. I added an answer below so I could provide the code. – tbroberg Feb 17 '16 at 20:37

2 Answers2

1

Be careful with your clock source, or you may get unexpected results:

#include <stdio.h>
#include <linux/time.h>

#define SAMPLES 10

long getNanoSecs(){
  struct timespec unixtimespec;
  clock_gettime(CLOCK_REALTIME_COARSE, &unixtimespec);
  return unixtimespec.tv_nsec;
}

int main (int argc, char* argv[]) {
  int i;
  long clocks[SAMPLES];

  for (i = 0; i < SAMPLES; i++)
    clocks[i] = getNanoSecs();
  for (i = 0; i < SAMPLES; i++)
    printf("%lu\n", getNanoSecs());

  return 0;
}

[tbroberg@www src]$ ./a.out 727544983 728544969 728544969 728544969 728544969 728544969 728544969 728544969 728544969 728544969

tbroberg
  • 635
  • 3
  • 11
0

you are definitely right, I wanted to add that I modified CLOCK_REALTIME_COARSE to CLOCK_REALTIME

as per linux man:

"CLOCK_REALTIME System-wide clock that measures real (i.e., wall-clock) time. Setting this clock requires appropriate privileges. This clock is affected by discontinuous jumps in the system time (e.g., if the system administrator manually changes the clock), and by the incremental adjustments performed by adjtime(3) and NTP.

CLOCK_REALTIME_COARSE (since Linux 2.6.32; Linux-specific) A faster but less precise version of CLOCK_REALTIME. Use when you need very fast, but not fine-grained timestamps."

However thank you for YOUR_TIME :)

Whitefield
  • 31
  • 6