12

我有一个类似这样的助记符”密码生成功能:

function Mnemonic($mnemonic)
{
    $result = null;
    $charset = array(str_split('aeiou', 1), str_split('bcdfghjklmnpqrstvwxyz', 1));

    for ($i = 1; $i <= $mnemonic; $i++)
    {
        $result .= $charset[$i % 2][array_rand($charset[$i % 2])];
    }

    return $result;
}

基本上,这会生成一个$mnemonic长度为每个奇数字符是辅音而每个偶数字符是元音的字符串。虽然我知道这会降低密码复杂性,但通常更容易记住现在我想通过生成易于键入的字符串来改进它。

QWERTY 键盘布局

例如,虽然我是一个 *nix 新手,但我总是更喜欢基于 RHEL 的发行版而不是 Debian 发行版,主要原因是易于打字yum而不是易于打字apt[-get],你自己试试吧。

我应该如何实现逻辑以生成易于在 QWERTY 键盘上键入的字符串?

4

8 回答 8

3

Carpalx对计算打字工作量进行了大量研究,其中包括:

  • 手指移动距离
  • 手、手指和行罚
  • 行程路径

他们的研究成果是声称比 Dvorak 更好的Colemak键盘布局。

但是,它是从您想要的内容向后编写的 - 他们的目标是根据输入找到更好的键盘布局,但您正试图根据键盘布局找到简单的输入。

所以 - 即使你可能无法直接使用它,我认为你可能会觉得它很有趣(谁知道,如果你的 Perl-fu 很强大,你可能能够提取和反转算法,因为它是GPL的)。

于 2010-02-09T19:36:46.570 回答
2

您可以消除所有用无名指和小指输入的字符(q、w、x、z、p),然后吐出用左手和右手输入的字符并在这些字母之间交替。

于 2010-02-05T17:44:57.697 回答
1

也许您可以使用一些启发式方法来衡量“打字的难易程度”。

例如,考虑在转到下一个字符时移动手指的成本。这可以是手指需要移动多远、方向等的函数。

当需要更换手指或手时,您还可以增加额外费用。

在稍微考虑一下成本之后,您可能会找到一个令人满意的解决方案。

希望有帮助。

于 2010-02-05T17:40:28.033 回答
1

您可能想看看Dvorak 键盘中使用的原理

应用于密码生成算法的那些原则是:

  • 字母应通过换手输入。
  • 使用易于键入的组合。看看德沃夏克布局,看看常见的二合字母及其字母的位置。
  • 仅使用底行中的一个字母,或不使用。让它随机!
  • 您可以将比率设为 2 比 1(右手键入的 2 个字母与左手键入的 1 个字母)。
  • 由于比率是 2 比 1,您将有 2 个连续的字母由同一只手输入,因此您必须确保它们是从键盘外侧向内侧输入的。这个原则适用于有向图。

我知道你说它是一个 QWERTY 键盘,但是在 QWERTY 键盘上使用这些原则可以给你一些非常好的结果,比如:

ktrd,ogkdo(德沃夏克语中的“打字机”)

kjg;g;akd;k(仅使用主行)

pjedoildupsk(只是一个遵循原则的随机密码)

所有讨厌德沃夏克的人,嘘!

我希望这有帮助。

于 2010-02-13T16:20:05.700 回答
1

很好的问题 - 采用上述建议,这是从键 i 到键 j 的距离的公式:

权重 = 距离 * a + switch * b + 相同 * c + shift * d + 怪异 * e + start * f

距离是一个值,其他是 0/1 值。

距离 - 通过在 QWERTY 键盘上叠加精细网格、查找 x、y 并计算距离来获得。距离具有正权重。如果字母组合使用不同的手(例如 aj、sk、wu...),则距离为零。

开关 - 负重;切换是好的

相同 - aq、qa、az、za 使用相同的手指。同样是正面

转变 - 任何有转变的事物都是积极的,而且非常糟糕

奇怪 - 我不知道 $ 或 ~ 不好,因为你必须看键盘。

开始 - asdfjkl 开始或结束。可能是消极的和好的,因为你的手指在那里休息。

系数 - 只要相对值看起来合理,就让它们开始。如果你真的想变得花哨 - 让某人输入几十组数字,使用秒表并拟合回归模型。

实施 - 假设我们有一个六个字符的密码。

