首页 > 代码库 > 生成密码

生成密码

现在好多人不想在每个网站都使用相同密码,他们又无法记住所有网站的密码。

本文提供一个简单的方式让大家可以轻松记住一个账户和密码,来得到对每个不同的网站有一个对应的密码。

本文还发在我自己搭建的博客: 生成密码,因为csdn的文章更新没有自己博客简单,所以如果想看更新的文章,请到我的博客去看。

当然自己的博客是放草稿的,如果文章写好了,我才发到csdn

这是一个生成密码算法。

首先是要求用户输入他要记住的账号和密码。

然后用户对他每个需要生成密码的网站,在程序输入域名。

接着就是选择生成的密码,有需要位数N,一般是6,8,10,16的长度。

然后就可以生成一段对应的密码。

生成密码的要求,就是用户需要密码包括的字符,一般有需要大写、需要小写、需要数字、需要特殊,我们把用于选择需要生成类型数记为n。也就是用户如果要求有英文大小写和数值,那么n=3。n用于生成密码中间变量,可以得到所有用户要求。

对于不同的域名可以生成不同的密码,除了域名,还可以使用其它的字符。那么算法的要求是对于不同的输入,很少会生成相同的密码。对于相同的输入,生成相同密码。

于是用户需要记住的就是他的账号密码,遇到了在网站输入,就输入网站,于是得到网站密码,这样可以让用户只记住一个账号就可以。

算法也比较简单,实现有点复杂。

算法:

可以分为3步,第一步是生成组合字符,第二步进行混淆,第三步生成密码。

第一步的作用是生成作为密码的字符,第二步是防止第一步密码过于简单,防止可以从生成密码计算出用户账号密码,第三步是核心,用于生成密码。

  1. 生成组合字符

第一步需要先计算中间的值,计算方法:

x=md5(+)<script id="MathJax-Element-267" type="math/tex">x=md5(账号+域名) </script>

x1=md5(+)<script id="MathJax-Element-268" type="math/tex">x1=md5(密码+域名) </script>

x2=md5(++)<script id="MathJax-Element-269" type="math/tex">x2=md5(账号+密码+域名)</script>

根据生成的中间值,可以计算出字符串s作为密码的生成字符,s的生成算法如下:
生成一段字符串s=x[0,1],x1[0,1],x2[0,1],x[2,3]<script id="MathJax-Element-270" type="math/tex">s=x[0,1],x1[0,1],x2[0,1],x[2,3]…</script>,也就是轮流三段字符串,按两个字符顺序组合出新的一段字符串,注意,这里使用md5得到的是一段把md5数值转16进制的字符。

最后还是需要把字符转数值,这里只是为了方便说明,实际可以直接就是数值放进去,但是注意分割时,需要拿一个8位数。也就是最大是255,用户要求所有字符加起来的值小于255,所以可以选8位,如果觉得这个选择太大,可以使用自己计算的方法。

假如生成md5的是49541A094FE0300DB87109AFEB306207其中的每一个字符表示16进制数值。

于是两个两个拿出来按照顺序放到s中。两个两个拿出来可以作为混淆,虽然现在md5可以被破解,但是生成密码是无法得到用户的账号和密码和输入域名,所以不需要担心。

  1. 进行混淆

上面得到的s可能不够复杂,于是需要对上面生成的s进行混淆,混淆可以使用我的加密算法进行混淆。

使用之前的我写的哈希算法,可以把s混淆。

使用方法是申请一段缓存区,使用任意的哈希算法,进行哈希乱序,哈希乱序使用的密码是用户输入的密码。

之前的哈希算法存在哈希乱序、填补空白、字符加密,这里只需要进行哈希乱序。输入是s,和用户输入的密码,输出是乱序的 t 。

但是不需要进行填补空白和加密字符。

乱序之后,需要拿出来,拿出来的做法是去掉所有空白部分。使用如下算法,可以获得乱序的s:

首先清空s,然后
循环缓存区,判断当前字符是否是空白,如果不是空白,那么添加进s

这样,得到乱序的s字符串。

虽然得到s可能和没有混淆是一样的,但是这一步即使不加上也是没有问题。

得到的s字符串还不可以作为密码,需要进行最后一步。

  1. 生成密码字符

生成密码字符的难点,如何对应 s 的字符和生成密码的字符。

s 的字符是16进制数值,那么就是表示很少的区,但是可以通过使用两个字符可以表示255个字符,基本用户的要求可以得到。

把s按照两个字符分割,得到48个子字符串s1[],每个s1都是有两个字符。这里的s1是一个数组,包括48个字符串。

两个字符可以算出所有用户要求的字符,可以看到这个方法的不好的地方在于有些字符被用到概率比较高。

所以还需要一个变量记录 a ,用于计算用户要求不同类型出现数,在得到字符步骤,对字符进行偏移。偏移的意思:先把字符组成环,然后把字符向右偏移 a 个字符。

计算生成密码字符串S算法如下

    循环所有 s1

首先将要求所有类型字符分区域,计算总数l,转换s1字符为数值。

对s1取模l,得到对应数所在区域。添加a[区域]+1,对应字符向后移动 a[区域]。

得到的字符添加到 S 

首先对 a 进行解释:

技术分享

首先把要求所有字符写成环,把获得字符向右移动a,得到字符。原先是n移动5得到s。

先说一个例子,对于区域和对应字符需要做解释。

