rotp 1.4.5 → 1.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rotp.rb +1 -1
- data/lib/rotp/base32.rb +48 -0
- data/lib/rotp/otp.rb +1 -1
- data/lib/rotp/version.rb +1 -1
- data/rotp.gemspec +0 -1
- data/spec/base_spec.rb +22 -0
- metadata +2 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9938a2125556d7dcd7b8eae64d58d28e90a6d0f
|
4
|
+
data.tar.gz: 053694aa169605804930a516e41294e3b78b0fe4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62890466fe02ab700ce21c7f882a6f25fddeb9e35b0bd51ef5bd9567ae4a1decea947dc729c74852d8e0f471474686ac4fdad08f6c51600e83b1abb8608f8464
|
7
|
+
data.tar.gz: fedda9e325a1e7513907ee8a1b2314a97b0fb55e1c6f848fc122f73031473dfad630220a943ba27af700f7eeb2418d0d0951d42f488cee2839ccebf8ab6fa609
|
data/lib/rotp.rb
CHANGED
data/lib/rotp/base32.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module ROTP
|
2
|
+
class Base32
|
3
|
+
CHARS = "abcdefghijklmnopqrstuvwxyz234567".each_char.to_a
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def decode(str)
|
7
|
+
output = []
|
8
|
+
str.scan(/.{1,8}/).each do |block|
|
9
|
+
char_array = decode_block(block).map{|c| c.chr}
|
10
|
+
output << char_array
|
11
|
+
end
|
12
|
+
output.join
|
13
|
+
end
|
14
|
+
|
15
|
+
def random_base32(length=16)
|
16
|
+
b32 = ''
|
17
|
+
OpenSSL::Random.random_bytes(length).each_byte do |b|
|
18
|
+
b32 << CHARS[b % 32]
|
19
|
+
end
|
20
|
+
b32
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def decode_block(block)
|
26
|
+
length = block.scan(/[^=]/).length
|
27
|
+
quints = block.each_char.map {|c| decode_quint(c)}
|
28
|
+
bytes = []
|
29
|
+
bytes[0] = (quints[0] << 3) + (quints[1] ? quints[1] >> 2 : 0)
|
30
|
+
return bytes if length < 3
|
31
|
+
bytes[1] = ((quints[1] & 3) << 6) + (quints[2] << 1) + (quints[3] ? quints[3] >> 4 : 0)
|
32
|
+
return bytes if length < 4
|
33
|
+
bytes[2] = ((quints[3] & 15) << 4) + (quints[4] ? quints[4] >> 1 : 0)
|
34
|
+
return bytes if length < 6
|
35
|
+
bytes[3] = ((quints[4] & 1) << 7) + (quints[5] << 2) + (quints[6] ? quints[6] >> 3 : 0)
|
36
|
+
return bytes if length < 7
|
37
|
+
bytes[4] = ((quints[6] & 7) << 5) + (quints[7] || 0)
|
38
|
+
bytes
|
39
|
+
end
|
40
|
+
|
41
|
+
def decode_quint(q)
|
42
|
+
CHARS.index(q.downcase)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
data/lib/rotp/otp.rb
CHANGED
data/lib/rotp/version.rb
CHANGED
data/rotp.gemspec
CHANGED
@@ -20,7 +20,6 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
21
|
s.require_paths = ["lib"]
|
22
22
|
|
23
|
-
s.add_dependency('base32', '~> 0.2.0')
|
24
23
|
s.add_development_dependency('rake')
|
25
24
|
s.add_development_dependency('rspec')
|
26
25
|
if RUBY_VERSION < "1.9"
|
data/spec/base_spec.rb
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
+
describe "the Base32 implementation" do
|
4
|
+
it "should be 16 characters by default" do
|
5
|
+
ROTP::Base32.random_base32.length.should == 16
|
6
|
+
ROTP::Base32.random_base32.should match /\A[a-z2-7]+\z/
|
7
|
+
end
|
8
|
+
it "should be allow a specific length" do
|
9
|
+
ROTP::Base32.random_base32(32).length.should == 32
|
10
|
+
end
|
11
|
+
it "should correctly decode a string" do
|
12
|
+
ROTP::Base32.decode("F").unpack('H*').first.should == "28"
|
13
|
+
ROTP::Base32.decode("23").unpack('H*').first.should == "d6"
|
14
|
+
ROTP::Base32.decode("234").unpack('H*').first.should == "d6f8"
|
15
|
+
ROTP::Base32.decode("234A").unpack('H*').first.should == "d6f800"
|
16
|
+
ROTP::Base32.decode("234B").unpack('H*').first.should == "d6f810"
|
17
|
+
ROTP::Base32.decode("234BCD").unpack('H*').first.should == "d6f8110c"
|
18
|
+
ROTP::Base32.decode("234BCDE").unpack('H*').first.should == "d6f8110c80"
|
19
|
+
ROTP::Base32.decode("234BCDEFG").unpack('H*').first.should == "d6f8110c8530"
|
20
|
+
ROTP::Base32.decode("234BCDEFG234BCDEFG").unpack('H*').first.should == "d6f8110c8536b7c0886429"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
3
24
|
describe "HOTP example values from the rfc" do
|
4
25
|
it "should match the RFC" do
|
5
26
|
# 12345678901234567890 in Bas32
|
@@ -57,6 +78,7 @@ describe "TOTP example values from the rfc" do
|
|
57
78
|
end
|
58
79
|
end
|
59
80
|
|
81
|
+
|
60
82
|
it "should output its provisioning URI" do
|
61
83
|
totp = ROTP::TOTP.new("wrn3pqx5uqxqvnqr")
|
62
84
|
totp.provisioning_uri('mark@percival').should == "otpauth://totp/mark@percival?secret=wrn3pqx5uqxqvnqr"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rotp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Percival
|
@@ -10,20 +10,6 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2013-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: base32
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ~>
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 0.2.0
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ~>
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 0.2.0
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: rake
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -99,6 +85,7 @@ files:
|
|
99
85
|
- doc/method_list.html
|
100
86
|
- doc/top-level-namespace.html
|
101
87
|
- lib/rotp.rb
|
88
|
+
- lib/rotp/base32.rb
|
102
89
|
- lib/rotp/hotp.rb
|
103
90
|
- lib/rotp/otp.rb
|
104
91
|
- lib/rotp/totp.rb
|