[RFC] Make uniqid() more unique

php.internals

Yasuo Ohgaki

9 years ago
Hi all, We all know, uniqid() is not unique at all and not safe as random ID at all. This would be one of the most misused function because of its name. https://github.com/php/php-src/blob/master/ext/standard/uniqid.c#L44 Bug report for this https://bugs.php.net/bug.php?id=55391 I would like to - Enable more entropy parameter on by default - Add 256 bits random value (64 chars by HEX) from php_random_bytes() instead of 1 char from php_combined_lcg() If all of us think "just fix it", then I'll just fix this in master w/o RFC. Any comments? Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Niklas Keller

9 years ago
2016-09-09 7:12 GMT+02:00 Yasuo Ohgaki <yohgaki@ohgaki.net>:
> Hi all, > > We all know, uniqid() is not unique at all and not safe as random ID > at all. This would be one of the most misused function because of its > name. > > https://github.com/php/php-src/blob/master/ext/standard/uniqid.c#L44 > > Bug report for this > https://bugs.php.net/bug.php?id=55391 > > I would like to > - Enable more entropy parameter on by default > - Add 256 bits random value (64 chars by HEX) from > php_random_bytes() instead of 1 char from php_combined_lcg() > > If all of us think "just fix it", then I'll just fix this in master w/o > RFC.
I think it's better to leave it as is and deprecate and discourage its use. There's already a big warning there. Dunno whether there are really valid use cases for it. Regards, Niklas

Yasuo Ohgaki

9 years ago
Hi Niklas, On Fri, Sep 9, 2016 at 4:40 PM, Niklas Keller <me@kelunik.com> wrote:
> 2016-09-09 7:12 GMT+02:00 Yasuo Ohgaki <yohgaki@ohgaki.net>: >> >> Hi all, >> >> We all know, uniqid() is not unique at all and not safe as random ID >> at all. This would be one of the most misused function because of its >> name. >> >> https://github.com/php/php-src/blob/master/ext/standard/uniqid.c#L44 >> >> Bug report for this >> https://bugs.php.net/bug.php?id=55391 >> >> I would like to >> - Enable more entropy parameter on by default >> - Add 256 bits random value (64 chars by HEX) from >> php_random_bytes() instead of 1 char from php_combined_lcg() >> >> If all of us think "just fix it", then I'll just fix this in master w/o >> RFC. > > > I think it's better to leave it as is and deprecate and discourage its use. > There's already a big warning there. Dunno whether there are really valid > use cases for it.
That's what I thought at first. It seems misuse is still common... https://searchcode.com/?q=uniqid&loc=0&loc2=10000&lan=24 64 chars hex value might be too long, though. Another option might be raising E_DEPRECATED, but chances are low that misused people correct usage by the error... It's their responsibility anyway, though. Just trying to be nice for our users :) Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Yasuo Ohgaki

9 years ago
On Fri, Sep 9, 2016 at 4:40 PM, Niklas Keller <me@kelunik.com> wrote:
> I think it's better to leave it as is and deprecate and discourage its use. > There's already a big warning there. Dunno whether there are really valid > use cases for it.
uniqid() is handy, when developer would like to sort something by "time" prefix/postfix in strings. For example, prefixed/postfixed session ID by "time". So E_DEPRECATE might be too much. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Arvids Godjuks

9 years ago
2016-09-09 11:07 GMT+03:00 Yasuo Ohgaki <yohgaki@ohgaki.net>:
> On Fri, Sep 9, 2016 at 4:40 PM, Niklas Keller <me@kelunik.com> wrote: > > I think it's better to leave it as is and deprecate and discourage its > use. > > There's already a big warning there. Dunno whether there are really valid > > use cases for it. > > uniqid() is handy, when developer would like to sort something by > "time" prefix/postfix in strings. For example, prefixed/postfixed > session ID by "time". > > So E_DEPRECATE might be too much. > > Regards, > > -- > Yasuo Ohgaki > yohgaki@ohgaki.net >
It's also useful in other cases, where using a full blown true random source is just overkill. For example, my recent usage was to use the result of uniqid('', true) as a few parameters in URL's instead of plain numeric ID. Client just wanted to users can't do a +1 and see someone else's result page that might have a different text or a different campaign even. And I do need to generate those id's in bursts - 200 to 600 id's in a single action, I would imagine generating 600 random strings of ~20 char length can be hard on the source of the randomness, may even deplete it. And I expect the numbers to grow. So, deprecating it I think is really an overreaction. It's a handy tool. It can be used to generate filenames too, and a lot of other stuff. My thoughts are - improve it. Yes, the standard uniqid() is a bit too short, I have never used it without the second "true" parameter and that dot in the middle of the string is annoying - I had to strip it out every use case I had. Arvids.