现在我需要以每个字母开头的六个字符的最小值。想象一列中有 N 个键的数组。现在想象六列。您最短的密码是通过六列的最短路径(允许循环)。您可能需要添加一些逻辑来消除循环,但这应该是一个很好的第一步。(我在这里变得懒惰了——可能有一个图论公式可以解决这个问题。)

我敢打赌以前有人这样做过——尤其是击键部分。

于 2010-02-05T20:28:19.177 回答
1

下面我一起砸了。这是一项黑客工作,但它似乎工作得很好。

<?
function Mnemonic($mnemonic)
{
    $result = null;
    $charset = array(str_split('@a3e!1i0ou', 1), str_split('#$*bcdfghjklmnpqrstvwxyz', 1));

    $lastchar = ' ';
    for ($i = 1; $i <= $mnemonic; $i++)
    {
      do {
        $char = $charset[$i % 2][array_rand($charset[$i % 2])];
      } while (!nextkey($lastchar, $char));
      $result .= $char;
    }

    return $result;
}

function nextkey($lastchar, $requestchar)
{
  $map = array();
  $map[] = '!qaz'; // ll
  $map[] = @#wsx1'; // lr
  $map[] = 'ed23'; // lm
  $map[] = '$%^rtfgcvb456'; // li
  $map[] = '&yhnujm7'; // ri
  $map[] = '*()ik89'; // rm
  $map[] = 'olp,.'; // rr
  $map[] = ';[]'; // rl
  $map[] = '!@#$%^&*()[]'; // special chars, don't follow
  $map[] = 'pbvcnmq'; // consonant clusters, don't follwo

  if($lastchar == $requestchar) return true;
  foreach($map as $string)
    if(strpos($string, $requestchar) && strpos($string, $lastchar)) return false;
  return true;
}

printf("%s\n", Mnemonic(8));
?>

于 2014-10-02T21:06:35.850 回答
0

如果您实施此操作,请在确定从一个字符移动到另一个字符的“成本”时考虑用户的语言环境。如果用户使用不同的键盘布局,易于键入的密码可能会变得相当麻烦。在一种语言的键盘上可能很容易访问的某些键在另一种语言的键盘上可能不可用,而无需额外的修饰键(shift、meta 等)。

为了保持这个想法的普遍性,我建议忽略哪个字符属于哪个键,而是将键视为具有行和列的数组。每行通常与前一行偏移大约 1/3 键宽度。考虑到这一点,计算任意两个任意键之间的距离应该不难:

# Key at top left corner is {0, 0}
key1 @ {x1, y1}
key2 @ {x2, y2}

xdistance = absolute_value(x2 - x1)
ydistance = absolute_value(y2 - y1)

if y1 > y2
  xdistance += (1/3 * ydistance)
else
  xdistance -= (1/3 * ydistance)

total_distance = square_root(xdistance^2 + ydistance^2)

生成一系列满足您的长度和“易于键入”要求的键位置,然后使用用户的当前键映射将这些索引重新映射为字符。

于 2010-02-08T17:44:12.183 回答
0

构建一个表示键盘的数据结构,并对用于键入每个字符的行、列、手和手指进行编码。编写一个函数,当出现一个字符时,它会根据您开发的灵活规则提供“易于键入的下一个”字符的列表。它可以依赖另一个计算键之间距离的函数。

就我个人而言,我并不觉得用同一只手输入两次字母很慢:只有在前一个字母使用过近的手指时才很难。例如,XQ 很难打字,因为我的手必须向上移动才能处理打字所需的相邻手指。但我一点也不觉得 BQ 很难打字,因为当我的食指还在敲 B 的时候,我的小指可以指向 Q。

AW 的输入也比 QS 容易得多,因为无名指较长,因此自然适合 W,而小指在 A,处于接近静止的位置,而 QS 需要伸展小指,同时,无名指相互冲突的肌肉紧缩。

如果你开始建立每个字母与其他字母的映射,你很快就会找到一种合理的方式来表示容易或困难的各个方面。概括我的 XQ/BQ 示例,您可以进行单行更改需要 2 个或更多手指的距离,2 行更改需要 3 个手指的距离,3 行更改(可能是数字)需要交替的手。

我还注意到 WD 和 IL 之间的距离比 SE 和 KO 稍长也改变了难度,因为键的位置略微呈锯齿状。

通过一些分析(我建议使用 Excel 来“绘制”输入难度),我相信您可以提出一种算法来帮助您构建易于输入的单词。

如果可能,尝试输入至少一个数字,并考虑使用空格。

于 2010-02-05T18:02:31.467 回答