YubiRuby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
File without changes
data/bin/modhex ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby -wKU
2
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
3
+ $:.unshift File.join(File.dirname(__FILE__),'..','ext')
4
+
5
+ require 'yubiruby'
6
+
7
+ if __FILE__ == $PROGRAM_NAME
8
+ if ARGV.length < 1
9
+ msg=<<-EOF
10
+ Usage: #{$PROGRAM_NAME} [-dh] <data>
11
+
12
+ Convert input DATA as specified and print output to STDOUT.
13
+
14
+ -d: Decode data (the default is to encode data).
15
+ -h: Use hex encoding for all non-modhex data.
16
+ DATA: string with data to encode
17
+
18
+ Examples:
19
+
20
+ ModHex encode ASCII-string \"test\":
21
+ #{$PROGRAM_NAME} test
22
+
23
+ Decode ModHex data \"ifhgieif\" into ASCII string:
24
+ #{$PROGRAM_NAME} -d ifhgieif
25
+
26
+ ModHex encode hex-encoded data \"b565716f\":
27
+ #{$PROGRAM_NAME} -h b565716f
28
+
29
+ Decode ModHex data \"nghgibhv\" and print hex-encode data:
30
+ #{$PROGRAM_NAME} -d -h nghgibhv
31
+ EOF
32
+ abort msg
33
+ end
34
+
35
+ hex = ARGV.include? "-h"
36
+ decode = ARGV.include? "-d"
37
+ data = ARGV.last
38
+
39
+ if decode
40
+ out = data.modhex_decode
41
+ out = YubiRuby::HEX.encode(out) if hex
42
+ puts out
43
+ else
44
+ data = YubiRuby::HEX.decode(data) if hex
45
+ puts data.modhex_encode
46
+ end
47
+
48
+ end
data/ext/extconf.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'mkmf'
2
+ #dir_config("libyubikey")
3
+ if ARGV.include?('-h')
4
+ abort <<-EOF
5
+ Usage: #{$PROGRAM_NAME} [options]
6
+
7
+ Options:
8
+ -d debug mode
9
+ -h print this help
10
+ EOF
11
+ end
12
+
13
+ $CFLAGS << " -DNDEBUG" unless ARGV.include?('-d')
14
+ create_makefile('libyubikey')
data/ext/libyubikey.c ADDED
@@ -0,0 +1,534 @@
1
+ /* libyubikey.c --- Ruby wrapper for low-level Yubikey OTP functions.
2
+ *
3
+ * Written by Alessio Caiazza <nolith@abisso.org>.
4
+ * Copyright (c) 2010 Alessio Caiazza
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
+ #include <ruby.h>
33
+ #include <stdlib.h>
34
+ #include "yubikey.h"
35
+
36
+ #define MODHEX_SING_ENCODE "encode"
37
+ #define MODHEX_SING_DECODE "decode"
38
+ #define MODHEX_ENCODE "modhex_encode"
39
+ #define MODHEX_DECODE "modhex_decode"
40
+ #define MODHEX_VALID "modhex?"
41
+
42
+ static VALUE mYubiRuby;
43
+ static VALUE mModHex;
44
+ static VALUE cYubikey;
45
+
46
+
47
+ /* ModHex */
48
+
49
+ /*
50
+ * call-seq:
51
+ * YubyRuby::ModHex.encode(obj) -> "modhex string"
52
+ *
53
+ * Encodes <tt>obj.to_str</tt> into a <tt>modhex string</tt>.
54
+ */
55
+ static VALUE modhex_sing_encode(VALUE self, VALUE obj)
56
+ {
57
+ VALUE str = StringValue(obj);
58
+ int src_size = RSTRING(str)->len;
59
+ char *dst = (char*) malloc((2*src_size+1)*sizeof(char));
60
+ /* ModHex encode input string SRC of length SRCSIZE and put the zero
61
+ terminated output string in DST. The size of the output string DST
62
+ must be at least 2*SRCSIZE+1. The output string is always
63
+ 2*SRCSIZE large plus the terminating zero. */
64
+ yubikey_modhex_encode(dst, RSTRING(str)->ptr, src_size);
65
+
66
+ return rb_str_new2(dst);
67
+ }
68
+
69
+ /*
70
+ * call-seq:
71
+ * str.modhex_encode -> "modhex string"
72
+ *
73
+ * Invokes YubyRuby::ModHex.encode on +self+.
74
+ */
75
+ static VALUE modhex_encode(VALUE self)
76
+ {
77
+ ID method = rb_intern(MODHEX_SING_ENCODE);
78
+
79
+ return rb_funcall(mModHex, method, 1, self);
80
+ }
81
+
82
+ /*
83
+ * call-seq:
84
+ * YubyRuby::ModHex.decode(obj) -> "string"
85
+ *
86
+ * Decodes <tt>obj.to_str</tt> into a <tt>string</tt>.
87
+ *
88
+ * No validatition of format in provided, use YubyRuby::ModHex.modhex?
89
+ * for checking.
90
+ */
91
+ static VALUE modhex_sing_decode(VALUE self, VALUE obj)
92
+ {
93
+ VALUE str = StringValue(obj);
94
+ int src_size = RSTRING(str)->len;
95
+ char *dst = (char*) malloc(((src_size/2)+1)*sizeof(char));
96
+ /* ModHex decode input string SRC of length DSTSIZE/2 into output
97
+ string DST. The output string DST is always DSTSIZE/2 large plus
98
+ the terminating zero. */
99
+ yubikey_modhex_decode(dst, RSTRING(str)->ptr, src_size);
100
+
101
+ return rb_str_new2(dst);
102
+ }
103
+
104
+ /*
105
+ * call-seq:
106
+ * str.modhec_decode -> "string"
107
+ *
108
+ * Invokes YubyRuby::ModHex.decode on +self+.
109
+ */
110
+ static VALUE modhex_decode(VALUE self)
111
+ {
112
+ ID method = rb_intern(MODHEX_SING_DECODE);
113
+
114
+ return rb_funcall(mModHex, method, 1, self);
115
+ }
116
+
117
+ /*
118
+ * call-seq:
119
+ * YubyRuby::ModHex.modhex?(obj) -> true or false
120
+ *
121
+ * Checks if <tt>obj.to_str</tt> is a valid <tt>modhex string</tt>.
122
+ */
123
+ static VALUE modhex_sing_is_modhex(VALUE self, VALUE obj)
124
+ {
125
+ VALUE str = StringValue(obj);
126
+ if (yubikey_modhex_p(RSTRING(str)->ptr) != 0)
127
+ return Qtrue;
128
+ else
129
+ return Qfalse;
130
+ }
131
+
132
+ /*
133
+ * call-seq:
134
+ * str.modhex? -> true or false
135
+ *
136
+ * Invokes YubyRuby::ModHex.modhex? on +self+
137
+ */
138
+ static VALUE modhex_is_modhex(VALUE self)
139
+ {
140
+ ID method = rb_intern(MODHEX_VALID);
141
+
142
+ return rb_funcall(mModHex, method, 1, self);
143
+ }
144
+ /* ModHex END */
145
+
146
+ /* Yubikey */
147
+
148
+ typedef struct {
149
+ uint8_t key[YUBIKEY_KEY_SIZE];
150
+ yubikey_token_t token;
151
+ } yubikey_data;
152
+
153
+ static void yubikey_free(void *p)
154
+ {
155
+ free(((yubikey_data*)p)->token);
156
+ free(p);
157
+ }
158
+
159
+ // allocate space for internal structures
160
+ static VALUE yubikey_alloc(VALUE klass)
161
+ {
162
+ yubikey_data* data;
163
+ VALUE obj;
164
+
165
+ data = (yubikey_data*) malloc(sizeof(yubikey_data));
166
+ data->token = (yubikey_token_t)malloc(sizeof(yubikey_token_st));
167
+
168
+ obj = Data_Wrap_Struct(klass, 0, yubikey_free, data);
169
+
170
+ return obj;
171
+ }
172
+
173
+ /* call-seq:
174
+ * yubikey.key = "hex string"
175
+ *
176
+ * Sets the AES key to the <tt>hex string</tt>.
177
+ */
178
+ static VALUE yubikey_set_key(VALUE self, VALUE key)
179
+ {
180
+ yubikey_data* data;
181
+
182
+ Data_Get_Struct(self, yubikey_data, data);
183
+ VALUE sKey = StringValue(key);
184
+
185
+ if (sKey == Qnil)
186
+ rb_raise(rb_eTypeError, "wrong parameter type.");
187
+
188
+ if (RSTRING(sKey)->len == YUBIKEY_KEY_SIZE*2) {
189
+ /* Hex */
190
+ if (yubikey_hex_p(RSTRING(sKey)->ptr) == 0)
191
+ rb_raise(rb_eTypeError, "not an HEX string."); //TODO:ArgumentError
192
+ char* buff = (char*) malloc(sizeof(char)*(YUBIKEY_KEY_SIZE +1));
193
+ yubikey_hex_decode( buff, RSTRING(sKey)->ptr, YUBIKEY_KEY_SIZE );
194
+ MEMCPY(&data->key, buff, uint8_t, YUBIKEY_KEY_SIZE);
195
+ }
196
+
197
+ return key;
198
+ }
199
+
200
+ /* call-seq:
201
+ * yubikey.key -> "hex string"
202
+ *
203
+ * Gets the AES key as an hex string.
204
+ */
205
+ static VALUE yubikey_get_key(VALUE self)
206
+ {
207
+ yubikey_data* data;
208
+
209
+ Data_Get_Struct(self, yubikey_data, data);
210
+
211
+ char key[YUBIKEY_KEY_SIZE*2 + 1];
212
+ char* buff = (char*) malloc(sizeof(char)*(YUBIKEY_KEY_SIZE +1));
213
+ MEMCPY(buff, &data->key, uint8_t, YUBIKEY_KEY_SIZE);
214
+ buff[YUBIKEY_KEY_SIZE] = '\0';
215
+
216
+ yubikey_hex_encode( key, buff, YUBIKEY_KEY_SIZE );
217
+
218
+ return rb_str_new2(key);
219
+ }
220
+
221
+ /* call-seq:
222
+ * Yubikey.new(aes_key) -> new_yubikey
223
+ *
224
+ * Creates a yubikey parser whith +aes_key+ ad AES key.
225
+ *
226
+ * +aes_key+ musb be encoded with YubiRuby::HEX.encode.
227
+ */
228
+ static VALUE yubikey_initialize(VALUE self, VALUE key)
229
+ {
230
+ yubikey_data* data;
231
+
232
+ Data_Get_Struct(self, yubikey_data, data);
233
+
234
+ yubikey_set_key(self, key);
235
+
236
+ return self;
237
+ }
238
+
239
+ static VALUE yubikey_init_copy(VALUE copy, VALUE orig)
240
+ {
241
+ yubikey_data *t_orig, *t_copy;
242
+
243
+ if (copy == orig)
244
+ return copy;
245
+
246
+ if (TYPE(orig) != T_DATA ||
247
+ RDATA(orig)->dfree != (RUBY_DATA_FUNC)yubikey_free) {
248
+ rb_raise(rb_eTypeError, "wrong argument type.");
249
+ }
250
+
251
+ Data_Get_Struct(orig, yubikey_data, t_orig);
252
+ Data_Get_Struct(copy, yubikey_data, t_copy);
253
+ MEMCPY(&t_copy->key, &t_orig->key, uint8_t, YUBIKEY_KEY_SIZE);
254
+ MEMCPY(t_copy->token, t_orig->token, yubikey_token_st, 1);
255
+
256
+ return copy;
257
+ }
258
+
259
+ /* call-seq:
260
+ * yubikey.parse(otp) -> true or false
261
+ *
262
+ * Checks the +otp+ for a valid SSO.
263
+ */
264
+ static VALUE yubikey_check(VALUE self, VALUE otp)
265
+ {
266
+ yubikey_data *data;
267
+
268
+ VALUE str = StringValue(otp);
269
+ if (str == Qnil)
270
+ rb_raise(rb_eTypeError, "wrong argument type.");
271
+
272
+ int start = RSTRING(str)->len - 32;
273
+
274
+ if (start < 0)
275
+ rb_raise(rb_eTypeError, "OTP too short."); //Argument error
276
+
277
+ Data_Get_Struct(self, yubikey_data, data);
278
+
279
+ #ifndef NDEBUG
280
+ /* Debug. */
281
+ char *buff = (char*)malloc(YUBIKEY_KEY_SIZE+1);
282
+ yubikey_modhex_decode ((char*)buff,
283
+ (RSTRING(str)->ptr+start),
284
+ YUBIKEY_KEY_SIZE);
285
+ printf ("Input:\n");
286
+ printf (" token: %s\n", (RSTRING(str)->ptr+start));
287
+
288
+ {
289
+ size_t i;
290
+ printf (" ");
291
+ for (i = 0; i < YUBIKEY_KEY_SIZE; i++)
292
+ printf ("%02x ", buff[i] & 0xFF);
293
+ printf ("\n");
294
+ }
295
+
296
+ printf (" aeskey: %s\n", RSTRING(yubikey_get_key(self))->ptr);
297
+
298
+ {
299
+ size_t i;
300
+ printf (" ");
301
+ for (i = 0; i < YUBIKEY_KEY_SIZE; i++)
302
+ printf ("%02x ", data->key[i] & 0xFF);
303
+ printf ("\n");
304
+ }
305
+ #endif
306
+
307
+ /* Decrypt TOKEN using KEY and store output in OUT structure. Note
308
+ that there is no error checking whether the output data is valid or
309
+ not, use yubikey_check_* for that. */
310
+ yubikey_parse ((uint8_t*)(RSTRING(str)->ptr+start), data->key, data->token);
311
+
312
+ #ifndef NDEBUG
313
+ printf ("Output:\n");
314
+ {
315
+ size_t i;
316
+ printf (" ");
317
+ for (i = 0; i < YUBIKEY_BLOCK_SIZE; i++)
318
+ printf ("%02x ", ((uint8_t*)data->token)[i] & 0xFF);
319
+ printf ("\n");
320
+ }
321
+
322
+ yubikey_token_st tok = *data->token;
323
+ printf ("\nStruct:\n");
324
+ /* Debug */
325
+ {
326
+ size_t i;
327
+ printf (" uid: ");
328
+ for (i = 0; i < YUBIKEY_UID_SIZE; i++)
329
+ printf ("%02x ", data->token->uid[i] & 0xFF);
330
+ printf ("\n");
331
+ }
332
+ printf (" counter: %d (0x%04x)\n", tok.ctr, tok.ctr);
333
+ printf (" timestamp (low): %d (0x%04x)\n", tok.tstpl, tok.tstpl);
334
+ printf (" timestamp (high): %d (0x%02x)\n", tok.tstph, tok.tstph);
335
+ printf (" session use: %d (0x%02x)\n", tok.use, tok.use);
336
+ printf (" random: %d (0x%02x)\n", tok.rnd, tok.rnd);
337
+ printf (" crc: %d (0x%04x)\n", tok.crc, tok.crc);
338
+
339
+ printf ("\nDerived:\n");
340
+ printf (" cleaned counter: %d (0x%04x)\n",
341
+ yubikey_counter (tok.ctr), yubikey_counter (tok.ctr));
342
+ yubikey_modhex_encode ((char*)buff, (char*)tok.uid, YUBIKEY_UID_SIZE);
343
+ printf (" modhex uid: %s\n", buff);
344
+ printf (" triggered by caps lock: %s\n",
345
+ yubikey_capslock(tok.ctr) ? "yes" : "no");
346
+ printf (" crc: %04X\n", yubikey_crc16 ((void*)&tok, YUBIKEY_KEY_SIZE));
347
+
348
+ printf (" crc check: ");
349
+ if (yubikey_crc_ok_p ((uint8_t*)&tok))
350
+ printf("ok\n");
351
+ else
352
+ printf ("fail\n");
353
+ #endif
354
+ if (yubikey_crc_ok_p ((uint8_t*)data->token))
355
+ return Qtrue;
356
+ else
357
+ return Qfalse;
358
+ }
359
+
360
+ /* call-seq:
361
+ * yubikey.to_str -> String
362
+ *
363
+ * Gets the decoded token as <tt>hex string</tt> representation.
364
+ */
365
+ static VALUE yubikey_to_str(VALUE self)
366
+ {
367
+ size_t i;
368
+ yubikey_data *data;
369
+ Data_Get_Struct(self, yubikey_data, data);
370
+
371
+ VALUE ary = rb_ary_new2(YUBIKEY_BLOCK_SIZE);
372
+ for (i = 0; i < YUBIKEY_BLOCK_SIZE; i++) {
373
+ VALUE num = INT2FIX(((uint8_t*)data->token)[i]);
374
+ //invoke .to_s 16 on each number
375
+ rb_ary_store(ary, i, rb_funcall(num, rb_intern("to_s"), 1, INT2FIX(16) ));
376
+ }
377
+
378
+ return rb_funcall(ary, rb_intern("join"), 0);
379
+ }
380
+
381
+ /* call-seq:
382
+ * yubikey.uid -> "hex string"
383
+ *
384
+ * Gets the decoded token UID field as <tt>hex string</tt> representation.
385
+ */
386
+ static VALUE yubikey_get_uid(VALUE self)
387
+ {
388
+ VALUE out = yubikey_to_str(self);
389
+
390
+ // *2 becaouse of hex
391
+ return rb_str_new(RSTRING(out)->ptr, YUBIKEY_UID_SIZE*2 );
392
+ }
393
+
394
+ /* call-seq:
395
+ * yubikey.counter -> Fixnum
396
+ *
397
+ * Gets the decoded token counter field.
398
+ */
399
+ static VALUE yubikey_get_counter(VALUE self)
400
+ {
401
+ yubikey_data *data;
402
+ Data_Get_Struct(self, yubikey_data, data);
403
+
404
+ return INT2FIX(yubikey_counter(data->token->ctr));
405
+ }
406
+
407
+ /* call-seq:
408
+ * yubikey.triggered_by_capslock? -> true or false
409
+ *
410
+ */
411
+ static VALUE yubikey_get_triggered_by_capslock(VALUE self)
412
+ {
413
+ yubikey_data *data;
414
+ Data_Get_Struct(self, yubikey_data, data);
415
+
416
+ if (yubikey_capslock(data->token->ctr))
417
+ return Qtrue;
418
+ else
419
+ return Qfalse;
420
+ }
421
+
422
+ static VALUE yubikey_get_tsl(VALUE self)
423
+ {
424
+ yubikey_data *data;
425
+ Data_Get_Struct(self, yubikey_data, data);
426
+
427
+ return INT2FIX(data->token->tstpl);
428
+ }
429
+
430
+ static VALUE yubikey_get_tsh(VALUE self)
431
+ {
432
+ yubikey_data *data;
433
+ Data_Get_Struct(self, yubikey_data, data);
434
+
435
+ return INT2FIX(data->token->tstph);
436
+ }
437
+
438
+ static VALUE yubikey_get_session(VALUE self)
439
+ {
440
+ yubikey_data *data;
441
+ Data_Get_Struct(self, yubikey_data, data);
442
+
443
+ return INT2FIX(data->token->use);
444
+ }
445
+
446
+ static VALUE yubikey_get_random(VALUE self)
447
+ {
448
+ yubikey_data *data;
449
+ Data_Get_Struct(self, yubikey_data, data);
450
+
451
+ return INT2FIX(data->token->rnd);
452
+ }
453
+
454
+ static VALUE yubikey_get_crc(VALUE self)
455
+ {
456
+ yubikey_data *data;
457
+ Data_Get_Struct(self, yubikey_data, data);
458
+
459
+ return INT2FIX(data->token->crc);
460
+ }
461
+
462
+ static VALUE yubikey_calc_crc(VALUE self)
463
+ {
464
+ yubikey_data *data;
465
+ Data_Get_Struct(self, yubikey_data, data);
466
+
467
+ return INT2FIX(yubikey_crc16 ((void*)data->token, YUBIKEY_KEY_SIZE));
468
+ }
469
+
470
+ static VALUE yubikey_check_crc(VALUE self)
471
+ {
472
+ yubikey_data *data;
473
+ Data_Get_Struct(self, yubikey_data, data);
474
+
475
+ if (yubikey_crc_ok_p ((uint8_t*)data->token))
476
+ return Qtrue;
477
+ else
478
+ return Qfalse;
479
+ }
480
+ /* Yubikey END */
481
+
482
+ /* Implementation of Yubikey OTP functions.
483
+ * This Module may be used to interact with a Yubikey
484
+ */
485
+ void Init_libyubikey() {
486
+ mYubiRuby = rb_define_module("YubiRuby");
487
+
488
+ /* ModHex string encoder/decoder
489
+ *
490
+ * The YubiKey uses a special data encoding format known as "modhex" rather
491
+ * than normal hex encoding or base64 encoding.
492
+ * Modhex is similar to hex encoding but with a different encoding alphabet.
493
+ * The reason is to achieve a keyboard layout independent encoding.
494
+ *
495
+ * The String class in extended with this module.
496
+ */
497
+ mModHex = rb_define_module_under(mYubiRuby, "ModHex");
498
+ rb_define_singleton_method(mModHex, "encode", modhex_sing_encode, 1);
499
+ rb_define_method(mModHex, "modhex_encode", modhex_encode, 0);
500
+ rb_define_singleton_method(mModHex, "decode", modhex_sing_decode, 1);
501
+ rb_define_method(mModHex, "modhex_decode", modhex_decode, 0);
502
+ rb_define_singleton_method(mModHex, "modhex?", modhex_sing_is_modhex, 1);
503
+ rb_define_method(mModHex, "modhex?", modhex_is_modhex, 0);
504
+ /* lists of allowed char in MODHEX enconding */
505
+ rb_define_const(mModHex, "MODHEX_MAP", rb_str_new2(YUBIKEY_MODHEX_MAP));
506
+
507
+ //extends String with ModHex
508
+ rb_include_module(rb_cString, mModHex);
509
+
510
+ /* Prototypes for low-level Yubikey OTP functions.
511
+ *
512
+ */
513
+ cYubikey = rb_define_class_under(mYubiRuby, "Yubikey", rb_cObject);
514
+ rb_define_alloc_func(cYubikey, yubikey_alloc);
515
+ rb_define_method(cYubikey, "initialize", yubikey_initialize, 1);
516
+ rb_define_method(cYubikey, "initialize_copy", yubikey_init_copy, 1);
517
+ /* CRC value for a valid token */
518
+ rb_define_const(cYubikey, "CRC_OK_RESIDUE", INT2FIX(YUBIKEY_CRC_OK_RESIDUE));
519
+ rb_define_method(cYubikey, "key", yubikey_get_key, 0);
520
+ rb_define_method(cYubikey, "key=", yubikey_set_key, 1);
521
+ rb_define_method(cYubikey, "parse", yubikey_check, 1);
522
+ rb_define_method(cYubikey, "to_str", yubikey_to_str, 0);
523
+ rb_define_alias(cYubikey, "to_s", "to_str");
524
+ rb_define_method(cYubikey, "uid", yubikey_get_uid, 0);
525
+ rb_define_method(cYubikey, "counter", yubikey_get_counter, 0);
526
+ rb_define_method(cYubikey, "triggered_by_capslock?", yubikey_get_triggered_by_capslock, 0);
527
+ rb_define_method(cYubikey, "timestamp_low", yubikey_get_tsl, 0);
528
+ rb_define_method(cYubikey, "timestamp_high", yubikey_get_tsh, 0);
529
+ rb_define_method(cYubikey, "session", yubikey_get_session, 0);
530
+ rb_define_method(cYubikey, "random", yubikey_get_random, 0);
531
+ rb_define_method(cYubikey, "crc", yubikey_get_crc, 0);
532
+ rb_define_method(cYubikey, "crc_residue", yubikey_calc_crc, 0);
533
+ rb_define_method(cYubikey, "crc?", yubikey_check_crc, 0);
534
+ }