Niklas Keller

9 years ago
2016-09-09 10:36 GMT+02:00 Arvids Godjuks <arvids.godjuks@gmail.com>:
> 2016-09-09 11:07 GMT+03:00 Yasuo Ohgaki <yohgaki@ohgaki.net>: > >> On Fri, Sep 9, 2016 at 4:40 PM, Niklas Keller <me@kelunik.com> wrote: >> > I think it's better to leave it as is and deprecate and discourage its >> use. >> > There's already a big warning there. Dunno whether there are really >> valid >> > use cases for it. >> >> uniqid() is handy, when developer would like to sort something by >> "time" prefix/postfix in strings. For example, prefixed/postfixed >> session ID by "time". >> >> So E_DEPRECATE might be too much. >> >> Regards, >> >> -- >> Yasuo Ohgaki >> yohgaki@ohgaki.net >> > > It's also useful in other cases, where using a full blown true random > source is just overkill. >
Most people think getting true random is a overkill and implement things non-secure.
> For example, my recent usage was to use the result of uniqid('', true) as > a few parameters in URL's instead of plain numeric ID. Client just wanted > to users can't do a +1 and see someone else's result page that might have a > different text or a different campaign even. >
That's exactly where uniqid SHOULD NOT be used. It's predictable. Anyone can easily guess these URLs. If you want to prevent that, you should use non-predictable secure random, also called cryptographically secure random: CSRPNG. See random_bytes and random_int.
> And I do need to generate those id's in bursts - 200 to 600 id's in a > single action, I would imagine generating 600 random strings of ~20 char > length can be hard on the source of the randomness, may even deplete it. > And I expect the numbers to grow. >
Could you outline why you need 200 - 600 IDs in a single action?
> So, deprecating it I think is really an overreaction. It's a handy tool. > It can be used to generate filenames too, and a lot of other stuff. >
Sure, but for that you can as well just use `microtime` or `time`. As shown, it's easily misused, you're the perfect example. :-)
> My thoughts are - improve it. Yes, the standard uniqid() is a bit too > short, I have never used it without the second "true" parameter and that > dot in the middle of the string is annoying - I had to strip it out every > use case I had. >
`true` gives you exactly one character of more, pretty low entropy. Regards, Niklas

Arvids Godjuks

