如何生成随机密码?

How to generate random password?

我需要生成一个随机密码,该密码将在 OpenPGP.js 中用于对称加密某些内容。用户永远不必触摸或看到密码(一切都在幕后发生)。 因此,理想情况下,密码只是一些随机字节。不幸的是,OpenPGP.js 不支持(据我所知)。它只支持字符串作为密码。

所以我需要生成一个随机密码字符串。我希望它尽可能随机;排除尽可能少的字符。

如何生成安全的随机密码字符串?

我目前有这个:

String.fromCharCode.apply(null, crypto.getRandomValues(new Uint8Array(32)));

但是,我有点担心它可能会在出现某些随机字节时弄乱 UTF-16 代理项对,并且密码可能会在其他浏览器上得到不同的解释,具体取决于它们的 Unicode 实现。

跨浏览器使用此解决方案安全吗?

我会很容易地使用类似的东西:

function generatePass() {
  var pass = "";
  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

  var passLength = (Math.random() * 15) + 5;
  
  for (var i = 0; i < passLength; i++)
    pass += possible.charAt(Math.floor(Math.random() * possible.length));

  return pass;
}

console.log(generatePass());

调整和改变代码也非常容易,并且适用于任何地方。

回答我自己的问题:

我系统的一部分加密和解密密码(例如问题中的随机密码)。 当用 OpenPGP.js 测试我的解决方案时,从解密操作(加密后)随机返回的字符串不完全等于原始字符串(可能是十分之一)。

这表明 OpenPGP.js 在输入不正确时无法正确序列化或反序列化 UTF-8(或它使用的任何编码)。我猜我生成的字符串是无效的 Unicode——至少在 Chrome.

中是这样

显然,我在定义有限的已知字符集时工作。

总结一下:

String.fromCharCode.apply(null, crypto.getRandomValues(new Uint8Array(32)));

使用不安全。

点此查看Fiddle

function CreateRandomPassword(Length, isUpperAlpha, isLowerAlpha, isNumaric ,SpecialChars)
{
  var _allowedChars = "";
  if (isUpperAlpha != false)
    _allowedChars += "ABCDEFGHJKLMNOPQRSTUVWXYZ";
  if (isLowerAlpha != false)
    _allowedChars += "abcdefghijkmnopqrstuvwxyz";
  if (isNumaric != false)
    _allowedChars += "0123456789";
  _allowedChars += SpecialChars;
  if(!Length)
    Length = 8
  var chars = "";
  allowedCharCount = _allowedChars.length;
  if(allowedCharCount == 0)
    return " ";
  for (var i = 0; i < Length; i++)
  {
    chars += _allowedChars[Math.floor(Math.random() * Math.floor(allowedCharCount))];
  }
  return chars;
}

我开发了简单的密码生成功能