#!/usr/bin/env ruby require 'gtk2' require 'dbus' require 'digest/sha1' module RandomServer class SessionEntry attr_accessor :h, :r1, :r2, :b1, :b2, :b def initialize(h, r1, b2) @h, @r1, @b2 = h, r1, b2 end def check h == Digest::SHA1.hexdigest(sprintf("%d-%d-%d", r1, r2, b1)) end def to_s "SessionEntry(h=#{h}, r1=#{r1}, r2=#{r2}, b1=#{b1}, b2=#{b2}, b=#{b})\n" end end class RandomObj < DBus::Object def initialize(path, max) super(path) @max = max @records = {} end dbus_interface "org.muadda.random" do dbus_method :suggest_random, "in h:s, in r1:u, out b2:u" do |h, r1| puts "suggest_random h=#{h}, r1=#{r1}" if @records.has_key?(h) puts "Detect replay attempt!" return [0] end b2 = rand(@max) puts "choose b2=#{b2}" @records[h] = SessionEntry.new(h, r1, b2) [b2] end dbus_method :confirm_random, "in h:s, in r2:u, in b1:u" do |h, r2, b1| puts "confirm_random h=#{h}, r2=#{r2} b1=#{b1}" if ! @records.has_key?(h) puts "Cannot confirm: missing key!" return end @records[h].r2 = r2 @records[h].b1 = b1 if !@records[h].check puts "Cannot confirm: cheat detected!" return end @records[h].b = (b1 + @records[h].b2).modulo(@max) puts "b = " + @records[h].b.to_s end end end srand DBus::SessionBus.instance.glibize bus = DBus.session_bus service = bus.request_service("org.muadda.random") r = RandomObj.new("/org/muadda/random256", 256) service.export(r) r = RandomObj.new("/org/muadda/random16", 16) service.export(r) r = RandomObj.new("/org/muadda/random2", 2) service.export(r) Gtk.main end