密码生成
至于对传输密码进行编码,唯一真正增加安全性的编码是加密。使用 Base-64 或十六进制不是为了安全,而只是为了能够将其包含在 XML 等文本格式中。
熵用于衡量密码质量。因此,使用随机“硬币翻转”选择每一位将为您提供最优质的密码。您希望密码与其他加密密钥一样强大,因此我建议至少 128 位的熵。
有两种简单的方法,具体取决于您希望如何将密码编码为文本(从安全角度来看,这并不重要)。
对于Base-64,使用如下内容:
SecureRandom rnd = new SecureRandom();
/* Byte array length is multiple of LCM(log2(64), 8) / 8 = 3. */
byte[] password = new byte[18];
rnd.nextBytes(password);
String encoded = Base64.encode(password);
以下内容不需要您提供 Base-64 编码器。生成的编码不是那么紧凑(26 个字符而不是 24 个),并且密码没有那么多的熵。(但 130 位已经很多了,与人类选择的至少 30 个字符的密码相当。)
SecureRandom rnd = new SecureRandom();
/* Bit length is multiple of log2(32) = 5. */
String encoded = new BigInteger(130, rnd).toString(32);
创建新的 SecureRandom 对象的计算成本很高,因此如果您要频繁生成密码,您可能需要创建一个实例并保留它。
更好的方法
将密码嵌入 XML 本身似乎是一个错误。
首先,您似乎希望在处理他们发送给您的任何文件之前对发件人进行身份验证。假设我讨厌你的胆量,并开始向你发送巨大的 XML 文件来执行拒绝服务攻击。您是否只想解析 XML 以发现我不是合法合作伙伴?如果 servlet 只是预先拒绝来自未经身份验证的用户的请求,不是更好吗?
其次,您的合法合作伙伴的密码在传输过程中受到 HTTPS 的保护,但现在它们很可能以“明文形式”存储在您系统的某个地方。那安全性很差。
更好的方法是在合作伙伴向您发送包含 HTTP 请求标头中的凭据的文档时对其进行身份验证。如果您只允许 HTTPS,则可以将密码完全从文档中取出,并将其放入HTTP“基本”身份验证标头中。它在传输过程中受到 SSL 的保护,并且不会以明文形式存储在您的系统中(您仅存储单向哈希以用于身份验证)。
HTTP 基本身份验证简单、受广泛支持,并且比 SSL 客户端证书更容易为您和您的合作伙伴实施。
保护文档内容
如果文档本身的内容是敏感的,那么它们确实应该由发件人加密,并由您以加密形式存储。最好的方法是使用公钥加密,但这将是另一个问题的主题。