yubioath 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 45db1b97a74e59b31a8b0070d1722b18d548bb20
4
- data.tar.gz: 81ea24c84fac5bf8d48d79a9c2a01939f234d305
3
+ metadata.gz: f65371dc5c676a809ec0481fee24ed3b044acb12
4
+ data.tar.gz: b44a22b1b0e222ddd183d8dc76fbf9acaad74438
5
5
  SHA512:
6
- metadata.gz: 37e6029de7cf3bde37755f1a7ab9d52a343ff3bddddb0160e3dccd4b2e6cf3d51d8b5cfacb61b0232c1ba7393ec61570033c989e234b7ef368c125f6f3551f92
7
- data.tar.gz: 50f79cc8c96e6a53c199351b8c941f713dfc4afa52794aad6fd01cde1428cc4d8bde2c7bca58ee5a01e025e23922aa8e92e0320426239926fb0b27d9e0c1cf99
6
+ metadata.gz: ad49ada87e761639a55ae16752b476f68e636dd928409b751fdc9fe7dbe764d7f98493d56d2c149ae6e01bb0f4cb0ffe2b6d3e78210be69a678a22e78f54c580
7
+ data.tar.gz: 31d59e657ca027f7c315a3ea54202378e04479759a709f049228b4b4da5e00cad62ce42293aeb4d9e6bbe971d500f642c4e1bd5bc09cc3f7bd164004c367bfa3
data/Gemfile CHANGED
@@ -3,15 +3,9 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in yubioath.gemspec
4
4
  gemspec
5
5
 
