network-secret
Encode, decode, and check network device secrets for Juniper/HPE JunOS, Nokia SR OS, and Cisco IOS, from the command line or Python. network-secret is a unified successor to juniper8-crypt and juniper9-crypt: it covers all seven formats in a single package with a single CLI.
Prefer a browser? Decode, encode, hash and verify all seven formats at network-secret.pages.dev. It runs the same algorithms fully client-side - nothing you type is ever sent to a server.
Repository layout
This repo holds both the Python package and the website that share these algorithms.
| Path | What |
|---|---|
network_secret/ |
The Python package published to PyPI as network-secret |
tests/ |
Python test suite |
web/ |
The Svelte site deployed to Cloudflare Pages, with its own README and tests |
The two implementations share known-answer vectors, so keeping them in one repo means a cipher fix and its test data land in a single commit.
Supported formats
| Format | CLI subcommand | Python module | Description |
|---|---|---|---|
$9$ |
juniper9 |
network_secret.juniper9 |
Juniper/HPE reversible obfuscation - keyless |
$8$ |
juniper8 |
network_secret.juniper8 |
Juniper/HPE AES-256-GCM - keyed by master password |
| Nokia custom-hash | nokia-sros-custom-hash |
network_secret.nokia_sros_custom_hash |
Nokia SR OS AES-ECB shared-key cipher |
| Type 6 | cisco-type6 |
network_secret.cisco_type6 |
Cisco IOS reversible AES + HMAC - keyed by the master key |
| Type 7 | cisco-type7 |
network_secret.cisco_type7 |
Cisco IOS legacy XOR obfuscation - keyless |
$8$ |
cisco-type8 |
network_secret.cisco_type8 |
Cisco IOS PBKDF2-SHA256 password hash - one-way |
$9$ |
cisco-type9 |
network_secret.cisco_type9 |
Cisco IOS scrypt password hash - one-way |
$8$and$9$mean two different things. Juniper/HPE and Cisco both use these markers, for unrelated algorithms. A Juniper/HPE$9$is a keyless substitution cipher; a Cisco$9$is a scrypt password hash. Pick the subcommand by the device the value came from, not by the prefix.network-secretnever guesses between them.
Install
pip install network-secret
Or with uv:
uv add network-secret
Python API
from network_secret import juniper8, juniper9, nokia_sros_custom_hash
# Juniper/HPE $9$ (keyless)
cipher9 = juniper9.encrypt("BGPsecret1")
plain9 = juniper9.decrypt(cipher9)
# 'BGPsecret1'
# Juniper/HPE $8$ (master-password keyed)
master = "MyMasterPassword"
cipher8 = juniper8.encrypt("BGPsecret1", master)
plain8 = juniper8.decrypt(cipher8, master)
# 'BGPsecret1'
plain_a, plain_b, match = juniper8.check(cipher8, "BGPsecret1", master)
# match is True
# Nokia SR OS custom-hash (16/24/32-character shared key)
key = "a3f8d9e112c04b7af1c3e8b92d057a4e"
cipher_nokia = nokia_sros_custom_hash.encrypt("BGPsecret1", key)
plain_nokia = nokia_sros_custom_hash.decrypt(cipher_nokia, key)
# 'BGPsecret1'
plain_a, plain_b, match = nokia_sros_custom_hash.check(cipher_nokia, "BGPsecret1", key)
# match is True
# Cisco IOS type 7 (keyless, legacy obfuscation)
from network_secret import cisco_type6, cisco_type7, cisco_type8, cisco_type9
cipher7 = cisco_type7.encrypt("BGPsecret1")
plain7 = cisco_type7.decrypt(cipher7)
# 'BGPsecret1'
# Cisco IOS type 6 (master-key keyed)
cipher6 = cisco_type6.encrypt("BGPsecret1", "MyMasterKey")
plain6 = cisco_type6.decrypt(cipher6, "MyMasterKey")
# 'BGPsecret1'
# Cisco IOS type 8 and type 9 are one-way hashes
hash8 = cisco_type8.encrypt("BGPsecret1")
given, recomputed, match = cisco_type8.check(hash8, "BGPsecret1")
# match is True
cisco_type8.decrypt(hash8)
# ValueError: Cisco type 8 is a one-way hash and cannot be decrypted. Use --check to test a password against it.
All seven check() functions return a tuple[str, str, bool]. For five of them the two strings are the decrypted plaintexts and whether they match. Cisco type 8 and type 9 cannot decrypt anything, so they return the hash you passed in, the hash recomputed from the candidate password, and whether those match. For Cisco type 6 and type 7, the second argument to check() is always read as cleartext, because neither format carries a marker that tells it apart from a password.
Command-line usage
# List all supported ciphers
network-secret --list
# Show the version
network-secret --version
Juniper/HPE $9$ (keyless)
network-secret juniper9 --encrypt 'BGPsecret1'
network-secret juniper9 --decrypt '$9$abc...'
network-secret juniper9 --check '$9$abc...' 'BGPsecret1'
Juniper/HPE $8$ (master-password keyed)
The master password is resolved in this order: -m/--master flag, then the JUNOS_MASTER_PASSWORD environment variable, then an interactive no-echo prompt.
# Master on the command line
network-secret juniper8 -m 'MyMaster' --encrypt 'BGPsecret1'
network-secret juniper8 -m 'MyMaster' --decrypt '$8$aes256-gcm$...'
network-secret juniper8 -m 'MyMaster' --check '$8$aes256-gcm$...' 'BGPsecret1'
# Master from the environment (keeps it out of shell history and the process list)
export JUNOS_MASTER_PASSWORD='MyMaster'
network-secret juniper8 --decrypt '$8$aes256-gcm$...'
# Master from an interactive prompt
network-secret juniper8 --decrypt '$8$aes256-gcm$...'
# Master password: <typed without echo>
Always quote
$8$and$9$strings with single quotes - the shell expands$8and$9as positional parameters otherwise.
Nokia SR OS custom-hash (shared-key)
The shared key is resolved in this order: -k/--key flag, then the SROS_CUSTOM_HASH_KEY environment variable, then an interactive no-echo prompt. Keys must be exactly 16, 24, or 32 characters.
# Key on the command line
network-secret nokia-sros-custom-hash -k 'a3f8d9e112c04b7af1c3e8b92d057a4e' --encrypt 'BGPsecret1'
network-secret nokia-sros-custom-hash -k 'a3f8d9e112c04b7af1c3e8b92d057a4e' --decrypt 'ABC123...'
network-secret nokia-sros-custom-hash -k 'a3f8d9e112c04b7af1c3e8b92d057a4e' --check 'ABC123...' 'BGPsecret1'
# Key from the environment
export SROS_CUSTOM_HASH_KEY='a3f8d9e112c04b7af1c3e8b92d057a4e'
network-secret nokia-sros-custom-hash --decrypt 'ABC123...'
Cisco IOS type 6 (master-key keyed)
The master key is the one set with key config-key password-encrypt. It is resolved in this order: -m/--master flag, then the CISCO_MASTER_KEY environment variable, then an interactive no-echo prompt.
network-secret cisco-type6 -m 'MyMasterKey' --encrypt 'BGPsecret1'
network-secret cisco-type6 -m 'MyMasterKey' --decrypt 'NdUI^_YP[VEP...'
network-secret cisco-type6 -m 'MyMasterKey' --check 'NdUI^_YP[VEP...' 'BGPsecret1'
export CISCO_MASTER_KEY='MyMasterKey'
network-secret cisco-type6 --decrypt 'NdUI^_YP[VEP...'
Cisco IOS type 7 (keyless)
network-secret cisco-type7 --encrypt 'BGPsecret1'
network-secret cisco-type7 --decrypt '060506324F41'
network-secret cisco-type7 --check '060506324F41' 'cisco'
Type 7 is obfuscation, not encryption. Anyone can decode it. Treat any type 7 value you find as cleartext.
Cisco IOS type 8 and type 9 (one-way)
These are password hashes, so there is nothing to decrypt. --encrypt computes a hash with a fresh random salt, and --check tests a password against an existing hash by reusing that hash's salt.
network-secret cisco-type8 --encrypt 'BGPsecret1'
network-secret cisco-type8 --check '$8$J5J/1K3e8gk974$HRez...' 'cisco123'
network-secret cisco-type9 --encrypt 'BGPsecret1'
network-secret cisco-type9 --check '$9$ihSswXDbk0kaVK$o.uy...' 'cisco123'
network-secret cisco-type9 --decrypt '$9$ihSswXDbk0kaVK$o.uy...'
# error: Cisco type 9 is a one-way hash and cannot be decrypted. Use --check to test a password against it.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success (or --check matched) |
| 1 | --check mismatched |
| 2 | Invalid input (malformed value, wrong key, etc.) |
Supersedes
network-secret supersedes the older single-format packages juniper8-crypt and juniper9-crypt. It exposes the same algorithms under the same function signatures (encrypt, decrypt, check); migrating is a matter of updating the import path.
License
MIT
Metadata
Release files for network-secret 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| network_secret-0.2.0.tar.gz | 24.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| network_secret-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 50.4 kB
Release files / network_secret-0.2.0.tar.gz
| Download URL | network_secret-0.2.0.tar.gz |
|---|---|
| Size | 24.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0c7556a6a35d702e8a6a8f52c01b2dd1ac735ddbb96d7b8ce31963f0059ca3ce
|
|
BLAKE2b-256 checksum How to use checksums |
c1712cc31610c637f0dd71b58a70b52875661fd8023f4fd2933eef9c7cd1da51
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 19, 2026.
Transparency logRelease files / network_secret-0.2.0-py3-none-any.whl
| Download URL | network_secret-0.2.0-py3-none-any.whl |
|---|---|
| Size | 26.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c708151a95ac92090bb9afc1d96b4ef258620a14fa0d013239ae1d47c143c4e2
|
|
BLAKE2b-256 checksum How to use checksums |
ace8ab0fa4be1509c629939e845b0e9171bc0788562c58ee945d82f27e6fff25
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 19, 2026.
Transparency log