9 years ago
2016-09-09 13:37 GMT+03:00 Niklas Keller <me@kelunik.com>:
> 2016-09-09 10:36 GMT+02:00 Arvids Godjuks <arvids.godjuks@gmail.com>: > >> 2016-09-09 11:07 GMT+03:00 Yasuo Ohgaki <yohgaki@ohgaki.net>: >> >>> On Fri, Sep 9, 2016 at 4:40 PM, Niklas Keller <me@kelunik.com> wrote: >>> > I think it's better to leave it as is and deprecate and discourage its >>> use. >>> > There's already a big warning there. Dunno whether there are really >>> valid >>> > use cases for it. >>> >>> uniqid() is handy, when developer would like to sort something by >>> "time" prefix/postfix in strings. For example, prefixed/postfixed >>> session ID by "time". >>> >>> So E_DEPRECATE might be too much. >>> >>> Regards, >>> >>> -- >>> Yasuo Ohgaki >>> yohgaki@ohgaki.net >>> >> >> It's also useful in other cases, where using a full blown true random >> source is just overkill. >> > > Most people think getting true random is a overkill and implement things > non-secure. >
I just don't need true random here, just some form of replacing an integer ID with a value, that cannot be changed just by "+1"
> > >> For example, my recent usage was to use the result of uniqid('', true) as >> a few parameters in URL's instead of plain numeric ID. Client just wanted >> to users can't do a +1 and see someone else's result page that might have a >> different text or a different campaign even. >> > > That's exactly where uniqid SHOULD NOT be used. It's predictable. Anyone > can easily guess these URLs. If you want to prevent that, you should use > non-predictable secure random, also called cryptographically secure random: > CSRPNG. See random_bytes and random_int. >
The way the system works and that this is a semi-closed tool for business purposes, the only real thing why we need these ID's is to track people. Before this plain numeric ID's from the DB records were used. With the rewrite the client asked to make ID's so you can't just do a +1 and see something different. No one will ever want to try and break the uniqid algo just to get the other page (probably the same text). I also use the extended version of the uniqid.
> > >> And I do need to generate those id's in bursts - 200 to 600 id's in a >> single action, I would imagine generating 600 random strings of ~20 char >> length can be hard on the source of the randomness, may even deplete it. >> And I expect the numbers to grow. >> > > Could you outline why you need 200 - 600 IDs in a single action? >
Because it's a CSV import and I need to assign every record an ID at that moment. Those ID's are then exported by admins to a 3rd party system.
> > >> So, deprecating it I think is really an overreaction. It's a handy tool. >> It can be used to generate filenames too, and a lot of other stuff. >> > > Sure, but for that you can as well just use `microtime` or `time`. As > shown, it's easily misused, you're the perfect example. :-) >
microtime and time are easier to guess. And time() is not an option, because I will get 600 equal ID's then. Microtime is an option, but then you get number only string and it looks awfully sequential :) Hence the uniqid usage, that is basically time + microtime if I understand from the manual, but it generates a bit more random result and I'm sure I get a unique value on every call. Improving it so it does not look awfully sequential would suffice for the use cases it is needed. In my case this was a clearly conscious choice with full understanding how it works. My thoughts are - improve it. Yes, the standard uniqid() is a bit too
>> short, I have never used it without the second "true" parameter and that >> dot in the middle of the string is annoying - I had to strip it out every >> use case I had. >> > > `true` gives you exactly one character of more, pretty low entropy. > > Regards, Niklas >
Hm, without "true" you get 13 chars, with "true" - 20+. Arvids.

Yasuo Ohgaki

9 years ago
Hi all, On Fri, Sep 9, 2016 at 8:18 PM, Arvids Godjuks <arvids.godjuks@gmail.com> wrote:
> > Hm, without "true" you get 13 chars, with "true" - 20+.
Sorry. It's $ php -r 'var_dump(uniqid(), uniqid("", true));' string(13) "57d29c20c04c3" string(23) "57d29c20c04c50.55225401" I misread sprintf format. Anyway, we may use extra 10 chars to make it more random if it should keep compatibility. It seems uniqid() is popular for test scripts, so it would be preferred keeping it. It does not harm any with test script thanks to higher precision timers of current systems. Some of us feel returning almost random value from uniqid() is overkill. This is reasonable. I'll prepare patch that uses 10 chars for 50 bits extra entropy from php_random_bytes() by default. It will be a little safer even when user misuses uniqid() while keeping most compatibility. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Niklas Keller

9 years ago
2016-09-09 13:48 GMT+02:00 Yasuo Ohgaki <yohgaki@ohgaki.net>:
> Hi all, > > On Fri, Sep 9, 2016 at 8:18 PM, Arvids Godjuks <arvids.godjuks@gmail.com> > wrote: > > > > Hm, without "true" you get 13 chars, with "true" - 20+. > > Sorry. It's > > $ php -r 'var_dump(uniqid(), uniqid("", true));' > string(13) "57d29c20c04c3" > string(23) "57d29c20c04c50.55225401" > > I misread sprintf format. > > Anyway, we may use extra 10 chars to make it more random if it should > keep compatibility.
That still breaks BC as the value is now longer than before.
> It seems uniqid() is popular for test scripts, so > it would be preferred keeping it.
Nobody said it should be removed now. Maybe in the future. But you might as well just use bin2hex(random_bytes(16)).
> It does not harm any with test > script thanks to higher precision timers of current systems. >
It's most often still abused for the wrong purpose.
> Some of us feel returning almost random value from uniqid() is > overkill.
It breaks BC, overkill isn't the issue.
> This is reasonable. I'll prepare patch that uses 10 chars > for 50 bits extra entropy from php_random_bytes() by default.
No please don't. Let's just deprecate it. Let's not break BC and make it kinda safe but not really.

Pierre Joye

