If we want to provide more security to the consumer for authenticating their product and by using QR code scans, what techniques we can used for making that QR code copy proof and non-duplicate?
You need to consider the digital image of the QR Code before printing. You can add a secure graphic or copy detection pattern (see https://en.wikipedia.org/wiki/Secure_graphic) into the QR Code (pay attention to the error-correction level of the QR Code versus the space you use). Once printed, the secure graphic will irreversibly loose information, and if someone tries to make a copy of it, there will be an additional information loss. As the secure graphic will a lower amount of information in the copy than in an original print, you can use that that to discriminate originals from counterfeits. An app is needed to analyse the image of the secure graphic in real-time when you scan the QR Code. See example of this is done with Scantrust, and there is a developer portal to support you in integrating in your app.
Note that there are other techniques based on digital watermarking, but they are easier to hack given that digital watermarks need to respect an imperceptibility constraint and the usable signal is much weaker.
Short answer: Think of a QR code as a compressed block of plain text. You can sign it for non purposes of authenticity and non-repudiation, or encrypt it for secrecy, but you can't magically stop it from being copied and reproduced as a whole.
Longer answer:
I think what you are asking is whether it is possible to add some kind of identification or signature to a QR-code? If so, then the answer is yes - you can put pretty much whatever you like in there, so long as you keep it within the storage limits for the input mode you are using (wikipedia).
This means you could for instance add a digital signature to it, if you wanted to.
Example:
Say you wanted to encode the text "Public Message" into a QR-code, and leave it for someone to read. To prove that the message is really from you, you could use PKI and sign it with your secret key - that is, append an encrypted version of "Public Message" to the text. Decryption of that last part will then only be possible using your public key, and doing so will prove that it was encrypted using your private key, which indicates that the message must have come from you (or someone with access to your private key).
Now if someone tried to copy your QR code, and change it's message to the slightly more kinky "Public Massage" instead, a recipient could check the attached signature and see that there is a mismatch, and so conclude that the code is invalid (i.e. has been manipulated).
If a message has a valid signature, this will prove that you are the author, and that the message has not been manipulated. You still won't be able to stop anyone from copying the code and reproducing it as a whole though.
Alternative: Encryption using a public key?
If you wanted to post a secret message intended for a specific recipient, you could encrypt it using that person's public key. In that case you could share the QR-code freely, and only the recipient would be able to read it's contents; anyone else would just see garbled text.
Alternative 2: One-Time Pass (OTP)?
If you want to make sure a QR-code is used only once, you could have it include a unique ID, and implement server side logic that accepts that code, checks it's validity, and invalidates it after a single use. You can also limit the time for which such a QR-Code is valid. This is how website logins using QR-codes work.
What are the most secure sources of entropy to seed a random number generator? This question is language and platform independent and applies to any machine on a network. Ideally I'm looking for sources available to a machine in a cloud environment or server provided by a hosting company.
There are two important weaknesses to keep in mind. The use of time for sending a random number generator is a violation of CWE-337. The use of a small seed space would be a violation of CWE-339.
Here are a few thoughts. If you are impatient, skip to the conclusion, at the end.
1. What is a secure seed ?
Security is defined only relatively to an attack model. We want here a sequence of n bits, that has n bits of entropy with regards to the attacker: in plain words, that any of the possible 2n values for that sequence are equally probable from the attacker point of view.
This is a model which relates to the information available to the attacker. The application which generates and uses the seed (normally in a PRNG) knows the exact seed; whether the seed is "secure" is not an absolute property of the seed or even of the seed generation process. What matters is the amount of information that the attacker has about the generation process. This level of information varies widely depending on the situation; e.g. on a multi-user system (say Unix-like, with hardware-enforced separation of applications), precise timing of memory accesses can reveal information on how a nominally protected process reads memory. Even a remote attacker can obtain such information; this has been demonstrated (in lab conditions) on AES encryption (typical AES implementations use internal tables, with access patterns which depend on the key; the attacker forces cache misses and detects them through precise timing of responses of the server).
The seed lifetime must be taken into account. The seed is secure as long as it remains unknown to the attacker; this property must hold true afterwards. In particular, it shall not be possible to recover the seed from excerpts of the subsequent PRNG output. Ideally, even obtaining the complete PRNG state at some point should offer no clue as to whatever bits the PRNG produced beforehand.
The point I want to make here is that a seed is "secure" only if it is used in a context where it can remain secure, which more or less implies a cryptographically secure PRNG and some tamper-resistant storage. If such storage is available, then the most secure seed is the one that was generated once, a long time ago, and used in a secure PRNG hosted by tamper-resistant hardware.
Unfortunately, such hardware is expensive (it is called a HSM and costs a few hundreds or thousands of dollars), and that cost usually proves difficult to justify (a bad seed will not prevent a system from operating; this is the usual problem of untestability of security). Hence it is customary to go for "mostly software" solutions. Since software is not good at providing long-term confidential storage, the seed lifetime is arbitrarily shortened: a new seed is periodically obtained. In Fortuna, such reseeding is supposed to happen at least once every megabyte of generated pseudo-random data.
To sum up, in a setup without a HSM, a secure seed is one that can be obtained relatively readily (since we will do it quite often) using data that cannot be gathered by the attacker.
2. Mixing
Random data sources do not produce nice uniform bits (each bit having value 1 with probability exactly 0.5, and bit values are independent of each other). Instead, random sources produce values in a source-specific sets. These values can be encoded as sequences of bits, but you do not get your money worth: to have n bits of entropy you must have values which, when encoded, uses much more than n bits.
The cryptographic tool to use here is a PRF which accepts an input of arbitrary length, and produces an n-bit output. A cryptographically secure PRF of that kind is modeled as a random oracle: in short terms, it is not computationally feasible to predict anything about the oracle output on a given input without trying it.
Right now, we have hash functions. Hash functions must fulfill a few security properties, namely resistance to preimages, second preimages, and collisions. We usually analyze hash functions by trying to see how they depart from the random oracle model. There is an important point here: a PRF which follows the random oracle model will be a good hash function, but there can be good hash functions (in the sense of resistance to preimages and collisions) which nonetheless are easy to distinguish from a random oracle. In particular, the SHA-2 functions (SHA-256, SHA-512...) are considered to be secure, but depart from the random oracle model due to the "length extension attack" (given h(m), it is possible to compute h(m || m') for a partially constrained message m' without knowing m). The length extension attack does not seem to provide any shortcut into the creation of preimages or collisions, but it shows that those hash functions are not random oracles. For the SHA-3 competition, NIST stated that candidates should not allow such "length extension".
Hence, the mixing step is not easy. Your best bet is still, right now, to use SHA-256 or SHA-512, and switch to SHA-3 when it is chosen (this should happen around mid-2012).
3. Sources
A computer is a deterministic machine. To get some randomness, you have to mix in the result of some measures of the physical world.
A philosophical note: at some point you have to trust some smart guys, the kind who may wear lab coats or get paid to do fundamental research. When you use a hash function such as SHA-256, you are actually trusting a bunch of cryptographers when they tell you: we looked for flaws, real hard, and for several years, and found none. When you use a decaying bit of radioactive matter with a Geiger counter, you are trusting some physicists who say: we looked real hard for ways to predict when the next atom kernel will go off, but we found none. Note that, in that specific case, the "physicists" include people like Becquerel, Rutherford, Bohr or Einstein, and "real hard" means "more than a century of accumulated research", so you are not exactly in untrodden territory here. Yet there is still a bit of faith in security.
Some computers already include hardware which generates random data (i.e. which uses and measures a physical process which, as far as physicist can tell, is random enough). The VIA C3 (a line of x86-compatible CPU) have such hardware. Strangely enough, the Commodore 64, home computer from 30 years ago, also had a hardware RNG (or so says Wikipedia, at least).
Barring special hardware, you have to use whatever physical events you may get. Typically, you would use keystrokes, incoming ethernet packets, mouse movements, harddisk accesses... every event comes with some data, and occurs at a measurable instant (modern processors have very accurate clocks, thanks to cycle counters). Those instants, and the event data contents, can be accumulated as entropy sources. This is much easier for the operating system itself (which has direct access to the hardware) than for applications, so the normal way of collecting a seed is to ask the operating system (on Linux, this is called /dev/random or /dev/urandom [both have advantages and problems, choose your poison]; on Windows, call CryptGenRandom()).
An extreme case is pre-1.2 Java applets, before the addition of java.security.SecureRandom; since Java is very effective at isolating the application code from the hardware, obtaining a random seed was a tough challenge. The usual solution was to have two or three threads running concurrently and thread-switching madly, so that the number of thread switches per second was somewhat random (in effect, this tries to extract randomness through the timing of the OS scheduler actions, which depend on what also occurs on the machine, including hardware-related events). This was quite unsatisfactory.
A problem with time-related measures is that the attacker also knows what is the current time. If the attacker has applicative access to the machine, then he can read the cycle counter as well.
Some people have proposed using audio cards as sources of "white noise" by setting the amplifier to its max (even servers have audio nowadays). Others argue for powering up webcams (we know that webcam videos are "noisy" and that's good for randomness, even if the webcam is facing a wall); but servers with webcams are not common. You can also ping an external network server (e.g. www.google.com) and see how much time it takes to come back (but this could be observed by an attacker spying on the network).
The beauty of the mixing step, with a hash function, is that entropy can only accumulate; there is no harm in adding data, even if that data is not that random. Just stuff as much as possible through the hash function. Hash functions are quite fast (a good SHA-512 implementation will process more than 150 MB/s on a typical PC, using a single core) and seeding does not happen that often.
4. Conclusion
Use a HSM. They cost a few hundred or thousands of dollars, but aren't your secrets worth much more than that ? A HSM includes RNG hardware, runs the PRNG algorithm, and stores the seed with tamper resistance. Also, most HSM are already certified with regards to various national regulations (e.g. FIPS 140 in the US, and the EAL levels in Europe).
If you are so cheap that you will not buy a HSM, or if you want to protect data which is actually not very worthwhile, then build up a cryptographically secure PRNG using a seed obtained by hashing lots of physical measures. Anything which comes from some hardware should be hashed, along with the instant (read "cycle counter") at which that data was obtained. You should hash data by the megabyte here. Or, better yet, do not do it: simply use the facilities offered by your operating system, which already includes such code.
The most secure seed is the one which has the highest level of entropy (or most number of bits that can not be predicted). Time is a bad seed generally because it has a small entropy (ie. if you know when the transaction took place you can guess the time stamp to within a few bits). Hardware entropy sources (e.g. from decay processes) are very good because they yield one bit of entropy for every bit of seed.
Usually a hardware source is impractical for most needs, so this leads you to rely on mixing a number of low quality entropy sources to produce a higher one. Typically this is done by estimating the number of bits of entropy for each sample and then gathering enough samples so that the search space for the entropy source is large enough that it is impractical for an attacker to search (128 bits is a good rule of thumb).
Some sources which you can use are: current time in microseconds (typically very low entropy of 1/2 a bit depending on resolution and how easy it is for an attacker to guess), interarrival time of UI events etc.
Operating system sources such as /dev/random and the Windows CAPI random number generator often provide a pre-mixed source of these low-entropy sources, for example the Windows generator CryptGenRandom includes:
The current process ID (GetCurrentProcessID).
The current thread ID (GetCurrentThreadID).
The tick count since boot time (GetTickCount).
The current time (GetLocalTime).
Various high-precision performance
counters (QueryPerformanceCounter).-
An MD4 hash of the user's environment
block, which includes username,
computer name, and search path. [...]-
High-precision internal CPU counters, such as RDTSC, RDMSR, RDPMC
Some PRNGs have built-in strategies to allow the mixing of entropy from low quality sources to produce high quality results. One very good generator is the Fortuna generator. It specifically uses strategies which limit the risk if any of the entropy sources are compromised.
The most secure seed is a truly random one, which you can approximate in practical computing systems of today by using, listed in decreasing degrees of confidence:
Special hardware
Facilities provided by your operating system that try to capture chaotic events like disk reads and mouse movements (/dev/random). Another option on this "capture unpredictable events" line is to use an independent process or machine that captures what happens to it as an entropy pool, instead of the OS provided 'secure' random number generator, for an example, see EntropyPool
Using a bad seed (ie, time) and combine it with other data only known to you (for instance, hashing the time with a secret and some other criteria such as PIDs or internal state of the application/OS, so it doesn't necessarily increase and decrease according to time)
As an interesting take on one-time pads, whenever I'm engaged in espionage I have a system whereby I need only communicate a few letters. For example, the last time I was selling secret plans to build toasters to the Duchy of Grand Fenwick, I only needed to whisper:
enonH
to my confederate. She knew to get http://is.gd/enonH- (this is a "safe" expander URL which takes you to the is.gd expansion page which in turn points to a completely SFW image of a frog). This gave us 409k bits of one-time pad or - if I wink while whispering "enonH" - she knows to take the hash of the image and use that as a decoding key for my next transmission.
Because of the compression in JPEG images they tend to be relatively good sources of entropy as reported by ent:
$ ent frog.jpg
Entropy = 7.955028 bits
per byte.
Optimum compression would reduce the
size of this 51092 byte file by 0
percent.
Chi square distribution for 51092
samples is 4409.15, and randomly would
exceed this value 0.01 percent of the
times.
Arithmetic mean value of data bytes is
129.0884 (127.5 = random).
Monte Carlo value for Pi is 3.053435115 (error
2.81 percent).
Serial correlation coefficient is 0.052738 (totally
uncorrelated = 0.0).uncorrelated = 0.0).
Combine that with the nearly impossible to guess image that I directed her to and my secret toaster plans are safe from The Man.
The answer is /dev/random on a Linux machine. This is very close to a "real" random number generator, where as /dev/urandom can be generated by a PRNG if the entropy pool runs dry. The following quote is taken from the Linux kernel's random.c This entire file is a beautiful read, plenty of comments. The code its self was adopted from from PGP. Its beauty is not bounded by the constraints of C, which is marked by global structs wrapped by accessors. It is a simply awe inspiring design.
This routine gathers environmental
noise from device drivers, etc., and
returns good random numbers, suitable
for cryptographic use. Besides the
obvious cryptographic uses, these
numbers are also good for seeding
TCP sequence numbers, and other places
where it is desirable to have
numbers which are not only random, but
hard to predict by an attacker.
Theory of operation
Computers are very predictable devices. Hence it is extremely hard
to produce truly random numbers on a
computer --- as opposed to
pseudo-random numbers, which can
easily generated by using a
algorithm. Unfortunately, it is very
easy for attackers to guess the
sequence of pseudo-random number
generators, and for some
applications this is not acceptable.
So instead, we must try to gather
"environmental noise" from the
computer's environment, which must
be hard for outside attackers to
observe, and use that to generate
random numbers. In a Unix
environment, this is best done from
inside the kernel.
Sources of randomness from the environment include inter-keyboard
timings, inter-interrupt timings from
some interrupts, and other events
which are both (a) non-deterministic
and (b) hard for an outside observer
to measure. Randomness from these
sources are added to an "entropy
pool", which is mixed using a CRC-like
function. This is not
cryptographically strong, but it is
adequate assuming the randomness is
not chosen maliciously, and it is fast
enough that the overhead of doing it
on every interrupt is very reasonable.
As random bytes are mixed into the
entropy pool, the routines keep an
estimate of how many bits of
randomness have been stored into the
random number generator's internal
state.
When random bytes are desired, they are obtained by taking the SHA
hash of the contents of the "entropy
pool". The SHA hash avoids exposing
the internal state of the entropy
pool. It is believed to be
computationally infeasible to derive
any useful information about the
input of SHA from its output. Even if
it is possible to analyze SHA in
some clever way, as long as the amount
of data returned from the generator
is less than the inherent entropy in
the pool, the output data is totally
unpredictable. For this reason, the
routine decreases its internal
estimate of how many bits of "true
randomness" are contained in the
entropy pool as it outputs random
numbers.
If this estimate goes to zero, the routine can still generate random
numbers; however, an attacker may (at
least in theory) be able to infer
the future output of the generator
from prior outputs. This requires
successful cryptanalysis of SHA, which
is not believed to be feasible, but
there is a remote possibility. Nonetheless, these numbers should be
useful for the vast majority of
purposes.
...
Write an Internet radio client, use a random sample from the broadcast. Have a pool of several stations to choose from and/or fall back to.
James is correct. In addition, there is hardware that you can purchase that will give you random data. Not sure where I saw it, but I think I read that some sound cards come with such hardware.
You can also use a site like http://www.random.org/
If you read into crypto-theory, it becomes apparent that the most secure seed would be one generated by a chaotic event. Throughout recent history, covert operations have made use of what is known as a "One-time pad" which is proven impossible to crack. Normally these are generated through an assortment of atmospheric listening posts scattered about the middle of nowhere. Atmospheric noise is sufficiently chaotic to be considered random. The main problem with this method is that the logistics for a one time pad are considerable.
My suggestion to you is to find a sufficiently chaotic event to somehow extract data from.
4 - chosen by very random dice roll. :-)
OK, assuming that the client needs a strong seed, and you are using cloud computing here is a solution, for some hardware random number generators you can look here:
http://en.wikipedia.org/wiki/Hardware_random_number_generator
So, this assumes that each client has a public/private key pair, where the server knows the public key for each client.
To generate a key you can use something similar to what was done with PGP, in the beginning, where you take the difference in time between key strokes as someone types, as that won't be guessable.
So, the client submits a request for a random number.
The server uses a hardware generator, encrypts it with the public key, and signs this with the server's private key.
The client then can verify where it came from and then decrypt it.
This will ensure that you can generate a random number and pass it back in a secure fashion.
UPDATE:
Your best bet is to look in the Art of Computer Programming or any of the Numerical Methods book, or look at what Bruce Schneier has written, such as these links:
http://www.schneier.com/blog/archives/2006/06/random_number_g.html http://www.cryptosys.net/rng_algorithms.html
http://www.schneier.com/blog/archives/2006/06/random_number_g.html http://www.schneier.com/blog/archives/2006/06/random_number_g.html
Suggestions for Random Number Generation in Software, ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf
You can also look at having Crypto++ do the generation, or at least look at how Wei Dai did it, http://www.cryptopp.com/
Random.org offers a true random number generator web service, "seeded" by the atmospheric noise.
You get 200,000 random bits for free each day, up to the 1 million random bits cap after that you should top up your account, it gets as cheap as 4 million bits per dollar.
Simple solution if no additional random hardware are available.
Use milliseconds, mouseX and mouseY to generate a seed.
As the consensus is cryptographically strong random numbers must derived form hardware. Some processors have this functionality (Intel chips amonst others). Also sound cards can be used for this by measuring the low-bit fluctuations in the a-d converter.
But due to the hardware needs the is no language and platform independent answer.
Pretty much any larger OS will have support for secure random numbers. It is also tricky to implement a good random number generator with good output, since you will have to track the remaining entropy in the pool.
So the first step is to determine what language(s) you will be using.
Some do have strong random number support - if this is not the case you would have to abstract the generation to call platform-dependent random sources.
Depending on your security needs be weary of "online" sources since a man-in-the midde can be a serious threat for unauthenticated online sources.
Your most secure methods will come from nature. That is to say, something that happens outside of your computer system and beyond our ability to predict it's patterns.
For instance, many researchers into Cryptographically secure PRNGs will use radioactive decay as a model, others might look into fractals, and so forth. There are existing means of creating true RNGs
One of my favorite ways of implementing a PRNG is from user interaction with a computer. For instance, this post was not something that could be pre-determined by forward-engineering from my past series of posts. Where I left my mouse on my screen is very random, the trail it made is also random. Seeing from user-interactions is. Abuse from the means of providing specific input such that specific numbers are generated could be mitigated by using a 'swarm' of user inputs and calculating it's 'vector', as long as you do not have every user in your system as an Eve, you should be fine. This is not suitable for many applications, as your pool of numbers is directly proportional to user input. Implementing this may have it's own issues.
People interested in RNG have already done things such as:
Use a web cam, whatever the random blips in the screen hash out to, when that truck passes by, that's all random data.
As mentioned already, radiation
Atmosphere
User interaction (as mentioned)
What's going on within the system EDG.
Secure seeds come from nature.
edit:
Based on what you're looking at doing, I might suggest using an aggregation of your cloud server's EDG.
First you need to define the actual use/purpose of the random number generator and why do you think in has to pass so high security standard? The reason I ask is that you mentioned picking it from the could - if you are using it indeed for security purposes then securing the source and the channel to send it around is much more important than anyone's academic knit-picking.
Second element is the size of the actual random numbers you need - big seed is good but only if the number generated is also big - otherwise you'll just be reading the small part of the generated number and that will increase your risk.
Look into reconfigurable ciphers, rather than things like SHA or AES. Here are 2 research papers if you want to read and verify how and why they work:
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.97.6594&rep=rep1&type=pdf
http://www.springerlink.com/index/q29t6v1p45515186.pdf
Or grab any reconfigurable GOST cipher source code you find on the net and then you an either feed it just any basic seed (like concatenated "ticker" plus a web server node ID (if it's in a web farm) plus a part of response on any internet news site that changes top news all the time or you can feed it highly controlled initial seed (which you can make on your own) and use a light pseudo-random sequence for selecting further cipher configurations. Even NSA can't break that one :-) Since it's always a different cipher. For actual crypto purposes one virtually has to use very controlled initial seed just to be able to replicate the sequence for validation. That's where we go back to first item - securing the source and distribution.
Use random.org they claim to offer true random numbers to anyone on the Internet and they also have an HTTP API which you can use. They offer both free and paid services.
disclaimer: i am not in any way affiliated with random.org
You can earn random numbers generated by radioactive decay. Sounds a little strange at first, but you get real random numbers out of this.
Radioactive Decay
Another Article
THIS IS A GUESS! Crypto geeks please correct if I've got it wrong
The official algorithm for UUID/GUID at this point returns a result that is run through a cryptographic hash function - it takes known information, such as time, mac addr, and a counter to form a UUID/GUID and then runs this through a cryptographic hash to ensure that the mac address cannot be extracted.
I believe you can XOR this down to the number of bits you require for a seed with a reasonably good guarantee that the resultant value is equally distributed over the number space defined by your desired bit count. Note I am not claiming this is secure, only that this action should produce a value that distributes evenly across the bit space over time.
(((PI X current thread ID) X current process ID) / tick count) x pi
Suppose you are designing a PC game that keeps track of high scores. In addition to keeping local scores, a global high score server is set up that is accessed by the game over the internet. Players should be able to submit their high scores to the global high score list right after they have completed a game, or later, from their local high score list. This must be a common problem; arcade games on modern game consoles often feature a global high score list that works like this.
My question boils down to: how can you prevent someone from submitting bogus high scores? Or, stated another way, how can the global high score server be sure that a submitted score was really produced by a run through the game?
The more I thought about this, the more I think it may be an unsolvable problem.
What you'd commonly do to verify that a message originated from a certain source is have the source digitally sign the message. You could certainly do that in this case, but the real problem is that the player, by having the software, also has the software's private key. No matter how obfuscated it might be, it can be reverse engineered, or even just plucked from memory.
Another option would be to send along a replay of the player's game to the high score server, which would quickly run the replay and verify that the submitted score matches the outcome of the replay. This doesn't solve the problem, but it certainly makes it more difficult to forge a bogus high score if you also have to produce a very complex replay that "proves" it.
Is this a problem that has a solution, or is it really unsolvable? Are there techniques used by the home game console developers to prevent this sort of exploit, or do they simply rely on the console preventing unauthorized code from running?
For a PC game where the score is generated by the client, this is not a solvable problem since the client is inherently untrustworthy.
The only thing you can try to do is make it harder for someone to submit a fake score.
Some thoughts:
Protect the in-memory score.
You can use API's like CryptProtectMemory to hide the score in memory - a simple memory write will not work. However, with an attached debugger or via injecting code into your process, they could still modify the score. You can look into various schemes for trying to defeat debuggers.
Protect the score en-route to the server.
You can encrypt the data being sent to the service, as you suggest, but since the untrusted party has control over the key, this is merely obfuscation and offers no solid protection.
Validate the score at the service.
I'd be loathe to do this, beyond very simple checks. A bug here will result in you rejecting valid scores. It'll be impossible to distinguish between cheaters and strong players.
At this point, you really have to ask your self if the engineering effort is really worth it. What if someone posts an invalid score? What do you actually lose? I would do the bare minimum to protect against a kid with a simple script. I.e., don't have your score submission be just:
http://myservice.com/submitscore.aspx?PlayerName=Michael&Score=999999999
I would just use simple protection in memory against casual snoops, some simple obfuscation on the wire (hash the score with a server cookie) and be done.
To my knowledge, this is unsolvable.
I have seen many people try to obfuscate the encryption key. I have seen a few people include other sanity checks like time elapsed, or enemies remaining. I have never seen one that sends a replay, though of course it is possible.
In a website that will remain unamed, they setup a fake send high score routine that is easily found. If a perpetrator uses it, their IP address will be automatically banned from future updates.
"Another option would be to send along a replay of the player's game ... This doesn't solve the problem, "
Really? Why not?
"you also have to produce a very complex replay that "proves" [the score]."
Are you suggesting someone could fake the replay? Reason out a super-high-score solution without actually playing the game? Fake the timestamps and everything? Pull a Donald Crowhurst?
Why not just play the game rather than attempt to fake a log of playing the game?
Or... if it's that easy to fake a history of game play that leads to a super high score, perhaps the game is misdesigned. If the game is "hard", the person must make all the right choices. If the game is easy, then the score doesn't reflect the player's choices and is fakable.
Think of it this way. Pick any game or sport. Someone says that -- say -- Switzerland beat New Zealand in a yacht race. You would challenge them by seeking substantiating details on the venue, the boats, the teams and the individual races to convince yourself it was true. Certainly, they could fake it, but if they've got a rich set of details covering the race, then... how's that not "proof"?
Forget the cryptogaphic issue; if your code can be hacked on the local machine, how do you keep someone from setting a crazy high score artificially and then transmitting it using the existing trusted mechanism?
Until you can establish trust in the code itself, a crypto mechanism for the communications isn't going to be the real problem.
Send the hash of the (software + a random salt) along with the score. Check this hash with the server. If it matches (meaning that the software is unaltered) accept it. Otherwise, the score comes from a "modded" version of the game. Reject it. The random salt should change every time the hash is generated (current sys time or something like that)
Check Quake III Arena source code. Their version was quite fool proof. Unfortunately, I don't remember the link now.
GUIDs get used a lot in creating session keys for web applications. I've always wondered about the safety of this practice. Since the GUID is generated based on information from the machine, and the time, along with a few other factors, how hard is it to guess of likely GUIDs that will come up in the future. Let's say you started 1000, or 10000 new sessions, to get a good dataset of the GUIDs being generated. Would this make it any easier to generate a GUID that might be used for another session. You wouldn't even have to guess a specific GUID, but just keep on trying GUIDs that might be generated at a specific period of time.
Here is some stuff from Wikipedia (original source):
V1 GUIDs which contain a MAC address
and time can be identified by the
digit "1" in the first position of the
third group of digits, for example
{2f1e4fc0-81fd-11da-9156-00036a0f876a}.
In my understanding, they don't really hide it.
V4 GUIDs use the later algorithm,
which is a pseudo-random number. These
have a "4" in the same position, for
example
{38a52be4-9352-453e-af97-5c3b448652f0}.
More specifically, the 'data3' bit
pattern would be 0001xxxxxxxxxxxx in
the first case, and 0100xxxxxxxxxxxx
in the second. Cryptanalysis of the
WinAPI GUID generator shows that,
since the sequence of V4 GUIDs is
pseudo-random, given the initial state
one can predict up to next 250 000
GUIDs returned by the function
UuidCreate1. This is why GUIDs
should not be used in cryptography, e.
g., as random keys.
GUIDs are guaranteed to be unique and that's about it. Not guaranteed to be be random or difficult to guess.
TO answer you question, at least for the V1 GUID generation algorithm if you know the algorithm, MAC address and the time of the creation you could probably generate a set of GUIDs one of which would be one that was actually generated. And the MAC address if it's a V1 GUID can be determined from sample GUIDs from the same machine.
Additional tidbit from wikipedia:
The OSF-specified algorithm for
generating new GUIDs has been widely
criticized. In these (V1) GUIDs, the
user's network card MAC address is
used as a base for the last group of
GUID digits, which means, for example,
that a document can be tracked back to
the computer that created it. This
privacy hole was used when locating
the creator of the Melissa worm. Most
of the other digits are based on the
time while generating the GUID.
.NET Web Applications call Guid.NewGuid() to create a GUID which is in turn ends up calling the CoCreateGuid() COM function a couple of frames deeper in the stack.
From the MSDN Library:
The CoCreateGuid function calls the
RPC function UuidCreate, which creates
a GUID, a globally unique 128-bit
integer. Use the CoCreateGuid function
when you need an absolutely unique
number that you will use as a
persistent identifier in a distributed
environment.To a very high degree of
certainty, this function returns a
unique value – no other invocation, on
the same or any other system
(networked or not), should return the
same value.
And if you check the page on UuidCreate:
The UuidCreate function generates a
UUID that cannot be traced to the
ethernet/token ring address of the
computer on which it was generated. It
also cannot be associated with other
UUIDs created on the same computer.
The last contains sentence is the answer to your question. So I would say, it is pretty hard to guess unless there is a bug in Microsoft's implementation.
If someone kept hitting a server with a continuous stream of GUIDs it would be more of a denial of service attack than anything else.
The possibility of someone guessing a GUID is next to nil.
Depends. It is hard if the GUIDs are set up sensibly, e.g. using salted secure hashes and you have plenty of bits. It is weak if the GUIDs are short and obvious.
You may well want to be taking steps to stop someone create 10000 new sessions anyway due to the server load this might create.
"GUIDs are guaranteed to be unique and that's about it". GUIDs are not garanteed to be unique. At least the ones generated by CoCreateGuid: "To a very high degree of certainty, this function returns a unique value – no other invocation, on the same or any other system (networked or not), should return the same value."