hashident 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. hashident-0.1.0/LICENSE +21 -0
  2. hashident-0.1.0/PKG-INFO +422 -0
  3. hashident-0.1.0/README.md +393 -0
  4. hashident-0.1.0/pyproject.toml +54 -0
  5. hashident-0.1.0/setup.cfg +4 -0
  6. hashident-0.1.0/src/hashident/__init__.py +3 -0
  7. hashident-0.1.0/src/hashident/cli.py +228 -0
  8. hashident-0.1.0/src/hashident/commands.py +39 -0
  9. hashident-0.1.0/src/hashident/context.py +56 -0
  10. hashident-0.1.0/src/hashident/engine.py +157 -0
  11. hashident-0.1.0/src/hashident/inputs.py +154 -0
  12. hashident-0.1.0/src/hashident/json_output.py +101 -0
  13. hashident-0.1.0/src/hashident/models.py +112 -0
  14. hashident-0.1.0/src/hashident/output.py +358 -0
  15. hashident-0.1.0/src/hashident/signatures.py +207 -0
  16. hashident-0.1.0/src/hashident/style.py +73 -0
  17. hashident-0.1.0/src/hashident/terminal.py +85 -0
  18. hashident-0.1.0/src/hashident/tips.py +45 -0
  19. hashident-0.1.0/src/hashident.egg-info/PKG-INFO +422 -0
  20. hashident-0.1.0/src/hashident.egg-info/SOURCES.txt +36 -0
  21. hashident-0.1.0/src/hashident.egg-info/dependency_links.txt +1 -0
  22. hashident-0.1.0/src/hashident.egg-info/entry_points.txt +2 -0
  23. hashident-0.1.0/src/hashident.egg-info/requires.txt +3 -0
  24. hashident-0.1.0/src/hashident.egg-info/top_level.txt +1 -0
  25. hashident-0.1.0/tests/test_cli.py +145 -0
  26. hashident-0.1.0/tests/test_color.py +270 -0
  27. hashident-0.1.0/tests/test_compact.py +362 -0
  28. hashident-0.1.0/tests/test_context.py +123 -0
  29. hashident-0.1.0/tests/test_engine.py +182 -0
  30. hashident-0.1.0/tests/test_inputs.py +337 -0
  31. hashident-0.1.0/tests/test_json.py +270 -0
  32. hashident-0.1.0/tests/test_models.py +75 -0
  33. hashident-0.1.0/tests/test_output.py +180 -0
  34. hashident-0.1.0/tests/test_packaging.py +56 -0
  35. hashident-0.1.0/tests/test_readme.py +89 -0
  36. hashident-0.1.0/tests/test_signatures.py +142 -0
  37. hashident-0.1.0/tests/test_tips.py +51 -0
  38. hashident-0.1.0/tests/test_verbose.py +150 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Javier Mendoza
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,422 @@
1
+ Metadata-Version: 2.4
2
+ Name: hashident
3
+ Version: 0.1.0
4
+ Summary: Identify likely hash algorithms from a hash string.
5
+ Author: Javier Mendoza
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/jmendoza167/hash_identifier
8
+ Project-URL: Issues, https://github.com/jmendoza167/hash_identifier/issues
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Education
12
+ Classifier: Intended Audience :: Information Technology
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Security
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest; extra == "dev"
28
+ Dynamic: license-file
29
+
30
+ # hashident
31
+
32
+ [![CI](https://github.com/jmendoza167/hash_identifier/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/jmendoza167/hash_identifier/actions/workflows/ci.yml)
33
+
34
+ hashident is a command-line tool that tells you which algorithm most likely
35
+ produced a hash string. It ranks every matching format with a confidence
36
+ level and the reasons behind it, says how hard the hash is to crack, and
37
+ prints ready-to-run Hashcat and John the Ripper commands. It is built for CTF
38
+ players, students working through security coursework, and auditors who find
39
+ password hashes and need to know what they are looking at. It runs on Python
40
+ 3.10+ with no third-party dependencies.
41
+
42
+ ## Why hashident
43
+
44
+ Many hash identifiers print a flat list of every format with the right length
45
+ and leave the rest to you. hashident tries to answer the next questions too:
46
+
47
+ - **Ranked, with reasons.** Candidates are ordered best first and labelled
48
+ HIGH, MEDIUM or LOW confidence, with the reasons for each: the shape that
49
+ matched, why one format outranks another, and what else the input could be.
50
+ - **Ready-to-run commands.** Each likely format comes with its Hashcat mode,
51
+ John format and the exact commands to start a wordlist attack, plus notes
52
+ where a tool needs the hash in a slightly different form.
53
+ - **Strength ratings.** Every format is rated WEAK, MODERATE or STRONG, with
54
+ a one-line explanation (fast and unsalted, or salted and deliberately slow).
55
+ - **Context hints.** Tell it where the hash came from (`--from windows`,
56
+ `linux`, `web` or `db`) and the ranking adapts: 32 hex characters from a
57
+ Windows box are more likely NTLM than MD5. When a hint would change the
58
+ answer, hashident suggests it.
59
+ - **Built for scripts too.** Batches of hashes from files or pipes, a compact
60
+ table for many values, meaningful exit codes, and `--json` output with a
61
+ versioned schema.
62
+
63
+ ## Example
64
+
65
+ One hash gets a full report:
66
+
67
+ ```sh
68
+ hashident 8743b52063cd84097a65d1633f5c74f5
69
+ ```
70
+
71
+ <!-- readme-test: output 8743b52063cd84097a65d1633f5c74f5 -->
72
+ ```text
73
+ Input: 8743b52063cd84097a65d1633f5c74f5
74
+ Length: 32 characters
75
+
76
+ # Format Confidence Hashcat John
77
+ - ------ ---------- ------- -------
78
+ 1 MD5 MEDIUM 0 raw-md5
79
+ 2 NTLM LOW 1000 nt
80
+
81
+ 1. MD5 - medium confidence
82
+ Reasons:
83
+ - 32 hexadecimal characters
84
+ - most common format with this shape
85
+ - also matches NTLM: same length and charset
86
+ Strength: WEAK - Fast and unsalted: GPUs test billions of guesses per second.
87
+ Crack it (save the hash to hash.txt first):
88
+ hashcat -m 0 -a 0 hash.txt wordlist.txt
89
+ john --format=raw-md5 --wordlist=wordlist.txt hash.txt
90
+
91
+ Low-confidence candidates are shown in the table only.
92
+
93
+ Tip: hash from a Windows system? Re-run with --from windows (NTLM ranks first)
94
+ ```
95
+
96
+ Several hashes get a compact table, one row per value. Given a file
97
+ `hashes.txt`:
98
+
99
+ <!-- readme-test: file hashes.txt -->
100
+ ```text
101
+ # hashes from the lab box
102
+ 8743b52063cd84097a65d1633f5c74f5
103
+ b89eaac7e61417341b710b727768294d0e6a277b
104
+ $2a$05$LhayLxezLhK1LhWvKxCyLOj0j1u.Kj0jZ0pEmm134uzrQlFvQJLF6
105
+ *FCF7C1B8749CF99D88E5F34271D636178FB5D130
106
+ $1$ehAsHC4t$4IbK3fHS/H1YGtNYBrIEB1
107
+ not-a-hash
108
+ ```
109
+
110
+ ```sh
111
+ hashident -f hashes.txt
112
+ ```
113
+
114
+ <!-- readme-test: output -f hashes.txt -->
115
+ ```text
116
+ Line Value Format Conf Hashcat
117
+ ------ ------------------------------------------ ----------- ------ -------
118
+ 2 8743b52063cd84097a65d1633f5c74f5 MD5 MEDIUM 0
119
+ 3 b89eaac7e61417341b710b727768294d0e6a277b SHA-1 MEDIUM 100
120
+ 4 $2a$05$LhayLxezLhK1L...pEmm134uzrQlFvQJLF6 bcrypt HIGH 3200
121
+ 5 *FCF7C1B8749CF99D88E5F34271D636178FB5D130 MySQL 4.1+ HIGH 300
122
+ 6 $1$ehAsHC4t$4IbK3fHS/H1YGtNYBrIEB1 md5crypt HIGH 500
123
+ 7 not-a-hash no match - -
124
+
125
+ 6 values: 1 MD5, 1 SHA-1, 1 bcrypt, 1 MySQL 4.1+, 1 md5crypt, 1 no match
126
+ Tip: --from windows would change the top format for 1 of 6 values.
127
+ Run hashident on a single value to see its full report and crack commands.
128
+ ```
129
+
130
+ The first column is the line number in the file, so you can find each value
131
+ again. Long values are shortened in the middle to keep every line within 80
132
+ columns. In a terminal, confidence levels and strength ratings are colored.
133
+
134
+ ## Installation
135
+
136
+ hashident needs Python 3.10 or newer.
137
+
138
+ ### From PyPI
139
+
140
+ hashident is on [PyPI](https://pypi.org/project/hashident/). The easiest way
141
+ to install a command-line tool is [pipx](https://pipx.pypa.io), which gives it
142
+ its own environment and puts the `hashident` command on your PATH:
143
+
144
+ ```sh
145
+ pipx install hashident
146
+ hashident --version
147
+ ```
148
+
149
+ Upgrade later with `pipx upgrade hashident`. To install with pip instead, use
150
+ a virtual environment and run `python -m pip install hashident`.
151
+
152
+ ### From source
153
+
154
+ To work on hashident itself, or to run the tests:
155
+
156
+ ```sh
157
+ git clone https://github.com/jmendoza167/hash_identifier.git
158
+ cd hash_identifier
159
+ python -m venv .venv
160
+ ```
161
+
162
+ Activate the virtual environment:
163
+
164
+ | Shell | Command |
165
+ | --- | --- |
166
+ | PowerShell (Windows) | `.\.venv\Scripts\Activate.ps1` |
167
+ | Git Bash (Windows) | `source .venv/Scripts/activate` |
168
+ | bash or zsh (Linux, macOS) | `source .venv/bin/activate` |
169
+
170
+ Then install hashident into it and check that it runs:
171
+
172
+ ```sh
173
+ python -m pip install -e .
174
+ hashident --version
175
+ ```
176
+
177
+ If PowerShell refuses to run `Activate.ps1`, allow scripts for the current
178
+ session only with `Set-ExecutionPolicy -Scope Process RemoteSigned`, then
179
+ activate again.
180
+
181
+ To run the tests, install the development extra and run pytest:
182
+
183
+ ```sh
184
+ python -m pip install -e ".[dev]"
185
+ python -m pytest
186
+ ```
187
+
188
+ ## Usage
189
+
190
+ ```text
191
+ usage: hashident [-h] [--version] [--from {windows,linux,web,db}]
192
+ [--color {auto,always,never} | --no-color] [-f PATH] [-v]
193
+ [--json]
194
+ [hash ...]
195
+ ```
196
+
197
+ Run `hashident --help` for the full reference.
198
+
199
+ ### Identify a hash
200
+
201
+ ```sh
202
+ hashident 8743b52063cd84097a65d1633f5c74f5
203
+ ```
204
+
205
+ ### Quoting hashes with `$` or `*`
206
+
207
+ Wrap hashes that contain `$` (bcrypt, md5crypt, sha512crypt) or start with `*`
208
+ (MySQL) in **single quotes**. Otherwise the shell changes them before
209
+ hashident sees them: bash and PowerShell both treat `$2a` as a variable, and
210
+ bash expands `*` as a filename pattern. Double quotes are not enough, because
211
+ both shells still expand `$` inside them.
212
+
213
+ The same command works in PowerShell and bash:
214
+
215
+ ```sh
216
+ hashident '$2a$05$LhayLxezLhK1LhWvKxCyLOj0j1u.Kj0jZ0pEmm134uzrQlFvQJLF6'
217
+ hashident '*FCF7C1B8749CF99D88E5F34271D636178FB5D130'
218
+ ```
219
+
220
+ In Windows `cmd.exe`, leave the quotes off: cmd does not expand `$`, and it
221
+ would pass the single quotes on as part of the hash.
222
+
223
+ Hashes read from a file or a pipe are never touched by the shell, so they need
224
+ no quoting.
225
+
226
+ ### Several hashes: arguments, files and stdin
227
+
228
+ Pass several hashes as arguments, read them from a file with `-f`, or pipe
229
+ them in:
230
+
231
+ ```sh
232
+ hashident 8743b52063cd84097a65d1633f5c74f5 b89eaac7e61417341b710b727768294d0e6a277b
233
+ hashident -f hashes.txt
234
+ ```
235
+
236
+ ```sh
237
+ # bash
238
+ cat hashes.txt | hashident
239
+ hashident < hashes.txt
240
+ ```
241
+
242
+ ```powershell
243
+ # PowerShell
244
+ Get-Content hashes.txt | hashident
245
+ ```
246
+
247
+ - Arguments come first, in order, then the lines of `-f PATH`. `-f -` reads
248
+ standard input. With neither, hashident reads standard input when it is
249
+ piped or redirected, and shows help otherwise.
250
+ - In files and piped input, blank lines and lines starting with `#` are
251
+ skipped, and surrounding whitespace is stripped.
252
+ - Files can be UTF-8 or UTF-16 with a byte order mark, so files written by
253
+ `>` in Windows PowerShell 5.1 work as they are.
254
+ - A missing or unreadable file, or input with no hashes in it, is an error
255
+ (exit code 2).
256
+
257
+ ### Context hints: `--from`
258
+
259
+ If you know where the hash came from, say so. Formats common in that
260
+ environment are ranked higher:
261
+
262
+ ```sh
263
+ hashident --from windows 8743b52063cd84097a65d1633f5c74f5
264
+ ```
265
+
266
+ Now NTLM ranks above MD5. The values are `windows`, `linux`, `web` and `db`.
267
+ A hint changes which plausible format comes first; it never makes an
268
+ ambiguous match certain, so both stay MEDIUM confidence. Without `--from`,
269
+ hashident suggests a value when one would change the top result.
270
+
271
+ ### Verbose: `-v`
272
+
273
+ ```sh
274
+ hashident -v 8743b52063cd84097a65d1633f5c74f5
275
+ hashident -v -f hashes.txt
276
+ ```
277
+
278
+ With one hash, `-v` also shows the details and commands of LOW-confidence
279
+ candidates, which are normally listed in the table only. With several, it
280
+ prints a full report for each value instead of the compact table, each under
281
+ a rule such as `== line 3 ====`.
282
+
283
+ ### Color: `--color`, `--no-color` and `NO_COLOR`
284
+
285
+ Output is colored only when it goes to a terminal. Piped or redirected output
286
+ is plain.
287
+
288
+ | Option | Effect |
289
+ | --- | --- |
290
+ | `--color auto` | Default: color in a terminal, unless `NO_COLOR` is set |
291
+ | `--color always` | Color even when piped, e.g. into `less -R` |
292
+ | `--color never`, `--no-color` | No color |
293
+
294
+ Setting the [`NO_COLOR`](https://no-color.org) environment variable to any
295
+ non-empty value turns color off in `auto` mode. The flags take precedence over
296
+ `NO_COLOR`:
297
+
298
+ ```sh
299
+ # bash
300
+ NO_COLOR=1 hashident 8743b52063cd84097a65d1633f5c74f5
301
+ ```
302
+
303
+ ```powershell
304
+ # PowerShell
305
+ $env:NO_COLOR = '1'
306
+ hashident 8743b52063cd84097a65d1633f5c74f5
307
+ ```
308
+
309
+ ### JSON: `--json`
310
+
311
+ `--json` prints one JSON object per hash, each on its own line
312
+ ([JSON Lines](https://jsonlines.org)), so large inputs stream and other tools
313
+ can process them line by line. It is never colored, and `-v` has no effect on
314
+ it: JSON always includes everything.
315
+
316
+ Pretty-print the output with Python:
317
+
318
+ ```sh
319
+ hashident --json 8743b52063cd84097a65d1633f5c74f5 | python -m json.tool
320
+ hashident --json -f hashes.txt | python -m json.tool --json-lines
321
+ ```
322
+
323
+ Print each value's line number and best format:
324
+
325
+ ```sh
326
+ hashident --json -f hashes.txt | python -c "import sys, json; [print(r['position'], r['candidates'][0]['format'] if r['matched'] else 'no match') for r in map(json.loads, sys.stdin)]"
327
+ ```
328
+
329
+ Or use [jq](https://jqlang.org) to list the values that matched nothing:
330
+
331
+ ```sh
332
+ hashident --json -f hashes.txt | jq -r 'select(.matched | not) | .input'
333
+ ```
334
+
335
+ In Windows PowerShell 5.1, if piping into Python fails with
336
+ `Unexpected UTF-8 BOM`, your console is set to UTF-8 *with* a byte order mark,
337
+ which PowerShell adds to everything it pipes into a program. Switch to UTF-8
338
+ without one for the session:
339
+
340
+ ```powershell
341
+ $OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
342
+ ```
343
+
344
+ The schema is described under JSON output below.
345
+
346
+ ## Supported formats
347
+
348
+ | Format | Hashcat mode | John format | Strength |
349
+ | --- | --- | --- | --- |
350
+ | MD5 | 0 | `raw-md5` | Weak |
351
+ | NTLM | 1000 | `nt` | Weak |
352
+ | SHA-1 | 100 | `raw-sha1` | Weak |
353
+ | SHA-224 | 1300 | `raw-sha224` | Moderate |
354
+ | SHA-256 | 1400 | `raw-sha256` | Moderate |
355
+ | SHA-512 | 1700 | `raw-sha512` | Moderate |
356
+ | MySQL 4.1+ | 300 | `mysql-sha1` | Weak |
357
+ | md5crypt | 500 | `md5crypt` | Weak |
358
+ | sha512crypt | 1800 | `sha512crypt` | Strong |
359
+ | bcrypt | 3200 | `bcrypt` | Strong |
360
+
361
+ Several formats share a shape: 32 hex characters fit both MD5 and NTLM, and
362
+ 40 fit both SHA-1 and a MySQL 4.1+ hash without its leading `*`. That is why
363
+ hashident ranks candidates instead of naming one.
364
+
365
+ For MySQL 4.1+, Hashcat mode 300 expects the 40 hex characters without the
366
+ `*`, while John's `mysql-sha1` format needs it. hashident prints a note saying
367
+ which form each tool wants.
368
+
369
+ ## Exit codes
370
+
371
+ | Code | Meaning |
372
+ | --- | --- |
373
+ | 0 | Every hash matched a known format |
374
+ | 1 | No hash matched |
375
+ | 2 | Invalid arguments, or input that cannot be read or contains no hashes |
376
+ | 3 | Some hashes matched and some did not |
377
+
378
+ The codes are the same with `--json` and `-v`.
379
+
380
+ ## JSON output
381
+
382
+ Each line of `--json` output is one object for one input value:
383
+
384
+ | Key | Type | Meaning |
385
+ | --- | --- | --- |
386
+ | `schema_version` | int | Schema version, currently `1` |
387
+ | `input` | string | The value as received |
388
+ | `source` | string | `"argument"`, `"<stdin>"` or the path given to `-f` |
389
+ | `position` | int | Argument index or line number, starting at 1 |
390
+ | `context` | string or null | The `--from` value, or null |
391
+ | `matched` | bool | Whether any known format matched |
392
+ | `candidates` | list | Matching formats, best first; empty if none |
393
+ | `tips` | list | `--from` values that would change the top format |
394
+
395
+ Each candidate has `rank`, `format`, `score`, `confidence`, `hashcat_mode`,
396
+ `john_format`, `strength`, `strength_note`, `reasons`, `commands` and `notes`.
397
+ Each tip has `context` and `top_format`. Absent values, such as a format John
398
+ does not support, are `null`. Keys are snake_case, and the output is pure
399
+ ASCII: other characters are written as `\uXXXX` escapes.
400
+
401
+ **Versioning:** new keys may be added within `schema_version` 1, so ignore
402
+ keys you don't recognize. Renaming or removing a key, or changing its type,
403
+ increases `schema_version`.
404
+
405
+ ## Responsible use
406
+
407
+ hashident only identifies hashes. It has no cracking built in: the commands
408
+ it prints are suggestions for Hashcat or John the Ripper, which you run
409
+ yourself. Only analyze hashes you are authorized to work with, such as CTF
410
+ challenges, your own systems, coursework material, or systems covered by a
411
+ written agreement for a security assessment.
412
+
413
+ ## Credits
414
+
415
+ The example hashes used in the tests and in this README come from the
416
+ [Hashcat example hashes](https://hashcat.net/wiki/doku.php?id=example_hashes)
417
+ list. The plaintext for all of them is `hashcat`. The MySQL 4.1+ example is
418
+ Hashcat's mode 300 hash written in MySQL's own `*` format.
419
+
420
+ ## License
421
+
422
+ MIT. See [LICENSE](https://github.com/jmendoza167/hash_identifier/blob/main/LICENSE).