9 years ago
Hi, On Sep 9, 2016 7:50 PM, "Niklas Keller" <me@kelunik.com> wrote:
> > 2016-09-09 13:48 GMT+02:00 Yasuo Ohgaki <yohgaki@ohgaki.net>: > > > Hi all, > > > > On Fri, Sep 9, 2016 at 8:18 PM, Arvids Godjuks <arvids.godjuks@gmail.com > > > wrote: > > > > > > Hm, without "true" you get 13 chars, with "true" - 20+. > > > > Sorry. It's > > > > $ php -r 'var_dump(uniqid(), uniqid("", true));' > > string(13) "57d29c20c04c3" > > string(23) "57d29c20c04c50.55225401" > > > > I misread sprintf format. > > > > Anyway, we may use extra 10 chars to make it more random if it should > > keep compatibility. > > > That still breaks BC as the value is now longer than before. > > > > It seems uniqid() is popular for test scripts, so > > it would be preferred keeping it. > > > Nobody said it should be removed now. Maybe in the future. But you might
as
> well just use bin2hex(random_bytes(16)).
Or uuid. This why this standard exists. I would recommend to move to that instead of trying to reinvent the wheel. https://github.com/ramsey/uuid is pretty good. Cheers Pierre

Lester Caine

9 years ago
On 10/09/16 04:35, Pierre Joye wrote:
> Or uuid. This why this standard exists. I would recommend to move to that > instead of trying to reinvent the wheel.
Which is what is provided by most databases and tailored to index efficiently and rather than 'more entropy' they simply add machine unique element for ensuring unique id's across the whole system.
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Tom Worster

9 years ago
On 9/9/16 7:48 AM, Yasuo Ohgaki wrote:
> Some of us feel returning almost random value from uniqid() is > overkill. This is reasonable.
How would it be overkill if uniqid() used, say, php_random_bytes()? Tom

Niklas Keller

9 years ago
2016-09-09 13:18 GMT+02:00 Arvids Godjuks <arvids.godjuks@gmail.com>:
> > > 2016-09-09 13:37 GMT+03:00 Niklas Keller <me@kelunik.com>: > >> 2016-09-09 10:36 GMT+02:00 Arvids Godjuks <arvids.godjuks@gmail.com>: >> >>> 2016-09-09 11:07 GMT+03:00 Yasuo Ohgaki <yohgaki@ohgaki.net>: >>> >>>> On Fri, Sep 9, 2016 at 4:40 PM, Niklas Keller <me@kelunik.com> wrote: >>>> > I think it's better to leave it as is and deprecate and discourage >>>> its use. >>>> > There's already a big warning there. Dunno whether there are really >>>> valid >>>> > use cases for it. >>>> >>>> uniqid() is handy, when developer would like to sort something by >>>> "time" prefix/postfix in strings. For example, prefixed/postfixed >>>> session ID by "time". >>>> >>>> So E_DEPRECATE might be too much. >>>> >>>> Regards, >>>> >>>> -- >>>> Yasuo Ohgaki >>>> yohgaki@ohgaki.net >>>> >>> >>> It's also useful in other cases, where using a full blown true random >>> source is just overkill. >>> >> >> Most people think getting true random is a overkill and implement things >> non-secure. >> > > I just don't need true random here, just some form of replacing an integer > ID with a value, that cannot be changed just by "+1" >
If you know the time something was created you can still easily retrieve it. It's not "+1" anymore, but only slightly better.
> >> >>> For example, my recent usage was to use the result of uniqid('', true) >>> as a few parameters in URL's instead of plain numeric ID. Client just >>> wanted to users can't do a +1 and see someone else's result page that might >>> have a different text or a different campaign even. >>> >> >> That's exactly where uniqid SHOULD NOT be used. It's predictable. Anyone >> can easily guess these URLs. If you want to prevent that, you should use >> non-predictable secure random, also called cryptographically secure random: >> CSRPNG. See random_bytes and random_int. >> > > The way the system works and that this is a semi-closed tool for business > purposes, the only real thing why we need these ID's is to track people. > Before this plain numeric ID's from the DB records were used. With the > rewrite the client asked to make ID's so you can't just do a +1 and see > something different. No one will ever want to try and break the uniqid algo > just to get the other page (probably the same text). I also use the > extended version of the uniqid. >
uniqid() is just the current time. It's enough to be about unique in some scenarios, but it's never unpredictable. If you want people not being able to guess these URLs (by adding +1 or whatever), you need unpredictable random. uniqid() doesn't fit here. uniqid("", true) doesn't fit either, as it's just adding more time resolution and ONLY ONE SINGLE CHAR of random data, which may be predictable, too, dunno what the generator here really does.
> And I do need to generate those id's in bursts - 200 to 600 id's in a >>> single action, I would imagine generating 600 random strings of ~20 char >>> length can be hard on the source of the randomness, may even deplete it. >>> And I expect the numbers to grow. >>> >> >> Could you outline why you need 200 - 600 IDs in a single action? >> > > Because it's a CSV import and I need to assign every record an ID at that > moment. Those ID's are then exported by admins to a 3rd party system. > >> >> >>> So, deprecating it I think is really an overreaction. It's a handy tool. >>> It can be used to generate filenames too, and a lot of other stuff. >>> >> >> Sure, but for that you can as well just use `microtime` or `time`. As >> shown, it's easily misused, you're the perfect example. :-) >> > > microtime and time are easier to guess. And time() is not an option, > because I will get 600 equal ID's then. Microtime is an option, but then > you get number only string and it looks awfully sequential :) Hence the > uniqid usage, that is basically time + microtime if I understand from the > manual, but it generates a bit more random result and I'm sure I get a > unique value on every call. Improving it so it does not look awfully > sequential would suffice for the use cases it is needed. In my case this > was a clearly conscious choice with full understanding how it works. > > My thoughts are - improve it. Yes, the standard uniqid() is a bit too >>> short, I have never used it without the second "true" parameter and that >>> dot in the middle of the string is annoying - I had to strip it out every >>> use case I had. >>> >> >> `true` gives you exactly one character of more, pretty low entropy. >> >> Regards, Niklas >> > > Hm, without "true" you get 13 chars, with "true" - 20+. >
You get more chars, it's still predictable. Regards, Niklas

