snuffleupagus 0.0.3
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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +19 -0
- data/README.md +36 -0
- data/Snuffy.png +0 -0
- data/lib/snuffleupagus/auth_token.rb +82 -0
- data/lib/snuffleupagus/version.rb +3 -0
- data/lib/snuffleupagus.rb +3 -0
- data/snuffleupagus.gemspec +19 -0
- data/spec/snuffleupagus_spec.rb +64 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e2673336e0bf2e923a6203b9068b5f6bb630a934
|
4
|
+
data.tar.gz: 56c409eeba11a75ceae8a975665dcbdf8f86a7a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 96fce7e91624f86d0b067338e82e9036f9e08940fc559a723609c0adc2c41db4b9ee3e593233802606c904d28652cd430ef1c2a72dbbf07be728c58ca5e607f4
|
7
|
+
data.tar.gz: 2327d6f3a086bfd3595906c69149c9d392a1e3aee79b6b58e7878dccf29307595fa5b64c236683f9818b2a1d68ceae2ff80d23b20d6b9548fe5abbd8d658ada7
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
Snuffleupagus
|
2
|
+
=============
|
3
|
+
|
4
|
+
A little simple.. auth token generator
|
5
|
+
|
6
|
+
Handles basic time-limited authentication token creation / validation
|
7
|
+
|
8
|
+
Uses Gibberish::AES with 256 bit CBC encryption
|
9
|
+
|
10
|
+

