├── .gitignore ├── Main.sublime-commands ├── README.md └── hasher.py /.gitignore: -------------------------------------------------------------------------------- 1 | package-metadata.json 2 | *.pyc -------------------------------------------------------------------------------- /Main.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Hasher: MD5", 4 | "command": "md5", 5 | "args": {} 6 | }, 7 | { 8 | "caption": "Hasher: SHA1", 9 | "command": "sha1", 10 | "args": {} 11 | }, 12 | { 13 | "caption": "Hasher: SHA224", 14 | "command": "sha224", 15 | "args": {} 16 | }, 17 | { 18 | "caption": "Hasher: SHA256", 19 | "command": "sha256", 20 | "args": {} 21 | }, 22 | { 23 | "caption": "Hasher: SHA384", 24 | "command": "sha384", 25 | "args": {} 26 | }, 27 | { 28 | "caption": "Hasher: SHA512", 29 | "command": "sha512", 30 | "args": {} 31 | }, 32 | { 33 | "caption": "Hasher: NTLM", 34 | "command": "ntlm", 35 | "args": {} 36 | }, 37 | { 38 | "caption": "Hasher: Base64 Encode", 39 | "command": "base64_encode", 40 | "args": {} 41 | }, 42 | { 43 | "caption": "Hasher: Base64 Decode", 44 | "command": "base64_decode", 45 | "args": {} 46 | }, 47 | { 48 | "caption": "Hasher: URI Component Encode", 49 | "command": "uri_component_encode", 50 | "args": {} 51 | }, 52 | { 53 | "caption": "Hasher: URI Component Decode", 54 | "command": "uri_component_decode", 55 | "args": {} 56 | }, 57 | { 58 | "caption": "Hasher: Entity Encode", 59 | "command": "entity_encode", 60 | "args": {} 61 | }, 62 | { 63 | "caption": "Hasher: Entity Decode", 64 | "command": "entity_decode", 65 | "args": {} 66 | }, 67 | { 68 | "caption": "Hasher: Unicode Escape", 69 | "command": "unicode_escape", 70 | "args": {} 71 | }, 72 | { 73 | "caption": "Hasher: Unicode Unescape", 74 | "command": "unicode_unescape", 75 | "args": {} 76 | }, 77 | { 78 | "caption": "Hasher: Insert UNIX Timestamp", 79 | "command": "current_unix_timestamp", 80 | "args": {} 81 | } 82 | ] 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # String Hasher 2 | 3 | Hasher is a small Sublime Text 2 & 3 Plugin that generates hashes from the selected text and some miscellaneous **Unicode aware** string conversions. Currently supported: 4 | 5 | * MD5 6 | * SHA1 7 | * SHA224 8 | * SHA256 9 | * SHA384 10 | * SHA512 11 | * NTLM 12 | * Base64 Encode 13 | * Base64 Decode 14 | * URI Component Encode 15 | * URI Component Decode 16 | * Entity Encode 17 | * Entity Decode 18 | * Unicode Escape 19 | * Unicode Unescape 20 | 21 | ## Key bindings 22 | 23 | Use _Cmd + Shift + P_ on Mac or _Ctrl + Shift + P_ on Windows and type the command you need. Type _hasher_ to see available commands. More to come. 24 | 25 | ## Hasher commands in the Context Menu 26 | 27 | IF you wish to add hasher commands to the context menu, see this [wiki entry](https://github.com/dangelov/hasher/wiki/Context-menu-instructions). 28 | 29 | ## How to install 30 | #### [Package Control](https://github.com/wbond/sublime_package_control) 31 | Just look for _Hasher_ and install. 32 | 33 | #### Git Clone 34 | Clone this repository in to the Sublime Text 2 or 3 "Packages" directory, which is located where ever the 35 | "Preferences" -> "Browse Packages" option in Sublime Text takes you. 36 | 37 | ## Thanks to 38 | - [titoBouzot](https://github.com/titoBouzout) - ST3 compatibility, fixes & additions 39 | - [earshinov](https://github.com/earshinov) - base64 fixes 40 | - [alimony](https://github.com/alimony) - Fixes for HTML Entities + enabled support for both ST2 & 3 in a single package 41 | - [ohaucke](https://github.com/ohaucke) - Context menu for the included commands 42 | - [alphaskade](https://github.com/alphaskade) - SHA256, SHA384, SHA512 and NTLM Hashing 43 | - [komaflash](https://github.com/komaflash) - SHA224, SHA256, SHA384 and SHA512 44 | 45 | ## License 46 | Copyright (C) 2012-2013 Dino Angelov & Contributors 47 | 48 | Permission is hereby granted, free of charge, to any person obtaining a copy of 49 | this software and associated documentation files (the "Software"), to deal in 50 | the Software without restriction, including without limitation the rights to 51 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 52 | of the Software, and to permit persons to whom the Software is furnished to do 53 | so, subject to the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be included in all 56 | copies or substantial portions of the Software. 57 | 58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 62 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 64 | SOFTWARE. 65 | -------------------------------------------------------------------------------- /hasher.py: -------------------------------------------------------------------------------- 1 | import sublime_plugin 2 | import binascii 3 | import hashlib 4 | try: 5 | from urllib import quote as urlquote 6 | from urllib import unquote as urlunquote 7 | except ImportError: 8 | from urllib.parse import quote as urlquote 9 | from urllib.parse import unquote as urlunquote 10 | import time 11 | import base64 12 | try: 13 | from HTMLParser import HTMLParser 14 | except ImportError: 15 | from html.parser import HTMLParser 16 | try: 17 | from htmlentitydefs import codepoint2name as cp2n 18 | except ImportError: 19 | from html.entities import codepoint2name as cp2n 20 | 21 | 22 | class Md5Command(sublime_plugin.TextCommand): 23 | def run(self, edit): 24 | for s in self.view.sel(): 25 | if s.empty(): 26 | s = self.view.word(s) 27 | selected = self.view.substr(s).encode('utf-8') 28 | m = hashlib.md5() 29 | m.update(selected) 30 | txt = m.hexdigest() 31 | self.view.replace(edit, s, txt) 32 | 33 | 34 | class Sha1Command(sublime_plugin.TextCommand): 35 | def run(self, edit): 36 | for s in self.view.sel(): 37 | if s.empty(): 38 | s = self.view.word(s) 39 | selected = self.view.substr(s).encode('utf-8') 40 | m = hashlib.sha1() 41 | m.update(selected) 42 | txt = m.hexdigest() 43 | self.view.replace(edit, s, txt) 44 | 45 | 46 | class Sha224Command(sublime_plugin.TextCommand): 47 | def run(self, edit): 48 | for s in self.view.sel(): 49 | if s.empty(): 50 | s = self.view.word(s) 51 | selected = self.view.substr(s).encode('utf-8') 52 | m = hashlib.sha224() 53 | m.update(selected) 54 | txt = m.hexdigest() 55 | self.view.replace(edit, s, txt) 56 | 57 | 58 | class Sha256Command(sublime_plugin.TextCommand): 59 | def run(self, edit): 60 | for s in self.view.sel(): 61 | if s.empty(): 62 | s = self.view.word(s) 63 | selected = self.view.substr(s).encode('utf-8') 64 | m = hashlib.sha256() 65 | m.update(selected) 66 | txt = m.hexdigest() 67 | self.view.replace(edit, s, txt) 68 | 69 | 70 | class Sha384Command(sublime_plugin.TextCommand): 71 | def run(self, edit): 72 | for s in self.view.sel(): 73 | if s.empty(): 74 | s = self.view.word(s) 75 | selected = self.view.substr(s).encode('utf-8') 76 | m = hashlib.sha384() 77 | m.update(selected) 78 | txt = m.hexdigest() 79 | self.view.replace(edit, s, txt) 80 | 81 | 82 | class Sha512Command(sublime_plugin.TextCommand): 83 | def run(self, edit): 84 | for s in self.view.sel(): 85 | if s.empty(): 86 | s = self.view.word(s) 87 | selected = self.view.substr(s).encode('utf-8') 88 | m = hashlib.sha512() 89 | m.update(selected) 90 | txt = m.hexdigest() 91 | self.view.replace(edit, s, txt) 92 | 93 | 94 | class NtlmCommand(sublime_plugin.TextCommand): 95 | def run(self, edit): 96 | for s in self.view.sel(): 97 | if s.empty(): 98 | s = self.view.word(s) 99 | selected = str(self.view.substr(s)) 100 | m = hashlib.new('md4', selected.encode('utf-16le')).digest() 101 | if(type(m) is str): 102 | txt = str(binascii.hexlify(m)).upper() 103 | elif(type(m) is bytes): 104 | txt = str(binascii.hexlify(m)).split('\'')[1].upper() 105 | else: 106 | txt = s 107 | self.view.replace(edit, s, txt) 108 | 109 | 110 | class Base64EncodeCommand(sublime_plugin.TextCommand): 111 | def run(self, edit): 112 | for s in self.view.sel(): 113 | if s.empty(): 114 | s = self.view.word(s) 115 | selected = self.view.substr(s).encode('utf-8') 116 | txt = base64.b64encode(selected).decode('utf-8') 117 | self.view.replace(edit, s, txt) 118 | 119 | 120 | class Base64DecodeCommand(sublime_plugin.TextCommand): 121 | def run(self, edit): 122 | for s in self.view.sel(): 123 | if s.empty(): 124 | s = self.view.word(s) 125 | selected = self.view.substr(s) 126 | 127 | # pad to 4 characters 128 | if len(selected) % 4 != 0: 129 | selected += "=" * (4 - len(selected) % 4) 130 | 131 | txt = base64.b64decode(selected).decode('utf8') 132 | self.view.replace(edit, s, txt) 133 | 134 | 135 | class UriComponentEncodeCommand(sublime_plugin.TextCommand): 136 | def run(self, edit): 137 | for s in self.view.sel(): 138 | if s.empty(): 139 | s = self.view.word(s) 140 | selected = self.view.substr(s) 141 | txt = urlquote(selected.encode('utf8'), '') 142 | self.view.replace(edit, s, txt) 143 | 144 | 145 | class UriComponentDecodeCommand(sublime_plugin.TextCommand): 146 | def run(self, edit): 147 | for s in self.view.sel(): 148 | if s.empty(): 149 | s = self.view.word(s) 150 | selected = self.view.substr(s) 151 | try: 152 | txt = urlunquote(selected.encode('utf8')).decode('utf8') 153 | except TypeError: 154 | txt = urlunquote(selected) 155 | self.view.replace(edit, s, txt) 156 | 157 | 158 | class EntityEncodeCommand(sublime_plugin.TextCommand): 159 | def run(self, edit): 160 | for s in self.view.sel(): 161 | if s.empty(): 162 | s = self.view.word(s) 163 | buf = [] 164 | for pt in range(s.begin(), s.end()): 165 | ch = self.view.substr(pt) 166 | ch_ord = ord(ch) 167 | try: 168 | ch = '&%s;' % cp2n[ch_ord] 169 | except: 170 | pass 171 | buf.append(ch) 172 | self.view.replace(edit, s, ''.join(buf)) 173 | 174 | 175 | class EntityDecodeCommand(sublime_plugin.TextCommand): 176 | def run(self, edit): 177 | for s in self.view.sel(): 178 | if s.empty(): 179 | s = self.view.word(s) 180 | selected = self.view.substr(s) 181 | parser = HTMLParser() 182 | selected = parser.unescape(selected) 183 | self.view.replace(edit, s, selected) 184 | 185 | 186 | class UnicodeEscapeCommand(sublime_plugin.TextCommand): 187 | def run(self, edit): 188 | for s in self.view.sel(): 189 | if s.empty(): 190 | s = self.view.word(s) 191 | selected = self.view.substr(s) 192 | self.view.replace(edit, s, selected.encode('ascii', 'backslashreplace').decode('utf-8')) 193 | 194 | class UnicodeUnescapeCommand(sublime_plugin.TextCommand): 195 | def run(self, edit): 196 | for s in self.view.sel(): 197 | if s.empty(): 198 | s = self.view.word(s) 199 | selected = self.view.substr(s) 200 | self.view.replace(edit, s, bytes(selected, 'utf8').decode('unicode_escape')) 201 | 202 | class CurrentUnixTimestamp(sublime_plugin.TextCommand): 203 | def run(self, edit): 204 | for s in self.view.sel(): 205 | txt = time.asctime(time.gmtime()) 206 | txt = time.ctime() 207 | txt = "%.0f" % round(time.time(), 3) 208 | self.view.replace(edit, s, txt) 209 | --------------------------------------------------------------------------------