> ## Content Index
> Fetch the complete content index at: https://www.pinglabz.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Cisco Password Types 7, 5, 8, 9: Audit and Migrate on IOS XE
- URL: https://www.pinglabz.com/cisco-password-types-7-5-8-9-audit-migrate/
- Published: 2026-10-26T16:00:51.000Z
- Updated: 2026-10-26T16:27:37.000Z
- Description: Built in my home lab on IOS XE 17.18: decoded every Type 7 password in seconds, migrated to Type 8, and broke Type 6 by removing the master key.
- Author: Jaime
- Tags: Network Security, IOS XE, Troubleshooting, OSPF, #nsa-guide

*Part of my series testing the* [*NSA Network Infrastructure Security Guide*](https://www.pinglabz.com/infrastructure-security/) *in my home lab.*

Most inherited Cisco configs I open still carry passwords that look protected but are not. A `password 7` string is one short script away from cleartext, an old `secret 5` MD5 hash is a fast cracking target, and OSPF or TACACS keys often sit there as Type 7 because nobody knew what else to use.

I built that kind of config in my home lab on IOS XE 17.18.2, decoded every Type 7 value from a Linux host in seconds, migrated the accounts to Type 8, moved the OSPF key to Type 6, and then broke Type 6 on purpose to show the failure everyone hits after a master key goes missing. The [NSA Network Infrastructure Security Guide (v1.2, Oct 2023)](https://www.nsa.gov/Press-Room/Digital-Media-Center/Document-Gallery/igphoto/2003018261/?ref=pinglabz.com) has a full section on password types, and this post tests its advice on a real router.

## The lab

Built in my home lab with Containerlab: two Cisco IOL routers running IOS XE 17.18.2 and one Alpine Linux host acting as the auditor's laptop.

- **EDGE1** is the router with the inherited config. It has a LAN interface (10.72.40.1/24) toward the audit host and a point-to-point link (10.72.12.0/30) to CORE2.
- **CORE2** is the OSPF neighbor. Both routers authenticate OSPF with a key chain using HMAC-SHA-256.
- **audit** (10.72.40.20) runs OpenSSH, sshpass and a 6-line Python Type 7 decoder.

![Lab diagram: audit host decoding Type 7 from EDGE1, EDGE1 and CORE2 running OSPF with a Type 6 key chain.](https://storage.ghost.io/c/ff/28/ff28db4a-11e1-4835-b928-158974cf96c1/content/images/2026/10/cisco-password-types-7-5-8-9-audit-migrate-1.png)

Every secret in this post is a placeholder like `<netops-pw>`. Hashes and encrypted strings are shortened with an ellipsis. The router printed them in full; I cut them.

## Step 1: audit an inherited config for Type 7, 5 and 9

The config came with `service password-encryption` turned on, which is what makes many people think it is safe:

```text
EDGE1#show version | include IOS Software
Cisco IOS Software [IOSXE], Linux Software (X86_64BI_LINUX-ADVENTERPRISEK9-M), Version 17.18.2, RELEASE SOFTWARE (fc3)
EDGE1#show running-config | include ^enable|^username|password|key-string|^service password
service password-encryption
  key-string 7 0329540236…
enable password 7 00352A2B37…
username netops privilege 15 password 7 144F040827…
username backup privilege 15 secret 9 $14$…
 password 7 071B287F4C…
EDGE1#show running-config | section line vty
line vty 0 4
 password 7 071B287F4C…
 activation-character 13
 login
 transport input ssh

```

Here is how each line maps to a password type:

| Config line                        | Type          | What it really is                              |
| ---------------------------------- | ------------- | ---------------------------------------------- |
| enable password 7                  | 7             | Reversible encoding of the enable password     |
| username netops ... password 7     | 7             | Reversible encoding of a privilege 15 password |
| password 7 under line vty          | 7             | Reversible encoding of a shared line password  |
| key-string 7 in the OSPF key chain | 7             | Reversible encoding of the routing key         |
| secret 9 $14$...                   | 9 (converted) | An old Type 5 MD5 hash wrapped in scrypt       |

The `backup` user is the interesting one. The lab startup config gave it a classic `secret 5 $1$...` MD5 hash. IOS XE 17.18 auto-converted it at boot and stored it as `secret 9 $14$...`. The `$14$` prefix marks what Cisco calls a convoluted Type 9 secret, auto-converted from Type 5\. It looks like Type 9, but it is still built on top of the original MD5 hash. [Cisco also warns](https://www.cisco.com/c/en/us/td/docs/switches/lan/catalyst9300/software/release/17-9/configuration%5Fguide/sec/b%5F179%5Fsec%5F9300%5Fcg/controlling%5Fswitch%5Faccess%5Fwith%5Fpasswords%5Fand%5Fprivilege%5Flevels.html?ref=pinglabz.com) that a `$14$` secret in startup config can lock you out if you downgrade below IOS XE 16.11.2\. The real fix is to set a new secret, not to trust the 9.

The logging buffer also complained about the enable password at boot. It says type 0 because the boot config held the enable password in clear before `service password-encryption` encoded it:

```text
*Oct 26 15:01:59.802: %AAAA-4-CLI_DEPRECATED: WARNING: Configured enable password CLI with weak encryption type 0 will be deprecated in future. Hence please migrate to enable secret CLI which accomplishes same functionality as enable password CLI and which also supports strong irreversible encryption type 9

```

## Step 2: decrypt Cisco Type 7 passwords in seconds

Type 7 is a XOR against a constant that has been public for decades. This is the whole decoder I ran on the audit host:

```python
import sys
# Cisco Type 7 is a fixed XOR (Vigenere-style) against a public constant
xlat = "dsfd;kfoA,.iyewrkldJKDHSUBsgvca69834ncxv9873254k;fg87"
h = sys.argv[1]
seed = int(h[:2])
print(''.join(chr(int(h[i:i+2], 16) ^ ord(xlat[(seed + i//2 - 1) % len(xlat)])) for i in range(2, len(h), 2)))

```

Run against the four strings from the config, it returned every original value, all four within the same few seconds (08:03:56 to 08:03:59 PT in the capture). My capture tool swaps each recovered value for its placeholder, so a matching placeholder means an exact match:

```text
$ python3 t7.py 071B287F4C…
<vty-pw>
$ python3 t7.py 0329540236…
<ospf-key>
$ python3 t7.py 00352A2B37…
<enable-legacy>
$ python3 t7.py 144F040827…
<netops-pw>

```

So anyone holding a config backup, a support bundle or a pasted config in a ticket has the enable password, a privilege 15 account and the OSPF key. `service password-encryption` only stops someone reading over your shoulder. For a read-only login, see [privilege levels vs parser views](https://www.pinglabz.com/cisco-read-only-noc-user-privilege-levels-parser-views/).

Before changing anything I moved the VTY lines from the shared line password to local accounts (`no password`, `login local`) and confirmed both inherited accounts still worked over SSH, including the converted `$14$` one:

```text
$ sshpass -p "<backup-pw>" ssh backup@10.72.40.1 "show privilege"
Current privilege level is 15
$ sshpass -p "<netops-pw>" ssh netops@10.72.40.1 "show privilege"
Current privilege level is 15

```

## Step 3: migrate enable and local users to Type 8 (PBKDF2)

The NSA guide recommends Type 8 (PBKDF2 with SHA-256). It also notes that Type 9 (scrypt) is not approved by NIST. NSA’s [Cisco Password Types: Best Practices](https://media.defense.gov/2022/Feb/17/2002940795/-1/-1/0/CSI%5FCISCO%5FPASSWORD%5FTYPES%5FBEST%5FPRACTICES%5F20220217.PDF?ref=pinglabz.com) sheet gives the same ranking: Type 8 recommended, Type 9 not NIST-approved. So Type 8 is the default choice even though Type 9 is often described as the strongest. On this image, `enable algorithm-type` still offers md5:

```text
EDGE1(config)#enable algorithm-type ?
  md5     Encode the password using the MD5 algorithm
  scrypt  Encode the password using the SCRYPT hashing algorithm
  sha256  Encode the password using the PBKDF2 hashing algorithm

```

A user cannot have both a `password` and a `secret`, so the clean path is to remove the user and recreate it. IOS asks for confirmation because it removes everything tied to that username:

```text
EDGE1(config)#enable algorithm-type sha256 secret <enable-new>
EDGE1(config)#no enable password
EDGE1(config)#no username netops
This operation will remove all username related configurations with same name.Do you want to continue? [confirm]
EDGE1(config)#username netops privilege 15 algorithm-type sha256 secret <netops-new>
EDGE1(config)#no username backup
This operation will remove all username related configurations with same name.Do you want to continue? [confirm]
EDGE1(config)#username backup privilege 15 algorithm-type sha256 secret <backup-new>
EDGE1(config)#end
EDGE1#show running-config | include ^enable|^username
enable secret 8 $8$ofLSQqiU…
username netops privilege 15 secret 8 $8$uju1344L…
username backup privilege 15 secret 8 $8$jUCYqd5.…

```

Do this from the console or with a second session open. If you remove the account you are logged in with and the new secret has a typo, you lock yourself out. The `algorithm-type` keyword is not saved; the config just shows `secret 8`.

Then I tested from the audit host. The old passwords fail (sshpass exit code 5 means the password was rejected) and the new ones work:

```text
$ sshpass -p "<backup-pw>" ssh backup@10.72.40.1 "show privilege"; echo "sshpass exit $?"
sshpass exit 5
$ sshpass -p "<netops-pw>" ssh netops@10.72.40.1 "show privilege"; echo "sshpass exit $?"
sshpass exit 5
$ sshpass -p "<backup-new>" ssh backup@10.72.40.1 "show privilege"
Current privilege level is 15
$ sshpass -p "<netops-new>" ssh netops@10.72.40.1 "show privilege"
Current privilege level is 15

```

## Step 4: Type 6 AES encryption and the master key

An OSPF key cannot be hashed, because the router needs the real value to compute the HMAC. For keys like this (routing keys, TACACS and RADIUS keys, VPN pre-shared keys) Type 6 AES encryption with a master key is the right replacement for Type 7\. NSA’s password-types guidance recommends Type 6 for VPN keys and wherever Type 8 is not available:

```text
EDGE1(config)#key config-key password-encrypt <master-key>
EDGE1(config)#password encryption aes
EDGE1(config)#end
EDGE1#show running-config | section key chain
key chain OSPF-CORE
 key 10
  key-string 6 HNMDe^egIW…
  cryptographic-algorithm hmac-sha-256
EDGE1#show running-config | include config-key|password encryption|^service password
service password-encryption
password encryption aes
EDGE1#show ip ospf neighbor

Neighbor ID     Pri   State           Dead Time   Address         Interface
10.72.255.2       0   FULL/  -        00:00:35    10.72.12.2      Ethernet0/1

```

Turning on `password encryption aes` converted the existing Type 7 key-string to Type 6 by itself, and OSPF stayed FULL. The master key does not appear in the running config. I saved, reloaded EDGE1, and the Type 6 key still worked after the reload, so the master key survived on this platform:

```text
EDGE1#show version | include uptime
EDGE1 uptime is 1 minute
EDGE1#show ip ospf neighbor

Neighbor ID     Pri   State           Dead Time   Address         Interface
10.72.255.2       0   FULL/  -        00:00:39    10.72.12.2      Ethernet0/1

```

## Fault 1: copying a Type 6 string to another router

The usual shortcut is to copy the key chain from one router to the next. I pasted EDGE1's Type 6 key-string onto CORE2, first with no master key on CORE2:

```text
CORE2(config-keychain-key)#key-string 6 HNMDe^egIW…
Invalid encrypted keystring: HNMDe^egIW…

CORE2(config-keychain-key)#end
CORE2#show running-config | section key chain
key chain OSPF-CORE
 key 10
  key-string <ospf-key>
  cryptographic-algorithm hmac-sha-256
CORE2#show ip ospf neighbor

Neighbor ID     Pri   State           Dead Time   Address         Interface
10.72.255.1       0   FULL/  -        00:00:32    10.72.12.1      Ethernet0/1
```

I set CORE2's own, different master key (a unique master key per device limits the blast radius) and tried again. Same result: `Invalid encrypted keystring`. The good news is that IOS rejected the line and kept the old working key, so the neighbor stayed FULL. Turning on `password encryption aes` on CORE2 encrypted the same OSPF key under CORE2's master key, and the ciphertext was completely different from EDGE1's:

```text
CORE2#show running-config | section key chain
key chain OSPF-CORE
 key 10
  key-string 6 XbQTZWCaDF…
  cryptographic-algorithm hmac-sha-256

```

So with unique master keys, Type 6 config is not portable between devices. Templates and automation have to push the clear key and let each router encrypt it locally.

## Fault 2: master key deleted, OSPF down after reload

This is the one that causes outages. Removing the master key prints a warning, but nothing visibly changes:

```text
CORE2(config)#no key config-key password-encrypt
WARNING: All type 6 encrypted keys will become unusable
Continue with master key deletion ? [yes/no]: yes
CORE2(config)#end
CORE2#show running-config | section key chain
key chain OSPF-CORE
 key 10
  key-string 6 XbQTZWCaDF…
  cryptographic-algorithm hmac-sha-256
CORE2#show ip ospf neighbor

Neighbor ID     Pri   State           Dead Time   Address         Interface
10.72.255.1       0   FULL/  -        00:00:37    10.72.12.1      Ethernet0/1

```

OSPF stays FULL because the router still holds the decrypted key in memory. I saved the config and reloaded CORE2\. After the reload the key chain looked fine, but the adjacency never came back:

```text
CORE2#show key chain OSPF-CORE
Key-chain OSPF-CORE:
    key 10 -- text "(Encrypted keystring)"
        cryptographic-algorithm: hmac-sha-256
        accept lifetime (always valid) - (always valid) [valid now]
        send lifetime (always valid) - (always valid) [valid now]
CORE2#show ip ospf neighbor
CORE2#show logging | include OSPF|KEY
*Oct 26 15:10:16.515: %KEYMAN-4-KEYSTR_BAD_CRYPTO: Bad encrypted keystring for key id 10.
*Oct 26 15:10:16.534: %OSPF-5-NOKEY: Key ID 10 in key chain OSPF-CORE does not have a key
*Oct 26 15:10:16.534: %OSPF-4-NOVALIDKEY: No valid authentication key is available on interface Ethernet0/1
*Oct 26 15:10:18.437: %OSPF-5-EXPIREDKEY: Packet sent on interface Ethernet0/1 with expired Key ID 0.

```

The delay is the trap. The change that breaks things and the outage can be weeks apart, so the reload gets the blame. If you see `%KEYMAN-4-KEYSTR_BAD_CRYPTO` after a reload, a password recovery or a hardware swap, check the master key first.

## The fix: new master key, re-enter the clear key

Set a master key again and re-enter the key in clear text. The router encrypts it to a new Type 6 string, and OSPF came back up:

```text
CORE2(config)#key config-key password-encrypt <master-key-core2>
CORE2(config)#key chain OSPF-CORE
CORE2(config-keychain)#key 10
CORE2(config-keychain-key)#key-string <ospf-key>
CORE2(config-keychain-key)#end
CORE2#show running-config | section key chain
key chain OSPF-CORE
 key 10
  key-string 6 _^QH]aXcMN…
  cryptographic-algorithm hmac-sha-256
CORE2#show ip ospf neighbor

Neighbor ID     Pri   State           Dead Time   Address         Interface
10.72.255.1       0   FULL/  -        00:00:33    10.72.12.1      Ethernet0/1

```

That recovery only works if you know the clear key. The master key never appears in the config and cannot be read back from the router. In practice I would keep either the per-device master key or the clear routing and AAA keys in a password vault, because one of them is what gets you out of Fault 2.

## Final state on EDGE1

```text
service password-encryption
password encryption aes
enable secret 8 $8$…
username netops privilege 15 secret 8 $8$…
username backup privilege 15 secret 8 $8$…
key chain OSPF-CORE
 key 10
  key-string 6 …
  cryptographic-algorithm hmac-sha-256
line vty 0 4
 login local
 transport input ssh

```

I left `service password-encryption` on. It no longer protects anything important here, but it still keeps any stray clear text line out of the config.

🧪

**Try it yourself.** Start with [the free IOS essentials lab](https://labs.pinglabz.com/labs/ess-01?plz%5Fplacement=post:pw-types:cta:v1&ref=pinglabz.com), no card needed. [PingLabz Pro](https://www.pinglabz.com/membership/?plz%5Fplacement=post:pw-types:cta:v1) unlocks every lab in the browser.

## Key takeaways

- Type 7 is encoding, not encryption. If an audit finds `password 7` or `key-string 7`, treat those values as already exposed and rotate them.
- Use Type 8 for local accounts and enable: `algorithm-type sha256 secret`. The NSA guide prefers it over Type 9 because scrypt is not NIST-approved.
- A `secret 9 $14$` hash came from an old Type 5 hash. Set a new password to get a real Type 8 hash.
- Use Type 6 (`password encryption aes` plus `key config-key password-encrypt`) only for keys that must stay reversible, and give each device its own master key.
- Type 6 strings do not move between routers with different master keys. Push clear keys and let each device encrypt locally.
- In my lab, deleting the master key did not break OSPF until the next reload. Keep the master key or the clear keys in a vault.

For the policy side, see [Password policies and MFA on network devices](https://www.pinglabz.com/password-policies-mfa-network-devices/). OSPF authentication itself is covered in [OSPF authentication configuration](https://www.pinglabz.com/ospf-authentication-cisco-configuration/), and centralized admin logins in [AAA with TACACS+ and RADIUS for device administration](https://www.pinglabz.com/aaa-tacacs-radius-device-administration/). Broader management-plane hardening is in [Hardening the management plane on IOS XE](https://www.pinglabz.com/hardening-management-plane-ios-xe/). Other fixes from the same series: [SNMP RW community abuse and the SNMPv3 fix](https://www.pinglabz.com/snmp-rw-community-abuse-snmpv3/), [login block-for locked out the NOC](https://www.pinglabz.com/login-block-for-quiet-mode-access-class/) and [VTY lines busy: exec-timeout and TCP keepalives](https://www.pinglabz.com/vty-lines-busy-ssh-exec-timeout-tcp-keepalives/). Source recommendations: [NSA Network Infrastructure Security Guide (v1.2, Oct 2023)](https://www.nsa.gov/Press-Room/Digital-Media-Center/Document-Gallery/igphoto/2003018261/?ref=pinglabz.com).