QWERTY 键盘的助记密码生成算法
我有一个“助记符”密码生成功能,其功能如下:
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
长度的字符串,其中每个奇数字符都是辅音,每个偶数字符都是元音。虽然我知道这会降低密码复杂性,但通常会更容易记住。现在我想通过生成易于键入的字符串来改进它。
例如,当*nix 新手 我总是更喜欢基于 RHEL 的发行版而不是 Debian 发行版,主要原因是输入 yum
容易,而输入 apt[-get]
容易,只需尝试一下为了你自己。
我应该如何实现逻辑来生成易于在 QWERTY 键盘上输入的字符串?
I've a "mnemonic" password generation function that goes something like this:
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;
}
Basically this generates a string with $mnemonic
length where every odd character is a consonant and every even character is a vowel. While I understand this reduces the password complexity it's usually much more easier to remember. Now I want to improve it by generating strings that are easy to type.
For instance, while a *nix newbie I always prefer RHEL based distributions over Debian ones, the main reason is the ease of typing yum
versus the ease of typing apt[-get]
, just try it for yourself.
How should I implement the logic to generate strings that are easy to type on QWERTY keyboards?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
Carpalx 在计算打字工作量,其中包括:
他们的研究成果是 Colemak 键盘布局,其中 声称比德沃夏克更好。
然而,它是从你想要的向后写的——他们的目标是根据输入找到更好的键盘布局,但你试图根据键盘布局找到简单的输入。
所以 - 即使你可能无法直接使用它,我想你可能会发现它很有趣(谁知道,如果你的 Perl-fu 很强大,你也许能够提取并反转算法,因为它是 GPL )。
Carpalx has a lot of research on calculating typing effort, which incorporates:
The outcome of their research is the Colemak keyboard layout, which claims to be better than Dvorak.
However, it's written backward from what you want - their goal is to find a better keyboard layout based on input, but you're trying to find easy input based on the keyboard layout.
So - even though you might not be able to use it directly, I thought you might find it interesting (and who knows, if your Perl-fu is strong, you might be able to extract and reverse the algorithm, since it's GPL'd).
您可以消除用无名指和小指(q、w、x、z、p)键入的所有字符,然后吐出用左手和右手键入的字符并在这些字母之间交替。
You could eliminate all characters that are typed with the ring and pinky finger (q,w,x,z,p), then spit the characters that are typed by the left and the right hands and alternate between these letters.
您可能想看看德沃夏克键盘中使用的原理,
这些原理已应用密码生成算法中的内容是:
我知道您说它是 QWERTY 键盘,但是在 QWERTY 键盘上使用这些原理可以给您带来一些非常好的结果,例如:
所有德沃夏克仇恨者,嘘!
我希望这有帮助。
You may wanna take a look at the principles used in the Dvorak keyboard,
Those principles applied in a password-generating algorithm would be:
I know you said it's a QWERTY keyboard but using these principles on a QWERTY keyboard can give you some very good results, like:
All Dvorak haters, shush it!
I hope this helps.
也许您可以使用一些启发式方法来衡量“打字的难易程度”。
例如,考虑转到下一个字符时移动手指的成本。这可以是手指需要移动多远、向哪个方向等的函数。
当需要切换手指或手时,您还可以增加额外的成本。
在考虑了一些成本之后,您可能会找到一个令人满意的解决方案。
希望有帮助。
Perhaps you can use some heuristic to measure the 'ease of typing'.
For instance, consider the cost of moving a finger when going to the next character. This can be a function of how far the finger needs to move, which direction etc.
You could also add extra costs, when it is required to switch fingers, or hands.
After playing around with the costs a bit, you will probably hit upon a satisfactory solution.
Hope that helps.
很好的问题 - 根据上述建议,这里有一个从键 i 到键 j 的距离的公式:
权重 = 距离 * a + switch * b + same * c + shift * d + 奇怪 * e + start * f
距离是一个值,其他均为 0/1 值。
距离 - 通过在 QWERTY 键盘上叠加精细网格来获取,查找 x,y
并计算距离。距离具有正权重。如果字母组合是使用不同的手(例如aj、sk、wu...),则距离为零。
开关-负权重;切换效果很好
相同 - aq、qa、az、za 使用相同的手指。同样是积极的
Shift - 任何有转变的东西都是积极的,而且非常糟糕
奇怪 - 我不知道 $ 或 ~ 是不好的,因为你必须看着键盘。
开始 - asdfjkl 开始或结束。可能是负数&很好,因为您的手指处于休息状态。
系数 - 只要相对值看起来合理,就可以开始设置它们。
如果你真的想要变得更奇特 - 让某人输入几十组数字,使用秒表并拟合回归模型。
实施 - 假设我们有一个六字符的密码。
现在我需要以每个字母开头的六个字符的最小值。想象一下 N 个键组成的数组,位于一列中。现在想象一下六列。您的最短密码是通过六列的最短路径(允许循环)。您可能需要添加一些逻辑来消除循环,但这应该是一个很好的第一步。 (我在这里变得懒惰了 - 可能有一个图论公式可以处理这个问题。)
我敢打赌以前有人做过这个 - 特别是击键部分。
Great question - taking the above suggestions, here's a formulae for the distance from key i to key j:
Weight = distance * a + switch * b + same * c + shift * d + weird * e + start * f
Distance is a value, the others are 0/1 values.
Distance - get by superimposing a fine grid over a QWERTY keyboard, lookup the x,y
and calculate the distance. Distance has a positive weight. If the letter combination is with the use of different hands (e.g aj, sk, wu...), the distance is zero.
Switch - negative weight; switching is good
Same - aq, qa, az, za use the same finger. Same is positive
Shift - anything with a shift is positive and real bad
Weird - I dunno $ or ~ is bad because you have to look at the keyboard.
Start - asdfjkl starting or ending. Probably negative & good since your fingers are there at rest.
Coefficients - just make 'em up to start as long as the relative values seem reasonable.
If you REALLY want to get fancy - get someone to type in several dozen sets of numbers, use a stop watch and fit a regression model.
Implementation - say we have a six character password.
Now I need the lowest value for six characters starting with each letter. Imagine an array of your N keys in a columns. Now imagine six columns. Your shortest password is the shortest path through the six columns (with cycles allowed). You might need to add some logic to eliminate cycles, but this should be a good first pass. (I'm getting lazy here - there's probably a graph theoretic formulation that handles this problem.)
I'll bet someone has done this before - especially the keystroke part.
我将以下内容粉碎在一起。这是一项黑客工作,但似乎效果很好。
I smashed together the following. It's a hack job but it seems to work pretty good.
构建一个代表键盘的数据结构,并对用于键入每个字符的行、列、手和手指进行编码。编写一个函数,当出现一个字符时,该函数会根据您开发的灵活规则提供“易于键入下一个”字符的列表。它可以依赖另一个计算键之间距离的函数。
就我个人而言,我并不认为用同一只手输入两次字母会很慢:只有当前一个字母使用的手指距离太近时才会很困难。例如,XQ 很难打字,因为我的手必须向上移动才能处理打字所需的相邻手指。但我一点也不觉得 BQ 很难打字,因为当我的食指仍在 B 上时,我的小指可以指向 Q。
打字 AW 也比 QS 容易得多,因为无名指更长因此,自然地适合 W,而小指位于 A,处于接近静止的位置,而 QS 则需要小指的伸展和无名指同时、相互冲突的肌肉紧缩。
如果您开始构建每个字母相对于其他字母的映射,您很快就会找到一种合理的方式来表示难易程度的各个方面。概括我的 XQ/BQ 示例,您可以进行 1 行更改需要 2 个或更多手指的距离,2 行更改需要 3 个手指的距离,而 3 行更改(可能是数字)需要交替双手。
我还注意到,WD 和 IL 之间的距离比 SE 和 KO 之间的距离稍长,这也会改变难度,因为按键的位置略有锯齿状。
通过一些分析(我建议使用 Excel 来“绘制”打字难度),我确信您可以想出一种算法来帮助您构建易于打字的单词。
如果可能,请尝试至少输入一个数字,并考虑使用空格。
Build a data structure that represents a keyboard and codes the row, column, hand, and finger used to type each character. Write a function that, when presented with a character, provides a list of "easy to type next" characters, based on flexible rules that you develop. It could rely on another function that calculates the distance between keys.
Personally, I don't find typing letters with the same hand twice to be slow: only if a previous letter used a finger that was too close is it difficult. For example, XQ is hard to type because my hand has to move upward to handle the adjacent fingers required to type them. But I don't find BQ hard to type at all, because while my forefinger is still working on the B, my pinkie finger can head for the Q.
It is also much easier to type AW than QS, because the ring finger is longer and so naturally fits on the W while the pinkie is on A, in a near-resting position, while QS requires a stretch of the pinkie and a simultaneous, conflicting muscular crunch of the ring finger.
If you start to build up a map of each letter against each other letter, you will soon find a reasonable way to represent various aspects of ease or difficulty. Generalizing my XQ/BQ example, you could make one-row changes require a distance of 2 or more fingers, 2-row changes require a distance of 3 fingers, and 3-row changes (numbers, perhaps) require alternate hands.
I'm also noticing that the slightly longer distance between WD and IL than SE and KO also alters difficulty, because of the slightly jagged placement of keys.
With some analysis (I recommend using Excel to "map out" typing difficulty) I'm sure you can come up with an algorithm that helps you construct easy-to-type words.
If possible, try throwing in at least one number, and consider using spaces as well.
如果您实现这一点,请在确定从一个角色移动到另一个角色的“成本”时考虑用户的区域设置。如果用户使用不同的键盘布局,那么易于输入的密码可能会变得相当麻烦。如果不需要额外的修饰键(shift、meta 等),某些在一种语言的键盘上可能易于访问的键可能在另一种语言的键盘上无法使用。
为了保持这个想法的通用性,我建议忽略哪个字符属于哪个键,而是将键视为具有行和列的数组。每行通常与前一行偏移大约 1/3 个键宽度。考虑到这一点,计算任意两个任意键之间的距离应该不难:
生成一系列满足您的长度和“易于打字”要求的键位置,然后使用用户当前的键盘映射来重新映射这些索引成字符。
If you implement this, please take the user's locale into account when determining the "cost" of moving from one character to another. An easy-to-type password might become rather cumbersome if the user is using a different keyboard layout. Some keys that might be easy to access on one language's keyboard might not be available on another language's keyboard without requiring extra modifier keys (shift, meta, etc).
To keep this idea universal, I would recommend ignoring what character belongs to what key and instead treating the keys as an array with rows and columns. Each row is typically offset from the previous by roughly 1/3 of a key width. With this in mind, it shouldn't be difficult to calculate the distance between any two arbitrary keys:
Generate a series of key positions meeting your length and "ease of typing" requirements, then use the user's current keymap to re-map those indices into characters.