wordhash 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bafbadf27d8434cf3cc4f76759abf5cdcea16c9c
4
+ data.tar.gz: 7147720cbd69eadcefdfe6cc3cdbedcf1c339bdb
5
+ SHA512:
6
+ metadata.gz: 1a575fd75b4116782b6318fff4eaab149f618660e29f383bb75ae7ca236a605ad5a77e9dfcc62d683d9abfea8e70bd1cb33f21a43316488824d3125aa3330ff2
7
+ data.tar.gz: 4dc26aa7779d1c85160f0f0079aa7f2b2aba1a7a882568eab772d90d3253bb359d12b2a759e59eb93373b8f28a2b1874ffb9d176fe09e63ad0f7398b87c83b52
data/LICENCE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright © 2015 Louis Pilfold. All Rights Reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # wordhash
2
+
3
+ [![Build Status](https://travis-ci.org/lpil/wordhash.svg?branch=master)](https://travis-ci.org/lpil/humanhash.rb)
4
+ [![Code Climate](https://codeclimate.com/github/lpil/wordhash/badges/gpa.svg)](https://codeclimate.com/github/lpil/humanhash.rb)
5
+
6
+ wordhash provides human-readable representations of digests.
7
+ A clone of Zachary Voase's
8
+ [humanhash](https://github.com/zacharyvoase/humanhash).
9
+
10
+ ## Example
11
+
12
+ ```ruby
13
+ require 'word_hash'
14
+
15
+ digest = '7528880a986c40e78c38115e640da2a1'
16
+ # => "7528880a986c40e78c38115e640da2a1"
17
+
18
+ WordHash.new.humanize digest
19
+ # => "three-georgia-xray-jig"
20
+ WordHash.new.humanize digest, 6
21
+ # => "high-mango-white-oregon-purple-charlie"
22
+
23
+ WordHash.new.uuid
24
+ # => ["04edcd5325a34dc191d4880676ebae61", "lemon-artist-snake-gee"]
25
+ ```
26
+
27
+ ## Caveats
28
+
29
+ Don't store the humanhash output, as its statistical uniqueness is only around
30
+ 1 in 4.3 billion. Its intended use is as a human-readable (and, most
31
+ importantly, memorable) representation of a longer digest, unique enough for
32
+ display in a user interface, where a user may need to remember or verbally
33
+ communicate the identity of a hash, without having to remember a 40-character
34
+ hexadecimal sequence. Nevertheless, you should keep original digests around,
35
+ then pass them through humanize() only as you're displaying them.
36
+
37
+ ## How It Works
38
+
39
+ The procedure for generating a humanhash involves compressing the input to a
40
+ fixed length (default: 4 bytes), then mapping each of these bytes to a word in
41
+ a pre-defined wordlist (a default wordlist is supplied with the library). This
42
+ algorithm is consistent, so the same input, given the same wordlist, will
43
+ always give the same output. You can also use your own wordlist, and specify a
44
+ different number of words for output.
45
+
46
+ (The algorithm and this text are completely lifted from Zachary's version)
47
+
48
+ ## Licence
49
+
50
+ ```
51
+ Copyright © 2015 Louis Pilfold. All Rights Reserved.
52
+
53
+ Permission is hereby granted, free of charge, to any person obtaining
54
+ a copy of this software and associated documentation files (the "Software"),
55
+ to deal in the Software without restriction, including without limitation
56
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
57
+ and/or sell copies of the Software, and to permit persons to whom the
58
+ Software is furnished to do so, subject to the following conditions:
59
+
60
+ The above copyright notice and this permission notice shall be included
61
+ in all copies or substantial portions of the Software.
62
+
63
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
64
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
65
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
66
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
67
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
68
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
69
+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
70
+ ```
data/lib/word_hash.rb ADDED
@@ -0,0 +1,108 @@
1
+ require 'securerandom'
2
+
3
+ # Transforms hex digests to human-readable strings.
4
+ #
5
+ # The format of these strings will look something like:
6
+ # `victor-bacon-zulu-lima`. The output is obtained by compressing the input
7
+ # digest to a fixed number of bytes, then mapping those bytes to one of 256
8
+ # words. A default wordlist is provided, but you can override this if you
9
+ # prefer.
10
+ #
11
+ # As long as you use the same wordlist, the output will be consistent (i.e.
12
+ # the same digest will always render the same representation).
13
+ class WordHash
14
+ attr_reader :wordlist
15
+
16
+ DEFAULT_WORDLIST = %w(
17
+ ack alabama alanine alaska alpha angel apart april arizona arkansas artist
18
+ asparagus aspen august autumn avocado bacon bakerloo batman beer berlin
19
+ beryllium black blossom blue bluebird bravo bulldog burger butter
20
+ california carbon cardinal carolina carpet cat ceiling charlie chicken
21
+ coffee cola cold colorado comet connecticut crazy cup dakota december
22
+ delaware delta diet don double early earth east echo edward eight eighteen
23
+ eleven emma enemy equal failed fanta fifteen fillet finch fish five fix
24
+ floor florida football four fourteen foxtrot freddie friend fruit gee
25
+ georgia glucose golf green grey hamper happy harry hawaii helium high hot
26
+ hotel hydrogen idaho illinois india indigo ink iowa island item jersey jig
27
+ johnny juliet july jupiter kansas kentucky kilo king kitten lactose lake
28
+ lamp lemon leopard lima lion lithium london louisiana low magazine
29
+ magnesium maine mango march mars maryland massachusetts may mexico michigan
30
+ mike minnesota mirror mississippi missouri mobile mockingbird monkey
31
+ montana moon mountain muppet music nebraska neptune network nevada nine
32
+ nineteen nitrogen north november nuts october ohio oklahoma one orange
33
+ oranges oregon oscar oven oxygen papa paris pasta pennsylvania pip pizza
34
+ pluto potato princess purple quebec queen quiet red river robert robin
35
+ romeo rugby sad salami saturn september seven seventeen shade sierra single
36
+ sink six sixteen skylark snake social sodium solar south spaghetti speaker
37
+ spring stairway steak stream summer sweet table tango ten tennessee tennis
38
+ texas thirteen three timing triple twelve twenty two uncle undress uniform
39
+ uranus utah vegan venus vermont victor video violet virginia washington
40
+ west whiskey white william winner winter wisconsin wolfram wyoming xray
41
+ yankee yellow zebra zulu
42
+ )
43
+
44
+ def initialize(wordlist = DEFAULT_WORDLIST)
45
+ fail ArgumentError, 'Wordlist must have exactly 256 items' unless
46
+ wordlist.length == 256
47
+
48
+ @wordlist = wordlist
49
+ end
50
+
51
+
52
+ # Compress a list of byte values to a fixed target length.
53
+ #
54
+ # Attempting to compress a smaller number of bytes to a larger
55
+ # number is an error
56
+ def compress(bytes, target)
57
+ fail ArgumentError, 'Fewer input bytes than requested output' if
58
+ target > bytes.size
59
+
60
+ slices = slice_bytes bytes, target
61
+
62
+ # XOR checksum-like compression
63
+ slices.map do |slice|
64
+ slice.reduce :^
65
+ end
66
+ end
67
+
68
+ # Humanize a given hexadecimal digest.
69
+ #
70
+ # Change the number of words output by specifying `words`. Change the
71
+ # word separator with `separator`.
72
+ def humanize(hexdigest, words = 4, separator = '-')
73
+ bytes = hexdigest.split('')
74
+ .each_slice(2).to_a
75
+ bytes.pop if bytes.last.size == 1
76
+
77
+ bytes = bytes.map { |byte| byte.join('').to_i 16 }
78
+
79
+ wordify_bytes(bytes, words, separator)
80
+ end
81
+
82
+ # Generate a UUID with a human-readable representation.
83
+ #
84
+ # Returns `[human_repr, full_digest]`.
85
+ # Accepts the same keyword arguments as `humanize`
86
+ def uuid(*args)
87
+ digest = SecureRandom.uuid.delete '-'
88
+ word_hash = humanize digest, *args
89
+ [digest, word_hash]
90
+ end
91
+
92
+ private
93
+
94
+ def wordify_bytes(bytes, words, separator)
95
+ compress(bytes, words).map { |byte| wordlist[byte] }
96
+ .join separator
97
+ end
98
+
99
+ def slice_bytes(bytes, target)
100
+ slice_size = bytes.size / target
101
+ slices = bytes.each_slice(slice_size).to_a
102
+
103
+ # Catch any left-over bytes in the last segment.
104
+ extra = slices.pop(slices.size - target).flatten
105
+ slices.last.concat extra unless extra.empty?
106
+ slices
107
+ end
108
+ end
@@ -0,0 +1 @@
1
+ require_relative '../lib/human_hash'
@@ -0,0 +1,81 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe WordHash do
4
+ describe '#initialize' do
5
+ it 'requires a wordlist of length 256' do
6
+ expect { WordHash.new Array.new(255, 'word') }
7
+ .to raise_error ArgumentError
8
+
9
+ expect { WordHash.new Array.new(257, 'word') }
10
+ .to raise_error ArgumentError
11
+
12
+ expect { WordHash.new Array.new(256, 'word') }
13
+ .not_to raise_error
14
+ end
15
+
16
+ it 'will initialize with no args to use a default' do
17
+ expect { WordHash.new }.not_to raise_error
18
+ end
19
+ end
20
+
21
+ describe '#compress' do
22
+ it 'requires a byte list longer than the target length' do
23
+ expect { WordHash.new.compress [1, 2, 3], 4 }
24
+ .to raise_error ArgumentError
25
+ end
26
+
27
+ it do
28
+ bytes = [96, 173, 141, 13, 135, 27, 96, 149, 128, 130, 151]
29
+ expect(WordHash.new.compress bytes, 4).to eq [205, 128, 156, 96]
30
+ end
31
+
32
+ it do
33
+ bytes = [96, 173, 141, 13, 135, 27, 96, 149, 128, 130, 151]
34
+ expect(WordHash.new.compress bytes, 2).to eq [202, 123]
35
+ end
36
+
37
+ it do
38
+ bytes = [96, 173, 141, 13, 135, 27, 96, 149, 128, 130, 151]
39
+ expect(WordHash.new.compress bytes, 8)
40
+ .to eq [96, 173, 141, 13, 135, 27, 96, 0]
41
+ end
42
+
43
+ it do
44
+ bytes = [96, 173, 141, 13, 135, 149, 128, 130, 151]
45
+ expect(WordHash.new.compress bytes, 3).to eq [64, 31, 149]
46
+ end
47
+ end
48
+
49
+ describe '#humanize' do
50
+ it 'humanizes' do
51
+ digest = '60ad8d0d871b6095808297'
52
+ expect(WordHash.new.humanize digest)
53
+ .to eq 'sodium-magnesium-nineteen-hydrogen'
54
+ end
55
+
56
+ it do
57
+ expect(WordHash.new.humanize '60ad8d0d871b60958082971')
58
+ .to eq 'sodium-magnesium-nineteen-hydrogen'
59
+ end
60
+
61
+ it do
62
+ expect(WordHash.new.humanize '295734958734589739587')
63
+ .to eq 'low-october-princess-pennsylvania'
64
+ end
65
+
66
+ it do
67
+ expect(WordHash.new.humanize '2398532498572856792989')
68
+ .to eq 'robin-lemon-south-oregon'
69
+ end
70
+
71
+ it do
72
+ expect(WordHash.new.humanize '205934859384566493698')
73
+ .to eq 'lima-pluto-blossom-six'
74
+ end
75
+
76
+ it do
77
+ expect(WordHash.new.humanize '298234859234895734895389')
78
+ .to eq 'november-cat-vegan-georgia'
79
+ end
80
+ end
81
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wordhash
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Louis Pilfold
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.28'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.28'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.10'
55
+ description: |2-
56
+
57
+ wordhash: Human-readable representations of digests.
58
+
59
+ A clone of Zachary Voase's humanhash.
60
+ email: louis@lpil.uk
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - LICENCE
66
+ - README.md
67
+ - lib/word_hash.rb
68
+ - spec/spec_helper.rb
69
+ - spec/word_hash_spec.rb
70
+ homepage: http://github.com/lpil/wordhash
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.4.5
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Human-readable representations of digests
94
+ test_files:
95
+ - spec/spec_helper.rb
96
+ - spec/word_hash_spec.rb