YubiRuby 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/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
+ }