class CryptoToolchain::DiffieHellman::Peer

Attributes

addresses[R]
channel[R]
debug[R]
debug?[R]
g[R]
name[R]
p[R]
received_messages[R]

Public Class Methods

new(debug: false, name: SecureRandom.uuid, p: NIST_P, g: NIST_G) click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 4
def initialize(debug: false, name: SecureRandom.uuid, p: NIST_P, g: NIST_G)
  @addresses = {}
  @channel = Queue.new
  @name = name
  @debug = debug
  @p = p
  @g = g
  @received_messages = []
end

Public Instance Methods

add_address(peer) click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 38
def add_address(peer)
  @addresses[peer.name] ||= PeerInfo.new(peer: peer, channel: peer.channel )
end
datum_response(msg) click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 68
def datum_response(msg)
  data = msg.decrypt(key: info_for(msg.peer).session_key)
  puts "#{name} got message containing #{data} from #{msg.peer.name}" if debug
  if msg.initial?
    encrypted = encrypted_message_for(msg.peer, message: data, initial: false)
    send_msg(msg.peer, encrypted)
  end
  @received_messages << ReceivedMessage.new(from: msg.peer.name, contents: data)
end
die_response(msg) click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 34
def die_response(msg)
  raise ReceivedDie
end
encrypted_message_for(peer, message: , initial: false) click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 111
def encrypted_message_for(peer, message: , initial: false)
  key = info_for(peer).session_key
  iv = Random.new.bytes(16)
  encrypted = (iv + message.encrypt_cbc(key: key, iv: iv))
  Messages::Datum.new(peer: self, contents: encrypted, initial: initial)
end
info_for(peer) click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 92
def info_for(peer)
  addresses.fetch(peer.name)
end
invalid_pubkey?() click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 122
def invalid_pubkey?
  !valid_pubkey?
end
key_exchange_response(msg) click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 50
def key_exchange_response(msg)
  info = info_for(msg.peer)
  if msg.initial?
    @p = msg.p
    @g = msg.g
  end
  info.update(p: p, g: g, pubkey: msg.pubkey)
  info.set_shared_secret(privkey)
  if debug
    puts "#{name} will use p = #{p}"
    puts "#{name} will use g = #{g}"
    puts "#{name} thinks #{msg.peer.name} has pubkey #{msg.pubkey}"
    puts "#{name} generated secret #{info.shared_secret} for #{msg.peer.name}"
  end
  my_pubkey_msg = Messages::KeyExchange.new(peer: self, pubkey: pubkey, initial: false)
  send_msg msg.peer, my_pubkey_msg if msg.initial?
end
my_address_message(initial: false) click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 107
def my_address_message(initial: false)
  Messages::PeerAddress.new(peer: self, channel: self.channel, initial: initial)
end
peer_address_response(msg) click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 42
def peer_address_response(msg)
  add_address(msg.peer)
  if msg.initial?
    send_msg msg.peer, my_address_message
  end
  puts "#{name} added #{msg.peer.name}" if debug
end
privkey() click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 102
def privkey
  raise RuntimeError.new("Can't generate private key until p has been set") if p.nil?
  @privkey ||= rand(1..0xffffffff) % p
end
process()
Alias for: process!
process!() click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 14
def process!
  when_ready do
    msg = channel.pop
    message_type = msg.class.to_s.split(':').last
    if msg.respond_to?(:peer)
      puts "#{name} got #{message_type} from #{msg.peer.name}" if debug
    end
    method = "#{message_type}_response".snakecase
    unless self.respond_to?(method)
      raise ArgumentError.new("Don't know how to process method :#{method}")
    end
    begin
      send(method, msg)
    rescue ReceivedDie
      break
    end
  end
end
Also aliased as: process
pubkey() click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 96
def pubkey
  raise RuntimeError.new("Can't generate public key until p has been set") if p.nil?
  raise RuntimeError.new("Can't generate public key until g has been set") if g.nil?
  @pubkey ||= g.modexp(privkey, p)
end
send_msg(peer, message) click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 87
def send_msg(peer, message)
  puts "#{name} sends #{message.class.to_s.split(':').last} to #{peer.name}" if debug
  peer.channel.enq(message)
end
valid_pubkey?() click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 118
def valid_pubkey?
  pubkey < p
end
when_ready() { || ... } click to toggle source
# File lib/crypto_toolchain/diffie_hellman/peer.rb, line 78
def when_ready
  loop do
    while(channel.empty?)
      sleep 0.001
    end
    yield
  end
end