In PHP, is there any way to make a variable "stick" across multiple invocations of my script? Specifically, I need to compute hash_hmac('sha-256', $data, $key)
where data will probably be different on each invocation of my script, but key needs to remain the same for all invocations on a specific server (Apache2) instance. Actually what I need is that key is initialized to a pseudo-random value once per server (Apache2) instance. Please note that I do not want the key to be hard-coded or loaded from a config file. The key should be generated pseudo-randomly when the server (Apache2) instance is starting up, or when it is needed (read) for the first time. Also the key should "stick" in the memory for as long as the specific server instance running, but, as soon as the server instance is shutting down, it should be discarded with no way to re-construct it!
I would be fine if $_SERVER
contained any value that is "unique" per server instance, with very high probability, so that I could just take that seed and pump it through a KDF in order to derive my unique key. But it seems there is no such entry in $_SERVER
, or am I missing something?
Also, I can not use uniqid()
, because it will give a different unique value on each call (script invocation), not a value that is unique per server (Apache2) instance.
Furthermore, I think that I can not use Cookies or session_start()
(or $_SESSION
), because key is not supposed to be per-user, and it certainly must not be visible to the users!
I could probably use an "in-memory" DB with something like SQLite, but this really feels like taking a sledgehammer to crack a nut. This "problem" of requiring a variable (value) to be initialized once and then "stick" across multiple invocations of a script seems like something that would arise naturally in many applications! So is there no simple straight-forward solution for this? 🤔
2
Answers
Since a satisfying solution was not readily available, I spent the afternoon creating a simple PHP extension that does exactly what I need. Since it may be helpful for others, I'm posting it here.
It simply generates a unique ID, via
getrandom()
system call, in the module initialization function, converts it to a Base64 string and exposes it to the PHP user script as a constant viaREGISTER_STRING_CONSTANT()
. That is a straight-forward way to ensure that the ID is generated exactly once per server instance, when the server is starting up, and it is then kept in a static memory location. Also, accessing the ID as a constant is much simpler than any other approach!It can be used like this:
Source code:
https://bitbucket.org/php-uniqueid/php-instanceid/
I'm still a bit surprised that something like this doesn't exist in PHP already...
I am curious to know why you want to do this? What is the use case? You are asking for an approach that makes your application extremely tightly coupled to a specific setup on a specific web server on a specific platform or at least OS. for example, you can use your root Apache2 process ID:
To get a unique process ID that will be changed with each apache2 restart, but as mentioned, this is a thing that will make you stuck to a specific setup, the previous command will be invoked using exec. For example, the previous command will not work when you run your PHP & Apache2 behind docker, using a function like
posix_getppid()
may fix this issue, but the function is getting the parent ID, so it is not a thing for Apache2.On the other hand, relying on a random number/string as keys will make you lose the saved encrypted / hashed data.
Alternatively, you can go with something like saving the key in a tmp file, Database, or Session and use cronjob or scheduled task to reload your key periodically.