6
- group :development do
7
- gem 'bundler'
8
- gem 'rake'
9
- gem 'rubocop'
10
- end
11
-
12
- group :test do
13
- gem 'rspec', '~> 3.3'
14
- gem 'rspec-its', '~> 1.2'
15
- gem 'rspec-the', '~> 1.0'
16
- gem 'smartcard', '~> 0.5.6'
17
- end
6
+ gem 'bundler', '~> 1.12'
7
+ gem 'rake', '~> 10.5'
8
+ gem 'rspec', '~> 3.3'
9
+ gem 'rspec-its', '~> 1.2'
10
+ gem 'rspec-the', '~> 1.0'
11
+ gem 'smartcard', '~> 0.5.6'
data/LICENSE.markdown CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015, James Ottaway
3
+ Copyright (c) 2016, James Ottaway
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -4,58 +4,49 @@ A mostly-complete Ruby implementation of the [YubiOATH applet protocol](https://
4
4
 
5
5
  ## Usage
6
6
 
7
- The `YubiOATH` class accepts a `card`, which must respond to `#transmit(apdu)`.
8
-
9
- You probably want to use [costan/smartcard](https://github.com/costan/smartcard).
10
-
11
- ```ruby
12
- yubioath = YubiOATH.new(card)
13
- ```
14
-
15
- ### Calculate
16
-
17
- Do calculate for one named code.
7
+ The `YubiOATH` class accepts a `card`, which must respond to `#transmit(apdu)`. See [costan/smartcard](https://github.com/costan/smartcard) for more info.
18
8
 
19
9
  ``` ruby
20
- yubioath.calculate(name: 'foo', timestamp: Time.now) # => '237893'
21
- ```
22
-
23
- ### Calculate All
24
-
25
- Do calculation for all available codes.
26
-
27
- ``` ruby
28
- yubioath.calculate_all(timestamp: Time.now) # => { 'foo' => '576238', 'bar' => '123895' }
29
- ```
30
-
31
- ### Delete
32
-
33
- Deletes an existing code.
34
-
35
- ``` ruby
36
- yubioath.delete(name: 'foo') # => true
37
- ```
38
-
39
- ### List
10
+ yubioath = YubiOATH.new(card)
40
11
 
41
- List configured codes.
12
+ yubioath.put(name: 'foo', secret: '123456') # => true
13
+ yubioath.calculate(name: 'foo', timestamp: Time.now) # => '237846'
42
14
 
43
- ``` ruby
44
- yubioath.list # => { 'foo' => { type: :totp, algorithm: :sha256 } }
45
- ```
15
+ yubioath.put(name: 'bar', secret: '345678') # => true
16
+ yubioath.put(name: 'qux', secret: '567890') # => true
17
+ yubioath.list.keys # => ['foo', 'bar', 'qux']
18
+ yubioath.calculate_all(timestamp: Time.now) # => {'foo' => '234526', 'bar' => '293857', 'qux' => '934856'}
46
19
 
47
- ### Put
20
+ yubioath.delete('qux') # => true
21
+ yubioath.list.keys # => ['foo', 'bar']
48
22
 
49
- Adds a new (or overwrites) OATH code.
50
-
51
- ``` ruby
52
- yubioath.put(name: 'foo', secret: 'bar', …) # => true
23
+ yubioath.reset # => true
24
+ yubioath.list.empty? # => true
53
25
  ```
54
26
 
55
- ### Reset
27
+ ### Instructions
56
28
 
57
- Reset the applet to just-installed state.
29
+ You can also trigger the instructions by instantiating the relevant class with a `card` and invoking its `#call` method.
58
30
 
59
31
  ``` ruby
60
- yubioath.reset # => true
32
+ calculate = YubiOATH::Calculate.new(card)
33
+ calculate_all = YubiOATH::CalculateAll.new(card)
34
+ delete = YubiOATH::Delete.new(card)
35
+ list = YubiOATH::List.new(card)
36
+ put = YubiOATH::Put.new(card)
37
+ reset = YubiOATH::Reset.new(card)
38
+
39
+ put.call(name: 'foo', secret: '123456') # => true
40
+ calculate.call(name: 'foo', timestamp: Time.now) # => '237846'
41
+
42
+ put.call(name: 'bar', secret: '345678') # => true
43
+ put.call(name: 'qux', secret: '567890') # => true
44
+ list.call.keys # => ['foo', 'bar', 'qux']
45
+ calculate_all.call(timestamp: Time.now) # => {'foo' => '234526', 'bar' => '293857', 'qux' => '934856'}
46
+
47
+ delete.call('qux') # => true
48
+ list.call.keys # => ['foo', 'bar']
49
+
50
+ reset.call # => true
51
+ list.call.empty? # => true
61
52
  ```
data/lib/yubioath.rb CHANGED
@@ -1,77 +1,40 @@
1
- require 'bindata'
2
- require 'yubioath/instructions'
3
- require 'yubioath/response'
1
+ require 'yubioath/calculate'
2
+ require 'yubioath/calculate_all'
3
+ require 'yubioath/delete'
4
+ require 'yubioath/list'
5
+ require 'yubioath/put'
6
+ require 'yubioath/reset'
7
+ require 'yubioath/select'
4
8
 
5
9
  class YubiOATH
6
10
  AID = [0xA0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x01, 0x01]
7
- ALGORITHMS = { SHA1: 0x1, SHA256: 0x2 }
8
- TYPES = { HOTP: 0x1, TOTP: 0x2 }
9
-
10
- RequestFailed = Class.new(StandardError)
11
11
 
12
12
  def initialize(card)
13
13
  @card = card
14
- select(AID)
14
+ Select.new(@card).call(aid: AID)
15
15
  end
16
16
 
17
- def calculate(name:, timestamp: Time.now)
18
- data = Calculate::Request::Data.new(name: name, timestamp: timestamp.to_i / 30)
19
- request = Calculate::Request.new(data: data.to_binary_s)
20
- response = Response.read(@card.transmit(request.to_binary_s))
21
- raise RequestFailed, response unless response.success?
22
- Calculate::Response.read(response.data).code.to_s
17
+ def calculate(name:, timestamp:)
18
+ Calculate.new(@card).call(name: name, timestamp: timestamp)
23
19
  end
24
20
 
25
- def calculate_all(timestamp: Time.now)
26
- data = CalculateAll::Request::Data.new(timestamp: timestamp.to_i / 30)
27
- request = CalculateAll::Request.new(data: data.to_binary_s)
28
- response = Response.read(@card.transmit(request.to_binary_s))
29
- raise RequestFailed, response unless response.success?
30
- CalculateAll::Response.read(response.data)[:codes].map do |code|
31
- [code.name, code.code.to_s]
32
- end.to_h
21
+ def calculate_all(timestamp:)
22
+ CalculateAll.new(@card).call(timestamp: timestamp)
33
23
  end
34
24
 
35
25
  def delete(name:)
36
- data = Delete::Request::Data.new(name: name)
37
- request = Delete::Request.new(data: data.to_binary_s)
38
- Response.read(@card.transmit(request.to_binary_s))
26
+ Delete.new(@card).call(name: name)
39
27
  end
40
28
 
41
29
  def list
42
- request = List::Request.new.to_binary_s
43
- response = Response.read(@card.transmit(request))
44
- raise RequestFailed, response unless response.success?
45
- List::Response.read(response.data)[:codes].map do |code|
46
- [code.name, {
47
- type: TYPES.key(code.type),
48
- algorithm: ALGORITHMS.key(code.algorithm),
49
- }]
50
- end.to_h
30
+ List.new(@card).call
51
31
  end
52
32
 
53
33
  def put(name:, secret:, algorithm: :SHA256, type: :TOTP, digits: 6)
54
- data = Put::Request::Data.new(
55
- name: name,
56
- type: TYPES.fetch(type),
57
- algorithm: ALGORITHMS.fetch(algorithm),
58
- digits: digits,
59
- secret: secret,
60
- )
61
- request = Put::Request.new(data: data.to_binary_s)
62
- Response.read(@card.transmit(request.to_binary_s))
63
- end
64
-
65
- def reset(confirm: false)
66
- Response.read(@card.transmit(Reset::Request.new.to_binary_s)) if confirm
34
+ Put.new(@card).call(name: name, secret: secret, algorithm: algorithm, type: type, digits: digits)
67
35
  end
68
36
 
69
- private
70
-
71
- def select(aid)
72
- request = Select::Request.new(aid: aid).to_binary_s
73
- response = Response.read(@card.transmit(request))
74
- raise RequestFailed, response unless response.success?
75
- Select::Response.read(response.data)
37
+ def reset
38
+ Reset.new(@card).call
76
39
  end
77
40
  end
@@ -0,0 +1,3 @@
1
+ class YubiOATH
2
+ ALGORITHMS = {SHA1: 0x1, SHA256: 0x2}
3
+ end
@@ -2,6 +2,18 @@ require 'bindata'
2
2
 
3
3
  class YubiOATH
4
4
  class Calculate
5
+ def initialize(card)
6
+ @card = card
7
+ end
8
+
9
+ def call(name:, timestamp:)
10
+ data = Request::Data.new(name: name, timestamp: timestamp.to_i / 30)
11
+ request = Request.new(data: data.to_binary_s)
12
+ bytes = @card.transmit(request.to_binary_s)
13
+ response = Response.read(bytes)
14
+ response.code.to_s
15
+ end
16
+
5
17
  class Request < BinData::Record
6
18
  uint8 :cla, value: 0x00
7
19
  uint8 :ins, value: 0xA2
@@ -2,6 +2,21 @@ require 'bindata'
2
2
 
3
3
  class YubiOATH
4
4
  class CalculateAll
5
+ def initialize(card)
6
+ @card = card
7
+ end
8
+
9
+ def call(timestamp:)
10
+ data = Request::Data.new(timestamp: timestamp.to_i / 30)
11
+ request = Request.new(data: data.to_binary_s)
12
+ bytes = @card.transmit(request.to_binary_s)
13
+ response = Response.read(bytes)
14
+
15
+ response[:codes].map do |code|
16
+ [code.name, code.code.to_s]
17
+ end.to_h
18
+ end
19
+
5
20
  class Request < BinData::Record
6
21
  uint8 :cla, value: 0x00
7
22
  uint8 :ins, value: 0xA4
@@ -1,7 +1,19 @@
1
1
  require 'bindata'
2
+ require 'yubioath/response'
2
3
 
3
4
  class YubiOATH
4
5
  class Delete
6
+ def initialize(card)
7
+ @card = card
8
+ end
9
+
10
+ def call(name:)
11
+ data = Request::Data.new(name: name)
12
+ request = Request.new(data: data.to_binary_s)
13
+ bytes = @card.transmit(request.to_binary_s)
14
+ Response.read(bytes).success?
15
+ end
16
+
5
17
  class Request < BinData::Record
6
18
  uint8 :cla, value: 0x00
7
19
  uint8 :ins, value: 0x02
data/lib/yubioath/list.rb CHANGED
@@ -1,7 +1,26 @@
1
1
  require 'bindata'
2
+ require 'yubioath/algorithms'
3
+ require 'yubioath/types'
2
4
 
3
5
  class YubiOATH
4
6
  class List
7
+ def initialize(card)
8
+ @card = card
9
+ end
10
+
11
+ def call
12
+ request = Request.new
13
+ bytes = @card.transmit(request.to_binary_s)
14
+ response = Response.read(bytes)
15
+
16
+ response[:codes].map do |code|
17
+ [code.name, {
18
+ type: TYPES.key(code.type),
19
+ algorithm: ALGORITHMS.key(code.algorithm),
20
+ }]
21
+ end.to_h
22
+ end
23
+
5
24
  class Request < BinData::Record
6
25
  uint8 :cla, value: 0x00
7
26
  uint8 :ins, value: 0xA1
data/lib/yubioath/put.rb CHANGED
@@ -1,7 +1,27 @@
1
1
  require 'bindata'
2
+ require 'yubioath/algorithms'
3
+ require 'yubioath/response'
4
+ require 'yubioath/types'
2
5
 
3
6
  class YubiOATH
4
7
  class Put
8
+ def initialize(card)
9
+ @card = card
10
+ end
11
+
12
+ def call(name:, secret:, algorithm:, type:, digits:)
13
+ data = Request::Data.new(
14
+ name: name,
15
+ type: TYPES.fetch(type),
16
+ algorithm: ALGORITHMS.fetch(algorithm),
17
+ digits: digits,
18
+ secret: secret,
19
+ )
20
+ request = Request.new(data: data.to_binary_s)
21
+ bytes = @card.transmit(request.to_binary_s)
22
+ Response.read(bytes).success?
23
+ end
24
+
5
25
  class Request < BinData::Record
6
26
  uint8 :cla, value: 0x00
7
27
  uint8 :ins, value: 0x01
@@ -1,7 +1,18 @@
1
1
  require 'bindata'
2
+ require 'yubioath/response'
2
3
 
3
4
  class YubiOATH
4
5
  class Reset
6
+ def initialize(card)
7
+ @card = card
8
+ end
9
+
10
+ def call
11
+ request = Reset::Request.new
12
+ bytes = @card.transmit(request.to_binary_s)
13
+ Response.read(bytes).success?
14
+ end
15
+
5
16
  class Request < BinData::Record
6
17
  uint8 :cla, value: 0x00
7
18
  uint8 :ins, value: 0x04
@@ -2,6 +2,16 @@ require 'bindata'
2
2
 
3
3
  class YubiOATH
4
4
  class Select
5
+ def initialize(card)
6
+ @card = card
7
+ end
8
+
9
+ def call(aid:)
10
+ request = Request.new(aid: aid)
11
+ bytes = @card.transmit(request.to_binary_s)
12
+ Response.read(bytes)
13
+ end
14
+
5
15
  class Request < BinData::Record
6
16
  uint8 :cla, value: 0x00
7
17
  uint8 :ins, value: 0xA4
@@ -0,0 +1,3 @@
1
+ class YubiOATH
2
+ TYPES = {HOTP: 0x1, TOTP: 0x2}
3
+ end
data/yubioath.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'yubioath'
7
- spec.version = '1.1.0'
7
+ spec.version = '1.2.0'
8
8
  spec.authors = ['James Ottaway']
9
9
  spec.email = ['yubioath@james.ottaway.io']
10
10
  spec.summary = 'A mostly-complete Ruby implementation of the YubiOATH applet protocol'
@@ -15,5 +15,5 @@ Gem::Specification.new do |spec|
15
15
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
16
16
  spec.require_paths = ['lib']
17
17
 
18
- spec.add_dependency 'bindata', '~> 2.1'
18
+ spec.add_dependency 'bindata', '~> 2.0'
19
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yubioath
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Ottaway
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-26 00:00:00.000000000 Z
11
+ date: 2016-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.1'
19
+ version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.1'
26
+ version: '2.0'
27
27
  description:
28
28
  email:
29
29
  - yubioath@james.ottaway.io
@@ -32,25 +32,22 @@ extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
34
  - ".gitignore"
35
- - ".rspec"
36
- - ".rubocop.yml"
37
- - ".rubocop_todo.yml"
38
35
  - ".ruby-version"
39
36
  - Gemfile
40
37
  - LICENSE.markdown
41
- - LICENSE.txt
42
38
  - README.md
43
39
  - Rakefile
44
40
  - lib/yubioath.rb
41
+ - lib/yubioath/algorithms.rb
45
42
  - lib/yubioath/calculate.rb
46
43
  - lib/yubioath/calculate_all.rb
47
44
  - lib/yubioath/delete.rb
48
- - lib/yubioath/instructions.rb
49
45
  - lib/yubioath/list.rb
50
46
  - lib/yubioath/put.rb
51
47
  - lib/yubioath/reset.rb
52
48
  - lib/yubioath/response.rb
53
49
  - lib/yubioath/select.rb
50
+ - lib/yubioath/types.rb
54
51
  - yubioath.gemspec
55
52
  homepage: https://github.com/jamesottaway/yubioath
56
53
  licenses:
@@ -72,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
69
  version: '0'
73
70
  requirements: []
74
71
  rubyforge_project:
75
- rubygems_version: 2.4.5
72
+ rubygems_version: 2.5.1
76
73
  signing_key:
77
74
  specification_version: 4
78
75
  summary: A mostly-complete Ruby implementation of the YubiOATH applet protocol
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --require spec_helper
data/.rubocop.yml DELETED
@@ -1,26 +0,0 @@
1
- inherit_from: .rubocop_todo.yml
2
-
3
- AllCops:
4
- Exclude:
5
- - 'yubioath.gemspec'
6
-
7
- Metrics/LineLength:
8
- Enabled: false
9
-
10
- Style/Documentation:
11
- Enabled: false
12
-
13
- Style/SpaceAroundOperators:
14
- Enabled: false
15
-
16
- Style/SpaceInsideHashLiteralBraces:
17
- Enabled: false
18
-
19
- Style/TrailingComma:
20
- EnforcedStyleForMultiline: comma
21
-
22
- Style/BracesAroundHashParameters:
23
- Enabled: false
24
-
25
- Style/IndentHash:
26
- Enabled: false
data/.rubocop_todo.yml DELETED
@@ -1,16 +0,0 @@
1
- # This configuration was generated by `rubocop --auto-gen-config`
2
- # on 2015-07-04 16:09:47 +1000 using RuboCop version 0.29.1.
3
- # The point is for the user to remove these configuration records
4
- # one by one as the offenses are removed from the code base.
5
- # Note that changes in the inspected code, or installation of new
6
- # versions of RuboCop, may require this file to be generated again.
7
-
8
- # Offense count: 2
9
- Metrics/AbcSize:
10
- Max: 19
11
-
12
- # Offense count: 6
13
- # Cop supports --auto-correct.
14
- # Configuration parameters: EnforcedStyle, SupportedStyles.
15
- Style/SignalException:
16
- Enabled: false
data/LICENSE.txt DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2015 James Ottaway
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,7 +0,0 @@
1
- require 'yubioath/calculate'
2
- require 'yubioath/calculate_all'
3
- require 'yubioath/delete'
4
- require 'yubioath/list'
5
- require 'yubioath/put'
6
- require 'yubioath/reset'
7
- require 'yubioath/select'