totp 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (9) hide show
  1. checksums.yaml +7 -0
  2. data/.gems +2 -0
  3. data/LICENSE +19 -0
  4. data/README.md +59 -0
  5. data/lib/totp.rb +50 -0
  6. data/makefile +4 -0
  7. data/test/totp_test.rb +36 -0
  8. data/totp.gemspec +14 -0
  9. metadata +78 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dc0d44097f7757f0363bb7ce7eaa4f236f86b0eb
4
+ data.tar.gz: 18c991e130d749c77a59da809066fe869a4f4623
5
+ SHA512:
6
+ metadata.gz: bb98acd87360c4b57f497aa7216cd9ab45ec2f7291c07ba04dcbd58ecc73cb5e0411653a7b2a1441ed54c82966c5975ec7314a5fc80d57e084c7a9ec85692c23
7
+ data.tar.gz: 3b844ad850ebddad6940991f021cf7a17e57949f4df79dc636fbde0f6821d12397b747863bea4425ff34168441fa425b1a8482ff7a18396a88dc8206d0350934
data/.gems ADDED
@@ -0,0 +1,2 @@
1
+ base32 -v 0.3.2
2
+ cutest -v 1.2.1
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2014 Michel Martens
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,59 @@
1
+ # Time-based One-Time Passwords
2
+
3
+ This is an implementation of a Time-Based One-Time Password
4
+ Algorithm compatible with Google Authenticator. You can read more
5
+ about TOTP at http://tools.ietf.org/html/rfc6238.
6
+
7
+ ## Usage
8
+
9
+ Passwords are derived from a secret and a time. You can use the
10
+ `TOTP.secret` function to obtain a new, random secret.
11
+
12
+ ``` ruby
13
+ TOTP.secret #=> "YYZ27CO4WZTPZAYX"
14
+ ```
15
+
16
+ This helper is handy if you want to implement 2 factor
17
+ authentication in your application.
18
+
19
+ In order to generate time based one time passwords, you can use
20
+ the `TOTP.passwords` function:
21
+
22
+ ``` ruby
23
+ # Using the secret "AAAAAAAAAAAAAAAA" and the current time
24
+ TOTP.passwords("AAAAAAAAAAAAAAAA") #=> [783743, 17086, 955099]
25
+ ```
26
+
27
+ You can also provide a specific time or timestamp:
28
+
29
+ ``` ruby
30
+ # Using the same secret and a timestamp
31
+ passwords = TOTP.passwords("AAAAAAAAAAAAAAAA", 1400000000)
32
+
33
+ assert_equal [306281, 553572, 304383], passwords #=> true
34
+ ```
35
+
36
+ To check the validity of a given password, you can use the
37
+ `TOTP.valid?` function:
38
+
39
+ ``` ruby
40
+ TOTP.valid?(secret, password)
41
+ ```
42
+
43
+ If you want to check if a password was valid at a particular time,
44
+ you can provide a time object or a timestamp as a third argument:
45
+
46
+ ``` ruby
47
+ TOTP.valid?(secret, password, time)
48
+ ```
49
+
50
+ ## Installation
51
+
52
+ $ gem install totp
53
+
54
+ ### Acknowledgments
55
+
56
+ This library is inspired by the following implementations:
57
+
58
+ - https://gist.github.com/bithive/987839
59
+ - https://github.com/nricciar/google_authenticator_auth
@@ -0,0 +1,50 @@
1
+ require 'openssl'
2
+ require 'base32'
3
+
4
+ module TOTP
5
+
6
+ # Generate a random secret
7
+ def self.secret
8
+ return Base32.encode((0...10).map { rand(255).chr }.join)
9
+ end
10
+
11
+ # Return whether or not the key is valid for the given secret
12
+ def self.valid?(secret, pass, time = Time.now)
13
+ return self.passwords(secret, time).include?(pass)
14
+ end
15
+
16
+ def self.totp(hmac, time)
17
+ bytes = [time].pack('>q').reverse
18
+
19
+ hmac.reset
20
+ hmac.update(bytes)
21
+
22
+ code = hmac.digest
23
+ offs = code[-1].ord & 0x0F
24
+ hash = code[offs...offs + 4]
25
+
26
+ pass = hash.reverse.unpack('L')[0]
27
+ pass &= 0x7FFFFFFF
28
+ pass %= 1000000
29
+
30
+ return pass
31
+ end
32
+
33
+ # Generate passwords based on the secret and time
34
+ def self.passwords(secret, time = Time.now)
35
+
36
+ interval = time.to_i / 30
37
+
38
+ hmac = OpenSSL::HMAC.new(
39
+ Base32.decode(secret),
40
+ OpenSSL::Digest::SHA1.new,
41
+ )
42
+
43
+ # Cover three 30 second intervals
44
+ return [
45
+ totp(hmac, interval.pred),
46
+ totp(hmac, interval),
47
+ totp(hmac, interval.succ),
48
+ ]
49
+ end
50
+ end
@@ -0,0 +1,4 @@
1
+ test:
2
+ cutest ./test/*.rb
3
+
4
+ .PHONY: test
@@ -0,0 +1,36 @@
1
+ require_relative "../lib/totp"
2
+
3
+ test "normal usage" do
4
+ secret = TOTP.secret
5
+
6
+ # Secret is a string of size 16
7
+ assert_equal 16, secret.size
8
+ assert_equal String, secret.class
9
+
10
+ # Secret should be different on each call
11
+ assert secret != TOTP.secret
12
+
13
+ passwords = TOTP.passwords(secret)
14
+
15
+ # Passwords should be unique
16
+ assert_equal passwords.size, passwords.uniq.size
17
+
18
+ # Passwords should be valid
19
+ passwords.each do |pass|
20
+ assert TOTP.valid?(secret, pass)
21
+ end
22
+ end
23
+
24
+ test "usage with known values" do
25
+ secret = "AAAAAAAAAAAAAAAA"
26
+ time = 1400000000
27
+ known = [306281, 553572, 304383]
28
+
29
+ # Accepts an optional argument for time
30
+ passwords = TOTP.passwords(secret, time)
31
+
32
+ # Accepts an optional argument for time
33
+ assert TOTP.valid?(secret, known[0], time)
34
+
35
+ assert_equal known, passwords
36
+ end
@@ -0,0 +1,14 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "totp"
3
+ s.version = "1.0.0"
4
+ s.summary = "Time-based One-Time Passwords"
5
+ s.description = "Time-based One-Time Passwords"
6
+ s.authors = ["Michel Martens"]
7
+ s.email = ["michel@soveran.com"]
8
+ s.homepage = "http://github.com/soveran/totp"
9
+
10
+ s.files = `git ls-files`.split("\n")
11
+
12
+ s.add_dependency "base32"
13
+ s.add_development_dependency "cutest"
14
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: totp
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Michel Martens
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-09 00:00:00.000000000 Z
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'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: cutest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Time-based One-Time Passwords
42
+ email:
43
+ - michel@soveran.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gems
49
+ - LICENSE
50
+ - README.md
51
+ - lib/totp.rb
52
+ - makefile
53
+ - test/totp_test.rb
54
+ - totp.gemspec
55
+ homepage: http://github.com/soveran/totp
56
+ licenses: []
57
+ metadata: {}
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project:
74
+ rubygems_version: 2.0.3
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: Time-based One-Time Passwords
78
+ test_files: []