# HG changeset patch # User Alessio Caiazza # Date 1266343424 -3600 # Node ID ba52b1257333046ce4f46556e8b6f16a9b02c4ab # Parent c9f74665d8ef42057396d66d91167216dc46d2b4 major version change. fixed (mod)hex decoding. FakeYubikey. Exceptions. Testing ( fixes #1 and #3 ) diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab .hgignore --- a/.hgignore Tue Feb 16 11:21:14 2010 +0100 +++ b/.hgignore Tue Feb 16 19:03:44 2010 +0100 @@ -15,6 +15,7 @@ *.framework *.pbxuser *.gem +*.bundle Makefile syntax: regexp @@ -22,4 +23,4 @@ ^tmp/*$ ^script/*$ ^doc/*$ -^pkg/*$ \ No newline at end of file +^pkg/*$ diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab CHANGELOG --- a/CHANGELOG Tue Feb 16 11:21:14 2010 +0100 +++ b/CHANGELOG Tue Feb 16 19:03:44 2010 +0100 @@ -1,3 +1,5 @@ +v1.0.0. broken api compatibility. TestCase. fixed some bugs in (mod)hex decoding. Exceptions. FakeYubikey generator + v0.1.1. fixed some bugs in hex decoding. v0.1.0. modhex installed as binary. diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab Manifest --- a/Manifest Tue Feb 16 11:21:14 2010 +0100 +++ b/Manifest Tue Feb 16 19:03:44 2010 +0100 @@ -3,7 +3,6 @@ Manifest README Rakefile -YubiRuby.gemspec bin/modhex ext/libyubikey/extconf.rb ext/libyubikey/libyubikey.c @@ -13,7 +12,12 @@ ext/libyubikey/ykmodhex.c ext/libyubikey/ykparse.c ext/libyubikey/yubikey.h +lib/exceptions.rb +lib/fake_yubikey.rb lib/hex.rb lib/yubiruby.rb -tests/tc_modhex.rb -tests/ts_yubiruby.rb +test/tc_crc16.rb +test/tc_fake_yubikey.rb +test/tc_hex.rb +test/tc_modhex.rb +test/test_helper.rb diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab Rakefile --- a/Rakefile Tue Feb 16 11:21:14 2010 +0100 +++ b/Rakefile Tue Feb 16 19:03:44 2010 +0100 @@ -41,7 +41,8 @@ p.email = "nolith@abisso.org" p.platform = Gem::Platform::RUBY p.ignore_pattern = ["tmp/**/*", "script/*"] - p.development_dependencies = [] + p.runtime_dependencies << ['ruby-aes-normal', '~> 1.0'] + p.runtime_dependencies << ['bit-struct'] #, '~> 0.13.6'] end Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext } diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab YubiRuby.gemspec --- a/YubiRuby.gemspec Tue Feb 16 11:21:14 2010 +0100 +++ b/YubiRuby.gemspec Tue Feb 16 19:03:44 2010 +0100 @@ -2,7 +2,7 @@ Gem::Specification.new do |s| s.name = %q{YubiRuby} - s.version = "0.1.1" + s.version = "1.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version= s.authors = ["Alessio Caiazza"] @@ -42,22 +42,29 @@ s.email = %q{nolith@abisso.org} s.executables = ["modhex"] s.extensions = ["ext/libyubikey/extconf.rb"] - s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "bin/modhex", "ext/libyubikey/extconf.rb", "ext/libyubikey/libyubikey.c", "ext/libyubikey/ykaes.c", "ext/libyubikey/ykcrc.c", "ext/libyubikey/ykhex.c", "ext/libyubikey/ykmodhex.c", "ext/libyubikey/ykparse.c", "ext/libyubikey/yubikey.h", "lib/hex.rb", "lib/yubiruby.rb"] - s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "YubiRuby.gemspec", "bin/modhex", "ext/libyubikey/extconf.rb", "ext/libyubikey/libyubikey.c", "ext/libyubikey/ykaes.c", "ext/libyubikey/ykcrc.c", "ext/libyubikey/ykhex.c", "ext/libyubikey/ykmodhex.c", "ext/libyubikey/ykparse.c", "ext/libyubikey/yubikey.h", "lib/hex.rb", "lib/yubiruby.rb", "tests/tc_modhex.rb", "tests/ts_yubiruby.rb"] + s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "bin/modhex", "ext/libyubikey/extconf.rb", "ext/libyubikey/libyubikey.c", "ext/libyubikey/ykaes.c", "ext/libyubikey/ykcrc.c", "ext/libyubikey/ykhex.c", "ext/libyubikey/ykmodhex.c", "ext/libyubikey/ykparse.c", "ext/libyubikey/yubikey.h", "lib/exceptions.rb", "lib/fake_yubikey.rb", "lib/hex.rb", "lib/yubiruby.rb"] + s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "bin/modhex", "ext/libyubikey/extconf.rb", "ext/libyubikey/libyubikey.c", "ext/libyubikey/ykaes.c", "ext/libyubikey/ykcrc.c", "ext/libyubikey/ykhex.c", "ext/libyubikey/ykmodhex.c", "ext/libyubikey/ykparse.c", "ext/libyubikey/yubikey.h", "lib/exceptions.rb", "lib/fake_yubikey.rb", "lib/hex.rb", "lib/yubiruby.rb", "test/tc_crc16.rb", "test/tc_fake_yubikey.rb", "test/tc_hex.rb", "test/tc_modhex.rb", "test/test_helper.rb", "YubiRuby.gemspec"] s.homepage = %q{http://bitbucket.org/nolith/yubiruby} s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "YubiRuby", "--main", "README"] s.require_paths = ["lib", "ext"] s.rubyforge_project = %q{yubiruby} s.rubygems_version = %q{1.3.5} s.summary = %q{Yubikey integration - Includes Prototypes for low-level Yubikey OTP functions witten by Simon Josefsson . Copyright (c) 2006, 2007, 2008, 2009 Yubico AB All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.} + s.test_files = ["test/test_helper.rb"] if s.respond_to? :specification_version then current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION s.specification_version = 3 if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["~> 1.0"]) + s.add_runtime_dependency(%q, [">= 0"]) else + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, [">= 0"]) end else + s.add_dependency(%q, ["~> 1.0"]) + s.add_dependency(%q, [">= 0"]) end end diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab ext/libyubikey/libyubikey.c --- a/ext/libyubikey/libyubikey.c Tue Feb 16 11:21:14 2010 +0100 +++ b/ext/libyubikey/libyubikey.c Tue Feb 16 19:03:44 2010 +0100 @@ -33,6 +33,8 @@ #include #include "yubikey.h" +//#undef NDEBUG + #define MODHEX_SING_ENCODE "encode" #define MODHEX_SING_DECODE "decode" #define MODHEX_ENCODE "modhex_encode" @@ -42,6 +44,7 @@ static VALUE mYubiRuby; static VALUE mModHex; static VALUE cYubikey; +static VALUE mCRC16; /* ModHex */ @@ -92,13 +95,15 @@ { VALUE str = StringValue(obj); int src_size = RSTRING(str)->len; + if (rb_funcall(str, rb_intern(MODHEX_VALID), 0) == Qfalse) + rb_raise(rb_eval_string("YubiRuby::NoModHexEncodedError"), ""); char *dst = (char*) malloc(((src_size/2)+1)*sizeof(char)); /* ModHex decode input string SRC of length DSTSIZE/2 into output string DST. The output string DST is always DSTSIZE/2 large plus the terminating zero. */ yubikey_modhex_decode(dst, RSTRING(str)->ptr, src_size); - return rb_str_new2(dst); + return rb_str_new(dst, src_size/2); } /* @@ -397,9 +402,9 @@ } /* call-seq: - * yubikey.counter -> Fixnum + * yubikey.session_counter -> Fixnum * - * Gets the decoded token counter field. + * Gets the decoded token session counter field. */ static VALUE yubikey_get_counter(VALUE self) { @@ -484,6 +489,13 @@ } /* Yubikey END */ +/* CRC 16 */ +static VALUE crc16_sing_calc(VALUE self, VALUE data) +{ + VALUE str = StringValue(data); + return INT2NUM(yubikey_crc16(RSTRING(str)->ptr, RSTRING(str)->len)); +} + /* Implementation of Yubikey OTP functions. * This Module may be used to interact with a Yubikey */ @@ -527,13 +539,16 @@ rb_define_method(cYubikey, "to_str", yubikey_to_str, 0); rb_define_alias(cYubikey, "to_s", "to_str"); rb_define_method(cYubikey, "uid", yubikey_get_uid, 0); - rb_define_method(cYubikey, "counter", yubikey_get_counter, 0); + rb_define_method(cYubikey, "session_counter", yubikey_get_counter, 0); rb_define_method(cYubikey, "triggered_by_capslock?", yubikey_get_triggered_by_capslock, 0); rb_define_method(cYubikey, "timestamp_low", yubikey_get_tsl, 0); rb_define_method(cYubikey, "timestamp_high", yubikey_get_tsh, 0); - rb_define_method(cYubikey, "session", yubikey_get_session, 0); + rb_define_method(cYubikey, "session_use", yubikey_get_session, 0); rb_define_method(cYubikey, "random", yubikey_get_random, 0); rb_define_method(cYubikey, "crc", yubikey_get_crc, 0); rb_define_method(cYubikey, "crc_residue", yubikey_calc_crc, 0); rb_define_method(cYubikey, "crc?", yubikey_check_crc, 0); + + mCRC16 = rb_define_module_under(mYubiRuby, "CRC16"); + rb_define_singleton_method(mCRC16, "calculate", crc16_sing_calc, 1); } \ No newline at end of file diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab lib/exceptions.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/exceptions.rb Tue Feb 16 19:03:44 2010 +0100 @@ -0,0 +1,52 @@ +# Author:: Alessio Caiazza (mailto:nolith@abisso.org) +# Copyright:: Copyright (c) 2010 Alessio Caiazza +# License:: New BSD License - http://www.opensource.org/licenses/bsd-license.php +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +module YubiRuby + class NoHexEncodedError < Exception + def initialize + super('The string provided isn\'t hex encoded') + end + end + + class NoModHexEncodedError < Exception + def inizialize(msg=nil) + if msg.nil? || msg.empty? + msg = 'The string provided isn\'t modhex encoded' + end + super(msg) + end + end + + class YubikeySessionCounterOverflow < Exception + def initialize + super('Session Counter Overflow') + end + end +end \ No newline at end of file diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab lib/fake_yubikey.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/fake_yubikey.rb Tue Feb 16 19:03:44 2010 +0100 @@ -0,0 +1,149 @@ +# Author:: Alessio Caiazza (mailto:nolith@abisso.org) +# Copyright:: Copyright (c) 2010 Alessio Caiazza +# License:: New BSD License - http://www.opensource.org/licenses/bsd-license.php +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +require 'rubygems' +require 'ruby-aes' +require 'bit-struct' + +# 1-complement is uses to computer crc field +# +# +class Numeric + def ones_complement(bits) + self ^ ((1 << bits) - 1) + end +end + +module YubiRuby + # + # This class simulate a yubikey allowing you make some test + # + class FakeYubikey + + class Data < BitStruct + YUBIKEY_BLOCK_SIZE = 16 + YUBIKEY_KEY_SIZE = 16 + YUBIKEY_UID_SIZE = 6 + SESSION_COUNTER_OVERFLOW = 0x7FFF + + hex_octets :uid, YUBIKEY_UID_SIZE*8, "User ID" + unsigned :session_counter, 16, {:endian=>:little, :display_name=>"Session Counter"} + unsigned :timestamp_low, 16, {:endian=>:little, :display_name=>"Timestamp low"} + unsigned :timestamp_high, 8, "Timestamp high" + unsigned :session_use, 8, "Session Use" + unsigned :random, 16, {:endian=>:little, :display_name=>"random"} + unsigned :crc, 16, {:endian=>:little, :display_name=>"crc"} + + end + + attr_accessor :key + + def initialize + @data = YubiRuby::FakeYubikey::Data.new + @data.session_counter = 0 + init + end + + def init + @data.session_counter += 1 + if (@data.session_counter == Data::SESSION_COUNTER_OVERFLOW+1) + raise YubikeySessionCounterOverflow.new + end + @data.session_use = 0 + @data.timestamp_low = rand(2**16) + @data.timestamp_high = rand(2**8) + end + + %w{session_use timestamp_low timestamp_high session_counter random crc}.each do |name| + define_method name do + @data.send name + end + end + + def set_random_key + @key = produce_random_bytes_in_hex Data::YUBIKEY_KEY_SIZE + end + + def set_random_uid + self.uid= produce_random_bytes_in_hex(Data::YUBIKEY_UID_SIZE) + end + + def uid=(value) + if YubiRuby::HEX.decode(value).size == Data::YUBIKEY_UID_SIZE + @data.uid = "#{value[0,2]}:#{value[2,2]}:#{value[4,2]}:#{value[6,2]}:#{value[8,2]}:#{value[10,2]}" + else + raise NoHexEncodedError.new + end + end + + def uid + @data.uid.gsub(':','') + end + + def otp + @data.random = rand(2**16) + @data.session_use += 1 + @data.session_counter +=1 if @data.session_use == 0 + generate_otp + end + + def to_s + @data.to_s + end + + def self.generate_specific_otp_and_fake_yubikey(key, uid, session_counter, + timestamp_low, timestamp_high, session_use, random) + y_key = FakeYubikey.new + y_key.key = key + y_key.uid = uid + y_key.data.session_use = session_use + y_key.data.timestamp_low = timestamp_low + y_key.data.timestamp_high = timestamp_high + y_key.data.session_counter = session_counter + y_key.data.random = random + [y_key.generate_otp, y_key] + end + + def data + @data + end + + def generate_otp + @data.crc = YubiRuby::CRC16.calculate(@data.to_s[0...-2]).ones_complement 16 + Aes.encrypt_block(128, 'ECB', YubiRuby::HEX.decode(@key), nil, @data.to_s).modhex_encode + end + + private + def produce_random_bytes_in_hex(size) + tmp = " "*size + 0.upto(size-1) { |i| tmp[i] = rand(2**8)} + YubiRuby::HEX.encode(tmp) + end + end +end \ No newline at end of file diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab lib/hex.rb --- a/lib/hex.rb Tue Feb 16 11:21:14 2010 +0100 +++ b/lib/hex.rb Tue Feb 16 19:03:44 2010 +0100 @@ -47,7 +47,7 @@ # def self.encode( obj ) s = obj.to_str - s.unpack('U'*s.length).collect {|x| x.to_s 16}.join + s.unpack('U'*s.length).collect {|x| tmp = x.to_s 16; tmp.length == 1 ? "0#{tmp}" : tmp }.join rescue ArgumentError #non UTF-8 string s = obj.to_str @@ -68,17 +68,19 @@ end # call-seq: - # YubiRuby::HEX.decode("hex string") -> "string" or "" + # YubiRuby::HEX.decode("hex string") -> "string" # # Decodes obj.to_str into a string. # - # An hex string length must be pair, if not an - # empty string is returned. + # An hex string length must be pair, if not a + # NoHexEncodedError excpetion is raised def self.decode( obj ) s = obj.to_str dec = "" - if (s.length % 2 == 0) + if hex?(s) (s.length/2).times { |i| dec << s[i*2,2].hex.chr } + else + raise NoHexEncodedError.new end return dec @@ -91,5 +93,25 @@ def hex_decode HEX.decode(self) end + + # call-seq: + # YubiRuby::HEX.hex?("hex string") -> true or false + # + # Tests if obj.to_str is a valid a hex string. + # + # An hex string length must be pair. + def self.hex?( obj ) + s = obj.to_str + return false unless (s.length % 2 == 0) + return (s.upcase =~ /[^A-F0-9]/).nil? + end + + # call-seq: + # hex? -> true or false + # + # Invokes YubiRuby::HEX.hex? on +self+. + def hex? + HEX.hex?(self) + end end end diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab lib/yubiruby.rb --- a/lib/yubiruby.rb Tue Feb 16 11:21:14 2010 +0100 +++ b/lib/yubiruby.rb Tue Feb 16 19:03:44 2010 +0100 @@ -27,8 +27,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +require 'exceptions' require 'libyubikey' require 'hex' +require 'fake_yubikey' module YubiRuby # C code version diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab test/tc_crc16.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tc_crc16.rb Tue Feb 16 19:03:44 2010 +0100 @@ -0,0 +1,10 @@ +class TestCRC16 < Test::Unit::TestCase + def test_crc_calculate + str = YubiRuby::HEX.decode '6d8dec07884101002216a1041b7c' + otp_decoded = YubiRuby::HEX.decode '6d8dec07884101002216a1041b7c105e' + crc = 24080 + assert_equal(0xF0B8, YubiRuby::CRC16.calculate(otp_decoded)) + assert_equal(crc, YubiRuby::CRC16.calculate(str).ones_complement(16)) + end + +end \ No newline at end of file diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab test/tc_fake_yubikey.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tc_fake_yubikey.rb Tue Feb 16 19:03:44 2010 +0100 @@ -0,0 +1,89 @@ +class TestFakeYubikey < Test::Unit::TestCase + def test_init + key = YubiRuby::FakeYubikey.new + assert_equal("000000000000", key.uid ) + assert_equal(0, key.session_use) + assert_equal(1, key.session_counter) + end + + def test_otp + key = YubiRuby::FakeYubikey.new + aes = key.set_random_key + uid = key.set_random_uid + assert(aes.hex?) + assert(uid.hex?) + validator = YubiRuby::Yubikey.new aes + assert(validator.parse(key.otp)) + assert_equal(validator.uid, uid) + assert_equal(validator.session_use, key.session_use) + assert_equal(validator.session_counter, key.session_counter) + end + + def test_generate_random_uid + key = YubiRuby::FakeYubikey.new + assert_equal(key.set_random_uid, key.uid) + end + + def test_generate_random_key + key = YubiRuby::FakeYubikey.new + assert_equal(key.set_random_key, key.key) + end + + def test_generate_specific_otp_and_fake_yubikey + aes = 'df5b9d7591b0b3c2819f7a0dd7d1547d' + session = 53 + tsl = 31716 + tsh = 106 + counter = 0 + random = 30172 + crc = 58822 + uid = "6d8dec078841" + check_otp = 'rfechkcdkjrflgrjlirdgivnedbbtcik' + result = YubiRuby::FakeYubikey.generate_specific_otp_and_fake_yubikey(aes, uid, session, + tsl, tsh, counter, random) + mycrc = YubiRuby::CRC16.calculate(result[1].to_s[0...-2]).ones_complement 16 + + + YubiRuby::Yubikey.new(aes).parse(result[0]) + assert_equal(aes,result[1].key) + assert_equal(session,result[1].session_counter) + assert_equal(tsl,result[1].timestamp_low) + assert_equal(tsh,result[1].timestamp_high) + assert_equal(counter,result[1].session_use) + assert_equal(random,result[1].random) + assert_equal(crc,result[1].crc) + assert_equal(uid,result[1].uid) + assert_equal(check_otp,result[0]) + end + + def test_session_use_overflow + key = YubiRuby::FakeYubikey.new + aes = key.set_random_key + uid = key.set_random_uid + session = key.session_counter + 1.upto(2**8-1) do |i| + key.otp + assert_equal(session, key.session_counter) + assert_equal(i, key.session_use) + end + key.otp + assert_equal(session+1, key.session_counter) + assert_equal(0, key.session_use) + end + +# ruby(71000) malloc: *** error for object 0x101aa6e70: +# incorrect checksum for freed object - object was probably modified after being freed. +# def test_session_counter_overflow +# key = YubiRuby::FakeYubikey.new +# aes = key.set_random_key +# uid = key.set_random_uid +# session = key.session_counter +# assert_equal(1, session) +# 2.upto(YubiRuby::FakeYubikey::Data::SESSION_COUNTER_OVERFLOW) do |i| +# key.init +# end +# assert_raise YubiRuby::YubikeySessionCounterOverflow do +# key.init +# end +# end +end \ No newline at end of file diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab test/tc_hex.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tc_hex.rb Tue Feb 16 19:03:44 2010 +0100 @@ -0,0 +1,29 @@ + +class TestHex < Test::Unit::TestCase + def test_string + str = "ciao\n" + hex = "6369616f0a" + assert_equal(YubiRuby::HEX.encode(str), hex) + assert_equal(YubiRuby::HEX.decode(hex), str) + end + + def test_reversible_operation + str = "ciao\n" + hex = "6369616f0a" + assert_equal(YubiRuby::HEX.decode(YubiRuby::HEX.encode(str)), str) + assert_equal(YubiRuby::HEX.encode(YubiRuby::HEX.decode(hex)), hex) + end + + def test_no_hex_encoded_exception + assert_raise YubiRuby::NoHexEncodedError do YubiRuby::HEX.decode('a') end + assert_raise YubiRuby::NoHexEncodedError do YubiRuby::HEX.decode('zebr') end + assert_raise YubiRuby::NoHexEncodedError do YubiRuby::HEX.decode('!af5') end + assert_raise YubiRuby::NoHexEncodedError do YubiRuby::HEX.decode('0x12ff') end + assert !YubiRuby::HEX.hex?('a') + assert !YubiRuby::HEX.hex?('zebr') + assert !YubiRuby::HEX.hex?('!af5') + assert !YubiRuby::HEX.hex?('0x12ff') + assert YubiRuby::HEX.hex?('7af5') + assert YubiRuby::HEX.hex?('12fF') + end +end \ No newline at end of file diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab test/tc_modhex.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tc_modhex.rb Tue Feb 16 19:03:44 2010 +0100 @@ -0,0 +1,36 @@ +class TestModHex < Test::Unit::TestCase + def test_string + str = "pippo234strd" + assert_equal(enc = str.modhex_encode, YubiRuby::ModHex.encode(str)) + assert_equal(enc.modhex_decode, YubiRuby::ModHex.decode(enc)) + assert_equal(str, str.modhex_encode().modhex_decode()) + assert(enc.modhex?) + end + + def test_reversible_operation + str = "test" + hex = "ifhgieif" + assert(hex.modhex?) + assert_equal(YubiRuby::ModHex.decode(YubiRuby::ModHex.encode(str)), str) + assert_equal(YubiRuby::ModHex.encode(YubiRuby::ModHex.decode(hex)), hex) + end + + def test_no_hex_encoded_exception + assert !YubiRuby::ModHex.modhex?('a') + assert !YubiRuby::ModHex.modhex?('zebr') + assert !YubiRuby::ModHex.modhex?('!af5') + assert !YubiRuby::ModHex.modhex?('0x12ff') + assert YubiRuby::ModHex.modhex?('ifhgieif') + assert YubiRuby::ModHex.modhex?('ichkicichv') + assert_raise YubiRuby::NoModHexEncodedError do YubiRuby::ModHex.decode('a') end + assert_raise YubiRuby::NoModHexEncodedError do YubiRuby::ModHex.decode('zebr') end + assert_raise YubiRuby::NoModHexEncodedError do YubiRuby::ModHex.decode('!af5') end + assert_raise YubiRuby::NoModHexEncodedError do YubiRuby::ModHex.decode('0x12ff') end + end + + def test_length + otp = 'dbkutdgrnlvrhdiregebvkkrgtuefjru' + assert_equal(32, otp.size) + assert_equal(16, otp.modhex_decode.size) + end +end \ No newline at end of file diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab test/test_helper.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test_helper.rb Tue Feb 16 19:03:44 2010 +0100 @@ -0,0 +1,13 @@ +$:.unshift File.join(File.dirname(__FILE__),'..','lib') +$:.unshift File.join(File.dirname(__FILE__),'..','ext') + +require "test/unit" + +require 'yubiruby' + +String.send(:include, YubiRuby::HEX) + +require "tc_modhex" +require "tc_hex" +require "tc_crc16" +require "tc_fake_yubikey" diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab tests/tc_modhex.rb --- a/tests/tc_modhex.rb Tue Feb 16 11:21:14 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -require "test/unit" - -require "libyubikey" - -class TestLibyubikey < Test::Unit::TestCase - def test_string - str = "pippo234strd" - assert_equal(enc = str.modhex_encode, YubiRuby::ModHex.encode(str)) - assert_equal(enc.modhex_decode, YubiRuby::ModHex.decode(enc)) - assert_equal(str, str.modhex_encode().modhex_decode()) - assert(enc.modhex?) - end -end \ No newline at end of file diff -r c9f74665d8ef42057396d66d91167216dc46d2b4 -r ba52b1257333046ce4f46556e8b6f16a9b02c4ab tests/ts_yubiruby.rb --- a/tests/ts_yubiruby.rb Tue Feb 16 11:21:14 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -$:.unshift File.join(File.dirname(__FILE__),'..','lib') -$:.unshift File.join(File.dirname(__FILE__),'..','ext') - -require "test/unit" - -require "tc_modhex"