Jetty密码混淆工具:安全还是假象?

java 复制代码
import java.util.Properties;


/**
 * Password obfuscate utility class. Lifted from Jetty org.mortbay.jetty.security.Password
 *
 * <p>Passwords that begin with OBF: are de obfuscated.</p>
 *
 * <p>Passwords can be obfuscated by running Obfuscate as a main class. Obfuscated password are required if a system needs
 * to recover the full password (eg. so that it may be passed to another system).</p>
 *
 * <p>They are not secure, but prevent casual observation.</p>
 *
 * @see <a
 *      href="http://grepcode.com/file_/repo1.maven.org/maven2/org.mortbay.jetty/jetty/6.1.11/org/mortbay/jetty/security/Password.java/?v=source"
 *      >Jetty Source org.mortbay.jetty.security.Password</a>
 * @since 2.0
 */
public class PasswordUtil
{
    public static final String __OBFUSCATE = "OBF:";

    /* ------------------------------------------------------------ */
    public static String obfuscate( String s )
    {
        StringBuilder buf = new StringBuilder();
        byte[] b = s.getBytes();

        buf.append( __OBFUSCATE );
        for ( int i = 0; i < b.length; i++ )
        {
            byte b1 = b[i];
            byte b2 = b[s.length() - ( i + 1 )];
            int i1 = 127 + b1 + b2;
            int i2 = 127 + b1 - b2;
            int i0 = i1 * 256 + i2;
            String x = Integer.toString( i0, 36 );

            switch ( x.length() )
            {
                case 1:
                    buf.append( '0' );
                case 2:
                    buf.append( '0' );
                case 3:
                    buf.append( '0' );
                default:
                    buf.append( x );
            }
        }
        return buf.toString();

    }

    /* ------------------------------------------------------------ */
    public static String deobfuscate( String s )
    {
        if ( s.startsWith( __OBFUSCATE ) )
        {
            s = s.substring( __OBFUSCATE.length() );

            byte[] b = new byte[s.length() / 2];
            int l = 0;
            for ( int i = 0; i < s.length(); i += 4 )
            {
                String x = s.substring( i, i + 4 );
                int i0 = Integer.parseInt( x, 36 );
                int i1 = ( i0 / 256 );
                int i2 = ( i0 % 256 );
                b[l++] = (byte) ( ( i1 + i2 - 254 ) / 2 );
            }
            return new String( b, 0, l );
        }
        else
        {
            return s;
        }

    }

    public static void deobfuscateSystemProps()
    {
        Properties props = System.getProperties();
        for ( Object obj : props.keySet() )
        {
            if ( obj instanceof String )
            {
                String key = (String) obj;
                String value = props.getProperty( key );
                if ( value != null && value.startsWith( __OBFUSCATE ) )
                {
                    System.setProperty( key, deobfuscate( value ) );
                }
            }
        }
    }

    public static void main( String[] args )
    {
        if ( args[0].startsWith( __OBFUSCATE ) )
        {
            System.out.println( PasswordUtil.deobfuscate( args[0] ) );
        }
        else
        {
            System.out.println( PasswordUtil.obfuscate( args[0] ) );
        }
    }
}

这段代码是 PasswordUtil 类,它是从 Jetty 6 的安全模块org.mortbay.jetty.security.Password)中"提取"(lifted)出来的一个密码混淆(obfuscation)工具类 。它的核心目的不是加密(encryption),而是防止密码被"一眼看到" ------ 即 防 casual observation(防随意窥视)

下面我将从 用途、原理、安全性、使用方式 四个维度帮你彻底理解。


🔍 一、用途:为什么需要它?

在配置文件(如 tomcat-users.xml、Maven settings.xml、系统属性等)中,有时需要写明用户名和密码:

xml 复制代码
<!-- Maven settings.xml -->
<server>
  <id>my-tomcat</id>
  <username>admin</username>
  <password>secret123</password> <!-- 明文!危险! -->
</server>

虽然这不是真正的"安全存储",但如果你把密码写成:

xml 复制代码
<password>OBF:1v2j1uum1xtv1uvk1v0h1v2j</password>

