The technique I used (I should publish it as open source) is using a Feistel cipher [2] with a key. The Feistel network could be adjusted to almost any size and the key used in every round is an expansion of a general key using a key derivation function [3] (KDF3 if I remember well).
Basically it is a symmetric cipher of arbitrary size.
[1] https://www.nektra.com/products/secure-coupon-code-generator...