#!/usr/bin/env python ############################################################################### # # String Encryption and File Encryption for programmers & developers # # String Encrypt can help you hide the things that shouldn't be visible at # first glance in your source code to anyone with a hex-editor. # # Supported programming languages code generation: # # * C/C++ - https://www.stringencrypt.com/c-cpp-encryption/ # * C# - https://www.stringencrypt.com/c-sharp-encryption/ # * Visual Basic .NET - https://www.stringencrypt.com/visual-basic-net-vb-net-encryption/ # * Delphi/Pascal - https://www.stringencrypt.com/delphi-pascal-encryption/ # * Java - https://www.stringencrypt.com/java-encryption/ # * JavaScript - https://www.stringencrypt.com/javascript-encryption/ # * Python - https://www.stringencrypt.com/python-encryption/ # * Ruby - https://www.stringencrypt.com/ruby-encryption/ # * AutoIt - https://www.stringencrypt.com/autoit-encryption/ # * PowerShell - https://www.stringencrypt.com/powershell-encryption/ # * Haskell - https://www.stringencrypt.com/haskell-encryption/ # * MASM - https://www.stringencrypt.com/masm-encryption/ # * FASM - https://www.stringencrypt.com/fasm-encryption/ # # Version : StringEncrypt v1.0 # Python : Python v3 # Dependencies : requests (https://pypi.python.org/pypi/requests/) # Author : Bartosz Wójcik (support@pelock.com) # Project page : https://www.stringencrypt.com # Web page : https://www.pelock.com # ############################################################################### import zlib import base64 from enum import * # required external package - install with "pip install requests" import requests class StringEncrypt(object): """StringEncrypt Python 3 module""" # # @var string default StringEncrypt WebApi endpoint # API_URL = "https://www.stringencrypt.com/api.php" # # @var string WebApi key for the service # _activationCode = "" # # @var bool input string / raw bytes compression enabled (enabled by default) # # if you set it to true, you need to compress input string / raw bytes eg. # # compressed = @base64_encode(@gzcompress(string, 9) # # and after encryption you need to decompress encrypted data # # decompressed = @gzuncompress(@base64_decode(source)); # # options["compression"] = true/false enableCompression = True # # @var bool treat input string as a UNICODE string (ANSI otherwise) # # options["unicode"] = true/false useUnicode = True class LangLocaleEncodings(Enum): """Input string default locale (only those listed below are supported currently)""" def __str__(self): return self.value LANG_US = "en_US.utf8" LANG_GB = "en_GB.utf8" LANG_DE = "de_DE.utf8" LANG_ES = "es_ES.utf8" LANG_BE = "fr_BE.utf8" LANG_FR = "fr_FR.utf8" LANG_PL = "pl_PL.utf8" # # @var string input string locate for UTF-8 encoded strings (en_US encoding is used by default ) # langLocaleEncoding = LangLocaleEncodings.LANG_US class NewLinesEncodings(Enum): """How to encode new lines, available values: "lf" - Unix style "crlf" - Windows style "cr" - Mac style""" def __str__(self): return self.value UNIX_STYLE_LF = "lf" WINDOWS_STYLE_CRLF = "crlf" MAC_STYLE_CR = "cr" # # @var string How to encode new lines (Unix LF is used by default) # newLinesEncoding = NewLinesEncodings.UNIX_STYLE_LF class AnsiEncodings(Enum): """Destination ANSI string encoding (if UNICODE encoding is disabled) only those listed below are supported""" def __str__(self): return self.value WINDOWS_1250 = "WINDOWS-1250" WINDOWS_1251 = "WINDOWS-1251" WINDOWS_1252 = "WINDOWS-1252" WINDOWS_1253 = "WINDOWS-1253" WINDOWS_1254 = "WINDOWS-1254" WINDOWS_1255 = "WINDOWS-1255" WINDOWS_1256 = "WINDOWS-1256" WINDOWS_1257 = "WINDOWS-1257" WINDOWS_1258 = "WINDOWS-1258" ISO_8859_1 = "ISO-8859-1" ISO_8859_2 = "ISO-8859-2" ISO_8859_3 = "ISO-8859-3" ISO_8859_9 = "ISO-8859-9" ISO_8859_10 = "ISO-8859-10" ISO_8859_14 = "ISO-8859-14" ISO_8859_15 = "ISO-8859-15" ISO_8859_16 = "ISO-8859-16" # # @var string ANSI encoding if UNICODE mode is disabled (WINDOWS-1250 encoding is used by default) # ansiEncoding = AnsiEncodings.WINDOWS_1250 class OutputProgrammingLanguages(Enum): """Output programming language. Only those listed below are supported, if you pass other name, service will return ERROR_INVALID_LANG""" def __str__(self): return self.value LANG_CPP = "cpp" LANG_CSHARP = "csharp" LANG_VBNET = "vbnet" LANG_DELPHI = "delphi" LANG_JAVA = "java" LANG_JS = "js" LANG_PYTHON = "python" LANG_RUBY = "ruby" LANG_AUTOIT = "autoit" LANG_POWERSHELL = "powershell" LANG_HASKELL = "haskell" LANG_MASM = "masm" LANG_FASM = "fasm" # # @var string Generate output source code in selected programming language (Python is selected by default) # outputProgrammingLanguage = OutputProgrammingLanguages.LANG_PYTHON # # @var integer minimum number of encryption commands # # Demo mode supports only up to 3 commands (50 in full version), # if you pass more than this number, service will return # ERROR_CMD_MIN # # options["cmd_min"] = 1 minEncryptionCommands = 1 # # @var integer maximum number of encryption commands # # demo mode supports only up to 3 commands (50 in full version), # if you pass more than this number, service will return # ERROR_CMD_MAX # # options["cmd_max"] = 50 maxEncryptionCommands = 3 # # @var bool store encrypted string as a local variable (if supported # by the programming language), otherwise it's stored as # a global variable # # options["local"] = true/false declareAsLocalVariable = False class ErrorCodes(IntEnum): """Possible error codes returned by the StringEncrypt WebAPI service""" # @var integer success ERROR_SUCCESS = 0 # @var integer label parameter is missing ERROR_EMPTY_LABEL = 1 # @var integer label length is too long ERROR_LENGTH_LABEL = 2 # @var integer input string is missing ERROR_EMPTY_STRING = 3 # @var integer input file is missing ERROR_EMPTY_BYTES = 4 # @var integer input string/file is missing ERROR_EMPTY_INPUT = 5 # @var integer string length is too long ERROR_LENGTH_STRING = 6 # @var integer bytes length is too long ERROR_LENGTH_BYTES = 11 # @var integer programming language not supported ERROR_INVALID_LANG = 7 # @var integer invalid locale defined ERROR_INVALID_LOCALE = 8 # @var integer min. number of encryption commands error ERROR_CMD_MIN = 9 # @var integer max. number of encryption commands error ERROR_CMD_MAX = 10 # @var integer you need a valid code to use full version features ERROR_DEMO = 100 def __init__(self, activation_code=None): """Initialize StringEncrypt class :param api_key: Activation code for the service (it can be empty for demo mode) """ self._activationCode = activation_code def is_demo(self): """Login to the service using previously provided activation code and get the information about the current license limits :return: An array with the results or False on error :rtype: bool,dict """ # parameters params = {"command": "is_demo"} return self.post_request(params) def encrypt_file_contents(self, file_path, label): """Encrypt binary file contents :param file_path: A path to any binary file. Demo mode doesn't support this parameter and the service will return ERROR_DEMO :param label: A label name. Demo mode supports up to 10 chars only (64 in full version), if you pass more than this number, service will return ERROR_LENGTH_LABEL :return: An array with the results or False on error :rtype: bool,dict """ source_file = open(file_path, 'rb') bytes = source_file.read() source_file.close() if not bytes: return False # additional parameters params_array = {"command": "encrypt", "bytes": bytes, "label": label} return self.post_request(params_array) def encrypt_string(self, string, label): """Encrypt a string into an encrypted source code in selected programming language :param string: An input string in UTF-8 or ANSI format (by default UTF-8 is used) demo mode supports up to 10 chars only, if you pass more than that, service will return ERROR_LENGTH_STRING :param label: label name. Demo mode supports up to 10 chars only (64 in full version), if you pass more than this number, service will return ERROR_LENGTH_LABEL :return: An array with the results or False on error :rtype: bool,dict """ # additional parameters params_array = {"command": "encrypt", "string": string, "label": label} return self.post_request(params_array) def post_request(self, params_array): """Send a POST request to the server :param params_array: An array with the parameters :return: An array with the results or false on error :rtype: bool,dict """ # add activation code to the parameters array params_array["code"] = self._activationCode # setup parameters for the "encrypt" command ("is_demo" doesn't require it) if params_array["command"] == "encrypt": params_array["unicode"] = 1 if self.useUnicode else 0 params_array["lang_locale"] = self.langLocaleEncoding params_array["ansi_encoding"] = self.ansiEncoding params_array["local"] = 1 if self.declareAsLocalVariable else 0 params_array["new_lines"] = self.newLinesEncoding # number of encryption commands params_array["cmd_min"] = self.minEncryptionCommands params_array["cmd_max"] = self.maxEncryptionCommands params_array["lang"] = self.outputProgrammingLanguage # # check if compression is enabled # if self.enableCompression: params_array["compression"] = "1" if "string" in params_array and params_array["string"]: compressed_data = zlib.compress(bytes(params_array["string"], 'utf-8'), 9) base64_encoded_data = base64.b64encode(compressed_data).decode() params_array["string"] = base64_encoded_data elif "bytes" in params_array and params_array["bytes"]: compressed_data = zlib.compress(bytes(params_array["bytes"]), 9) base64_encoded_data = base64.b64encode(compressed_data).decode() params_array["bytes"] = base64_encoded_data response = requests.post(self.API_URL, data=params_array) # no response at all or an invalid response code if not response or not response.ok: return False # decode to json array result = response.json() # depack output code back into the string if "source" in result and self.enableCompression and result["error"] == self.ErrorCodes.ERROR_SUCCESS: result["source"] = str(zlib.decompress(base64.b64decode(result["source"])), "utf-8") # append error code in string format if "error" in result: result["error_string"] = self.ErrorCodes(result["error"]).name # return original JSON response code return result