sixword 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc9f0517fd216584e553dc2e71e960bdd0b25848
4
- data.tar.gz: 31a69ccaf02db205bf290d384fe705491ac6be11
3
+ metadata.gz: 412a951ad1786d3f978ebc77305e6b7094004b36
4
+ data.tar.gz: 1a70321549259a131a8a10a536117d29a529110a
5
5
  SHA512:
6
- metadata.gz: 6d6cfc2a72925aaa382748c85d7e803668f5df4b9a41a6a1421ea3a26ffa738650f04013bb33ee6a6f9f5957cb09d1bf2c87610825249291d158d7d1846374c9
7
- data.tar.gz: 952b8f2e92c338863d39e39e59a83c41aae3e5c24e592ea770426d7353561624474be41a96869fd67c833b5f4963cda738d79e58cc89d9731c3b5700322c7c10
6
+ metadata.gz: 9a2ca1765246ff2b0df8e4ae6b6f8554abec1fbbf7c07478b5e9b36ea38e7b34cb22e352b8c49c4786e9ebaf85927a3d270c48f005fa7e8fba4a00ab24ea09b0
7
+ data.tar.gz: 0b44ad6d9bd5c7d2b7d0c5ddf9272357be00bf4e1917a46321c595afd72d754a33eae2eda1af3c503539f388427345b59d8ffc81e0505e544b139e910845d760
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --color
2
+ --require spec_helper
2
3
  --format progress
