第三章:Type 7密码实战——用Python搞定加密、解密与批量处理

说实话,Type 7密码在思科设备里太常见了。我当年刚入行时,第一次看到配置文件里那些7 0822455D0A16之类的字符串,完全摸不着头脑。后来才知道,这玩意儿其实就是个简单的Vigenère密码变种。嗯,今天我们就用Python把它彻底扒干净。

3.1 Type 7密码的加密原理

先说说它的核心逻辑。Type 7加密其实不复杂,说白了就是:

  • 一个固定的密钥串(思科官方用的那串字符)
  • 每个明文字符与密钥中对应位置的字符做XOR运算
  • 结果转成两位十六进制数
  • 第一个字节是密钥的起始偏移量

我在项目中遇到过好几次,有人拿着Type 7密文问我能不能解。其实只要知道密钥串,解密就是反过来做一遍XOR。但要注意,密钥串是循环使用的——这一点很多人会忽略。

核心要点:Type 7的密钥串是固定的,但起始位置由密文的第一个字节决定。这个偏移量范围是0到15,超过15会循环。

3.2 解密函数实现

先写解密函数。我个人习惯从解密入手,因为验证起来方便——你加密一段明文,再用解密函数还原,能对上就说明逻辑没问题。

def type7_decrypt(encrypted_string):
    # 思科Type 7密钥串
    key = "dsfd;kfoA,.iyewrkldJKDHSUBsgvca69834ncx"
    
    # 去掉开头的'7'和空格
    encrypted_string = encrypted_string.strip()
    if encrypted_string.startswith('7 '):
        encrypted_string = encrypted_string[2:]
    
    # 第一个字节是偏移量
    offset = int(encrypted_string[:2], 16)
    
    # 剩下的每两个字节一组
    hex_pairs = [encrypted_string[i:i+2] for i in range(2, len(encrypted_string), 2)]
    
    result = []
    for i, pair in enumerate(hex_pairs):
        # 密文字节
        cipher_byte = int(pair, 16)
        # 密钥字节(注意循环)
        key_byte = ord(key[(offset + i) % len(key)])
        # XOR解密
        plain_byte = cipher_byte ^ key_byte
        result.append(chr(plain_byte))
    
    return ''.join(result)

你看,核心就三行:取偏移、取密钥字节、做XOR。我曾经在调试一个老设备时,发现解密出来的密码总是少一位。排查了半天,原来是配置文件里Type 7密文后面跟了个换行符没处理。嗯,这种坑踩过一次就记住了。

小技巧:解密时建议先打印出偏移量和密钥字节序列,方便调试。我一般会在代码里加个print(f"offset={offset}, key_index={i}"),一眼就能看出问题。

3.3 加密函数实现

加密就是解密的逆过程。但有个细节:加密时你需要自己选一个偏移量。思科设备默认用0,但我建议随机选一个,这样每次加密结果都不一样,更安全一点——虽然Type 7本身就不安全。

import random

def type7_encrypt(plaintext, offset=None):
    key = "dsfd;kfoA,.iyewrkldJKDHSUBsgvca69834ncx"
    
    # 如果没有指定偏移量,随机选一个
    if offset is None:
        offset = random.randint(0, 15)
    
    # 先写偏移量
    result = f"{offset:02X}"
    
    for i, char in enumerate(plaintext):
        key_byte = ord(key[(offset + i) % len(key)])
        cipher_byte = ord(char) ^ key_byte
        result += f"{cipher_byte:02X}"
    
    return result

这里要注意:偏移量范围是0到15,超过15密钥串会循环。我见过有人写死偏移量,结果加密出来的密文在设备上死活认不了。为什么?因为思科设备解析时,偏移量必须和密钥串位置对应上。

避坑指南:我曾经在批量处理时,发现有些密文解密出来是乱码。后来一查,是明文里包含了中文字符。Type 7只支持ASCII字符集,中文会直接崩掉。所以加密前一定要做字符集校验。

3.4 批量处理配置文件

实战中,你很少只处理一条密码。更多时候是面对整个配置文件,里面可能有几十上百条Type 7密码。手动一条条处理?那得累死。写个批量处理函数才是正经事。

import re

def batch_process_config(config_text, mode='decrypt'):
    """
    批量处理配置文件中的Type 7密码
    mode: 'decrypt' 或 'encrypt'
    """
    # 匹配Type 7密码的正则:7 后面跟十六进制字符串
    pattern = r'7\s+([0-9A-Fa-f]+)'
    
    def replace_match(match):
        encrypted = match.group(0)
        if mode == 'decrypt':
            return type7_decrypt(encrypted)
        else:
            # 加密模式需要知道明文,这里假设从外部传入
            # 实际使用时需要根据业务逻辑调整
            return type7_encrypt(encrypted)
    
    return re.sub(pattern, replace_match, config_text)

