Maven 3密码加密如何工作?

aar*_*ell 20 security encryption passwords maven

我正在尝试了解Maven 3的[密码加密功能.我发现这个功能记录不清,令人困惑.例如,该功能的作者功能文档博客文章在几个方面相互矛盾.

这个问题比maven --encrypt-master-password如何工作更广泛,并且不受Maven encrypt-master-password选择密码的良好做法的限制.

具体来说,我试图回答文档未涵盖的以下问题.到目前为止,我已经在斜体字下面提供了我能够收集的信息.

  1. 加密的主密码是否仅通过存在于settings-security.xml只有一个用户可以访问(~/.m2)的文件夹中来提供安全性?如果是这样,为什么还要加密'主密码'(为什么不使用一些随机值)呢?"主密码"不仅仅是加密函数的熵输入吗?将其称为密码令人困惑 - 我希望Maven在解密任何加密的服务器密码之前提示我输入此密码,但事实并非如此.

我的理解是,这只是通过受操作系统保护的文件中存在来提供安全性.我相信Maven允许您加密主密码,这样如果您丢失settings-security.xml文件,您可以重新生成它.它是否正确?

  1. 主密码和服务器密码是否使用相同的加密过程/密码?服务器密码基于主密码,因此算法必须存在一些差异.这个源代码在哪里?

Marcelo Morales关于如何将maven --encrypt-master-password工作链接到GitHub上plexus-cihper项目的回答.目前尚不清楚这只是密码,还是提供密码功能的实际Maven插件.

  1. 我观察到多次加密相同的主密码或服务器密码会产生不同的哈希值.根据Marcelo Morales关于maven --encrypt-master-password如何工作的回答,这是因为在加密之前,'JVM配置特定的(通常是SHA1PRNG)64位随机盐'被添加到密码中.Maven在编译时使用它们来解密存储的密码.这是不是意味着盐必须存放在某个地方?

我不知道.

  1. 我还观察到,如果主密码被重新加密并存储在settings-security.xml文件中,使用一个加密的主密码加密的常规密码仍然可用,即使加密的主密码密文现在不同.谁能解释一下这是如何工作的?

我不知道.在我看来,Maven正在做一些可疑的事情或在某处存储明文.

  1. 我的理解是加密的密码只能与文件中的<server />标签一起使用settings.xml.这是真的?在哪里可以使用定义的服务器settings.xml

我的理解是<server />定义可用于<repositories /><distributionManagement />,但不是<scm />.有人可以验证吗?

  1. 对于这样一个关键特性(构建系统安全性),在我看来存在很多混乱和糟糕的文档.有人能指出Maven 3网站上的文档是如何工作的吗?是否有某个wiki链接允许我尝试改进文档?

我不知道

对不起文字的墙,谢谢你的答案.

Gre*_*ant 14

我的回答是基于阅读Maven源代码并进行一些研究.

  1. 加密的主密码是否仅通过存在于settings-security.xml只有一个用户可以访问(~/.m2)的文件夹中来提供安全性?如果是这样,为什么还要加密'主密码'(为什么不使用一些随机值)呢?"主密码"不仅仅是加密函数的熵输入吗?将其称为密码令人困惑 - 我希望Maven在解密任何加密的服务器密码之前提示我输入此密码,但事实并非如此.

主密码是加密功能的输入,用于加密/解密服务器密码.如果某人拥有您的个人加密服务器密码,除非他们也拥有您的主密码,否则他们将无法对其进行解密.这意味着您可以与其他人自由共享您的maven settings.xml文件,而无需他们解密您的服务器密码.这也是主密码保存在单独文件中的原因.

这个基本原理在加密指南中有所解释

  1. 主密码和服务器密码是否使用相同的加密过程/密码?服务器密码基于主密码,因此算法必须存在一些差异.这个源代码在哪里?

据我所知,主密码使用与服务器密码相同的密码加密.解密服务器密码时,主密码(加密形式)是输入; 在解密主密码时,魔术字符串'"settings.security"'用作附加输入.

您可以看到源代码PBECipherMavenCli.java.

  1. 我观察到多次加密相同的主密码或服务器密码会产生不同的哈希值.根据Marcelo Morales关于maven --encrypt-master-password如何工作的回答,这是因为在加密之前,'JVM配置特定的(通常是SHA1PRNG)64位随机盐'被添加到密码中.Maven在编译时使用它们来解密存储的密码.这是不是意味着盐必须存放在某个地方?

处理盐的传统方法是随机盐与加密文本一起存储.请参阅Wikipedia文章.

根据上面链接的源代码,salt似乎存储为Base64解码字节的前8个字节,就在加密密码之前.

  1. 我还观察到,如果主密码被重新加密并存储在settings-security.xml文件中,使用一个加密的主密码加密的常规密码仍然可用,即使加密的主密码密文现在不同.谁能解释一下这是如何工作的?

这是因为使用了主密码的解密形式,而不是加密的"密文".因此,重新加密它不会影响服务器密码加密/解密.

我不知道你最后两个(5和6)问题的答案.


Pet*_*ens 6

我需要了解 bnd(tools) 的这一点,以便我可以分享一些更深入的分析。

“加密”密码的语法为:

output    ::= '{' base64(packet) '}'
packet    ::= salt[8] padlen[1] encrypted[?] padding[padlen]
salt      ::= <random>
padlen    ::= <length of padding >
padding   ::= <random to make packet length a multiple of 16>
Run Code Online (Sandbox Code Playgroud)

使用的密码是AES/CBC/PKCS5Padding. 密钥和初始化向量计算如下:

sha = sha256( X + salt[8] )
key = sha[0..16]
iv  = sha[16..32]
Run Code Online (Sandbox Code Playgroud)

主密码 X 是“security.settings”。由于这是一个众所周知的常量,因此主密码不会被加密,而只是被掩盖。对于服务器密码,X 是解码后的主密码。

为什么生成的数据包被填充似乎是浪费字节,因为数据包格式使得剥离变得微不足道,并且它们从来不是加密/解密的一部分。他们只是向 Base64 字符串添加一些随机字符。

唯一有用的方法是使用重定位工具。例如,如果您将 settings-security.xml 挂载到构建服务器上的私有挂载上。然后您就可以settings.xml在公共存储库中自由共享该文件。然而,这也是一个糟糕的解决方案,因为您需要为所有用户和 CI 构建服务器将其安装到相同的安装点。

请注意,任何插件都可以解码您的所有服务器密码,因此切勿对服务器使用真实密码。Nexus 可以创建代理密码。