-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Description
The current implementation of admin key auto-generation in apisix/core/id.lua uses math.random() to generate the key:
Lines 108 to 112 in 4990927
| admin_keys[i].key = "" | |
| for _ = 1, 32 do | |
| admin_keys[i].key = admin_keys[i].key .. | |
| string.char(math.random(65, 90) + math.random(0, 1) * 32) | |
| end |
This has two security concerns:
-
math.randomis a predictable PRNG
math.randomis not a cryptographically secure pseudo-random number generator (CSPRNG). It is seeded predictably, meaning an attacker with knowledge of the seed or timing information could reconstruct or predict the generated key. -
Limited character set reduces entropy
The generated key only uses A–Z and a–z (52 characters), giving approximately 5.7 bits of entropy per character.
Over 32 characters this yields ~182 bits of theoretical entropy, but the effective entropy is significantly lower due to the use of a predictable PRNG.
Suggested improvement:
Both lua-resty-random and lua-resty-string are already available in the APISIX codebase (used in apisix/patch.lua and various plugins). A more secure implementation could leverage these existing dependencies:
local resty_random = require("resty.random")
local resty_str = require("resty.string")
local key = resty_str.to_hex(resty_random.bytes(16)) -- 32 hex chars, 128 bits of true entropy resty.random.bytes() is backed by OpenSSL's RAND_bytes, making it a proper CSPRNG. Combined with hex encoding via resty.string.to_hex(), this produces a 32-character alphanumeric key with 128 bits of true entropy — a significant improvement over the current approach with no new dependencies required.
This issue was identified during the fix for #12170 . Since it is a separate concern, it is being tracked here independently.
Credits: inspired by @fekitibi from #12170 (comment)
Metadata
Metadata
Assignees
Labels
Type
Projects
Status