这个正则匹配很关键。我刚开始写的时候,直接用7\s+[0-9A-Fa-f]+,结果把配置里其他带7的行也匹配上了。后来加了个边界条件,只匹配password 7后面的密文。你想想看,如果匹配错了,把接口编号给改了,那设备配置就全乱了。

3.5 完整实战脚本

把上面这些整合到一起,就是一个完整的Type 7密码处理工具。我个人习惯把它做成命令行工具,支持文件输入输出。

#!/usr/bin/env python3
# type7_tool.py - Type 7密码处理工具

import sys
import re
import random

# 密钥串
KEY = "dsfd;kfoA,.iyewrkldJKDHSUBsgvca69834ncx"

def decrypt(encrypted):
    """解密Type 7密码"""
    encrypted = encrypted.strip()
    if encrypted.startswith('7 '):
        encrypted = encrypted[2:]
    
    offset = int(encrypted[:2], 16)
    hex_pairs = [encrypted[i:i+2] for i in range(2, len(encrypted), 2)]
    
    result = []
    for i, pair in enumerate(hex_pairs):
        cipher_byte = int(pair, 16)
        key_byte = ord(KEY[(offset + i) % len(KEY)])
        plain_byte = cipher_byte ^ key_byte
        result.append(chr(plain_byte))
    
    return ''.join(result)

def encrypt(plaintext, offset=None):
    """加密明文为Type 7密码"""
    if offset is None:
        offset = random.randint(0, 15)
    
    result = f"{offset:02X}"
    for i, char in enumerate(plaintext):
        key_byte = ord(KEY[(offset + i) % len(KEY)])
        cipher_byte = ord(char) ^ key_byte
        result += f"{cipher_byte:02X}"
    
    return result

def batch_process(input_file, output_file, mode='decrypt'):
    """批量处理配置文件"""
    with open(input_file, 'r') as f:
        config = f.read()
    
    pattern = r'password\s+7\s+([0-9A-Fa-f]+)'
    
    def replace_match(match):
        encrypted = match.group(1)
        if mode == 'decrypt':
            return f"password 0 {decrypt(encrypted)}"
        else:
            # 加密模式需要明文密码
            return f"password 7 {encrypt(match.group(1))}"
    
    result = re.sub(pattern, replace_match, config)
    
    with open(output_file, 'w') as f:
        f.write(result)
    
    print(f"处理完成!结果已保存到 {output_file}")

if __name__ == '__main__':
    if len(sys.argv) < 3:
        print("用法: python type7_tool.py <input> <output> [mode]")
        print("mode: decrypt(默认) 或 encrypt")
        sys.exit(1)
    
    mode = sys.argv[3] if len(sys.argv) > 3 else 'decrypt'
    batch_process(sys.argv[1], sys.argv[2], mode)

使用示例:

  • 解密配置文件:python type7_tool.py running-config.txt decrypted-config.txt decrypt
  • 加密配置文件:python type7_tool.py plain-config.txt encrypted-config.txt encrypt

3.6 知识体系总览

下面这张图把Type 7密码的整个处理流程串起来了。从配置文件读取,到正则匹配,再到加密/解密,最后写回文件。你跟着这个流程走,基本不会出错。

Type 7密码处理流程 配置文件输入 正则匹配 password 7 密文 模式选择 解密:XOR + 密钥串 加密:XOR + 随机偏移 配置文件输出

3.7 实战中的注意事项

最后说几个我在项目中踩过的坑:

  • 字符集问题:Type 7只支持ASCII,遇到中文、特殊符号会出错。处理前最好用isascii()做校验。
  • 偏移量范围:思科设备只认0-15的偏移量。如果你加密时用了16,设备会解析失败。
  • 正则匹配精度:尽量用password\s+7\s+开头匹配,避免误伤其他配置行。
  • 文件编码:配置文件可能是UTF-8或Latin-1,读取时指定编码,否则解密出来是乱码。

我的经验:批量处理前,先拿一条密文做测试。确认解密结果正确后,再跑全文件。我曾经一次性处理了5000行配置,结果因为一个换行符没处理好,全废了。从那以后,我养成了先测试再批量处理的习惯。

好了,Type 7密码的实战就到这里。代码都给你了,拿去用就行。记住,Type 7只是弱加密,别把它当安全方案用。真正的密码保护,还得靠Type 5或Type 8/9。

专注资料整理