Arvids Godjuks

9 years ago
2016-09-09 15:46 GMT+03:00 Niklas Keller <me@kelunik.com>:
> 2016-09-09 13:18 GMT+02:00 Arvids Godjuks <arvids.godjuks@gmail.com>: > >> >> >> 2016-09-09 13:37 GMT+03:00 Niklas Keller <me@kelunik.com>: >> >>> 2016-09-09 10:36 GMT+02:00 Arvids Godjuks <arvids.godjuks@gmail.com>: >>> >>>> 2016-09-09 11:07 GMT+03:00 Yasuo Ohgaki <yohgaki@ohgaki.net>: >>>> >>>>> On Fri, Sep 9, 2016 at 4:40 PM, Niklas Keller <me@kelunik.com> wrote: >>>>> > I think it's better to leave it as is and deprecate and discourage >>>>> its use. >>>>> > There's already a big warning there. Dunno whether there are really >>>>> valid >>>>> > use cases for it. >>>>> >>>>> uniqid() is handy, when developer would like to sort something by >>>>> "time" prefix/postfix in strings. For example, prefixed/postfixed >>>>> session ID by "time". >>>>> >>>>> So E_DEPRECATE might be too much. >>>>> >>>>> Regards, >>>>> >>>>> -- >>>>> Yasuo Ohgaki >>>>> yohgaki@ohgaki.net >>>>> >>>> >>>> It's also useful in other cases, where using a full blown true random >>>> source is just overkill. >>>> >>> >>> Most people think getting true random is a overkill and implement things >>> non-secure. >>> >> >> I just don't need true random here, just some form of replacing an >> integer ID with a value, that cannot be changed just by "+1" >> > > If you know the time something was created you can still easily retrieve > it. It's not "+1" anymore, but only slightly better. > > >> >>> >>>> For example, my recent usage was to use the result of uniqid('', true) >>>> as a few parameters in URL's instead of plain numeric ID. Client just >>>> wanted to users can't do a +1 and see someone else's result page that might >>>> have a different text or a different campaign even. >>>> >>> >>> That's exactly where uniqid SHOULD NOT be used. It's predictable. Anyone >>> can easily guess these URLs. If you want to prevent that, you should use >>> non-predictable secure random, also called cryptographically secure random: >>> CSRPNG. See random_bytes and random_int. >>> >> >> The way the system works and that this is a semi-closed tool for business >> purposes, the only real thing why we need these ID's is to track people. >> Before this plain numeric ID's from the DB records were used. With the >> rewrite the client asked to make ID's so you can't just do a +1 and see >> something different. No one will ever want to try and break the uniqid algo >> just to get the other page (probably the same text). I also use the >> extended version of the uniqid. >> > > uniqid() is just the current time. It's enough to be about unique in some > scenarios, but it's never unpredictable. If you want people not being able > to guess these URLs (by adding +1 or whatever), you need unpredictable > random. uniqid() doesn't fit here. uniqid("", true) doesn't fit either, as > it's just adding more time resolution and ONLY ONE SINGLE CHAR of random > data, which may be predictable, too, dunno what the generator here really > does. >
No, I actually don't need unpredictable random :) Nor it is required for the task, nor it was an issue before with straight id's from the DB that are sequential. It just was a request, if I can replace id's with a string that you just can't do a +1 and see something. Second - this is not a security feature, it is not intended to hide stuff from people. There are other mechanics involved that make sure that just by changing the uniqid to a different and existing value will not yield a page. What I needed is a fast way to generate 600 semi-random strings in one go. I'm not an expert on cryptography, but I do know that exhausting a random source is a real issue, and the scope of the project did not involve nor time, nor the payment to deal with such complex issues and making sure that does not happen. More over, the sequential nature of the uniqid for me was a +, because I do not have to check if there already is such a value. So, from my personal perspective, it was a right tool for the job. The only thing I would like, is that it would make a visually more random string. That's all.
> > >> And I do need to generate those id's in bursts - 200 to 600 id's in a >>>> single action, I would imagine generating 600 random strings of ~20 char >>>> length can be hard on the source of the randomness, may even deplete it. >>>> And I expect the numbers to grow. >>>> >>> >>> Could you outline why you need 200 - 600 IDs in a single action? >>> >> >> Because it's a CSV import and I need to assign every record an ID at that >> moment. Those ID's are then exported by admins to a 3rd party system. >> >>> >>> >>>> So, deprecating it I think is really an overreaction. It's a handy >>>> tool. It can be used to generate filenames too, and a lot of other stuff. >>>> >>> >>> Sure, but for that you can as well just use `microtime` or `time`. As >>> shown, it's easily misused, you're the perfect example. :-) >>> >> >> microtime and time are easier to guess. And time() is not an option, >> because I will get 600 equal ID's then. Microtime is an option, but then >> you get number only string and it looks awfully sequential :) Hence the >> uniqid usage, that is basically time + microtime if I understand from the >> manual, but it generates a bit more random result and I'm sure I get a >> unique value on every call. Improving it so it does not look awfully >> sequential would suffice for the use cases it is needed. In my case this >> was a clearly conscious choice with full understanding how it works. >> >> My thoughts are - improve it. Yes, the standard uniqid() is a bit too >>>> short, I have never used it without the second "true" parameter and that >>>> dot in the middle of the string is annoying - I had to strip it out every >>>> use case I had. >>>> >>> >>> `true` gives you exactly one character of more, pretty low entropy. >>> >>> Regards, Niklas >>> >> >> Hm, without "true" you get 13 chars, with "true" - 20+. >> > > You get more chars, it's still predictable. > > Regards, Niklas >
And there is nothing wrong with predictable in this situation.

