Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ add mode: cmiyc (KoreLogic CMIYC 2026 contest algo)
add modes: Streebog/GOST 2012 -m 11700, 11750, 11760, 11800, 11850, 11860
add modes: SHA-384 UTF-16LE -m 10830, 10840, 10870
add modes: LDAP SHA/SSHA -m 101, 1411, 1711
add modes: -m 3500, 4300, 4400, 4700, 18500, 18501, 20800, 32800, 34400, 34500, 35900
refactor modes: -m 2600 and 4500
```
### v1.3.1; 2026-04-13
```
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ To use hashgen, type your mode, wordlist input & hash output files with a simple
| md4 | 900 |
| md5 | 0 |
| md5md5 | 2600 |
| 3500 | (hashcat compatible md5(md5(md5($pass)))) |
| 4300 | (hashcat compatible md5(strtoupper(md5($pass)))) |
| 4400 | (hashcat compatible md5(sha1($pass))) |
| 32800 | (hashcat compatible md5(sha1(md5($pass)))) |
| halfmd5 | 5100 |
| md5passsalt | 10 |
| md5saltpass | 20 |
Expand All @@ -106,6 +110,9 @@ To use hashgen, type your mode, wordlist input & hash output files with a simple
| sha1 | 100 |
| ldap-sha | 101 (Netscape LDAP {SHA}) |
| sha1sha1 | 4500 |
| 4700 | (hashcat compatible sha1(md5($pass))) |
| 18500 | (hashcat compatible sha1(md5(md5($pass)))) |
| 18501 | (sha1(md5(sha1($pass)))) |
| sha1passsalt | 110 |
| sha1saltpass | 120 |
| ssha | 111 (NSLDAPS SSHA-1) |
Expand All @@ -119,9 +126,13 @@ To use hashgen, type your mode, wordlist input & hash output files with a simple
| sha224 | 1300 |
| sha224passsalt | 1310 |
| sha224saltpass | 1320 |
| 34400 | (hashcat compatible sha224(sha224($pass))) |
| 34500 | (hashcat compatible sha224(sha1($pass))) |
| sha256 | 1400 |
| sha256passsalt | 1410 |
| sha256saltpass | 1420 |
| 20800 | (hashcat compatible sha256(md5($pass))) |
| 35900 | (sha256(sha1($pass))) |
| ssha256 | 1411 (LDAP {SSHA256}) |
| 1430 | (hashcat compatible sha256 utf16le($pass).$salt) |
| 1440 | (hashcat compatible sha256 $salt.utf16le($pass)) |
Expand Down
133 changes: 123 additions & 10 deletions hashgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ v1.3.2; 2026-08-18
add modes: Streebog/GOST 2012 -m 11700, 11750, 11760, 11800, 11850, 11860
add modes: SHA-384 UTF-16LE -m 10830, 10840, 10870
add modes: LDAP SHA/SSHA -m 101, 1411, 1711
add modes: -m 3500, 4300, 4400, 4700, 18500, 18501, 20800, 32800, 34400, 34500, 35900
refactor modes: -m 2600 and 4500
*/

