Project

flexkey

0.0
No commit activity in last 3 years
No release in over 3 years
Flexible product key generation
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0
~> 1.3
>= 0
>= 0
 Project Readme

Flexkey

Flexkey is a Ruby gem for generating unique, random strings for use as product keys, redemption codes, invoice numbers, passwords, etc.

Installation

Add this line to your application's Gemfile:

gem 'flexkey'

And then execute:

$ bundle

Or install it yourself as:

$ gem install flexkey
Dependencies

None. Flexkey has been tested with Ruby 1.9.3 and 2.0.

Usage

Basic usage

Instantiate a new generator with Flexkey::Generator.new and provide a format and char_pool. Then, generate a single key or multiple unique keys with the generate method:

keygen = Flexkey::Generator.new(format: 'aaaa-aa', char_pool: { 'a' => :alpha_upper })
# => #<Flexkey::Generator @format="aaaa-aa", @char_pool={"a"=>:alpha_upper}, @n_possible_keys=308915776>
keygen.generate
# => "KBND-NR"
keygen.generate(3)
# => ["IVXT-LB", "BFZB-LM", "WIVG-ZJ"]

In this example, Flexkey generates a key by replacing each instance of 'a' in the string 'aaaa-aa' with a character randomly drawn from a pool of uppercase letters while leaving unspecified characters (i.e. '-') alone.

Since you're most likely persisting generated keys in a database, even though generate(n) will return n unique keys, you'll still want to validate them for uniqueness against keys you've previously saved.

Built-in character types
Character type Description
alpha_upper uppercase letters
alpha_lower lowercase letters
numeric numerals
alpha_upper_clear alpha_upper without ambiguous letters ("S", "O", etc.)
alpha_lower_clear alpha_lower without ambiguous letters ("l", "O", etc.)
numeric_clear numeric without ambiguous numerals ("0", "1", and "5")
symbol symbols on a standard U.S. keyboard
basic_symbol basic symbols on a standard U.S. keyboard

The names and characters present in each type can be retrieved as such:

Flexkey::CharPool.available_char_types
# => [:alpha_upper, :alpha_lower, :numeric, :alpha_upper_clear, :alpha_lower_clear, :numeric_clear, :symbol, :basic_symbol]
Flexkey::CharPool.available_char_pools
# => {:alpha_upper=>"ABCDEFGHIJKLMNOPQRSTUVWXYZ", :alpha_lower=>"abcdefghijklmnopqrstuvwxyz", :numeric=>"0123456789", :alpha_upper_clear=>"ABCDEFGHJKLMNPQRTUVWXYZ", :alpha_lower_clear=>"abcdefghjkmnpqrtuvwxyz", :numeric_clear=>"2346789", :symbol=>"!@\#$%^&*;:()_+-=[]{}\\|'\",.<>/?", :basic_symbol=>"!@\#$%^&*;:"}
Examples
Flexkey::Generator.new(format: 'a-nnnn', char_pool: {
  'a' => :alpha_upper, 'n' => :numeric
}).generate
# => "Y-1145"
Flexkey::Generator.new(format: 'SN-nnnnnnnnn', char_pool: {
  'n' => :numeric
}).generate
# => "SN-181073470"
Flexkey::Generator.new(format: 'AA.aa.nn.ss', char_pool: {
  'A' => :alpha_upper_clear, 'a' => :alpha_lower_clear, 'n' => :numeric_clear, 's' => :basic_symbol
}).generate
# => "MX.mh.33.*:"

You can also specify a custom string instead of using a built-in type.

Flexkey::Generator.new(format: 'annn/c', char_pool: {
  'a' => :alpha_upper, 'n' => :numeric, 'c' => 'LMN'
}).generate(5)
# => ["X905/N", "F865/L", "M423/N", "V564/L", "V874/M"]
Flexkey::Generator.new(format: 'mnnnnnnn', char_pool: {
  'm' => '123456789', 'n' => :numeric
}).generate(5)
# => ["45862188", "23054329", "36248220", "56044911", "49873464"]
Selecting from multiple character types

To replace a character in the format from a pool of multiple character types, specify the both the types and proportions in the char_pool. For example, to generate keys of length 10 where each character is randomly selected from a pool of uppercase letters and numerals with equal proportions, do the following:

Flexkey::Generator.new(format: '..........', char_pool: {
  '.' => { alpha_upper: 0.5, numeric: 0.5 }
}).generate(5)
# => ["OXAEXC2O87", "3D95JXQ60P", "8F28OX31Y8", "65ZY7IM6TL", "B971Q602SO"]

You can specify proportions with any positive numbers:

Flexkey::Generator.new(format: 'U-ccccc-ccccc', char_pool: {
  'U' => :alpha_upper_clear, 'c' => { numeric_clear: 1, alpha_upper_clear: 7 }
}).generate(5)
# => ["H-KYLYK-DQLK3", "U-7QUXV-6DXNW", "X-REYAX-LL489", "L-8ABNJ-ZW3A7", "M-TPVTW-VEMTE"]
Flexkey::Generator.new(format: 'UUUUU.LLLLL', char_pool: {
  'U' => { 'WXYZ' => 3, 'FGH' => 1 }, 'L' => :alpha_lower_clear
}).generate(5)
# => ["XZYYF.kwkth", "HHFYW.nkpdr", "WXXGW.fvyeu", "HWFXW.xzgeq", "WXWXW.twrdk"]
Number of possible keys

Flexkey will raise an exception if you try to request more keys than are possible with the format you provided:

keygen = Flexkey::Generator.new(format: 'annn', char_pool: {
  'a' => :alpha_upper, 'n' => :numeric
})
keygen.generate(3)
# => ["F202", "U811", "W802"]
keygen.generate(26001)
# Flexkey::GeneratorError: There are only 26000 possible keys
keygen.n_possible_keys
# => 26000

The instance method n_possible_keys is available for reference as seen above.

Since generate(n) works by building an array of randomly-generated keys while checking new keys for uniqueness, it's not a good choice for generating all possible keys for a particular format. In that case, it makes more sense to simply build your list of keys iteratively.

CharPool

If you're only interested in using the proportional sampling feature of Flexkey and will generate keys yourself, use Flexkey::CharPool.generate with a single hash argument:

char_pool = Flexkey::CharPool.generate({ alpha_upper: 0.75, numeric: 0.25 })
10.times.map { char_pool.sample }.join
=> "XC3RPKKWK4"

Additional documentation

At Rubydocs.

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request