Tom Worster

9 years ago
On 9/9/16 7:18 AM, Arvids Godjuks wrote:
> 2016-09-09 13:37 GMT+03:00 Niklas Keller <me@kelunik.com>: > >> Most people think getting true random is a overkill and implement things >> non-secure.
Most? Idk. But there certainly are many programmers that still believe the **myth** that one should be conservative of the randoms. It's nonsense. And uniqid() should either step aside or be properly random.
> I just don't need true random here, just some form of replacing an integer > ID with a value, that cannot be changed just by "+1"
You can't have a "true" random -- at best you can have the kind of pseudo-randomness the CSPRNG provides, which, btw, is ideal for this purpose. Another way of doing this is encrypt your predictable IDs. But this is rather similar to using random IDs since the CSPRNG is using the key stream of a symmetric encryption cipher.
>> That's exactly where uniqid SHOULD NOT be used. It's predictable. Anyone >> can easily guess these URLs. If you want to prevent that, you should use >> non-predictable secure random, also called cryptographically secure random: >> CSRPNG. See random_bytes and random_int.
I agree with Niklas.
> The way the system works and that this is a semi-closed tool for business > purposes, the only real thing why we need these ID's is to track people. > Before this plain numeric ID's from the DB records were used. With the > rewrite the client asked to make ID's so you can't just do a +1 and see > something different. No one will ever want to try and break the uniqid algo > just to get the other page (probably the same text). I also use the > extended version of the uniqid.
Sounds like old-fashioned "security through obscurity", where the level of obscurity is somewhere between using strong crypto and trivially predictable. I don't think PHP should encourage it. There is no reason for it. If you want unpredictability, there is no reason to hesitate to use random_bytes() or random_int() as much as needed. You won't break anything.
>> Could you outline why you need 200 - 600 IDs in a single action? >> > > Because it's a CSV import and I need to assign every record an ID at that > moment. Those ID's are then exported by admins to a 3rd party system.
Go ahead and read 64 KiB from random_bytes() if that's what you need. It's safe and not worth your time to worry about it.
>> Sure, but for that you can as well just use `microtime` or `time`. As >> shown, it's easily misused, you're the perfect example. :-) >> > > microtime and time are easier to guess. And time() is not an option, > because I will get 600 equal ID's then. Microtime is an option, but then > you get number only string and it looks awfully sequential :) Hence the > uniqid usage, that is basically time + microtime if I understand from the > manual, but it generates a bit more random result and I'm sure I get a > unique value on every call. Improving it so it does not look awfully > sequential would suffice for the use cases it is needed. In my case this > was a clearly conscious choice with full understanding how it works.
You are free to devise your own algorithm for generating "somewhat unpredictable" identifiers. But PHP should not should not be involved. I think we should either deprecate uniqid() or make it use php_random_bytes() and ignore its second parameter. Tom

