├── .gems ├── CHANGELOG ├── CONTRIBUTING ├── LICENSE ├── README.md ├── lib └── stringent.rb ├── makefile ├── stringent.gemspec └── test └── all.rb /.gems: -------------------------------------------------------------------------------- 1 | cutest -v 1.2.2 2 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | This code tries to solve a particular problem with a very simple 2 | implementation. We try to keep the code to a minimum while making 3 | it as clear as possible. The design is very likely finished, and 4 | if some feature is missing it is possible that it was left out on 5 | purpose. That said, new usage patterns may arise, and when that 6 | happens we are ready to adapt if necessary. 7 | 8 | A good first step for contributing is to meet us on IRC and discuss 9 | ideas. We spend a lot of time on #lesscode at freenode, always ready 10 | to talk about code and simplicity. If connecting to IRC is not an 11 | option, you can create an issue explaining the proposed change and 12 | a use case. We pay a lot of attention to use cases, because our 13 | goal is to keep the code base simple. Usually the result of a 14 | conversation is the creation of a different tool. 15 | 16 | Please don't start the conversation with a pull request. The code 17 | should come at last, and even though it may help to convey an idea, 18 | more often than not it draws the attention to a particular 19 | implementation. 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Michel Martens 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Stringent 2 | ========= 3 | 4 | Generate a string with a target entropy 5 | 6 | Description 7 | ----------- 8 | 9 | Stringent uses `SecureRandom` to generate a pseudo-random number 10 | with a target entropy, and proceeds to encode it with a given table 11 | of symbols. The target entropy defaults to 256 bits, and the table 12 | of symbols defaults to case sensitive alphanumeric characters. Both 13 | values can be passed as parameters. 14 | 15 | The entropy parameter means that there are `2^entropy` possible 16 | outputs for a given call. However, it does not mean that each bit 17 | is actually generated using one bit of entropy, since `SecureRandom` 18 | may use `/dev/urandom` which, while unguessable, may have less than 19 | 1 bit of entropy for each bit of output. 20 | 21 | Usage 22 | ----- 23 | 24 | Generate a random string with the default values for target entropy 25 | and symbols table: 26 | 27 | ```ruby 28 | >> Stringent.generate 29 | => "kEPcWwph6OkyHIKZtw4DwnWnlJo0Q6QoDp8Iykshrfm" 30 | ``` 31 | 32 | Generate a random string with a custom target entropy: 33 | 34 | ```ruby 35 | >> Stringent.generate(entropy: 32) 36 | => "Kqd6e0" 37 | ``` 38 | 39 | Generate a random string with a custom target entropy and a custom 40 | table: 41 | 42 | ```ruby 43 | >> Stringent.generate(entropy: 16, table: "01") 44 | => "1000100110000000" 45 | ``` 46 | 47 | Installation 48 | ------------ 49 | 50 | ``` 51 | $ gem install stringent 52 | ``` 53 | -------------------------------------------------------------------------------- /lib/stringent.rb: -------------------------------------------------------------------------------- 1 | require "securerandom" 2 | 3 | module Stringent 4 | TABLE = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.freeze 5 | 6 | def self.generate(entropy: 256, table: TABLE) 7 | number = SecureRandom.random_number(2 ** entropy) 8 | length = (entropy / Math.log2(table.size)).ceil 9 | 10 | Array.new(length) { 11 | number, modulo = number.divmod(table.size) 12 | table[modulo] 13 | }.join 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | test: 4 | cutest ./test/*.rb 5 | -------------------------------------------------------------------------------- /stringent.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = "stringent" 3 | s.version = "0.0.1" 4 | s.summary = "Generate a string with a target entropy" 5 | s.description = "Generate a string with a target entropy" 6 | s.authors = ["Michel Martens"] 7 | s.email = ["michel@soveran.com"] 8 | s.homepage = "https://github.com/soveran/stringent" 9 | s.license = "MIT" 10 | 11 | s.files = `git ls-files`.split("\n") 12 | 13 | s.add_development_dependency "cutest" 14 | end 15 | -------------------------------------------------------------------------------- /test/all.rb: -------------------------------------------------------------------------------- 1 | require_relative "../lib/stringent" 2 | 3 | test do 4 | assert_equal 1, Stringent.generate(entropy: 1, table: '01').size 5 | assert_equal 2, Stringent.generate(entropy: 2, table: '01').size 6 | end 7 | --------------------------------------------------------------------------------