#ifndef __ServerSigner_h_ #define __ServerSigner_h_ #include #include ///////////////////////////////////////////////////////////////////// // ServerSigner // // Given a number (or similar data) outputs a string. The string // contains the original value plus a signature. The string can be // fed back in to recover the original number. The recovery process // will verify the signature. This way you can hand data to a // client or user who is not trusted and get it back. No one can // fake a value. But you don't have to store a list of valid // values. // // This was inspired by HasNamedReference, but this is simpler. // The ti::get_current_channel command stores the socket id and the // response id in an object and wraps that in a named reference. // That's overkill. You could just put those two values into a // TCL list. The advantage of the named reference is that the // user can't make up his own values or easily guess at a valid // value. // // Limit alerts are similar to sockets. In both cases we have // a list of objects. We export an integer to other threads, // rather than an object. If the object is deleted, the integer // will match nothing, and the code will know that the object is // no longer valid. We use a 64 bit integer and we never reuse // a number (until we restart the server) so we're not worried // about someone trying to access a deleted object and getting // a different object instead. In both cases 0 is reserved and // and will never be assigned to any object. // // We use a secret, basically a random number, to sign the // messages. Each ServerSigner has a different secret, so if // you've got a signed copy of socket #1, that doesn't help you // access limit alert #1. We use different secrets each time // the program starts, which is important because the id numbers // typically restart at 1 each time we restart the program. ///////////////////////////////////////////////////////////////////// class ServerSigner { private: const std::string _secret; static std::string makeSecret(); static std::string hashHex(std::string const &input); std::string encodeString(std::string const &input) const; // On failure output will be "" and the return value will be false. bool decodeString(std::string const &encoded, std::string &output) const; public: ServerSigner(); std::string encodeInt(int64_t input) const; int64_t decodeInt(std::string const &encoded, int64_t onFail = 0) const; std::string encodeInts(std::vector< int64_t > const &input) const; // The input to this function should be the output from encodeInts(). // On success the output variable should contain exactly the inputs to // encodeInts() and the return value will be true. On failure output will // be empty and the return value will be false. We need a return value in // case the empty list is a valid value. bool decodeInts(std::string const &encoded, std::vector< int64_t > &output) const; }; #endif