yubikey 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README.rdoc +33 -0
- data/examples/otp.rb +12 -0
- data/ext/yubikey_ext/extconf.rb +7 -0
- data/ext/yubikey_ext/ykaes.c +214 -0
- data/ext/yubikey_ext/ykcrc.c +54 -0
- data/ext/yubikey_ext/ykmodhex.c +76 -0
- data/ext/yubikey_ext/yubikey.h +75 -0
- data/ext/yubikey_ext/yubikey_ext.c +76 -0
- data/lib/yubikey/hex.rb +23 -0
- data/lib/yubikey/otp.rb +57 -0
- data/lib/yubikey.rb +6 -0
- data/spec/hex_spec.rb +27 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/yubikey_ext_spec.rb +48 -0
- data/spec/yubikey_otp_spec.rb +28 -0
- metadata +71 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2009 Jonathan Rudenberg
|
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 NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
= yubikey
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
A library to decode, decrypt and parse Yubikey[http://www.yubico.com/home/index/] one-time passwords.
|
6
|
+
|
7
|
+
== Usage
|
8
|
+
|
9
|
+
key = 'ecde18dbe76fbd0c33330f1c354871db'
|
10
|
+
otp = 'dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh'
|
11
|
+
token = Yubikey::OTP.new(otp, key)
|
12
|
+
|
13
|
+
p "Device public id: #{token.public_id}" #=> 'dteffuje'
|
14
|
+
p "Device secret id: #{token.secret_id}" #=> '8792ebfe26cc'
|
15
|
+
p "Device insertions: #{token.insert_counter}" #=> 19
|
16
|
+
p "Session activation counter: #{token.session_counter}" #=> 17
|
17
|
+
p "Session timestamp: #{token.timestamp}" #=> 49712
|
18
|
+
p "OTP random data: #{token.random_number}" #=> 40904
|
19
|
+
|
20
|
+
== Install
|
21
|
+
|
22
|
+
sudo gem install yubikey
|
23
|
+
|
24
|
+
== Copyright
|
25
|
+
|
26
|
+
=== Ruby library
|
27
|
+
Written by Jonathan Rudenberg <jon335@gmail.com>
|
28
|
+
Copyright (c) 2009 Jonathan Rudenberg
|
29
|
+
The MIT License. See LICENSE.
|
30
|
+
|
31
|
+
=== AES, ModHex, and CRC code
|
32
|
+
Written by Simon Josefsson <simon@josefsson.org>
|
33
|
+
Copyright (c) 2006, 2007, 2008, 2009 Yubico AB
|
data/examples/otp.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'yubikey'
|
2
|
+
|
3
|
+
key = 'ecde18dbe76fbd0c33330f1c354871db'
|
4
|
+
otp = 'dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh'
|
5
|
+
token = Yubikey::OTP.new(otp, key)
|
6
|
+
|
7
|
+
p "Device public id: #{token.public_id}"
|
8
|
+
p "Device secret id: #{token.secret_id}"
|
9
|
+
p "Device insertions: #{token.insert_counter}"
|
10
|
+
p "Session activation counter: #{token.session_counter}"
|
11
|
+
p "Session timestamp: #{token.timestamp}"
|
12
|
+
p "OTP random data: #{token.random_number}"
|
@@ -0,0 +1,214 @@
|
|
1
|
+
/* ykaes.c --- Implementation of AES-128.
|
2
|
+
*
|
3
|
+
* Copyright (c) 2006, 2007, 2008, 2009 Yubico AB
|
4
|
+
* All rights reserved.
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions are
|
8
|
+
* met:
|
9
|
+
*
|
10
|
+
* * Redistributions of source code must retain the above copyright
|
11
|
+
* notice, this list of conditions and the following disclaimer.
|
12
|
+
*
|
13
|
+
* * Redistributions in binary form must reproduce the above
|
14
|
+
* copyright notice, this list of conditions and the following
|
15
|
+
* disclaimer in the documentation and/or other materials provided
|
16
|
+
* with the distribution.
|
17
|
+
*
|
18
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
19
|
+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
20
|
+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
21
|
+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
22
|
+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
23
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
24
|
+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
26
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
27
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
28
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
*
|
30
|
+
*/
|
31
|
+
|
32
|
+
#include "yubikey.h"
|
33
|
+
|
34
|
+
#define NUMBER_OF_ROUNDS 10
|
35
|
+
|
36
|
+
static const uint8_t RC[] =
|
37
|
+
{ 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 };
|
38
|
+
|
39
|
+
static const uint8_t rijndael_sbox[] = {
|
40
|
+
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
|
41
|
+
0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
|
42
|
+
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
|
43
|
+
0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
|
44
|
+
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
|
45
|
+
0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
|
46
|
+
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
|
47
|
+
0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
|
48
|
+
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
|
49
|
+
0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
|
50
|
+
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
|
51
|
+
0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
|
52
|
+
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
|
53
|
+
0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
|
54
|
+
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
|
55
|
+
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
|
56
|
+
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
|
57
|
+
0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
|
58
|
+
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
|
59
|
+
0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
|
60
|
+
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
|
61
|
+
0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
|
62
|
+
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
|
63
|
+
0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
|
64
|
+
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
|
65
|
+
0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
|
66
|
+
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
|
67
|
+
0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
|
68
|
+
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
|
69
|
+
0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
|
70
|
+
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
|
71
|
+
0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
|
72
|
+
};
|
73
|
+
|
74
|
+
static const uint8_t rijndael_inv_sbox[] = {
|
75
|
+
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
|
76
|
+
0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
|
77
|
+
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
|
78
|
+
0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
|
79
|
+
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
|
80
|
+
0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
|
81
|
+
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
|
82
|
+
0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
|
83
|
+
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
|
84
|
+
0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
|
85
|
+
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
|
86
|
+
0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
|
87
|
+
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
|
88
|
+
0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
|
89
|
+
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
|
90
|
+
0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
|
91
|
+
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
|
92
|
+
0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
|
93
|
+
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
|
94
|
+
0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
|
95
|
+
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
|
96
|
+
0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
|
97
|
+
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
|
98
|
+
0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
|
99
|
+
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
|
100
|
+
0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
|
101
|
+
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
|
102
|
+
0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
|
103
|
+
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
|
104
|
+
0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
|
105
|
+
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
|
106
|
+
0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
|
107
|
+
};
|
108
|
+
|
109
|
+
static inline uint8_t
|
110
|
+
xtime (uint8_t b)
|
111
|
+
{
|
112
|
+
return (b & 0x80) ? ((b << 1) ^ 0x1b) : (b << 1);
|
113
|
+
}
|
114
|
+
|
115
|
+
void
|
116
|
+
yubikey_aes_decrypt (uint8_t * state, const uint8_t * key)
|
117
|
+
{
|
118
|
+
uint8_t i, j, round_key[0x10];
|
119
|
+
uint8_t a02x, a13x;
|
120
|
+
uint8_t a02xx, a13xx;
|
121
|
+
uint8_t k1, k2;
|
122
|
+
|
123
|
+
memcpy (round_key, key, sizeof (round_key));
|
124
|
+
for (i = 0; i < NUMBER_OF_ROUNDS; i++)
|
125
|
+
{
|
126
|
+
round_key[0] ^= RC[i];
|
127
|
+
|
128
|
+
round_key[0] ^= rijndael_sbox[round_key[13]];
|
129
|
+
round_key[1] ^= rijndael_sbox[round_key[14]];
|
130
|
+
round_key[2] ^= rijndael_sbox[round_key[15]];
|
131
|
+
round_key[3] ^= rijndael_sbox[round_key[12]];
|
132
|
+
|
133
|
+
for (j = 4; j < 16; j++)
|
134
|
+
round_key[j] ^= round_key[j - 4];
|
135
|
+
}
|
136
|
+
for (i = 0; i < 0x10; i++)
|
137
|
+
state[i] ^= round_key[i];
|
138
|
+
|
139
|
+
for (i = 1; i <= NUMBER_OF_ROUNDS; i++)
|
140
|
+
{
|
141
|
+
// inv_byte_sub_shift_row();
|
142
|
+
|
143
|
+
/* First row: 0 shift, 0 4 8 12 */
|
144
|
+
state[0] = rijndael_inv_sbox[state[0]];
|
145
|
+
state[4] = rijndael_inv_sbox[state[4]];
|
146
|
+
state[8] = rijndael_inv_sbox[state[8]];
|
147
|
+
state[12] = rijndael_inv_sbox[state[12]];
|
148
|
+
|
149
|
+
/* Second row: -1 shift, 1 5 9 13 */
|
150
|
+
j = state[13];
|
151
|
+
state[13] = rijndael_inv_sbox[state[9]];
|
152
|
+
state[9] = rijndael_inv_sbox[state[5]];
|
153
|
+
state[5] = rijndael_inv_sbox[state[1]];
|
154
|
+
state[1] = rijndael_inv_sbox[j];
|
155
|
+
|
156
|
+
/* Third row: -2 shift, 2 6 10 14 */
|
157
|
+
j = state[2];
|
158
|
+
state[2] = rijndael_inv_sbox[state[10]];
|
159
|
+
state[10] = rijndael_inv_sbox[j];
|
160
|
+
j = state[6];
|
161
|
+
state[6] = rijndael_inv_sbox[state[14]];
|
162
|
+
state[14] = rijndael_inv_sbox[j];
|
163
|
+
|
164
|
+
/* Fourth row: -3 shift, 3 7 11 15 */
|
165
|
+
j = state[3];
|
166
|
+
state[3] = rijndael_inv_sbox[state[7]];
|
167
|
+
state[7] = rijndael_inv_sbox[state[11]];
|
168
|
+
state[11] = rijndael_inv_sbox[state[15]];
|
169
|
+
state[15] = rijndael_inv_sbox[j];
|
170
|
+
|
171
|
+
// get_inv_round_key(i);
|
172
|
+
|
173
|
+
for (j = 15; j > 3; j--)
|
174
|
+
round_key[j] ^= round_key[j - 4];
|
175
|
+
|
176
|
+
round_key[0] ^=
|
177
|
+
(RC[NUMBER_OF_ROUNDS - i] ^ rijndael_sbox[round_key[13]]);
|
178
|
+
|
179
|
+
round_key[1] ^= rijndael_sbox[round_key[14]];
|
180
|
+
round_key[2] ^= rijndael_sbox[round_key[15]];
|
181
|
+
round_key[3] ^= rijndael_sbox[round_key[12]];
|
182
|
+
|
183
|
+
for (j = 0; j < 16; j++)
|
184
|
+
state[j] ^= round_key[j];
|
185
|
+
if (i != NUMBER_OF_ROUNDS)
|
186
|
+
{
|
187
|
+
|
188
|
+
//inv_mix_column();
|
189
|
+
|
190
|
+
for (j = 0; j < 16; j += 4)
|
191
|
+
{
|
192
|
+
k1 = state[j] ^ state[j + 2];
|
193
|
+
a02x = xtime (k1);
|
194
|
+
k2 = state[j + 1] ^ state[j + 3];
|
195
|
+
a13x = xtime (k2);
|
196
|
+
|
197
|
+
k1 ^= (k2 ^ xtime (state[j + 1] ^ state[j + 2]));
|
198
|
+
k2 = k1;
|
199
|
+
|
200
|
+
a02xx = xtime (a02x);
|
201
|
+
a13xx = xtime (a13x);
|
202
|
+
|
203
|
+
k1 ^= (xtime (a02xx ^ a13xx) ^ a02xx);
|
204
|
+
k2 ^= (xtime (a02xx ^ a13xx) ^ a13xx);
|
205
|
+
|
206
|
+
state[j] ^= (k1 ^ a02x);
|
207
|
+
state[j + 1] ^= k2;
|
208
|
+
state[j + 2] ^= (k1 ^ a13x);
|
209
|
+
state[j + 3] ^= (k2 ^ a02x ^ a13x);
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
}
|
214
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
/* ykcrc.c --- Implementation of Yubikey CRC-16 function.
|
2
|
+
*
|
3
|
+
* Written by Simon Josefsson <simon@josefsson.org>.
|
4
|
+
* Copyright (c) 2006, 2007, 2008, 2009 Yubico AB
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions are
|
9
|
+
* met:
|
10
|
+
*
|
11
|
+
* * Redistributions of source code must retain the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer.
|
13
|
+
*
|
14
|
+
* * Redistributions in binary form must reproduce the above
|
15
|
+
* copyright notice, this list of conditions and the following
|
16
|
+
* disclaimer in the documentation and/or other materials provided
|
17
|
+
* with the distribution.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
20
|
+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
21
|
+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
22
|
+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
23
|
+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
25
|
+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
26
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
27
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
*
|
31
|
+
*/
|
32
|
+
|
33
|
+
#include "yubikey.h"
|
34
|
+
|
35
|
+
uint16_t
|
36
|
+
yubikey_crc16 (const uint8_t *buf, size_t buf_size)
|
37
|
+
{
|
38
|
+
uint16_t m_crc = 0xffff;
|
39
|
+
|
40
|
+
while (buf_size--)
|
41
|
+
{
|
42
|
+
int i, j;
|
43
|
+
m_crc ^= (uint8_t) * buf++ & 0xFF;
|
44
|
+
for (i = 0; i < 8; i++)
|
45
|
+
{
|
46
|
+
j = m_crc & 1;
|
47
|
+
m_crc >>= 1;
|
48
|
+
if (j)
|
49
|
+
m_crc ^= 0x8408;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
return m_crc;
|
54
|
+
}
|
@@ -0,0 +1,76 @@
|
|
1
|
+
/* ykmodhex.c --- Implementation of modhex encoding/decoding
|
2
|
+
*
|
3
|
+
* Written by Simon Josefsson <simon@josefsson.org>.
|
4
|
+
* Copyright (c) 2006, 2007, 2008, 2009 Yubico AB
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions are
|
9
|
+
* met:
|
10
|
+
*
|
11
|
+
* * Redistributions of source code must retain the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer.
|
13
|
+
*
|
14
|
+
* * Redistributions in binary form must reproduce the above
|
15
|
+
* copyright notice, this list of conditions and the following
|
16
|
+
* disclaimer in the documentation and/or other materials provided
|
17
|
+
* with the distribution.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
20
|
+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
21
|
+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
22
|
+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
23
|
+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
25
|
+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
26
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
27
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
*
|
31
|
+
*/
|
32
|
+
|
33
|
+
#include "yubikey.h"
|
34
|
+
|
35
|
+
#include <stdbool.h>
|
36
|
+
|
37
|
+
static const char trans[] = YUBIKEY_MODHEX_MAP;
|
38
|
+
|
39
|
+
void
|
40
|
+
yubikey_modhex_encode (char *dst, const char *src, size_t srcSize)
|
41
|
+
{
|
42
|
+
while (srcSize--)
|
43
|
+
{
|
44
|
+
*dst++ = trans[(*src >> 4) & 0xf];
|
45
|
+
*dst++ = trans[*src++ & 0xf];
|
46
|
+
}
|
47
|
+
|
48
|
+
*dst = '\0';
|
49
|
+
}
|
50
|
+
|
51
|
+
void
|
52
|
+
yubikey_modhex_decode (char *dst, const char *src, size_t dstSize)
|
53
|
+
{
|
54
|
+
char b;
|
55
|
+
bool flag = false;
|
56
|
+
char *p1;
|
57
|
+
|
58
|
+
for (; *src && dstSize > 0; src++)
|
59
|
+
{
|
60
|
+
if ((p1 = strchr (trans, *src)) == NULL)
|
61
|
+
b = 0;
|
62
|
+
else
|
63
|
+
b = (char) (p1 - trans);
|
64
|
+
|
65
|
+
if ((flag = !flag))
|
66
|
+
*dst = b;
|
67
|
+
else
|
68
|
+
{
|
69
|
+
*dst = (*dst << 4) | b;
|
70
|
+
dst++;
|
71
|
+
dstSize--;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
while (dstSize--)
|
75
|
+
*dst++ = 0;
|
76
|
+
}
|
@@ -0,0 +1,75 @@
|
|
1
|
+
/* yubikey.h --- Prototypes for low-level Yubikey OTP functions.
|
2
|
+
*
|
3
|
+
* Written by Simon Josefsson <simon@josefsson.org>.
|
4
|
+
* Copyright (c) 2006, 2007, 2008, 2009 Yubico AB
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions are
|
9
|
+
* met:
|
10
|
+
*
|
11
|
+
* * Redistributions of source code must retain the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer.
|
13
|
+
*
|
14
|
+
* * Redistributions in binary form must reproduce the above
|
15
|
+
* copyright notice, this list of conditions and the following
|
16
|
+
* disclaimer in the documentation and/or other materials provided
|
17
|
+
* with the distribution.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
20
|
+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
21
|
+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
22
|
+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
23
|
+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
25
|
+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
26
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
27
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
28
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
*
|
31
|
+
*/
|
32
|
+
|
33
|
+
#ifndef YUBIKEY_H
|
34
|
+
#define YUBIKEY_H
|
35
|
+
|
36
|
+
#include <stdint.h>
|
37
|
+
#include <string.h>
|
38
|
+
|
39
|
+
#define YUBIKEY_BLOCK_SIZE 16
|
40
|
+
#define YUBIKEY_KEY_SIZE 16
|
41
|
+
#define YUBIKEY_UID_SIZE 6
|
42
|
+
|
43
|
+
#define YUBIKEY_CRC_OK_RESIDUE 0xf0b8
|
44
|
+
|
45
|
+
#define yubikey_crc_ok_p(tok) (yubikey_crc16 ((tok), YUBIKEY_BLOCK_SIZE) == YUBIKEY_CRC_OK_RESIDUE)
|
46
|
+
|
47
|
+
/*
|
48
|
+
* Low-level functions; ModHex.
|
49
|
+
*/
|
50
|
+
|
51
|
+
#define YUBIKEY_MODHEX_MAP "cbdefghijklnrtuv"
|
52
|
+
|
53
|
+
/* ModHex encode input string SRC of length SRCSIZE and put the zero
|
54
|
+
terminated output string in DST. The size of the output string DST
|
55
|
+
must be at least 2*SRCSIZE+1. The output string is always
|
56
|
+
2*SRCSIZE large plus the terminating zero. */
|
57
|
+
extern void yubikey_modhex_encode(char *dst, const char *src, size_t srcsize);
|
58
|
+
|
59
|
+
/* ModHex decode input string SRC of length DSTSIZE/2 into output
|
60
|
+
string DST. The output string DST is always DSTSIZE/2 large plus
|
61
|
+
the terminating zero. */
|
62
|
+
extern void yubikey_modhex_decode(char *dst, const char *src, size_t dstsize);
|
63
|
+
|
64
|
+
/* Low-level functions; AES. */
|
65
|
+
|
66
|
+
/* AES-decrypt one 16-byte block STATE using the 128-bit KEY, leaving
|
67
|
+
the decrypted output in the STATE buffer. */
|
68
|
+
void yubikey_aes_decrypt(uint8_t *state, const uint8_t *key);
|
69
|
+
|
70
|
+
/*
|
71
|
+
* Low-level functions; CRC.
|
72
|
+
*/
|
73
|
+
uint16_t yubikey_crc16 (const uint8_t *buf, size_t buf_size);
|
74
|
+
|
75
|
+
#endif
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "yubikey.h"
|
3
|
+
|
4
|
+
/*
|
5
|
+
* call-seq:
|
6
|
+
* decode(modhex_string) -> string
|
7
|
+
*
|
8
|
+
* Decode a ModHex string into binary data
|
9
|
+
*/
|
10
|
+
static VALUE
|
11
|
+
modhex_decode(VALUE self, VALUE modhex_string) {
|
12
|
+
char* modhex_string_ptr = StringValuePtr(modhex_string);
|
13
|
+
size_t modhex_string_size = strlen(modhex_string_ptr);
|
14
|
+
size_t decoded_string_size = modhex_string_size/2;
|
15
|
+
char* decoded_string;
|
16
|
+
|
17
|
+
if (modhex_string_size % 2 != 0)
|
18
|
+
rb_raise(rb_eArgError, "ModHex string length is not even");
|
19
|
+
|
20
|
+
yubikey_modhex_decode(decoded_string, modhex_string_ptr, modhex_string_size);
|
21
|
+
|
22
|
+
return rb_str_new(decoded_string, decoded_string_size);
|
23
|
+
}
|
24
|
+
|
25
|
+
/*
|
26
|
+
* call-seq:
|
27
|
+
* decrypt(state, key) -> plaintext
|
28
|
+
*
|
29
|
+
* Decrypt 16 bytes of binary AES ciphertext to binary plaintext with the Yubico implementation of AES-128 ECB
|
30
|
+
*
|
31
|
+
* [+state+] 16 bytes of binary ciphertext
|
32
|
+
* [+key+] 16-byte binary key
|
33
|
+
*
|
34
|
+
*/
|
35
|
+
static VALUE
|
36
|
+
aes_decrypt(VALUE self, VALUE state, VALUE key) {
|
37
|
+
char* state_ptr = StringValuePtr(state);
|
38
|
+
char* key_ptr = StringValuePtr(key);
|
39
|
+
|
40
|
+
if (RSTRING(state)->len != YUBIKEY_BLOCK_SIZE || RSTRING(key)->len != YUBIKEY_KEY_SIZE)
|
41
|
+
rb_raise(rb_eArgError, "key and state must be 16 bytes");
|
42
|
+
|
43
|
+
yubikey_aes_decrypt((uint8_t*)state_ptr, (uint8_t*)key_ptr);
|
44
|
+
|
45
|
+
return rb_str_new(state_ptr, YUBIKEY_BLOCK_SIZE);
|
46
|
+
}
|
47
|
+
|
48
|
+
/*
|
49
|
+
* call-seq:
|
50
|
+
* valid?(token)
|
51
|
+
*
|
52
|
+
* Check the CRC of a decrypted Yubikey OTP
|
53
|
+
*
|
54
|
+
* [+token+] 16-byte binary token
|
55
|
+
*/
|
56
|
+
static VALUE
|
57
|
+
crc_check(VALUE self, VALUE token) {
|
58
|
+
char* token_ptr = StringValuePtr(token);
|
59
|
+
|
60
|
+
if (RSTRING(token)->len != YUBIKEY_BLOCK_SIZE)
|
61
|
+
rb_raise(rb_eArgError, "token must be 16 bytes");
|
62
|
+
|
63
|
+
return yubikey_crc_ok_p((uint8_t*)token_ptr) ? Qtrue : Qfalse;
|
64
|
+
}
|
65
|
+
|
66
|
+
void
|
67
|
+
Init_yubikey_ext() {
|
68
|
+
VALUE rb_mYubikey = rb_define_module("Yubikey");
|
69
|
+
VALUE rb_mYubikeyAES = rb_define_module_under(rb_mYubikey, "AES");
|
70
|
+
VALUE rb_mYubikeyModHex = rb_define_module_under(rb_mYubikey, "ModHex");
|
71
|
+
VALUE rb_mYubikeyCRC = rb_define_module_under(rb_mYubikey, "CRC");
|
72
|
+
|
73
|
+
rb_define_module_function(rb_mYubikeyModHex, "decode", modhex_decode, 1);
|
74
|
+
rb_define_module_function(rb_mYubikeyAES, "decrypt", aes_decrypt, 2);
|
75
|
+
rb_define_module_function(rb_mYubikeyCRC, "valid?", crc_check, 1);
|
76
|
+
}
|
data/lib/yubikey/hex.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
# Convert hex string to binary
|
4
|
+
def to_bin
|
5
|
+
to_a.pack('H*')
|
6
|
+
end
|
7
|
+
|
8
|
+
# Convert binary string to hex
|
9
|
+
def to_hex
|
10
|
+
unpack('H*')[0]
|
11
|
+
end
|
12
|
+
|
13
|
+
# Check if the string is hex encoded
|
14
|
+
def hex?
|
15
|
+
self =~ /^[0-9a-fA-F]+$/ ? true : false
|
16
|
+
end
|
17
|
+
|
18
|
+
# Check if the string is modhex encoded
|
19
|
+
def modhex?
|
20
|
+
self =~ /^[cbdefghijklnrtuv]+$/ ? true : false
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/yubikey/otp.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
class Yubikey::OTP
|
2
|
+
# first few modhex encoded characters of the OTP
|
3
|
+
attr_reader :public_id
|
4
|
+
# decrypted binary token
|
5
|
+
attr_reader :token
|
6
|
+
# binary AES key
|
7
|
+
attr_reader :aes_key
|
8
|
+
# hex id (encrypted in OTP)
|
9
|
+
attr_reader :secret_id
|
10
|
+
# integer that increments each time the Yubikey is plugged in
|
11
|
+
attr_reader :insert_counter
|
12
|
+
# ~8hz timer, reset on every insert
|
13
|
+
attr_reader :timestamp
|
14
|
+
# activation counter, reset on every insert
|
15
|
+
attr_reader :session_counter
|
16
|
+
# random integer used as padding and extra random noise
|
17
|
+
attr_reader :random_number
|
18
|
+
|
19
|
+
|
20
|
+
# Decode/decrypt a Yubikey one-time password
|
21
|
+
#
|
22
|
+
# [+otp+] ModHex encoded Yubikey OTP (at least 32 characters)
|
23
|
+
# [+key+] 32-character hex AES key
|
24
|
+
def initialize(otp, key)
|
25
|
+
raise InvalidOTPError, 'OTP must be at least 32 characters of modhex' unless otp.modhex? && otp.length >= 32
|
26
|
+
raise InvalidKeyError, 'Key must be 32 hex characters' unless key.hex? && key.length == 32
|
27
|
+
|
28
|
+
@public_id = otp[0,otp.length-32] if otp.length > 32
|
29
|
+
|
30
|
+
@token = Yubikey::ModHex.decode(otp[-32,32])
|
31
|
+
@aes_key = key.to_bin
|
32
|
+
|
33
|
+
decrypt
|
34
|
+
parse
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def decrypt
|
40
|
+
@token = Yubikey::AES.decrypt(@token, @aes_key)
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse
|
44
|
+
raise BadCRCError unless Yubikey::CRC.valid?(@token)
|
45
|
+
|
46
|
+
@secret_id = @token[0,6].to_hex
|
47
|
+
@insert_counter = @token[7] * 256 + @token[6]
|
48
|
+
@timestamp = @token[10] * 65536 + @token[9] * 256 + @token[8]
|
49
|
+
@session_counter = @token[11]
|
50
|
+
@random_number = @token[13] * 256 + @token[12]
|
51
|
+
end
|
52
|
+
|
53
|
+
# :stopdoc:
|
54
|
+
class InvalidOTPError < StandardError; end
|
55
|
+
class InvalidKeyError < StandardError; end
|
56
|
+
class BadCRCError < StandardError; end
|
57
|
+
end # Yubikey::OTP
|
data/lib/yubikey.rb
ADDED
data/spec/hex_spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe 'hex' do
|
4
|
+
it 'should encode binary to hex' do
|
5
|
+
"i\266H\034\213\253\242\266\016\217\"\027\233X\315V".to_hex.
|
6
|
+
should == '69b6481c8baba2b60e8f22179b58cd56'
|
7
|
+
|
8
|
+
"\354\336\030\333\347o\275\f33\017\0345Hq\333".to_hex.
|
9
|
+
should == 'ecde18dbe76fbd0c33330f1c354871db'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should decode hex to binary' do
|
13
|
+
'69b6481c8baba2b60e8f22179b58cd56'.to_bin.
|
14
|
+
should == "i\266H\034\213\253\242\266\016\217\"\027\233X\315V"
|
15
|
+
|
16
|
+
'ecde18dbe76fbd0c33330f1c354871db'.to_bin.
|
17
|
+
should == "\354\336\030\333\347o\275\f33\017\0345Hq\333"
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should know whether a string is hex' do
|
21
|
+
'ecde18dbe76fbd0c33330f1c354871db'.hex?.should == true
|
22
|
+
'dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh'.modhex?.should == true
|
23
|
+
|
24
|
+
'foobar'.hex?.should == false
|
25
|
+
'test'.modhex?.should == false
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__) + '/../ext/yubikey_ext'
|
4
|
+
require 'yubikey_ext.so'
|
5
|
+
|
6
|
+
describe 'yubikey_ext' do
|
7
|
+
it 'should decode modhex' do
|
8
|
+
Yubikey::ModHex.decode('hknhfjbrjnlnldnhcujvddbikngjrtgh').should == "i\266H\034\213\253\242\266\016\217\"\027\233X\315V"
|
9
|
+
Yubikey::ModHex.decode('urtubjtnuihvntcreeeecvbregfjibtn').should == "\354\336\030\333\347o\275\f33\017\0345Hq\333"
|
10
|
+
|
11
|
+
Yubikey::ModHex.decode('dteffuje').should == "-4N\203"
|
12
|
+
|
13
|
+
Yubikey::ModHex.decode('ifhgieif').should == 'test'
|
14
|
+
Yubikey::ModHex.decode('hhhvhvhdhbid').should == 'foobar'
|
15
|
+
|
16
|
+
Yubikey::ModHex.decode('cc').should == "\000"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should raise if modhex string length uneven' do
|
20
|
+
lambda { Yubikey::ModHex.decode('ifh') }.should raise_error(ArgumentError)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should decrypt aes' do
|
24
|
+
key = '72992427a3b8ccd20697493b5532561f'.to_bin
|
25
|
+
state = 'ddf43aec57366784e061a12f767e728a'.to_bin
|
26
|
+
plain = '619dd70df3b30300de1bdb00ffbf6f26'.to_bin
|
27
|
+
|
28
|
+
Yubikey::AES.decrypt(state, key).should == plain
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should raise if aes key or state length is not 16' do
|
32
|
+
lambda { Yubikey::AES.decrypt("i\266H\034\213\253\242\266\016\217\"\027\233X\315V", 'test') }.
|
33
|
+
should raise_error(ArgumentError)
|
34
|
+
|
35
|
+
lambda { Yubikey::AES.decrypt('test', "\354\336\030\333\347o\275\f33\017\0345Hq\333") }.
|
36
|
+
should raise_error(ArgumentError)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should check a crc' do
|
40
|
+
Yubikey::CRC.valid?('619dd70df3b30300de1bdb00ffbf6f26'.to_bin).should == true
|
41
|
+
Yubikey::CRC.valid?('ddf43aec57366784e061a12f767e728a'.to_bin).should == false
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should raise if crc token length not 16' do
|
45
|
+
lambda { Yubikey::CRC.valid?('619dd70df3b30300de1bdb00ffbf6f'.to_bin) }.
|
46
|
+
should raise_error(ArgumentError)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe 'Yubikey::OTP' do
|
4
|
+
it 'should parse a otp' do
|
5
|
+
token = Yubikey::OTP.new('dteffujehknhfjbrjnlnldnhcujvddbikngjrtgh', 'ecde18dbe76fbd0c33330f1c354871db')
|
6
|
+
|
7
|
+
token.public_id.should == 'dteffuje'
|
8
|
+
token.secret_id.should == '8792ebfe26cc'
|
9
|
+
token.insert_counter.should == 19
|
10
|
+
token.session_counter.should == 17
|
11
|
+
token.timestamp.should == 49712
|
12
|
+
token.random_number.should == 40904
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should raise if key or otp invalid' do
|
16
|
+
otp = 'hknhfjbrjnlnldnhcujvddbikngjrtgh'
|
17
|
+
key = 'ecde18dbe76fbd0c33330f1c354871db'
|
18
|
+
|
19
|
+
lambda { Yubikey::OTP.new(key, key) }.should raise_error(Yubikey::OTP::InvalidOTPError)
|
20
|
+
lambda { Yubikey::OTP.new(otp, otp) }.should raise_error(Yubikey::OTP::InvalidKeyError)
|
21
|
+
|
22
|
+
lambda { Yubikey::OTP.new(otp[0,31], key) }.should raise_error(Yubikey::OTP::InvalidOTPError)
|
23
|
+
lambda { Yubikey::OTP.new(otp, key[0,31]) }.should raise_error(Yubikey::OTP::InvalidKeyError)
|
24
|
+
|
25
|
+
lambda { Yubikey::OTP.new(otp[1,31]+'d', key) }.should raise_error(Yubikey::OTP::BadCRCError)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: yubikey
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jonathan Rudenberg
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-04-02 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A library to decode, decrypt and parse Yubikey one-time passwords.
|
17
|
+
email: jon335@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions:
|
21
|
+
- ext/yubikey_ext/extconf.rb
|
22
|
+
extra_rdoc_files:
|
23
|
+
- ext/yubikey_ext/yubikey_ext.c
|
24
|
+
- README.rdoc
|
25
|
+
- LICENSE
|
26
|
+
files:
|
27
|
+
- lib/yubikey.rb
|
28
|
+
- lib/yubikey/hex.rb
|
29
|
+
- lib/yubikey/otp.rb
|
30
|
+
- examples/otp.rb
|
31
|
+
- spec/hex_spec.rb
|
32
|
+
- spec/spec.opts
|
33
|
+
- spec/spec_helper.rb
|
34
|
+
- spec/yubikey_ext_spec.rb
|
35
|
+
- spec/yubikey_otp_spec.rb
|
36
|
+
- ext/yubikey_ext/ykaes.c
|
37
|
+
- ext/yubikey_ext/ykcrc.c
|
38
|
+
- ext/yubikey_ext/ykmodhex.c
|
39
|
+
- ext/yubikey_ext/yubikey_ext.c
|
40
|
+
- ext/yubikey_ext/yubikey.h
|
41
|
+
- ext/yubikey_ext/extconf.rb
|
42
|
+
- README.rdoc
|
43
|
+
- LICENSE
|
44
|
+
has_rdoc: true
|
45
|
+
homepage: http://github.com/titanous/yubikey
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --charset=UTF-8
|
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
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project: yubikey
|
66
|
+
rubygems_version: 1.3.1
|
67
|
+
signing_key:
|
68
|
+
specification_version: 2
|
69
|
+
summary: A library to decode, decrypt and parse Yubikey one-time passwords.
|
70
|
+
test_files: []
|
71
|
+
|