# Path: ss/utils.py
# PY2 = sys.version_info[0] == 2
# def compat_ord(s):
# def compat_chr(d):
# def to_bytes(s):
# def to_str(s):
# def inet_ntop(family, ipstr):
# def inet_pton(family, addr):
# def is_ip(address):
# def patch_socket():
# def pack_addr(address):
# def errno_from_exception(e):
# def get_sock_error(sock):
# def merge_prefix(deque, size):
# 
# Path: ss/crypto/rc4_md5.py
# def create_cipher(alg, key, iv, op, key_as_bytes=0, d=None, salt=None,
#                   i=1, padding=1):
# def test():
# 
# Path: ss/crypto/openssl.py
# def load_openssl():
# def load_cipher(cipher_name):
#     def __init__(self, cipher_name, key, iv, op):
#     def update(self, data):
#     def __del__(self):
#     def clean(self):
# def run_method(method):
# def test_aes_128_cfb():
# def test_aes_256_cfb():
# def test_aes_128_cfb8():
# def test_aes_256_ofb():
# def test_aes_256_ctr():
# def test_bf_cfb():
# def test_rc4():
# class OpenSSLCrypto(object):
# 
# Path: ss/crypto/sodium.py
# BLOCK_SIZE = 64
# def load_libsodium():
#     def __init__(self, cipher_name, key, iv, op):
#     def update(self, data):
# def test_salsa20():
# def test_chacha20():
# class SodiumCrypto(object):
# 
# Path: ss/crypto/table.py
# def get_table(key):
# def init_table(key):
#     def __init__(self, cipher_name, key, iv, op):
#     def update(self, data):
# def test_table_result():
# def test_encryption():
# class TableCipher(object):


import os
import sys
import hashlib
import logging
from ss import utils
from ss.crypto import rc4_md5, openssl, sodium, table
    from os import urandom
    from os import urandom
        data = password
        if i > 0:
            data = m[i - 1] + password
        md5.update(data)
        m.append(md5.digest())
        i += 1
    ms = b''.join(m)
    key = ms[:key_len]
    iv = ms[key_len:key_len + iv_len]
    cached_keys[cached_key] = (key, iv)
    return key, iv


class Encryptor(object):
    def __init__(self, key, method):
        self.key = key
        self.method = method
        self.iv = None
        self.iv_sent = False
        self.cipher_iv = b''
        self.decipher = None
        method = method.lower()
        self._method_info = self.get_method_info(method)
        if self._method_info:
            self.cipher = self.get_cipher(key, method, 1,
                                          random_string(self._method_info[1]))
        else:
            logging.error('method %s not supported' % method)
            sys.exit(1)


# Path: ss/utils.py
# PY2 = sys.version_info[0] == 2
# def compat_ord(s):
# def compat_chr(d):
# def to_bytes(s):
# def to_str(s):
# def inet_ntop(family, ipstr):
# def inet_pton(family, addr):
# def is_ip(address):
# def patch_socket():
# def pack_addr(address):
# def errno_from_exception(e):
# def get_sock_error(sock):
# def merge_prefix(deque, size):
# 
# Path: ss/crypto/rc4_md5.py
# def create_cipher(alg, key, iv, op, key_as_bytes=0, d=None, salt=None,
#                   i=1, padding=1):
# def test():
# 
# Path: ss/crypto/openssl.py
# def load_openssl():
# def load_cipher(cipher_name):
#     def __init__(self, cipher_name, key, iv, op):
#     def update(self, data):
#     def __del__(self):
#     def clean(self):
# def run_method(method):
# def test_aes_128_cfb():
# def test_aes_256_cfb():
# def test_aes_128_cfb8():
# def test_aes_256_ofb():
# def test_aes_256_ctr():
# def test_bf_cfb():
# def test_rc4():
# class OpenSSLCrypto(object):
# 
# Path: ss/crypto/sodium.py
# BLOCK_SIZE = 64
# def load_libsodium():
#     def __init__(self, cipher_name, key, iv, op):
#     def update(self, data):
# def test_salsa20():
# def test_chacha20():
# class SodiumCrypto(object):
# 
# Path: ss/crypto/table.py
# def get_table(key):
# def init_table(key):
#     def __init__(self, cipher_name, key, iv, op):
#     def update(self, data):
# def test_table_result():
# def test_encryption():
# class TableCipher(object):


# Path: ss/encrypt.py
import os
import sys
import hashlib
import logging
from ss import utils
from ss.crypto import rc4_md5, openssl, sodium, table
    from os import urandom
    from os import urandom

        data = password
        if i > 0:
            data = m[i - 1] + password
        md5.update(data)
        m.append(md5.digest())
        i += 1
    ms = b''.join(m)
    key = ms[:key_len]
    iv = ms[key_len:key_len + iv_len]
    cached_keys[cached_key] = (key, iv)
    return key, iv


class Encryptor(object):
    def __init__(self, key, method):
        self.key = key
        self.method = method
        self.iv = None
        self.iv_sent = False
        self.cipher_iv = b''
        self.decipher = None
        method = method.lower()
        self._method_info = self.get_method_info(method)
        if self._method_info:
            self.cipher = self.get_cipher(key, method, 1,
                                          random_string(self._method_info[1]))
        else:
            logging.error('method %s not supported' % method)
            sys.exit(1)


    def get_method_info(self, method):