rocra 0.0.1
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/.gitignore +21 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +59 -0
- data/Rakefile +5 -0
- data/lib/rocra.rb +217 -0
- data/lib/rocra/version.rb +3 -0
- data/rocra.gemspec +22 -0
- data/spec/rocra_spec.rb +86 -0
- metadata +78 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 phil
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
[](https://travis-ci.org/branch14/rocra)
|
2
|
+
|
3
|
+
_ __ ___ ___ _ __ __ _
|
4
|
+
| '__/ _ \ / __| '__/ _` |
|
5
|
+
| | | (_) | (__| | | (_| |
|
6
|
+
|_| \___/ \___|_| \__,_|
|
7
|
+
|
8
|
+
# Welcome to rocra
|
9
|
+
|
10
|
+
rocra is an OCRA (RFC 6287) implementation in Ruby.
|
11
|
+
|
12
|
+
see http://tools.ietf.org/html/rfc6287
|
13
|
+
|
14
|
+
It is based on the implementations found here https://github.com/SURFnet/ocra-implementations
|
15
|
+
|
16
|
+
## Installation
|
17
|
+
|
18
|
+
Add this line to your application's Gemfile:
|
19
|
+
|
20
|
+
gem 'rocra'
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install rocra
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
suite = 'OCRA-1:HOTP-SHA1-6:QN08' # string, mandatory
|
33
|
+
key = "3132333435363738393031323334353637383930" # hex, mandatory
|
34
|
+
counter = nil # hex, optional
|
35
|
+
question = '12345678'.to_i.to_s(16) # hex, mandatory
|
36
|
+
password = nil # hex, optional
|
37
|
+
session = nil # hex, optional
|
38
|
+
timestamp = nil # optional
|
39
|
+
|
40
|
+
Rocra.generate(suite, key, counter, question, password, session, timestamp)
|
41
|
+
|
42
|
+
## Specs
|
43
|
+
|
44
|
+
Run
|
45
|
+
|
46
|
+
rspec
|
47
|
+
|
48
|
+
## Contributing
|
49
|
+
|
50
|
+
1. Fork it
|
51
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
52
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
53
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
54
|
+
5. Create new Pull Request
|
55
|
+
|
56
|
+
## Todo
|
57
|
+
|
58
|
+
- fix jruby issues
|
59
|
+
- make api more rubyesque
|
data/Rakefile
ADDED
data/lib/rocra.rb
ADDED
@@ -0,0 +1,217 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
require "rocra/version"
|
4
|
+
|
5
|
+
class Rocra
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# This method generates an OCRA HOTP value for the given set of
|
10
|
+
# parameters.
|
11
|
+
#
|
12
|
+
# @param ocraSuite the OCRA Suite
|
13
|
+
# @param key the shared secret, HEX encoded
|
14
|
+
# @param counter the counter that changes
|
15
|
+
# on a per use basis,
|
16
|
+
# HEX encoded
|
17
|
+
# @param question the challenge question, HEX encoded
|
18
|
+
# @param password a password that can be used,
|
19
|
+
# HEX encoded
|
20
|
+
# @param sessionInformation
|
21
|
+
# Static information that identifies the
|
22
|
+
# current session, Hex encoded
|
23
|
+
# @param timestamp a value that reflects a time
|
24
|
+
#
|
25
|
+
# @return A numeric String in base 10 that includes
|
26
|
+
# {@link truncationDigits} digits
|
27
|
+
def generate(ocra_suite, key, counter, question, password, session_information, timestamp)
|
28
|
+
|
29
|
+
code_digits = 0
|
30
|
+
crypto = ""
|
31
|
+
result = nil
|
32
|
+
ocra_suite_length = ocra_suite.length
|
33
|
+
counter_length = 0
|
34
|
+
question_length = 0
|
35
|
+
password_length = 0
|
36
|
+
|
37
|
+
session_information_length = 0
|
38
|
+
timestamp_length = 0
|
39
|
+
|
40
|
+
# How many digits should we return
|
41
|
+
components = ocra_suite.split(':')
|
42
|
+
cryptoFunction = components[1]
|
43
|
+
dataInput = components[2].downcase # lower here so we can do case insensitive comparisons
|
44
|
+
|
45
|
+
crypto = 'sha1' if cryptoFunction.downcase.include?('sha1')
|
46
|
+
crypto = 'sha256' if cryptoFunction.downcase.include?('sha256')
|
47
|
+
crypto = 'sha512' if cryptoFunction.downcase.include?('sha512')
|
48
|
+
|
49
|
+
code_digits = cryptoFunction.split('-').last
|
50
|
+
|
51
|
+
# The size of the byte array message to be encrypted
|
52
|
+
|
53
|
+
# Counter
|
54
|
+
if dataInput[0,1] == "c"
|
55
|
+
# Fix the length of the HEX string
|
56
|
+
counter_length=8
|
57
|
+
counter = counter.rjust(16, '0')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Question
|
61
|
+
if dataInput[0,1] == "q" || dataInput.include?('-q')
|
62
|
+
question = question.ljust(256, '0')
|
63
|
+
question_length = 128
|
64
|
+
end
|
65
|
+
|
66
|
+
# Password
|
67
|
+
if dataInput.include?("psha1")
|
68
|
+
password = password.ljust(40, '0')
|
69
|
+
password_length = 20
|
70
|
+
end
|
71
|
+
|
72
|
+
if dataInput.include?("psha256")
|
73
|
+
password = password.ljust(64, '0')
|
74
|
+
password_length = 32
|
75
|
+
end
|
76
|
+
|
77
|
+
if dataInput.include?("psha512")
|
78
|
+
password = password.ljust(128, '0')
|
79
|
+
password_length = 64
|
80
|
+
end
|
81
|
+
|
82
|
+
# session_information
|
83
|
+
if dataInput.include?("s064")
|
84
|
+
session_information = session_information.ljust(128, '0')
|
85
|
+
session_information_length = 64
|
86
|
+
end
|
87
|
+
|
88
|
+
if dataInput.include?("s128")
|
89
|
+
session_information = session_information.ljust(256, '0')
|
90
|
+
session_information_length = 128
|
91
|
+
end
|
92
|
+
|
93
|
+
if dataInput.include?("s256")
|
94
|
+
session_information = session_information.ljust(512, '0')
|
95
|
+
session_information_length = 256
|
96
|
+
end
|
97
|
+
|
98
|
+
if dataInput.include?("s512")
|
99
|
+
session_information = session_information.ljust(128, '0')
|
100
|
+
session_information_length = 64
|
101
|
+
end
|
102
|
+
|
103
|
+
# TimeStamp
|
104
|
+
if dataInput[0,1] == "t" || dataInput.include?("-t")
|
105
|
+
timestamp = timestamp.rjust(16, '0')
|
106
|
+
timestamp_length = 8
|
107
|
+
end
|
108
|
+
|
109
|
+
# Put the bytes of "ocra_suite" parameters into the message
|
110
|
+
length = ocra_suite_length +
|
111
|
+
counter_length +
|
112
|
+
question_length +
|
113
|
+
password_length +
|
114
|
+
session_information_length +
|
115
|
+
timestamp_length + 1
|
116
|
+
msg = "\0" * length
|
117
|
+
msg[0, ocra_suite.length] = ocra_suite
|
118
|
+
|
119
|
+
# Delimiter
|
120
|
+
# msg[ocra_suite.length] = hex2str("0")
|
121
|
+
|
122
|
+
# Put the bytes of "Counter" to the message
|
123
|
+
# Input is HEX encoded
|
124
|
+
if counter_length > 0
|
125
|
+
pos = ocra_suite_length + 1
|
126
|
+
msg[pos, counter.length] = hex2str(counter)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Put the bytes of "question" to the message
|
130
|
+
# Input is text encoded
|
131
|
+
if question_length > 0
|
132
|
+
pos = ocra_suite_length + 1 + counter_length
|
133
|
+
msg[pos, question.length] = hex2str(question)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Put the bytes of "password" to the message
|
137
|
+
# Input is HEX encoded
|
138
|
+
if password_length > 0
|
139
|
+
pos = ocra_suite_length + 1 + counter_length + question_length
|
140
|
+
msg[pos, password.length] = hex2str(password)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Put the bytes of "session_information" to the message
|
144
|
+
# Input is text encoded
|
145
|
+
if session_information_length > 0
|
146
|
+
pos = ocra_suite_length + 1 + counter_length + question_length + password_length
|
147
|
+
msg[pos, session_information.length] = hex2str(session_information)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Put the bytes of "time" to the message
|
151
|
+
# Input is text value of minutes
|
152
|
+
if timestamp_length > 0
|
153
|
+
pos = ocra_suite_length + 1 + counter_length + question_length +
|
154
|
+
password_length + session_information_length
|
155
|
+
msg[pos, timestamp.length] = hex2str(timestamp)
|
156
|
+
end
|
157
|
+
|
158
|
+
byteKey = hex2str(key)
|
159
|
+
hash = hmac_sha1(crypto, byteKey, msg)
|
160
|
+
oath_truncate(hash, code_digits)
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
# Truncate a result to a certain length
|
167
|
+
#
|
168
|
+
# - hash is a hex string
|
169
|
+
def oath_truncate(hash, length = 6)
|
170
|
+
|
171
|
+
# Convert to array of decimals
|
172
|
+
hmac_result = hash.scan(/../).map { |e| e.hex }
|
173
|
+
|
174
|
+
# Find offset
|
175
|
+
offset = hmac_result.last & 0xf
|
176
|
+
|
177
|
+
v =
|
178
|
+
(hmac_result[offset + 0] & 0x7f) << 24 |
|
179
|
+
(hmac_result[offset + 1] & 0xff) << 16 |
|
180
|
+
(hmac_result[offset + 2] & 0xff) << 8 |
|
181
|
+
(hmac_result[offset + 3] & 0xff)
|
182
|
+
|
183
|
+
r = v % 10 ** length.to_i
|
184
|
+
|
185
|
+
"%0#{length}d" % r
|
186
|
+
end
|
187
|
+
|
188
|
+
# This method uses the hmac_hash function to provide the crypto
|
189
|
+
# algorithm.
|
190
|
+
# HMAC computes a Hashed Message Authentication Code with the
|
191
|
+
# crypto hash algorithm as a parameter.
|
192
|
+
#
|
193
|
+
# @param String crypto the crypto algorithm (sha1, sha256 or sha512)
|
194
|
+
# @param String keyBytes the bytes to use for the HMAC key
|
195
|
+
# @param String text the message or text to be authenticated.
|
196
|
+
#
|
197
|
+
def hmac_sha1(crypto, keyBytes, text)
|
198
|
+
digest = OpenSSL::Digest::Digest.new(crypto)
|
199
|
+
str2hex(OpenSSL::HMAC.digest(digest, keyBytes, text))
|
200
|
+
end
|
201
|
+
|
202
|
+
# This method converts HEX string to Byte[]
|
203
|
+
#
|
204
|
+
# @param String hex the HEX string
|
205
|
+
#
|
206
|
+
# @return String a string with raw bytes
|
207
|
+
def hex2str(hex)
|
208
|
+
[hex].pack('H*')
|
209
|
+
end
|
210
|
+
|
211
|
+
def str2hex(str)
|
212
|
+
str.unpack('H*').first
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
data/rocra.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rocra/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "rocra"
|
8
|
+
gem.version = Rocra::VERSION
|
9
|
+
gem.authors = ["Phil Hofmann"]
|
10
|
+
gem.email = ["phil@branch14.org"]
|
11
|
+
gem.description = %q{An OCRA (RFC 6287) implementation in Ruby}
|
12
|
+
gem.summary = %q{An OCRA (RFC 6287) implementation in Ruby}
|
13
|
+
gem.homepage = "https://github.com/branch14/rocra"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_development_dependency 'rake'
|
21
|
+
gem.add_development_dependency 'rspec'
|
22
|
+
end
|
data/spec/rocra_spec.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.expand_path('../../lib/rocra', __FILE__)
|
2
|
+
|
3
|
+
describe Rocra do
|
4
|
+
|
5
|
+
it 'should nicely translate binary strings into hex strings' do
|
6
|
+
Rocra.send(:str2hex, 'ab').should == '6162'
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should nicely translate hex strings into binary strings' do
|
10
|
+
Rocra.send(:hex2str, '6162').should == 'ab'
|
11
|
+
end
|
12
|
+
|
13
|
+
# examples from http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
|
14
|
+
it 'should nicely calculate hmac_sha1' do
|
15
|
+
Rocra.send(:hmac_sha1, 'sha1', '', '').should == 'fbdb1d1b18aa6c08324b7d64b71fb76370690e1d'
|
16
|
+
Rocra.send(:hmac_sha1, 'sha1', "key", "The quick brown fox jumps over the lazy dog").should ==
|
17
|
+
'de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9'
|
18
|
+
end
|
19
|
+
|
20
|
+
KEY_20 = "3132333435363738393031323334353637383930"
|
21
|
+
KEY_32 = "3132333435363738393031323334353637383930313233343536373839303132"
|
22
|
+
KEY_64 = "3132333435363738393031323334353637383930313233343536373839303132"+
|
23
|
+
"3334353637383930313233343536373839303132333435363738393031323334"
|
24
|
+
PIN_1234_HASH = "7110eda4d09e062aa5e4a390b0a572ac0d2c0220"
|
25
|
+
|
26
|
+
it 'should work for OCRA-1:HOTP-SHA1-6:QN08' do
|
27
|
+
suite = "OCRA-1:HOTP-SHA1-6:QN08"
|
28
|
+
Rocra.generate(suite, KEY_20, nil, '00000000'.to_i.to_s(16), nil, nil, nil).should == '237653'
|
29
|
+
Rocra.generate(suite, KEY_20, nil, '11111111'.to_i.to_s(16), nil, nil, nil).should == '243178'
|
30
|
+
Rocra.generate(suite, KEY_20, nil, '22222222'.to_i.to_s(16), nil, nil, nil).should == '653583'
|
31
|
+
Rocra.generate(suite, KEY_20, nil, '33333333'.to_i.to_s(16), nil, nil, nil).should == '740991'
|
32
|
+
Rocra.generate(suite, KEY_20, nil, '44444444'.to_i.to_s(16), nil, nil, nil).should == '608993'
|
33
|
+
Rocra.generate(suite, KEY_20, nil, '55555555'.to_i.to_s(16), nil, nil, nil).should == '388898'
|
34
|
+
Rocra.generate(suite, KEY_20, nil, '66666666'.to_i.to_s(16), nil, nil, nil).should == '816933'
|
35
|
+
Rocra.generate(suite, KEY_20, nil, '77777777'.to_i.to_s(16), nil, nil, nil).should == '224598'
|
36
|
+
Rocra.generate(suite, KEY_20, nil, '88888888'.to_i.to_s(16), nil, nil, nil).should == '750600'
|
37
|
+
Rocra.generate(suite, KEY_20, nil, '99999999'.to_i.to_s(16), nil, nil, nil).should == '294470'
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should work with counter' do
|
41
|
+
suite = "OCRA-1:HOTP-SHA256-8:C-QN08-PSHA1"
|
42
|
+
Rocra.generate(suite, KEY_32, "0", "12345678".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "65347737"
|
43
|
+
Rocra.generate(suite, KEY_32, "1", "12345678".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "86775851"
|
44
|
+
Rocra.generate(suite, KEY_32, "2", "12345678".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "78192410"
|
45
|
+
Rocra.generate(suite, KEY_32, "3", "12345678".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "71565254"
|
46
|
+
Rocra.generate(suite, KEY_32, "4", "12345678".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "10104329"
|
47
|
+
Rocra.generate(suite, KEY_32, "5", "12345678".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "65983500"
|
48
|
+
Rocra.generate(suite, KEY_32, "6", "12345678".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "70069104"
|
49
|
+
Rocra.generate(suite, KEY_32, "7", "12345678".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "91771096"
|
50
|
+
Rocra.generate(suite, KEY_32, "8", "12345678".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "75011558"
|
51
|
+
Rocra.generate(suite, KEY_32, "9", "12345678".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "08522129"
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should work for OCRA-1:HOTP-SHA256-8:QN08-PSHA1' do
|
55
|
+
suite = "OCRA-1:HOTP-SHA256-8:QN08-PSHA1"
|
56
|
+
Rocra.generate(suite, KEY_32, nil, "00000000".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "83238735"
|
57
|
+
Rocra.generate(suite, KEY_32, nil, "11111111".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "01501458"
|
58
|
+
Rocra.generate(suite, KEY_32, nil, "22222222".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "17957585"
|
59
|
+
Rocra.generate(suite, KEY_32, nil, "33333333".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "86776967"
|
60
|
+
Rocra.generate(suite, KEY_32, nil, "44444444".to_i.to_s(16), PIN_1234_HASH, nil, nil).should == "86807031"
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should work for OCRA-1:HOTP-SHA512-8:C-QN08' do
|
64
|
+
suite = "OCRA-1:HOTP-SHA512-8:C-QN08"
|
65
|
+
Rocra.generate(suite, KEY_64, "00000", "00000000".to_i.to_s(16), nil, nil, nil).should == "07016083"
|
66
|
+
Rocra.generate(suite, KEY_64, "00001", "11111111".to_i.to_s(16), nil, nil, nil).should == "63947962"
|
67
|
+
Rocra.generate(suite, KEY_64, "00002", "22222222".to_i.to_s(16), nil, nil, nil).should == "70123924"
|
68
|
+
Rocra.generate(suite, KEY_64, "00003", "33333333".to_i.to_s(16), nil, nil, nil).should == "25341727"
|
69
|
+
Rocra.generate(suite, KEY_64, "00004", "44444444".to_i.to_s(16), nil, nil, nil).should == "33203315"
|
70
|
+
Rocra.generate(suite, KEY_64, "00005", "55555555".to_i.to_s(16), nil, nil, nil).should == "34205738"
|
71
|
+
Rocra.generate(suite, KEY_64, "00006", "66666666".to_i.to_s(16), nil, nil, nil).should == "44343969"
|
72
|
+
Rocra.generate(suite, KEY_64, "00007", "77777777".to_i.to_s(16), nil, nil, nil).should == "51946085"
|
73
|
+
Rocra.generate(suite, KEY_64, "00008", "88888888".to_i.to_s(16), nil, nil, nil).should == "20403879"
|
74
|
+
Rocra.generate(suite, KEY_64, "00009", "99999999".to_i.to_s(16), nil, nil, nil).should == "31409299"
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should work for OCRA-1:HOTP-SHA512-8:QN08-T1M' do
|
78
|
+
suite = "OCRA-1:HOTP-SHA512-8:QN08-T1M"
|
79
|
+
Rocra.generate(suite, KEY_64, nil, "00000000".to_i.to_s(16), nil, nil, "132d0b6").should == "95209754"
|
80
|
+
Rocra.generate(suite, KEY_64, nil, "11111111".to_i.to_s(16), nil, nil, "132d0b6").should == "55907591"
|
81
|
+
Rocra.generate(suite, KEY_64, nil, "22222222".to_i.to_s(16), nil, nil, "132d0b6").should == "22048402"
|
82
|
+
Rocra.generate(suite, KEY_64, nil, "33333333".to_i.to_s(16), nil, nil, "132d0b6").should == "24218844"
|
83
|
+
Rocra.generate(suite, KEY_64, nil, "44444444".to_i.to_s(16), nil, nil, "132d0b6").should == "36209546"
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rocra
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Phil Hofmann
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &82726890 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *82726890
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &82726670 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *82726670
|
36
|
+
description: An OCRA (RFC 6287) implementation in Ruby
|
37
|
+
email:
|
38
|
+
- phil@branch14.org
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- .travis.yml
|
45
|
+
- Gemfile
|
46
|
+
- LICENSE.txt
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- lib/rocra.rb
|
50
|
+
- lib/rocra/version.rb
|
51
|
+
- rocra.gemspec
|
52
|
+
- spec/rocra_spec.rb
|
53
|
+
homepage: https://github.com/branch14/rocra
|
54
|
+
licenses: []
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.8.15
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: An OCRA (RFC 6287) implementation in Ruby
|
77
|
+
test_files:
|
78
|
+
- spec/rocra_spec.rb
|