douzhang1364 2014-01-27 02:55 采纳率: 0%
浏览 490
已采纳

如何使用PHP生成强大的唯一API密钥?

I need to generate a strong unique API key.

Can anyone suggest the best solution for this? I don't want to use rand() function to generate random characters. Is there an alternative solution?

  • 写回答

5条回答

  • duanpasi6287 2014-01-28 05:20
    关注

    This is the best solution i found.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • duandu1915 2014-01-27 02:57
    关注

    You can try with uniqid function.

    uniqid — Generate a unique ID

    string uniqid ([ string $prefix = "" [, bool $more_entropy = false ]] )

    评论
  • doufan3958 2014-01-27 03:00
    关注

    PHP has uniqid function http://php.net/manual/en/function.uniqid.php with optional prefix and you can even add additional entropy to further avoid collision. But if you absolutely possitevily need something unique you should not use anything with randomness in it.

    评论
  • du7999 2014-01-27 03:12
    关注

    using mcrypt:

    <?php
    $bytes  = mcrypt_create_iv(4, MCRYPT_DEV_URANDOM);
    $unpack = unpack("Nint", $bytes);
    $id     = $unpack['int'] & 0x7FFFFFFF;
    
    评论
  • duanou1904 2017-09-13 13:46
    关注

    As of PHP 7.0, you can use the random_bytes($length) method to generate a cryptographically-secure random string. This string is going to be in binary, so you'll want to encode it somehow. A straightforward way of doing this is with bin2hex($binaryString). This will give you a string $length * 2 bytes long, with $length * 8 bits of entropy to it.

    You'll want $length to be high enough such that your key is effectively unguessable and that the chance of there being another key being generated with the same value is practically nil.

    Putting this all together, you get this:

    $key = bin2hex(random_bytes(32)); // 64 characters long
    

    When you verify the API key, use only the first 32 characters to select the record from the database and then use hash_equals() to compare the API key as given by the user against what value you have stored. This helps protect against timing attacks. ParagonIE has an excellent write-up on this.

    For an example of the checking logic:

    $token = $request->bearerToken();
    
    // Retrieve however works best for your situation,
    // but it's critical that only the first 32 characters are used here.
    $users = app('db')->table('users')->where('api_key', 'LIKE', substr($token, 0, 32) . '%')->get();
    
    // $users should only have one record in it,
    // but there is an extremely low chance that
    // another record will share a prefix with it.
    foreach ($users as $user) {
        // Performs a constant-time comparison of strings,
        // so you don't leak information about the token.
        if (hash_equals($user->api_token, $token)) {
            return $user;
        }
    }
    
    return null;
    

    Bonus: Slightly More Advanced Use With Base64 Encoding

    Using Base64 encoding is preferable to hexadecimal for space reasons, but is slightly more complicated because each character encodes 6 bits (instead of 4 for hexadecimal), which can leave the encoded value with padding at the end.

    To keep this answer from dragging on, I'll just put some suggestions for handling Base64 without their supporting arguments. Pick a $length greater than 32 that is divisible by both 3 and 2. I like 42, so we'll use that for $length. Base64 encodings are of length 4 * ceil($length / 3), so our $key will be 56 characters long. You can use the first 28 characters for selection from your storage, leaving another 28 characters on the end that are protected from leaking by timing attacks with hash_equals.

    Bonus 2: Secure Key Storage

    Ideally, you should be treating the key much like a password. This means that instead of using hash_equals to compare the full string, you should hash the remainder of the key like a password, store that separately than the first half of your key (which is in plain-text), use the first half for selection from your database and verify the latter half with password_verify.

    展开全部

    评论
收起4条回答
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部