class ShadowsocksRuby::Protocols::VerifySha1Protocol

Origin shadowsocks protocols with One Time Authenticate

specification: shadowsocks.org/en/spec/protocol.html

Constants

ATYP_DOMAIN
ATYP_IPV4
ATYP_IPV6

Attributes

next_protocol[RW]

Public Class Methods

new(params = {}) click to toggle source

@param [Hash] configuration parameters @option params [Cipher::OpenSSL, Cipher::RbNaCl, Cipher::RC4_MD5] :cipher a cipher object with IV and a key, required @option params [Boolean] :compatible compatibility with origin mode, default true

# File lib/shadowsocks_ruby/protocols/cipher/verify_sha1.rb, line 19
def initialize params = {}
  @params = {:compatible => true}.merge(params)
  @cipher = @params[:cipher] or raise ProtocolError, "params[:cipher] is required"
  raise ProtocolError, "cipher object mush have an IV and a key" if @cipher.iv_len == 0 || @cipher.key == nil
  @buffer = ""
  @counter = 0
end

Public Instance Methods

tcp_receive_from_localbackend(n)
tcp_receive_from_localbackend_first_packet(n) click to toggle source
# File lib/shadowsocks_ruby/protocols/cipher/verify_sha1.rb, line 61
def tcp_receive_from_localbackend_first_packet n
  class << self
    alias tcp_receive_from_localbackend tcp_receive_from_localbackend_other_packet
  end
  data = async_recv(-1) # first packet
  @recv_iv = data.slice!(0, @cipher.iv_len)
  data = @cipher.decrypt(data, @recv_iv)
  @atyp = data.unpack("C")[0]
  if @atyp & 0x10 == 0x10 # OTA mode
    hmac = data[-10, 10]
    raise PharseError, "hmac_sha1 is not correct" \
      unless ShadowsocksRuby::Cipher.hmac_sha1_digest(@recv_iv + @cipher.key, data[0 ... -10]) == hmac
    data[0] = [0x0F & @atyp].pack("C") # clear ota flag
    @buffer << data[0 ... -10]
    tcp_receive_from_localbackend_other_packet_helper n
  else # origin mode
    if @params[:compatible] == false
      raise PharseError, "invalid OTA first packet in strict OTA mode"
    end
    @buffer << data
    tcp_receive_from_localbackend_other_packet_helper n
  end

end
tcp_receive_from_localbackend_other_packet(n) click to toggle source
# File lib/shadowsocks_ruby/protocols/cipher/verify_sha1.rb, line 88
def tcp_receive_from_localbackend_other_packet n
  if @atyp & 0x10 == 0x10 # OTA mode
    len = async_recv(2).unpack("n").first
    hmac = async_recv(10)
    data = async_recv(len)
    raise PharseError, "hmac_sha1 is not correct" \
      unless ShadowsocksRuby::Cipher.hmac_sha1_digest(@recv_iv + [@counter].pack("n"), data) == hmac
    @buffer << @cipher.decrypt(data, @recv_iv)
    @counter += 1
    tcp_receive_from_localbackend_other_packet_helper n
  else # origin mode
    @buffer << @cipher.decrypt(async_recv(-1), @recv_iv)
    tcp_receive_from_localbackend_other_packet_helper n
  end
end
tcp_receive_from_remoteserver(n)
tcp_receive_from_remoteserver_first_packet(n) click to toggle source
# File lib/shadowsocks_ruby/protocols/cipher/verify_sha1.rb, line 27
def tcp_receive_from_remoteserver_first_packet n
  @recv_iv = async_recv(@cipher.iv_len)
  class << self
    alias tcp_receive_from_remoteserver tcp_receive_from_remoteserver_other_packet
  end
  tcp_receive_from_remoteserver_other_packet n
end
tcp_receive_from_remoteserver_other_packet(n) click to toggle source
# File lib/shadowsocks_ruby/protocols/cipher/verify_sha1.rb, line 37
def tcp_receive_from_remoteserver_other_packet n
  @buffer << @cipher.decrypt(async_recv(-1), @recv_iv)
  tcp_receive_from_remoteserver_other_packet_helper n
end
tcp_send_to_localbackend(data)
tcp_send_to_localbackend_first_packet(data) click to toggle source
# File lib/shadowsocks_ruby/protocols/cipher/verify_sha1.rb, line 104
def tcp_send_to_localbackend_first_packet data
  @send_iv = @cipher.random_iv
  send_data @send_iv + @cipher.encrypt(data, @send_iv)
  class << self
    alias tcp_send_to_localbackend tcp_send_to_localbackend_other_packet
  end
end
Also aliased as: tcp_send_to_localbackend
tcp_send_to_localbackend_other_packet(data) click to toggle source
# File lib/shadowsocks_ruby/protocols/cipher/verify_sha1.rb, line 114
def tcp_send_to_localbackend_other_packet data
  send_data @cipher.encrypt(data, @send_iv)
end
tcp_send_to_remoteserver(data)
tcp_send_to_remoteserver_first_packet(data) click to toggle source
# File lib/shadowsocks_ruby/protocols/cipher/verify_sha1.rb, line 42
def tcp_send_to_remoteserver_first_packet data
  data[0] = [0x10 | data.unpack("C").first].pack("C") # set ota flag
  @send_iv = @cipher.random_iv
  hmac = ShadowsocksRuby::Cipher.hmac_sha1_digest(@send_iv + @cipher.key, data)
  send_data @send_iv + @cipher.encrypt(data + hmac, @send_iv)
  class << self
    alias tcp_send_to_remoteserver tcp_send_to_remoteserver_other_packet
  end
end
Also aliased as: tcp_send_to_remoteserver
tcp_send_to_remoteserver_other_packet(data) click to toggle source
# File lib/shadowsocks_ruby/protocols/cipher/verify_sha1.rb, line 54
def tcp_send_to_remoteserver_other_packet data
  data = @cipher.encrypt(data, @send_iv)
  hmac = ShadowsocksRuby::Cipher.hmac_sha1_digest(@send_iv + [@counter].pack("n"), data)
  send_data [data.length].pack("n") << hmac << data
  @counter += 1
end