假如用户要求有3种,英文、数值、特殊符号

假如英文数量有 25 个,数值有 10 个,特殊符号有10个

那么组成的线大小是 l 25+10+10=45

技术分享

对应英文区是 [0,24] 对应数值区是[25,34] 对应特殊符号区是 [35,44]

技术分享

两个16进制字符最大值是 255

所以先把两个字符转数值 n

对n取模l,得到x。那么在l中,x一定会在某个区域,判断x落下区域。

添加对应区域 (a[区域]+1) 对应字符,如果字符超过区域,那么对字符取模,得到的值添加到S。

技术分享

循环直到结束。

就可以获得S密码字符。

假如 s1[0]=49 s1[1]=54 ,这里不是十进制

那么第一个字符取模得到 28, 第二个得到 39

那么第一个字符所在位置是 数值区,于是 a[数值]+1=1

技术分享

技术分享

28+1对应数值区的’4’,于是记录到S+=’4’

第二个字符所在区是特殊字符区,a[特殊]+1=1

39+1 对应特殊的’$’ 于是记录到S,这里,我特殊字符的排序没有给出来,实际的排序可以任意排序,但是特殊字符排序是算法中固定的。

这样就得到 S=4$

继续计算就可以得到S。

这样算法对于计算首先是对于区域进行计算,可以得到落在不同区域的概率是不同的,这是算法的缺点,但是和现实需要是一样的。

网站让用户输入英文和数值,那么比较多的人会输入英文数多于中文,这是某大神提供的。


接着计算S是否包含有用户选择的所有类型,如果存在一个类型没有存在,那么使用哈希S+=has(类型) 添加一个类型到字符串最后。

这个算法是可以让生成的S包含所有类型。虽然一般需要的类型都可以生成,但是有些输入可以存在某些类型不存在,于是需要让S添加所有存在的类型。假如生成的S只有英文和数值,没有特殊字符,但是用户需要特殊字符,那么就需要这个算法来得到特殊字符。得到的特殊字符需要和用户输入关联,所以需要has算法。

如何识别存在哪些类型,哪些没有,编码难度还是比较高,但是不难做,一次循环就可以做到,只是定义的数据结构相对比较难。当然,相信花10分钟还是可以想出来,这是我做过的ACM有的。

其中has函数为

char has(类型)
{
    var h = 3655; 这是一个大的数,工程经验
    var a = 0;
    var b = Int.Max;这是最大的一个数
    var str=new {x,x1,x2};//直接组合中间值
    foreach(s:str) 循环str
    {
        foreach(t:s) 循环所有字符
        {
            h=(a+t)&&b || (a+t); 算法是选一个哈希算法,可以选择其他
            a=b<<t;
            b=b<<t;
        }
    }

    return (char)(h%(类型上限-类型下限)+类型下限+1);
}

has就是生成一个类型随机的字符,当然随机只是说生成的很难猜出,只要给出一样的输入,得到的字符是一样的。

接着就是从S里得到生成密码,生成密码就是给用户的密码。用户可以用生成密码做他需要使用的域名的密码。

取出生成密码算法:

取长度 l=N?n<script id="MathJax-Element-7" type="math/tex">l=N-n</script>

N就是需要生成密码的长度,n就是选择类型数。

假如用户需要生成长度为5,需要英文、数值和特殊,那么得到 l=2

我们将会在S取出前l个字符,之所以要取出前l个,是因为用于必须要有类型,如果取出来的字符没有存在一个被选择类型的,那么在最后加类型。

循环密码k=S[0,l],如果k存在不包含选择的类型,那么继续往s[l] 之后的字符找,找到第一个选择的类型,放入k,直到所有类型都被找到。

如果这时密码的长度小于N,那么往下取 s[l] 的字符,直到密码长度为N。

假如生成的S是 4$5123123123123123123123a

用户需要的长度N=5

于是计算 l = 5-3=2

取出S前 2 字符 4$

判断存在类型 数值和特殊,于是剩下英文,从2开始向后寻找,直到第一个英文,找到a,于是得到4$a。判断不存在的类型,已经所有类型都存在,于是继续往下拿字符,直到N。l之后的字符是512312312,最后得到4$a51

这就是密码生成算法。

但是可以看到,如果用户需要一个域名多个账户,也就是需要一个域名有多个密码,那么上面算法就无法得到。如果用户输入一个密码,一段时间想换新的密码,上面算法也无法得到。所以算法需要用户再输入一个数值,表示这是第多少次的密码。

所以用户的输入就包括:

  1. 用户账号

  2. 用户密码

  3. 域名

  4. 要求

  5. 备用

其中最后一个备用就是让用户输入这是第n次生成密码,也就是前面第n次都是他不喜欢的,或者使用的。

那么算法需要做哪些调节?

首先在开始的生成s算法,把组合改成

x=md5(++)<script id="MathJax-Element-8" type="math/tex">x=md5(账号+域名+备用)</script>

x1=md5(++)<script id="MathJax-Element-9" type="math/tex">x1=md5(密码+域名+备用)</script>

x2=md5(+++)<script id="MathJax-Element-10" type="math/tex">x2=md5(账号+密码+域名+备用)</script>

这样就可以。

上次申请ca发现这个算法和LassPass算法差不多,只是使用我之前的算法混淆和一些地方不同,但是基本流程相同,可以认为这个算法是比较好的,可以自己试试写自己的生成密码算法。

技术分享
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    生成密码