yubikey 1.0.2 → 1.1.0
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.
- data/README.rdoc +20 -1
- data/ext/yubikey_ext/yubikey.h +0 -17
- data/lib/yubikey.rb +5 -1
- data/lib/yubikey/otp_verify.rb +44 -0
- data/spec/yubikey_otp_verify_spec.rb +38 -0
- metadata +6 -3
data/README.rdoc
CHANGED
@@ -5,7 +5,9 @@
|
|
5
5
|
A library to decode, decrypt and parse Yubikey[http://www.yubico.com/home/index/] one-time passwords.
|
6
6
|
|
7
7
|
== Usage
|
8
|
-
|
8
|
+
|
9
|
+
=== OTP Decryption
|
10
|
+
|
9
11
|
key = 'ecde18dbe76fbd0c33330f1c354871db'
|
10
12
|
otp = 'dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh'
|
11
13
|
token = Yubikey::OTP.new(otp, key)
|
@@ -16,7 +18,21 @@ A library to decode, decrypt and parse Yubikey[http://www.yubico.com/home/index/
|
|
16
18
|
p "Session activation counter: #{token.session_counter}" #=> 17
|
17
19
|
p "Session timestamp: #{token.timestamp}" #=> 49712
|
18
20
|
p "OTP random data: #{token.random_number}" #=> 40904
|
21
|
+
|
22
|
+
== OTP Verification
|
23
|
+
|
24
|
+
begin
|
25
|
+
otp = Yubikey::OTP::Verify.new('dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh')
|
19
26
|
|
27
|
+
if otp.valid?
|
28
|
+
p 'valid OTP'
|
29
|
+
elsif otp.replayed?
|
30
|
+
p 'replayed OTP'
|
31
|
+
end
|
32
|
+
rescue Yubikey::OTP::InvalidOTPError
|
33
|
+
p 'invalid OTP'
|
34
|
+
end
|
35
|
+
|
20
36
|
== Install
|
21
37
|
|
22
38
|
sudo gem install yubikey
|
@@ -28,6 +44,9 @@ A library to decode, decrypt and parse Yubikey[http://www.yubico.com/home/index/
|
|
28
44
|
Copyright (c) 2009 Jonathan Rudenberg
|
29
45
|
The MIT License. See LICENSE.
|
30
46
|
|
47
|
+
=== Contributors
|
48
|
+
Erik Ruwalder
|
49
|
+
|
31
50
|
=== AES, ModHex, and CRC code
|
32
51
|
Written by Simon Josefsson <simon@josefsson.org>
|
33
52
|
Copyright (c) 2006, 2007, 2008, 2009 Yubico AB
|
data/ext/yubikey_ext/yubikey.h
CHANGED
@@ -44,23 +44,6 @@
|
|
44
44
|
|
45
45
|
#define yubikey_crc_ok_p(tok) (yubikey_crc16 ((tok), YUBIKEY_BLOCK_SIZE) == YUBIKEY_CRC_OK_RESIDUE)
|
46
46
|
|
47
|
-
/*
|
48
|
-
* Low-level functions; ModHex.
|
49
|
-
*/
|
50
|
-
|
51
|
-
#define YUBIKEY_MODHEX_MAP "cbdefghijklnrtuv"
|
52
|
-
|
53
|
-
/* ModHex encode input string SRC of length SRCSIZE and put the zero
|
54
|
-
terminated output string in DST. The size of the output string DST
|
55
|
-
must be at least 2*SRCSIZE+1. The output string is always
|
56
|
-
2*SRCSIZE large plus the terminating zero. */
|
57
|
-
extern void yubikey_modhex_encode(char *dst, const char *src, size_t srcsize);
|
58
|
-
|
59
|
-
/* ModHex decode input string SRC of length DSTSIZE/2 into output
|
60
|
-
string DST. The output string DST is always DSTSIZE/2 large plus
|
61
|
-
the terminating zero. */
|
62
|
-
extern void yubikey_modhex_decode(char *dst, const char *src, size_t dstsize);
|
63
|
-
|
64
47
|
/* Low-level functions; AES. */
|
65
48
|
|
66
49
|
/* AES-decrypt one 16-byte block STATE using the 128-bit KEY, leaving
|
data/lib/yubikey.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__)) unless
|
2
2
|
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
3
|
|
4
|
+
require 'net/http'
|
5
|
+
require 'openssl'
|
6
|
+
|
4
7
|
require 'yubikey_ext'
|
5
8
|
require 'yubikey/hex'
|
6
9
|
require 'yubikey/modhex'
|
7
|
-
require 'yubikey/otp'
|
10
|
+
require 'yubikey/otp'
|
11
|
+
require 'yubikey/otp_verify'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Yubikey
|
2
|
+
|
3
|
+
API_URL = 'https://api.yubico.com/wsapi/'
|
4
|
+
API_ID = 2549
|
5
|
+
API_KEY = 'e928a7d3076516a8c8c879f42c3ea0388f3b19f'
|
6
|
+
|
7
|
+
class OTP::Verify
|
8
|
+
|
9
|
+
# The raw status from the Yubico server
|
10
|
+
attr_reader :status
|
11
|
+
|
12
|
+
def initialize(otp)
|
13
|
+
verify("id=#{API_ID}&otp=#{otp}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid?
|
17
|
+
@status == 'OK'
|
18
|
+
end
|
19
|
+
|
20
|
+
def replayed?
|
21
|
+
@status == 'REPLAYED_OTP'
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def verify(query)
|
27
|
+
uri = URI.parse(API_URL) + 'verify'
|
28
|
+
uri.query = query
|
29
|
+
|
30
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
31
|
+
http.use_ssl = true
|
32
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
33
|
+
|
34
|
+
req = Net::HTTP::Get.new(uri.request_uri)
|
35
|
+
result = http.request(req).body
|
36
|
+
|
37
|
+
@status = result[/status=(.*)$/,1].strip
|
38
|
+
|
39
|
+
if @status == 'BAD_OTP' || @status == 'BACKEND_ERROR'
|
40
|
+
raise OTP::InvalidOTPError, "Received error: #{@status}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end # OTP::Verify
|
44
|
+
end # Yubikey
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe 'Yubikey::OTP::Verify' do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@otp = 'dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh'
|
7
|
+
|
8
|
+
@mock_http = mock('http')
|
9
|
+
@mock_http_get = mock('http_get')
|
10
|
+
|
11
|
+
Net::HTTP.should_receive(:new).with('api.yubico.com', 443).and_return(@mock_http)
|
12
|
+
@mock_http.should_receive(:use_ssl=).and_return(nil)
|
13
|
+
@mock_http.should_receive(:verify_mode=).and_return(nil)
|
14
|
+
@mock_http.should_receive(:request).with(@mock_http_get).and_return(@mock_http_get)
|
15
|
+
Net::HTTP::Get.should_receive(:new).with(/otp=#{@otp}/).and_return(@mock_http_get)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should verify a valid OTP' do
|
19
|
+
@mock_http_get.should_receive(:body).and_return('status=OK')
|
20
|
+
otp = Yubikey::OTP::Verify.new(@otp)
|
21
|
+
otp.valid?.should == true
|
22
|
+
otp.replayed?.should == false
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should verify a replayed OTP' do
|
26
|
+
@mock_http_get.should_receive(:body).and_return('status=REPLAYED_OTP')
|
27
|
+
otp = Yubikey::OTP::Verify.new(@otp)
|
28
|
+
otp.valid?.should == false
|
29
|
+
otp.replayed?.should == true
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should raise on invalid OTP' do
|
33
|
+
@mock_http_get.should_receive(:body).and_return('status=BAD_OTP')
|
34
|
+
lambda { otp = Yubikey::OTP::Verify.new(@otp) }.should raise_error(Yubikey::OTP::InvalidOTPError)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yubikey
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Rudenberg
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04
|
12
|
+
date: 2009-06-04 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -34,12 +34,14 @@ files:
|
|
34
34
|
- lib/yubikey/hex.rb
|
35
35
|
- lib/yubikey/modhex.rb
|
36
36
|
- lib/yubikey/otp.rb
|
37
|
+
- lib/yubikey/otp_verify.rb
|
37
38
|
- spec/hex_spec.rb
|
38
39
|
- spec/spec.opts
|
39
40
|
- spec/spec_helper.rb
|
40
41
|
- spec/yubikey_ext_spec.rb
|
41
42
|
- spec/yubikey_modhex_spec.rb
|
42
43
|
- spec/yubikey_otp_spec.rb
|
44
|
+
- spec/yubikey_otp_verify_spec.rb
|
43
45
|
- LICENSE
|
44
46
|
- README.rdoc
|
45
47
|
has_rdoc: true
|
@@ -70,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
72
|
requirements: []
|
71
73
|
|
72
74
|
rubyforge_project: yubikey
|
73
|
-
rubygems_version: 1.3.
|
75
|
+
rubygems_version: 1.3.4
|
74
76
|
signing_key:
|
75
77
|
specification_version: 3
|
76
78
|
summary: A library to decode, decrypt and parse Yubikey one-time passwords.
|
@@ -80,4 +82,5 @@ test_files:
|
|
80
82
|
- spec/yubikey_ext_spec.rb
|
81
83
|
- spec/yubikey_modhex_spec.rb
|
82
84
|
- spec/yubikey_otp_spec.rb
|
85
|
+
- spec/yubikey_otp_verify_spec.rb
|
83
86
|
- examples/otp.rb
|