那么:

  • 普通人看不出这是什么密码
  • 但程序在运行时能自动还原成明文(因为 Tomcat 或插件会调用 deobfuscate
  • 适用于那些必须传递明文密码给其他系统的场景(比如 Tomcat Manager 部署)

✅ 所以文档注释说:
"Obfuscated passwords are required if a system needs to recover the full password (e.g. so that it may be passed to another system)."


⚙️ 二、工作原理:如何混淆/还原?

1. 混淆(obfuscate)算法

对字符串 s,从两端向中间配对字符:

  • 第 i 个字符:b1 = s[i]
  • 对称位置字符:b2 = s[len - 1 - i]

然后计算两个整数:

  • i1 = 127 + b1 + b2
  • i2 = 127 + b1 - b2

合并成一个 16 位整数:i0 = i1 * 256 + i2

再将 i0 转为 36 进制字符串(用 0-9 + a-z 表示),并补零到 4 位。

最后拼接所有 4 位块,加上前缀 "OBF:"

示例:
java 复制代码
PasswordUtil.obfuscate("admin") 
// 输出:OBF:1v2j1uum1xtv1uvk1v0h1v2j

2. 还原(deobfuscate)算法

  • 去掉 "OBF:" 前缀
  • 每 4 个字符一组,转回十进制 i0
  • 分解出 i1 = i0 / 256, i2 = i0 % 256
  • 计算原始字节:b = (i1 + i2 - 254) / 2
  • 拼成字符串

🔁 这是一个可逆的、确定性的变换,不是哈希,也不是加密。


🛡️ 三、安全性:它安全吗?

不安全!绝对不要用于真正敏感的场景!

  • 不是加密:没有密钥,算法公开,任何人都能还原
  • 不是哈希:可以反向计算出明文
  • 只是"混淆"(Obfuscation):让密码看起来不像密码

📌 官方注释明确说:
"They are not secure, but prevent casual observation."

(它们不安全,但能防止随意观察。)

适用场景:

  • 开发环境配置
  • 内部测试服务器
  • 自动化脚本中的临时凭证
  • 不能用于生产环境的高敏感密码!

🧪 四、如何使用?

1. 命令行工具

bash 复制代码
# 混淆密码
java PasswordUtil admin
# 输出:OBF:1v2j1uum1xtv1uvk1v0h1v2j

# 还原密码
java PasswordUtil OBF:1v2j1uum1xtv1uvk1v0h1v2j
# 输出:admin

💡 注意:main 方法逻辑有 bug!应该是 args[0],不是 args[1]。正确写法:

java 复制代码
public static void main(String[] args) {
    if (args.length == 0) return;
    String input = args[0];
    if (input.startsWith(__OBFUSCATE)) {
        System.out.println(deobfuscate(input));
    } else {
        System.out.println(obfuscate(input));
    }
}

2. 在系统属性中自动解混淆

java 复制代码
PasswordUtil.deobfuscateSystemProps();

→ 遍历所有 -Dkey=value 系统属性,如果 value 以 OBF: 开头,就自动替换成明文。

例如启动 Java 应用:

bash 复制代码
java -Dtomcat.password=OBF:1v2j... MyApp

程序内调用 deobfuscateSystemProps() 后,System.getProperty("tomcat.password") 就是 "admin"

3. 在 Tomcat Maven Plugin 中使用

你可以在 pom.xmlsettings.xml 中写混淆密码:

xml 复制代码
<!-- settings.xml -->
<server>
  <id>tomcat</id>
  <username>admin</username>
  <password>OBF:1v2j1uum1xtv1uvk1v0h1v2j</password>
</server>

Tomcat Maven Plugin 在内部会自动调用 deobfuscate 来还原密码,用于连接远程 Tomcat Manager。


✅ 总结:关键要点

项目 说明
本质 密码混淆(Obfuscation),非加密
目的 防止密码被"一眼看到",提升基本安全性
安全性 低!仅防 casual observation,不能防攻击
可逆性 完全可逆,算法公开
典型用途 Tomcat 用户密码、Maven server 密码、系统属性
前缀标识 OBF:(代表 Obfuscated)
来源 源自 Jetty 6,被 Tomcat Maven Plugin 引入

💡 最佳实践建议

  • 开发/测试环境可用
  • 生产环境应使用 真正的密钥管理(如 Vault、KMS、环境变量 + 权限控制)
  • 永远不要认为 OBF: 是"加密"

这个工具的价值在于 平衡便利性与最低限度的隐私保护,而不是提供安全保障。

相关推荐
冰敷逆向2 小时前
京东h5st纯算分析
java·前端·javascript·爬虫·安全·web
晚风吹长发2 小时前
初步了解Linux中的线程同步问题及线程安全和死锁与生产消费者模型
linux·运维·服务器·开发语言·数据结构·安全
ALex_zry2 小时前
分布式缓存安全最佳实践
分布式·安全·缓存
科技块儿3 小时前
在线考试防作弊IP工具选型:5款主流IP查询API精度、成本、场景适配全测评
服务器·网络·tcp/ip·安全
Linux运维技术栈3 小时前
运维安全: SSH 公钥认证算法加固
linux·运维·安全
模型时代3 小时前
Infosecurity Europe欧洲信息安全展将推出网络安全初创企业专区
安全·web安全·区块链
加密狗复制模拟4 小时前
破解加密狗时间限制介绍
安全·软件工程·个人开发
兆龙电子单片机设计4 小时前
【STM32项目开源】STM32单片机厂房环境安全监测
stm32·单片机·安全·开源·毕业设计·电子信息
木子啊4 小时前
优雅接管异常:打造安全的用户体验
安全·ux