rotp 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+ gemspec
3
+ gem 'rspec'
4
+ gem 'timecop'
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,8 @@
1
+ require 'rotp/otp'
2
+ require 'rotp/hotp'
3
+ require 'rotp/totp'
4
+ require 'base32'
5
+ require 'openssl'
6
+
7
+ module Rotp
8
+ end
@@ -0,0 +1,8 @@
1
+ module ROTP
2
+ class HOTP < OTP
3
+ def at(count)
4
+ generate_otp(count)
5
+ end
6
+ end
7
+
8
+ end
@@ -0,0 +1,37 @@
1
+ module ROTP
2
+ class OTP
3
+ attr_reader :secret, :digits, :digest
4
+
5
+ # Params: secret in base32
6
+ def initialize(s, options = {})
7
+ @digits = options[:digits] || 6
8
+ @digest = options[:digest] || "sha1"
9
+ @secret = options[:raw_secret] ? s : Base32.decode(s)
10
+ end
11
+
12
+ def generate_otp(count)
13
+ hmac = OpenSSL::HMAC.digest(
14
+ OpenSSL::Digest::Digest.new(digest),
15
+ secret,
16
+ int_to_bytestring(count)
17
+ )
18
+
19
+ offset = hmac[19] & 0xf
20
+ code = (hmac[offset] & 0x7f) << 24 |
21
+ (hmac[offset + 1] & 0xff) << 16 |
22
+ (hmac[offset + 2] & 0xff) << 8 |
23
+ (hmac[offset + 3] & 0xff)
24
+ code % 10 ** digits
25
+ end
26
+
27
+ def int_to_bytestring(int, padding = 8)
28
+ result = []
29
+ until int == 0
30
+ result << (int & 0xFF).chr
31
+ int >>= 8
32
+ end
33
+ result.reverse.join.rjust(8, 0.chr)
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,31 @@
1
+ module ROTP
2
+ class TOTP < OTP
3
+
4
+ attr_reader :interval
5
+
6
+ def initialize(s, options = {})
7
+ @interval = options[:interval] || 30
8
+ super
9
+ end
10
+
11
+ def at(time)
12
+ unless time.class == Time
13
+ time = Time.at(time.to_i)
14
+ end
15
+ generate_otp(timehash(time))
16
+ end
17
+
18
+ def now
19
+ generate_otp(timehash(Time.now))
20
+ end
21
+
22
+ private
23
+
24
+ def timehash(time)
25
+ i = time.utc.to_i * 1000
26
+ i = i / (interval * 1000)
27
+ i
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Rotp
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rotp/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rotp"
7
+ s.version = Rotp::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Mark Percival"]
10
+ s.email = ["mark@markpercival.us"]
11
+ s.homepage = ""
12
+ s.summary = %q{A Ruby library for generating and verifying one time passwords}
13
+ s.description = %q{Works for both HOTP and TOTP, and include QR Code provisioning}
14
+
15
+ s.rubyforge_project = "rotp"
16
+
17
+ s.add_dependency('base32', '0.1.2')
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe "HOTP example values from the rfc" do
4
+ it "should match the RFC" do
5
+ # 12345678901234567890 in Bas32
6
+ # GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ
7
+ hotp = ROTP::HOTP.new("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ")
8
+ hotp.at(0).should ==(755224)
9
+ hotp.at(1).should ==(287082)
10
+ hotp.at(2).should ==(359152)
11
+ hotp.at(3).should ==(969429)
12
+ hotp.at(4).should ==(338314)
13
+ hotp.at(5).should ==(254676)
14
+ hotp.at(6).should ==(287922)
15
+ hotp.at(7).should ==(162583)
16
+ hotp.at(8).should ==(399871)
17
+ hotp.at(9).should ==(520489)
18
+ end
19
+ end
20
+
21
+ describe "TOTP example values from the rfc" do
22
+ it "should match the RFC" do
23
+ totp = ROTP::TOTP.new("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ")
24
+ totp.at(1111111111).should ==(50471)
25
+ totp.at(1234567890).should ==(5924)
26
+ totp.at(2000000000).should ==(279037)
27
+ end
28
+
29
+ it "should match the Google Authenticator output" do
30
+ totp = ROTP::TOTP.new("wrn3pqx5uqxqvnqr")
31
+ Timecop.freeze(Time.at(1297553958)) do
32
+ totp.now.should ==(102705)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'timecop'
4
+
5
+ require 'rotp'
6
+
7
+ RSpec.configure do |config|
8
+ # some (optional) config here
9
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rotp
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Mark Percival
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-12 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: base32
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - "="
28
+ - !ruby/object:Gem::Version
29
+ hash: 31
30
+ segments:
31
+ - 0
32
+ - 1
33
+ - 2
34
+ version: 0.1.2
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: Works for both HOTP and TOTP, and include QR Code provisioning
38
+ email:
39
+ - mark@markpercival.us
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - Rakefile
50
+ - lib/rotp.rb
51
+ - lib/rotp/hotp.rb
52
+ - lib/rotp/otp.rb
53
+ - lib/rotp/totp.rb
54
+ - lib/rotp/version.rb
55
+ - rotp.gemspec
56
+ - spec/base_spec.rb
57
+ - spec/spec_helper.rb
58
+ has_rdoc: true
59
+ homepage: ""
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options: []
64
+
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ hash: 3
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ requirements: []
86
+
87
+ rubyforge_project: rotp
88
+ rubygems_version: 1.5.2
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: A Ruby library for generating and verifying one time passwords
92
+ test_files:
93
+ - spec/base_spec.rb
94
+ - spec/spec_helper.rb