Creates a serial key from a seed, based on this article.
The serial key can be checked for validity, either by using a checksum or by verifying bytes in the key.
cargo install keygen
Windows/Linux: Compile from source using Rust - no binaries at the mo.
Mac: v1.1
Creates a key from an initial string value.
Initial value to use to create the string
keygen create -s myname@example.com
String to combine with the seed when creating the key. If you don't provide a hash, a random one will be generated and used.
keygen create -s myname@example.com -h aLongstringValueasaHash
Path to existing JSON config file. This file will be read when creating the key.
keygen create -s myname@example.com -c config.json
Seed values to add to a blacklist. Any keys with seed values in the blacklist will fail verification.
// key = 53A5-4C20-A43E-6490-052A
keygen create -s myname@examplecom -b 11111111 -b 53A54C20
keygen verify -k 53A5-4C20-A43E-6490-052A -c config.json // => Blacklisted
Number of bytes to create in the key. Longer keys should be tricker to crack but are more difficult for users to type. Keys are made up of the seed (8 characters long), a length of bytes (2 characters per byte), then the checksum (4 characters).
keygen create -s myname@example.com -l 12 // => 53A5-4C20-7474-CC94-AF39-B63D-8B34-54A7-C1DA
keygen create -s myname@example.com -l 4 // => 53A5-4C20-A43E-6490-052A
OPTIONAL Byte shifts to use when creating a key. If not provided, then these will be generated. Must be triplets of i16 ie 12,242,45 16,80,52
keygen create -y 74,252,42 178,245,197 1,201,98
Path to which to write config settings. When creating a key it's vital to save the config used to create the key, otherwise you won't be able to verify it. If you provide an output value, then a file with the value's name will be created and the config will be saved there as JSON. If this value isn't provided, JSON config will be printed out to the terminal.
keygen create -s myname@example.com -o config.json
Flag: if present, output will be written to stdout as JSON data. A config file will not be created/written if this flag is set.
keygen create -s myname@example.com -l 8 -h abc123 -j
// =>
{"config":{"blacklist":[],"byte_shifts":[[98,133,163],[26,206,205],[244,140,88],[149,39,147],[208,215,29],[161,77,140],[178,216,229],[216,29,79]],"hash":"Cc7MgAsUr43PyT4U2zW5dDkVIKK23hB","num_bytes":8},"key":"92E7-A4A6-265A-5425-99FC-3088-C404"}
Check that a key is valid. Returns Keygen::Status
.
keygen verify -k 1234-5678-abcd-1234 -c config.json // => Status::Good, Status::Invalid, Status::Blacklisted, Status::Phony
Key to check.
Path to JSON config file; must be the config used to create the key.
Byte shifts used when generating the key, triplets of i16. These must match the position params ie if position is [0, 1] then you must pass the first two byte shifts which were used when creating the key.
Bytes to check in the key
ie with a key of 1234-5678-abcd-1234, positions of [0, 1] would check the first two bytes in the key (ab
and cd
- 1234-5678
is the seed value).
keygen verify -k 1234-5678-abcd-1234 -s 74,252,42 42,116,226 -p 0 1
Check that a key's checksum is correct (ie that the key hasn't been altered). Returns bool
.
Requires either the expected length of the key or a path to a config file (where it reads the expected length).
keygen checksum -k 1234-5678-abcd-1234 -c config.json // => true
keygen checksum -k 1234-5678-abcd-1234 -l 2 // => true
Key to check.
Expected length of key to check.
Path to JSON config file; must be the config used to create the key.
Seeds are created from the input and hash being run through CRC32
- they are always eight characters long in hexadecimal format.
The config is vital once a key has been created - if you don't save the config, or try to use a different one to verify a key, you won't be able to validate keys! The config file contains information which can be used to generate keys, so needs to be kept secret. You can use the same config to generate multiple keys by using the -c
argument when creating a key.
"num_bytes": 8, // length of key
"byte_shifts": [ // array of arrays - these are used to check each byte
[62, 252, 46],
[57, 195, 131],
[21, 251, 32],
[129, 94, 254],
[205, 24, 45],
[161, 36, 17],
[88, 109, 26],
[105, 237, 248]
],
"hash": "hash", // the hash used in creating the string
"blacklist": ["11111111"] // blacklisted seeds
}
The keygen checksum
method is a quick and fairly inaccurate way to determine whether a key is invalid or not - it only checks whether the checksum matches the rest of the key, although it is possible to alter the key and checksum and still end up valid. The verify function checks the checksum along with several bytes in the key to determine if the key actually is valid - the full reasoning is in the original article, but essentially this is so you have a quick-and-dirty way to check the key's valid on startup (checksum
), and a full check later when trying to use more funcationlity like saving. Having the quick check on startup means reverse-engineers don't know exactly when the full check happens in the software so there isn't an obvious entry point.