func versionFunc() {
Expand Down Expand Up @@ -130,6 +132,10 @@ func helpFunc() {
"40\t\t(hashcat compatible md5 $salt.utf16le($pass))\n" +
"70\t\t(hashcat compatible md5 utf16le($pass))\n" +
"md5md5\t\t2600\n" +
"3500\t\t(hashcat compatible md5(md5(md5($pass))))\n" +
"4300\t\t(hashcat compatible md5(strtoupper(md5($pass))))\n" +
"4400\t\t(hashcat compatible md5(sha1($pass)))\n" +
"32800\t\t(hashcat compatible md5(sha1(md5($pass))))\n" +
"md5crypt\t500 (Linux shadow $1$)\n" +
"md6-128\n" +
"md6-224\n" +
Expand All @@ -145,6 +151,9 @@ func helpFunc() {
"sha1\t\t100\n" +
"ldap-sha\t101 (Netscape LDAP {SHA})\n" +
"sha1sha1\t4500\n" +
"4700\t\t(hashcat compatible sha1(md5($pass)))\n" +
"18500\t\t(hashcat compatible sha1(md5(md5($pass))))\n" +
"18501\t\t(sha1(md5(sha1($pass))))\n" +
"sha1passsalt\t110\n" +
"sha1saltpass\t120\n" +
"sha1crypt\t15100 (NetBSD/Juniper SHA1 crypt)\n" +
Expand All @@ -155,9 +164,13 @@ func helpFunc() {
"sha224\t\t1300\n" +
"sha224passsalt\t1310\n" +
"sha224saltpass\t1320\n" +
"34400\t\t(hashcat compatible sha224(sha224($pass)))\n" +
"34500\t\t(hashcat compatible sha224(sha1($pass)))\n" +
"sha256\t\t1400\n" +
"sha256passsalt\t1410\n" +
"sha256saltpass\t1420\n" +
"20800\t\t(hashcat compatible sha256(md5($pass)))\n" +
"35900\t\t(sha256(sha1($pass)))\n" +
"ssha256\t\t1411 (LDAP {SSHA256})\n" +
"1430\t\t(hashcat compatible sha256 utf16le($pass).$salt)\n" +
"1440\t\t(hashcat compatible sha256 $salt.utf16le($pass))\n" +
Expand Down Expand Up @@ -307,6 +320,35 @@ func utf16LEPassStrict(data []byte) ([]byte, bool) {
return out, true
}

// nested hash modes pass lowercase hex text between digest stages
func md5HexBytes(data []byte) [32]byte {
sum := md5.Sum(data)
var out [32]byte
hex.Encode(out[:], sum[:])
return out
}

func sha1HexBytes(data []byte) [40]byte {
sum := sha1.Sum(data)
var out [40]byte
hex.Encode(out[:], sum[:])
return out
}

func sha224HexBytes(data []byte) [56]byte {
sum := sha256.Sum224(data)
var out [56]byte
hex.Encode(out[:], sum[:])
return out
}

func sha256HexBytes(data []byte) [64]byte {
sum := sha256.Sum256(data)
var out [64]byte
hex.Encode(out[:], sum[:])
return out
}

// LDAP SHA/SSHA family -m 101 / 111 / 1411 / 1711
func ldapSHA(password []byte, mode string, saltRaw []byte) string {
if mode == "101" || mode == "ldap-sha" {
Expand Down Expand Up @@ -1649,11 +1691,40 @@ func hashBytesDispatch(hashFunc string, data []byte, cost int) (string, bool) {

// -m 2600 md5(md5($pass))
case "md5md5", "2600":
inner := md5.Sum(data)
var innerHex [32]byte
hex.Encode(innerHex[:], inner[:])
outer := md5.Sum(innerHex[:])
return hex.EncodeToString(outer[:]), true
inner := md5HexBytes(data)
outer := md5HexBytes(inner[:])
return string(outer[:]), true

// -m 3500 md5(md5(md5($pass)))
case "3500":
inner := md5HexBytes(data)
middle := md5HexBytes(inner[:])
outer := md5HexBytes(middle[:])
return string(outer[:]), true

// -m 4300 md5(strtoupper(md5($pass)))
case "4300":
inner := md5HexBytes(data)
for i := range inner {
if inner[i] >= 'a' && inner[i] <= 'f' {
inner[i] -= 'a' - 'A'
}
}
outer := md5HexBytes(inner[:])
return string(outer[:]), true

// -m 4400 md5(sha1($pass))
case "4400":
inner := sha1HexBytes(data)
outer := md5HexBytes(inner[:])
return string(outer[:]), true

// -m 32800 md5(sha1(md5($pass)))
case "32800":
inner := md5HexBytes(data)
middle := sha1HexBytes(inner[:])
outer := md5HexBytes(middle[:])
return string(outer[:]), true

// MD6

Expand Down Expand Up @@ -1753,11 +1824,29 @@ func hashBytesDispatch(hashFunc string, data []byte, cost int) (string, bool) {

// -m 4500 sha1(sha1($pass))
case "sha1sha1", "4500":
inner := sha1.Sum(data)
var innerHex [40]byte
hex.Encode(innerHex[:], inner[:])
outer := sha1.Sum(innerHex[:])
return hex.EncodeToString(outer[:]), true
inner := sha1HexBytes(data)
outer := sha1HexBytes(inner[:])
return string(outer[:]), true

// -m 4700 sha1(md5($pass))
case "4700":
inner := md5HexBytes(data)
outer := sha1HexBytes(inner[:])
return string(outer[:]), true

// -m 18500 sha1(md5(md5($pass)))
case "18500":
inner := md5HexBytes(data)
middle := md5HexBytes(inner[:])
outer := sha1HexBytes(middle[:])
return string(outer[:]), true

// -m 18501 sha1(md5(sha1($pass)))
case "18501":
inner := sha1HexBytes(data)
middle := md5HexBytes(inner[:])
outer := sha1HexBytes(middle[:])
return string(outer[:]), true

// SHA2

Expand Down Expand Up @@ -1790,11 +1879,35 @@ func hashBytesDispatch(hashFunc string, data []byte, cost int) (string, bool) {
copy(out[57:], salt)
return string(out), true

// -m 34400 sha224(sha224($pass))
case "34400":
inner := sha224HexBytes(data)
outer := sha224HexBytes(inner[:])
return string(outer[:]), true

// -m 34500 sha224(sha1($pass))
case "34500":
inner := sha1HexBytes(data)
outer := sha224HexBytes(inner[:])
return string(outer[:]), true

// sha2-256 -m 1400
case "sha2-256", "sha256", "1400":
h := sha256.Sum256(data)
return hex.EncodeToString(h[:]), true

// -m 20800 sha256(md5($pass))
case "20800":
inner := md5HexBytes(data)
outer := sha256HexBytes(inner[:])
return string(outer[:]), true

// -m 35900 sha256(sha1($pass))
case "35900":
inner := sha1HexBytes(data)
outer := sha256HexBytes(inner[:])
return string(outer[:]), true

// -m 1410 sha256(pass.salt), -m 1420 sha256(salt.pass)
case "1410", "sha256passsalt", "1420", "sha256saltpass":
var saltBuf [16]byte
Expand Down
Loading