Here's two ideas:
- Use a reversible hash. Whether this works depends on what you consider to be security, since it's essentially just obfuscation. But if you customize it (perhaps altering the order some of the steps in the algorithm), and you prevent source from being leaked, it will prevent all but the most determined attackers. (Depending on your security goals, you'd probably want to combine with a few other techniques to mitigate the risk of leaks, eg, employees leaving the company. Consider keeping part of the algorithm secret, as if it were a cryptographic key, and having additional, variable, pretransformations to the input.)
Off the top of my head, a simple reversible hash might just be "lateral addition" of bits. For something more sophisticated, off the top of my head, the popular "MurmurHash" family of algorithms is claimed to be reversible.
I am not aware of any cryptographically-strong reversible hashes. However, other answers on the topic of symmetric encryption are similar to this idea.
- Use a stream cipher, AKA cryptographic RNG. This is appropriate if the total number of orders is going to be fairly small. What you need is a unique sequence of numbers that maps one-to-one with the counting number sequence. So generate a sequence of unique random numbers, using RC4 or HMAC of your choice, eliminating duplicates as you go. (Maybe a creative way to make this go fast is a bloom filter.)
For mapping from internal IDs to external IDs, you just generate the sequence. For the reverse, you keep going until you find the ID, or hit the maximum order ID. This algorithm is O(n), which is obviously not ideal, but if you're willing to compromise a little, add more complexity, or be clever, you might find a way to mitigate this. For instance, you might be able to keep a cache of the IDs in RAM.
Edited:
I myself feel skeptical about #2 due to the linear complexity, so I ran some numbers. Using Crypto++'s benchmark numbers from a Core2 processor, if you budget 10 ms to the number transformation, and you use 40-bit IDs (which gets you hypothetically to one quadrillion orders), you get to an order ID max of about 2,500,000. And I think you could double that by using a smaller key.
So this method could go either way. For small-scale stuff, it's fine. (The assumptions above are conservative.) But for large-scale stuff, this could be an annoyance. It's enough to get you through a product launch; you'd want to revisit it at about the time you started talking about how to build your software as a distributed system, which would also help solve this problem. But at that point, you're probably better off questioning initial assumptions, and just storing this thing in a database somewhere.