@@ -0,0 +1,174 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2015-11-21 23:48:38 -0800 using RuboCop version 0.35.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
10
+ Style/StringLiterals:
11
+ Enabled: false
12
+
13
+ # Offense count: 3
14
+ Lint/LiteralInCondition:
15
+ Enabled: false
16
+
17
+ # Offense count: 6
18
+ Metrics/AbcSize:
19
+ Max: 50
20
+
21
+ # Offense count: 1
22
+ Metrics/BlockNesting:
23
+ Max: 4
24
+
25
+ # Offense count: 1
26
+ # Configuration parameters: CountComments.
27
+ Metrics/ClassLength:
28
+ Enabled: false
29
+
30
+ # Offense count: 4
31
+ Metrics/CyclomaticComplexity:
32
+ Max: 15
33
+
34
+ # Offense count: 12
35
+ # Configuration parameters: CountComments.
36
+ Metrics/MethodLength:
37
+ Max: 45
38
+ Exclude:
39
+ - bin/sixword
40
+
41
+ # Offense count: 2
42
+ # Configuration parameters: CountComments.
43
+ Metrics/ModuleLength:
44
+ Enabled: false
45
+
46
+ # Offense count: 3
47
+ Metrics/PerceivedComplexity:
48
+ Max: 15
49
+
50
+ # Offense count: 256
51
+ # Cop supports --auto-correct.
52
+ Style/AlignArray:
53
+ Exclude:
54
+ - 'lib/sixword/words.rb'
55
+
56
+ # Offense count: 5
57
+ Style/ConstantName:
58
+ Enabled: false
59
+
60
+ # Configuration parameters: Exclude.
61
+ #
62
+ # We could re-enable this if it understood that the top level module should
63
+ # *not* be documented in files that are not the first to define it.
64
+ #
65
+ Style/Documentation:
66
+ Enabled: false
67
+ Exclude:
68
+ - 'spec/**/*'
69
+ - 'test/**/*'
70
+
71
+ # ********************************
72
+ # Disagree with these style points
73
+ # ********************************
74
+
75
+ Style/DotPosition:
76
+ Enabled: false
77
+ Style/DoubleNegation:
78
+ Enabled: false
79
+ Style/EmptyLines:
80
+ Enabled: false
81
+ Style/EmptyLinesAroundClassBody:
82
+ Enabled: false
83
+ Style/EmptyLinesAroundMethodBody:
84
+ Enabled: false
85
+ Style/EmptyLinesAroundModuleBody:
86
+ Enabled: false
87
+ Style/GuardClause:
88
+ Enabled: false
89
+
90
+ # Don't favor modifier style ever.
91
+ Style/IfUnlessModifier:
92
+ Enabled: false
93
+ Style/WhileUntilModifier:
94
+ Enabled: false
95
+
96
+ Style/InfiniteLoop:
97
+ Enabled: false
98
+ Style/PercentLiteralDelimiters:
99
+ PreferredDelimiters:
100
+ '%w': '{}'
101
+ '%W': '{}'
102
+ Style/RaiseArgs:
103
+ EnforcedStyle: compact
104
+ Style/RedundantReturn:
105
+ Enabled: false
106
+ Style/Alias:
107
+ Enabled: false
108
+ Style/SignalException:
109
+ EnforcedStyle: only_raise
110
+ Style/SpaceAroundEqualsInParameterDefault:
111
+ EnforcedStyle: no_space
112
+
113
+ # Arguable
114
+ # Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
115
+ Style/SpaceInsideBlockBraces:
116
+ Enabled: false
117
+
118
+ # Arguable
119
+ # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SupportedStyles.
120
+ Style/SpaceInsideHashLiteralBraces:
121
+ Enabled: false
122
+
123
+ # TODO this is affected by rubocop bug
124
+ # https://github.com/bbatsov/rubocop/issues/2448
125
+ #
126
+ # Offense count: 27
127
+ # Cop supports --auto-correct.
128
+ # Configuration parameters: EnforcedStyleForMultiline, SupportedStyles.
129
+ Style/TrailingComma:
130
+ # SupportedStyles:
131
+ # - comma
132
+ # - no_comma
133
+ EnforcedStyleForMultiline: comma
134
+
135
+ # Don't favor %w for arrays of words.
136
+ Style/WordArray:
137
+ Enabled: false
138
+
139
+ # ********************************
140
+
141
+ # Configuration parameters: AllowedVariables.
142
+ Style/GlobalVars:
143
+ Exclude:
144
+ - 'spec/spec_helper.rb'
145
+
146
+ # I disagree with this cop for the specific case of
147
+ # if !foo.empty?
148
+ # because I think it's a shame that ruby has no nonempty? predicate, and it's
149
+ # clearer if the double negative is all on the RHS.
150
+ #
151
+ Style/NegatedIf:
152
+ Exclude:
153
+ - 'lib/sixword/cli.rb'
154
+
155
+ # Torn on this one, not really sure what improves clarity.
156
+ # TODO
157
+ # Offense count: 7
158
+ # Cop supports --auto-correct.
159
+ Style/SpaceAfterColon:
160
+ Exclude:
161
+ - 'lib/sixword.rb'
162
+ - 'lib/sixword/cli.rb'
163
+
164
+ # Offense count: 2
165
+ Style/SpaceInsideBrackets:
166
+ Exclude:
167
+ - 'lib/sixword/words.rb'
168
+
169
+ # Offense count: 2
170
+ # Cop supports --auto-correct.
171
+ Style/SpecialGlobalVars:
172
+ Exclude:
173
+ - 'bin/sixword'
174
+ - 'sixword.gemspec'
@@ -0,0 +1,3 @@
1
+ ---
2
+ inherit_from:
3
+ - .rubocop-disables.yml
@@ -0,0 +1,40 @@
1
+ # Change Log
2
+ All notable changes to Sixword should be documented in this file.
3
+ This project adheres to [Semantic Versioning](http://semver.org).
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [0.3.2] -- 2015-11-25
8
+
9
+ - Add lots of documentation and a change log!
10
+ - Upgrade tests to rspec 3.
11
+ - Introduce rubocop style config and fix lots of warnings.
12
+ - Make `sixword --version` actually work.
13
+
14
+ ## [0.3.1] -- 2015-03-21
15
+
16
+ - Run tests on travis on various ruby versions.
17
+ - Fix tests on ruby 2.0+
18
+ - Add `-e` option flag to the CLI.
19
+
20
+ ## [0.3.0] -- 2014-07-10
21
+
22
+ - Fix handling of leading null bytes.
23
+
24
+ ## [0.2.0] -- 2013-09-27
25
+
26
+ - Add a command line interface, `sixword`.
27
+ - Handle various forms of hexadecimal notations, including colon or whitespace
28
+ delimited fingerprints.
29
+
30
+ ## [0.1.0] -- 2013-09-26
31
+
32
+ - Add and implement custom padding scheme for strings that are not a multiple
33
+ of 8 bytes.
34
+ - Add lots of tests and refactor the code.
35
+
36
+ ## [0.0.1] -- 2013-09-25
37
+
38
+ - Initial public release
39
+
40
+ <!-- vim: set tw=79 : -->
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # Sixword
2
2
 
3
- ![Build status](https://travis-ci.org/ab/sixword.svg)
3
+ [![Gem Version](https://badge.fury.io/rb/sixword.svg)](https://rubygems.org/gems/sixword)
4
+ [![Build status](https://travis-ci.org/ab/sixword.svg)](https://travis-ci.org/ab/sixword)
5
+ [![Code Climate](https://codeclimate.com/github/ab/sixword.svg)](https://codeclimate.com/github/ab/sixword)
6
+ [![Inline Docs](http://inch-ci.org/github/ab/sixword.svg?branch=master)](http://www.rubydoc.info/github/ab/sixword/master)
4
7
 
5
8
  Sixword implements the 6-word binary encoding created for S/Key (tm) and
6
9
  standardized by RFC 2289, RFC 1760, and RFC 1751. Binary data may be
@@ -46,9 +49,69 @@ Or install it yourself as:
46
49
 
47
50
  $ gem install sixword
48
51
 
49
- ## Usage
52
+ ## Usage: Command Line
50
53
 
51
- TODO: Write usage instructions here
54
+ Sixword operates similarly to `base64(1)`, it operates on a file or on STDIN in two modes:
55
+
56
+ - encode: accept binary data (or hexadecimal in hex modes) and print six-word
57
+ encoded data on stdout.
58
+ - decode: accept six-word encoded data and print binary data (or hex) on
59
+ stdout.
60
+
61
+ ### Examples
62
+
63
+ Normal encoding and decoding
64
+
65
+ $ sixword <<< 'Testing'
66
+ BEAK NET SITE ROTH SWIM FORM
67
+
68
+ $ sixword -d <<< 'BEAK NET SITE ROTH SWIM FORM'
69
+ Testing
70
+
71
+ $ sixword -d <<< 'beak net site roth swim form'
72
+ Testing
73
+
74
+ The same data, but hex encoded
75
+
76
+ $ sixword -H <<< '54:65:73:74:69:6e:67:0a'
77
+ BEAK NET SITE ROTH SWIM FORM
78
+
79
+ $ sixword -dH <<< 'BEAK NET SITE ROTH SWIM FORM'
80
+ 54657374696e670a
81
+
82
+ $ sixword -dF <<< 'BEAK NET SITE ROTH SWIM FORM'
83
+ 5465 7374 696E 670A
84
+
85
+ $ sixword -d -S colons <<< 'BEAK NET SITE ROTH SWIM FORM'
86
+ 54:65:73:74:69:6e:67:0a
87
+
88
+ Error handling
89
+
90
+ $ sixword -d <<< 'BEAK NET SITE ROTH SWIM FOR'
91
+ sixword: Parity bits do not match
92
+ [exit status 3]
93
+
94
+ $ sixword -p <<< '.'
95
+ sixword: Must pad bytes to multiple of 8 or use pad_encode
96
+
97
+ ## Usage: Library
98
+
99
+ See the [YARD documentation](http://www.rubydoc.info/github/ab/sixword/master).
100
+ The top-level `Sixword` module contains the main API (`Sixword.encode` and
101
+ `Sixword.decode`), while various utilities can be found in `Sixword::Hex` and
102
+ `Sixword::Lib`. Most of the code powering the command line interface is in
103
+ `Sixword::CLI`.
104
+
105
+ >> require 'sixword'
106
+
107
+ >> Sixword.encode('Hi world')
108
+ => ["ACRE", "ADEN", "INN", "SLID", "MAD", "PAP"]
109
+
110
+ >> Sixword.decode(["ACRE", "ADEN", "INN", "SLID", "MAD", "PAP"])
111
+ => 'Hi world'
112
+
113
+ >> Sixword.decode("acre aden inn slid mad pap")
114
+ => 'Hi world'
52
115
 
53
116
  ## Contributing
54
117
 
data/Rakefile CHANGED
@@ -13,4 +13,3 @@ def alias_task(alias_task, original)
13
13
  task alias_task, Rake.application[original].arg_names => original
14
14
  end
15
15
  alias_task(:test, :spec)
16
-
@@ -55,6 +55,10 @@ Options:
55
55
  $stderr.puts opts, ''
56
56
  exit 0
57
57
  end
58
+ opts.on('-v', '--version', 'Print version number', ' ') do
59
+ puts 'sixword ' + Sixword::VERSION
60
+ exit 0
61
+ end
58
62
 
59
63
  #
60
64
 
@@ -87,7 +91,12 @@ Options:
87
91
  end
88
92
  end
89
93
 
90
- optparse.parse!
94
+ begin
95
+ optparse.parse!
96
+ rescue OptionParser::InvalidOption => err
97
+ puts_err(err.message)
98
+ exit 1
99
+ end
91
100
 
92
101
  case ARGV.length
93
102
  when 0
@@ -4,43 +4,158 @@ require_relative 'sixword/lib'
4
4
  require_relative 'sixword/version'
5
5
  require_relative 'sixword/words'
6
6
 
7
+ # Sixword, a binary encoder using the 6-word scheme from S/key standardized by
8
+ # RFC 2289, RFC 1760, and RFC 1751.
9
+ #
10
+ # All of the public methods are static methods on the Sixword module, for
11
+ # example {Sixword.encode} and {Sixword.decode}.
12
+ #
13
+ # The <tt>sixword</tt> command line interface and corresponding {Sixword::CLI}
14
+ # class is also very convenient for more complex use. It supports a variety of
15
+ # different styles for translating binary data and hexadecimal fingerprints.
16
+ #
17
+ # These hexadecimal methods are implemented in the {Sixword::Hex} module.
18
+ #
7
19
  module Sixword
8
20
 
9
21
  # Parent class for inputs that could plausibly occur at runtime.
10
22
  class InputError < ArgumentError; end
11
23
 
24
+ # Raised when the parity check fails
12
25
  class InvalidParity < InputError; end
26
+
27
+ # Raised in decoding when an unrecognized word is encountered
13
28
  class UnknownWord < InputError; end
29
+
30
+ # Raised in decoding when a word of invalid format is encountered
14
31
  class InvalidWord < InputError; end
15
32
 
33
+ # Encode a string of bytes in six-word encoding. If you want to use the
34
+ # custom padding scheme for inputs that are not a multiple of 8 in length,
35
+ # use Sixword.pad_encode instead.
36
+ #
37
+ # @param byte_string [String] Length must be a multiple of 8
38
+ # @return [Array<String>] an array of string words
39
+ #
40
+ # @raise Sixword::InputError
41
+ #
42
+ # @see Sixword.encode_iter
43
+ #
44
+ # @example
45
+ # >> Sixword.encode('Hi world')
46
+ # => ["ACRE", "ADEN", "INN", "SLID", "MAD", "PAP"]
47
+ #
16
48
  def self.encode(byte_string)
17
- encode_to_a(byte_string)
49
+ encode_iter(byte_string).to_a
18
50
  end
19
51
 
52
+ # Encode a string of bytes in six-word encoding, using the custom padding
53
+ # scheme established by this library. The output will be identical to
54
+ # {Sixword.encode} for strings that are a multiple of 8 in length.
55
+ #
56
+ # @param byte_string [String] A string of any length
57
+ # @return [Array<String>] an array of string words
58
+ #
59
+ # @see Sixword.encode_iter
60
+ #
61
+ # @example
62
+ # >> Sixword.encode('Hi wor')
63
+ # => ["ACRE", "ADEN", "INN", "SLID", "MAD", "PAP"]
64
+ #
20
65
  def self.pad_encode(byte_string)
21
- pad_encode_to_a(byte_string)
66
+ encode_iter(byte_string, words_per_slice:1, pad:true).to_a
22
67
  end
23
68
 
69
+ # aliases for clarity on what the default encode(), pad_encode() return
70
+ class << self
71
+ alias_method :encode_to_a, :encode
72
+ alias_method :pad_encode_to_a, :pad_encode
73
+ end
74
+
75
+ # Like {Sixword.encode}, but return six words at a time (a complete block).
76
+ #
77
+ # @param byte_string [String] Length must be a multiple of 8
78
+ # @return [Array<String>] an array of 6-word string sentences
79
+ #
80
+ # @raise Sixword::InputError
81
+ #
82
+ # @example
83
+ # Sixword.encode_to_sentences('Hi world' * 2)
84
+ # => ["ACRE ADEN INN SLID MAD PAP",
85
+ # "ACRE ADEN INN SLID MAD PAP"]
86
+ #
87
+ # @see Sixword.encode
88
+ #
24
89
  def self.encode_to_sentences(byte_string)
25
90
  encode_iter(byte_string, words_per_slice:6).to_a
26
91
  end
27
92
 
93
+ # Like {Sixword.encode}, but return a single string.
94
+ #
95
+ # @param byte_string [String] Length must be a multiple of 8
96
+ # @return [String] a string of words separated by spaces
97
+ #
98
+ # @raise Sixword::InputError
99
+ #
100
+ # @example
101
+ # Sixword.encode_to_s('Hi world' * 2)
102
+ # => "ACRE ADEN INN SLID MAD PAP ACRE ADEN INN SLID MAD PAP"
103
+ #
104
+ # @see Sixword.encode
105
+ #
28
106
  def self.encode_to_s(byte_string)
29
107
  encode(byte_string).join(' ')
30
108
  end
31
109
 
32
- def self.encode_to_a(byte_string)
33
- encode_iter(byte_string).to_a
34
- end
35
-
36
- def self.pad_encode_to_a(byte_string)
37
- encode_iter(byte_string, words_per_slice:1, pad:true).to_a
38
- end
39
-
110
+ # Like {Sixword.encode_to_sentences}, but allow variable length input.
111
+ #
112
+ # @param byte_string [String] A string of any length
113
+ # @return [Array<String>] an array of 6-word string sentences
114
+ #
115
+ # @example
116
+ # >> Sixword.pad_encode_to_sentences('Hi worl' * 2)
117
+ # => ["ACRE ADEN INN SLID MAD LEW", "CODY AS SIGH SUIT MUDD ABE2"]
118
+ #
40
119
  def self.pad_encode_to_sentences(byte_string)
41
120
  encode_iter(byte_string, words_per_slice:6, pad:true).to_a
42
121
  end
43
122
 
123
+ # Like {Sixword.encode_to_s}, but allow variable length input.
124
+ #
125
+ # @param byte_string [String] A string of any length
126
+ # @return [String] a string of words separated by spaces
127
+ #
128
+ # @example
129
+ # >> Sixword.pad_encode_to_s('Hi worl' * 2)
130
+ # => "ACRE ADEN INN SLID MAD LEW CODY AS SIGH SUIT MUDD ABE2"
131
+ #
132
+ def self.pad_encode_to_s(byte_string)
133
+ pad_encode(byte_string).join(' ')
134
+ end
135
+
136
+ # Encode a string of bytes in six-word encoding (full API). This is the
137
+ # relatively low level method that supports all the major options. See the
138
+ # various other top-level methods for convenience helpers.
139
+ #
140
+ # @param byte_string [String] A byte string to encode
141
+ # @param options [Hash]
142
+ #
143
+ # @option options [Boolean] :pad (false) Whether to use the custom padding
144
+ # scheme established by this library. If false, then byte_string length
145
+ # must be a multiple of 8.
146
+ # @option options [Integer] :words_per_slice (1) The number of words to
147
+ # yield together in each iteration. By default, yield only a single word at
148
+ # a time. You can yield up to 6 words together, which will be joined by a
149
+ # space ` ` character.
150
+ #
151
+ # @yield [String] A String word (or String of space separated words, if
152
+ # :words_per_slice is given)
153
+ #
154
+ # @return [Enumerator, nil] If no block is given, return an Enumerator
155
+ #
156
+ # @raise Sixword::InputError on incorrectly padded inputs
157
+ # @raise ArgumentError on bad argument types
158
+ #
44
159
  def self.encode_iter(byte_string, options={})
45
160
  options = {words_per_slice: 1, pad: false}.merge(options)
46
161
  words_per_slice = options.fetch(:words_per_slice)
@@ -51,7 +166,7 @@ module Sixword
51
166
  end
52
167
 
53
168
  unless block_given?
54
- return Enumerator.new(self, :encode_iter, byte_string, options)
169
+ return to_enum(__method__, byte_string, options)
55
170
  end
56
171
 
57
172
  if !pad && byte_string.bytesize % 8 != 0
@@ -87,6 +202,39 @@ module Sixword
87
202
  end
88
203
  end
89
204
 
205
+ # Decode a six-word encoded string or string array.
206
+ #
207
+ # @param string_or_words [String, Array<String>] Either a String containing
208
+ # whitespace separated words or an Array of String words
209
+ # @param options [Hash]
210
+ #
211
+ # @option options [Boolean] :padding_ok (false) Whether to accept the custom
212
+ # padding format established by this library
213
+ #
214
+ # @return [String] A binary string of bytes
215
+ #
216
+ # @raise InputError if the input is malformed or invalid in various ways
217
+ #
218
+ # @example
219
+ # >> Sixword.decode("ACRE ADEN INN SLID MAD PAP")
220
+ # => "Hi world"
221
+ #
222
+ # @example
223
+ # >> Sixword.decode("acre aden inn slid mad pap")
224
+ # => "Hi world"
225
+ #
226
+ # @example
227
+ # Sixword.decode(%w{ACRE ADEN INN SLID MAD PAP})
228
+ # => "Hi world"
229
+ #
230
+ # @example
231
+ # Sixword.decode([])
232
+ # => ""
233
+ #
234
+ # @example
235
+ # Sixword.decode("COAT ACHE A A A ACT6", padding_ok: true)
236
+ # => "hi"
237
+ #
90
238
  def self.decode(string_or_words, options={})
91
239
  options = {padding_ok: false}.merge(options)
92
240
  padding_ok = options.fetch(:padding_ok)
@@ -110,6 +258,21 @@ module Sixword
110
258
  bstring
111
259
  end
112
260
 
261
+ # Like {Sixword.decode}, but allow input to contain custom padding scheme.
262
+ #
263
+ # @see Sixword.decode
264
+ #
265
+ # @param string_or_words [String, Array<String>] Either a String containing
266
+ # whitespace separated words or an Array of String words
267
+ #
268
+ # @return [String] A binary string of bytes
269
+ #
270
+ # @raise InputError if the input is malformed or invalid in various ways
271
+ #
272
+ # @example
273
+ # Sixword.decode("COAT ACHE A A A ACT6", padding_ok: true)
274
+ # => "hi"
275
+ #
113
276
  def self.pad_decode(string_or_words)
114
277
  decode(string_or_words, padding_ok: true)
115
278
  end