Tom Worster

9 years ago
On 9/9/16 4:36 AM, Arvids Godjuks wrote:
> It's also useful in other cases, where using a full blown true random > source is just overkill.
Users should not hesitate to use random_bytes() or php_random_bytes() or any of the functions that use them.
> For example, my recent usage was to use the result of uniqid('', true) as a > few parameters in URL's instead of plain numeric ID. Client just wanted to > users can't do a +1 and see someone else's result page that might have a > different text or a different campaign even. And I do need to generate > those id's in bursts - 200 to 600 id's in a single action, I would imagine > generating 600 random strings of ~20 char length can be hard on the source > of the randomness, may even deplete it.
It is not possible to deplete this source of randomness.

Lester Caine

9 years ago
On 09/09/16 06:12, Yasuo Ohgaki wrote:
> I would like to > - Enable more entropy parameter on by default > - Add 256 bits random value (64 chars by HEX) from > php_random_bytes() instead of 1 char from php_combined_lcg() > > If all of us think "just fix it", then I'll just fix this in master w/o RFC.
The problem with 'fixing it' is perhaps what are all the requirements. Certainly I use a version supplied with Firebird which as been 'fixed' so that indexing produces a much more even spread across the search tree. I will not pretend to understand all the details, but the results are demonstrable. I presume similar methods are used by the other database engines, so would it be worth seeing if there is some common 'fix' which gives good results across a few databases.
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Nikita Popov

9 years ago
On Fri, Sep 9, 2016 at 7:12 AM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> Hi all, > > We all know, uniqid() is not unique at all and not safe as random ID > at all. This would be one of the most misused function because of its > name. > > https://github.com/php/php-src/blob/master/ext/standard/uniqid.c#L44 > > Bug report for this > https://bugs.php.net/bug.php?id=55391 > > I would like to > - Enable more entropy parameter on by default > - Add 256 bits random value (64 chars by HEX) from > php_random_bytes() instead of 1 char from php_combined_lcg() > > If all of us think "just fix it", then I'll just fix this in master w/o > RFC. > > Any comments? >
The problem with "fixing" this function to be cryptographically unpredictable (rather than just unique, for a limited definition of unique) is that it will necessarily change the size of the output, on which there may be assumptions. A 128 bit random value is 22 chars in base64, which is a good bit larger than the current uniqid() output. I agree with Niklas, this function should simply be deprecated. Nikita

Tom Worster