|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Include it in your Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'snuffleupagus', :git => 'git@github.com:TutoringAustralasia/snuffleupagus.git'
|
18
|
+
```
|
19
|
+
|
20
|
+
## Basic Usage
|
21
|
+
|
22
|
+
### Token creation
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
snuffy = Snuffleupagus::AuthToken.new('p4ssw0rd')
|
26
|
+
snuffy.create_token
|
27
|
+
#=> "53616c7465645f5f25dba4d4a97b238c4560ab46ffdfb77b28ad3e7121ab1917"
|
28
|
+
```
|
29
|
+
|
30
|
+
### Token validation
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
snuffy = Snuffleupagus::AuthToken.new('p4ssw0rd')
|
34
|
+
snuffy.check_token("53616c7465645f5f25dba4d4a97b238c4560ab46ffdfb77b28ad3e7121ab1917")
|
35
|
+
#=> true
|
36
|
+
```
|
data/Snuffy.png
ADDED
Binary file
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Snuffleupagus
|
2
|
+
# Handles basic time-limited authentication token creation / validation
|
3
|
+
#
|
4
|
+
# Uses Gibberish::AES with 256 bit CBC encryption
|
5
|
+
#
|
6
|
+
# ## Basic Usage
|
7
|
+
#
|
8
|
+
# ### Token creation
|
9
|
+
#
|
10
|
+
# snuffy = Snuffleupagus::AuthToken.new('p4ssw0rd')
|
11
|
+
# snuffy.create_token
|
12
|
+
# #=> "53616c7465645f5f25dba4d4a97b238c4560ab46ffdfb77b28ad3e7121ab1917"
|
13
|
+
#
|
14
|
+
# ### Token validation
|
15
|
+
#
|
16
|
+
# snuffy = Snuffleupagus::AuthToken.new('p4ssw0rd')
|
17
|
+
# snuffy.check_token("53616c7465645f5f25dba4d4a97b238c4560ab46ffdfb77b28ad3e7121ab1917")
|
18
|
+
# #=> true
|
19
|
+
#
|
20
|
+
class AuthToken
|
21
|
+
|
22
|
+
# tokens are only valid for 2 minutes
|
23
|
+
MAX_VALID_TIME_DIFFERENCE = 120
|
24
|
+
|
25
|
+
def initialize(key)
|
26
|
+
@key = key
|
27
|
+
@cipher = OpenSSL::Cipher::AES256.new :CBC
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_token
|
31
|
+
encode encrypt "#{CONSTANT}#{Time.now.to_i}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def check_token(token)
|
35
|
+
return false unless token && token.is_a?(String)
|
36
|
+
decoded = decrypt decode token
|
37
|
+
match = /^#{CONSTANT}([0-9]+)$/.match decoded
|
38
|
+
return false unless match
|
39
|
+
(match[1].to_i - Time.now.to_i).abs < MAX_VALID_TIME_DIFFERENCE
|
40
|
+
rescue
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
CONSTANT = 'date:'.freeze
|
47
|
+
|
48
|
+
attr_reader :cipher
|
49
|
+
|
50
|
+
def encrypt(data)
|
51
|
+
salt = generate_salt
|
52
|
+
setup_cipher(:encrypt, salt)
|
53
|
+
e = cipher.update(data) + cipher.final
|
54
|
+
"Salted__#{salt}#{e}" #OpenSSL compatible
|
55
|
+
end
|
56
|
+
|
57
|
+
def decrypt(data)
|
58
|
+
raise ArgumentError, 'Data is too short' unless data.length >= 16
|
59
|
+
salt = data[8..15]
|
60
|
+
data = data[16..-1]
|
61
|
+
setup_cipher(:decrypt, salt)
|
62
|
+
cipher.update(data) + cipher.final
|
63
|
+
end
|
64
|
+
|
65
|
+
def setup_cipher(method, salt)
|
66
|
+
cipher.send(method)
|
67
|
+
cipher.pkcs5_keyivgen(@key, salt, 1)
|
68
|
+
end
|
69
|
+
|
70
|
+
def generate_salt
|
71
|
+
8.times.map { rand(255).chr }.join
|
72
|
+
end
|
73
|
+
|
74
|
+
def encode(data)
|
75
|
+
Digest.hexencode(data) if data
|
76
|
+
end
|
77
|
+
|
78
|
+
def decode(hexstring)
|
79
|
+
hexstring.scan(/../).map { |n| n.to_i(16) }.pack('C*')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path('lib/snuffleupagus/version', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'snuffleupagus'
|
5
|
+
s.version = Snuffleupagus::VERSION
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.authors = [ 'Andrew Bromwich' ]
|
8
|
+
s.email = [ 'abromwich@studiosity.com' ]
|
9
|
+
s.homepage = 'https://studiosity.com'
|
10
|
+
s.description = 'Simple auth token generator/validator'
|
11
|
+
s.summary = "snuffleupagus-#{s.version}"
|
12
|
+
s.required_rubygems_version = '> 1.3.6'
|
13
|
+
|
14
|
+
s.add_development_dependency 'timecop'
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split($\)
|
17
|
+
s.executables = `git ls-files`.split("\n").map{ |f| f =~ /^bin\/(.*)/ ? $1 : nil }.compact
|
18
|
+
s.require_path = 'lib'
|
19
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require './lib/snuffleupagus'
|
2
|
+
require 'timecop'
|
3
|
+
|
4
|
+
describe Snuffleupagus::AuthToken do
|
5
|
+
let(:snuffy) { Snuffleupagus::AuthToken.new('sup3r4w3s0m3p4ssw0rd') }
|
6
|
+
|
7
|
+
describe '#create_token' do
|
8
|
+
subject { snuffy.create_token }
|
9
|
+
|
10
|
+
it { is_expected.to be_a String }
|
11
|
+
it { expect(subject.length).to eq 64 }
|
12
|
+
it { is_expected.to match /\A[a-f0-9]{64}\z/ }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#check_token' do
|
16
|
+
subject { snuffy.check_token(token) }
|
17
|
+
|
18
|
+
context 'with a valid token' do
|
19
|
+
let(:token) { snuffy.create_token }
|
20
|
+
it { is_expected.to be_truthy }
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'with an invalid token' do
|
24
|
+
let(:token) { 'F00B44' }
|
25
|
+
it { is_expected.to be_falsey }
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with an empty token' do
|
29
|
+
let(:token) { '' }
|
30
|
+
it { is_expected.to be_falsey }
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'with a nil token' do
|
34
|
+
let(:token) { nil }
|
35
|
+
it { is_expected.to be_falsey }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'testing expired tokens' do
|
39
|
+
let(:token) { snuffy.create_token }
|
40
|
+
before { token } # pre-load the token
|
41
|
+
after { Timecop.return }
|
42
|
+
|
43
|
+
context 'just inside the time difference (expired token)' do
|
44
|
+
before { Timecop.freeze Time.now - 119 }
|
45
|
+
it { is_expected.to be_truthy }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'just outside the time difference (expired token)' do
|
49
|
+
before { Timecop.freeze Time.now - 120 }
|
50
|
+
it { is_expected.to be_falsey }
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'just inside the time difference (future token)' do
|
54
|
+
before { Timecop.freeze Time.now + 119 }
|
55
|
+
it { is_expected.to be_truthy }
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'just outside the time difference (future token)' do
|
59
|
+
before { Timecop.freeze Time.now + 120 }
|
60
|
+
it { is_expected.to be_falsey }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: snuffleupagus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Bromwich
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-03-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: timecop
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Simple auth token generator/validator
|
28
|
+
email:
|
29
|
+
- abromwich@studiosity.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- ".gitignore"
|
35
|
+
- Gemfile
|
36
|
+
- Gemfile.lock
|
37
|
+
- README.md
|
38
|
+
- Snuffy.png
|
39
|
+
- lib/snuffleupagus.rb
|
40
|
+
- lib/snuffleupagus/auth_token.rb
|
41
|
+
- lib/snuffleupagus/version.rb
|
42
|
+
- snuffleupagus.gemspec
|
43
|
+
- spec/snuffleupagus_spec.rb
|
44
|
+
homepage: https://studiosity.com
|
45
|
+
licenses: []
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.3.6
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.6.14
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: snuffleupagus-0.0.3
|
67
|
+
test_files: []
|