9 years ago
On 9/9/16 6:12 AM, Nikita Popov wrote:
> > The problem with "fixing" this function to be cryptographically > unpredictable (rather than just unique, for a limited definition of unique) > is that it will necessarily change the size of the output, on which there > may be assumptions. A 128 bit random value is 22 chars in base64, which is > a good bit larger than the current uniqid() output. > > I agree with Niklas, this function should simply be deprecated.
It is already in the sin bin, with that warning that steers users to safer options, so it makes more sense to deprecate than to reform. Tom

Yasuo Ohgaki

9 years ago
Hi all, On Fri, Sep 9, 2016 at 2:12 PM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> We all know, uniqid() is not unique at all and not safe as random ID > at all. This would be one of the most misused function because of its > name. > > https://github.com/php/php-src/blob/master/ext/standard/uniqid.c#L44 > > Bug report for this > https://bugs.php.net/bug.php?id=55391 > > I would like to > - Enable more entropy parameter on by default > - Add 256 bits random value (64 chars by HEX) from > php_random_bytes() instead of 1 char from php_combined_lcg() > > If all of us think "just fix it", then I'll just fix this in master w/o RFC. > > Any comments?
It seems we need RFC. I'll correct opinions and make them vote options. If you have thought about uniqid(), please let me know. Thank you.
-- Yasuo Ohgaki yohgaki@ohgaki.net

Christoph Becker

9 years ago
On 09.09.2016 at 07:12, Yasuo Ohgaki wrote:
> We all know, uniqid() is not unique at all and not safe as random ID > at all. This would be one of the most misused function because of its > name.
uniqid() yields truly unique values for a single machine (except for CYGWIN, and potentially older Windows versions), if $more_entropy is FALSE[1]. Of course, the function shouldn't be used for any crypto purposes, but it is fine to get a unique ID if you have no database that delivers a sequential index number (aka. autoincrement field), for instance. [1] <https://github.com/php/php-src/blob/PHP-7.0.11/ext/standard/uniqid.c#L68>
-- Christoph M. Becker

Yasuo Ohgaki

9 years ago
Hi Christoph, On Fri, Sep 9, 2016 at 10:56 PM, Christoph M. Becker <cmbecker69@gmx.de> wrote:
>> We all know, uniqid() is not unique at all and not safe as random ID >> at all. This would be one of the most misused function because of its >> name. > > uniqid() yields truly unique values for a single machine (except for > CYGWIN, and potentially older Windows versions), if $more_entropy is > FALSE[1]. Of course, the function shouldn't be used for any crypto > purposes, but it is fine to get a unique ID if you have no database that > delivers a sequential index number (aka. autoincrement field), for instance. > > [1] > <https://github.com/php/php-src/blob/PHP-7.0.11/ext/standard/uniqid.c#L68>
I think uniqid() is intended for mail message ID originally. User's shouldn't use crypto purpose anyway. Although user shouldn't use it for security related usage, improving more entropy is reasonable since we have better entropy source now. i.e. php_random_bytes() I'm going to write patch enable more entropy by default and change more more entropy source from php_combined_lcg() to php_randam_bytes(). This will improve windows compatibility :) Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Yasuo Ohgaki

9 years ago
Hi all, On Sat, Sep 10, 2016 at 5:49 AM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> On Fri, Sep 9, 2016 at 10:56 PM, Christoph M. Becker <cmbecker69@gmx.de> wrote: >>> We all know, uniqid() is not unique at all and not safe as random ID >>> at all. This would be one of the most misused function because of its >>> name. >> >> uniqid() yields truly unique values for a single machine (except for >> CYGWIN, and potentially older Windows versions), if $more_entropy is >> FALSE[1]. Of course, the function shouldn't be used for any crypto >> purposes, but it is fine to get a unique ID if you have no database that >> delivers a sequential index number (aka. autoincrement field), for instance. >> >> [1] >> <https://github.com/php/php-src/blob/PHP-7.0.11/ext/standard/uniqid.c#L68> > > I think uniqid() is intended for mail message ID originally. > User's shouldn't use crypto purpose anyway. > > Although user shouldn't use it for security related usage, improving > more entropy is reasonable since we have better entropy source > now. i.e. php_random_bytes() > > I'm going to write patch enable more entropy by default and change > more more entropy source from php_combined_lcg() to > php_randam_bytes(). This will improve windows compatibility :)
PR is sent. https://github.com/php/php-src/pull/2123 Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net