如何将少于8个字符的SSID转换为字节[]作为Rfc2898 (WPA)的盐

本文关键字:作为 字节 Rfc2898 的盐 WPA 转换 8个 SSID 字符 | 更新日期: 2023-09-27 18:07:11

我试图将SSID和口令转换为加密的WPA密钥,我发现了一个实现,但不是在。net中,而且相当复杂。通过一些研究,我发现了类Rfc2898DeriveBytes,这几乎肯定是用来创建WPA密钥的。问题是这里使用的盐是字节数组,而SSID(我认为这是在WPA中专门使用的盐)是一个字符串。

如果SSID的长度等于或大于8个字符,我可以使用UTF8.GetBytes方法将其转换为byte[]并用作盐OK。测试表明,它产生的加密密钥与我发现的另一个实现完全相同。

var ssid = "mySSID";//this is less than 8 and can cause exception 
                    //later on
var salt = Encoding.UTF8.GetBytes(ssid);
var wpaEncryptor = new Rfc2898DeriveBytes("myPassword", salt, 4096);
var bytes = wpaEncryptor.GetBytes(32);

但是现在如果SSID的长度小于8个字符,我不知道如何将其转换为byte[] (盐要求最小长度为8)。我想我们需要执行一些填充算法但不确定怎么做。

我发现是用JavaScript编写的,我当然可以将其转换为c#而无需太多修改,但我真的很想使用Rfc2898DeriveBytes类。如果您对JavaScript实现感兴趣,可以查看此页面的源代码http://jorisvr.nl/wpapsk.html

如何将少于8个字符的SSID转换为字节[]作为Rfc2898 (WPA)的盐

您指向的JavaScript代码包含以下代码片段:

while (hash.length < 64) {
    /* prepare 20-byte (5-word) output vector */
    var u = [ 0, 0, 0, 0, 0 ];
    /* prepare input vector for the first SHA1 update (salt + block number) */
    i++;
    var w = stringtowords(salt, i);

现在您可以看到,这意味着盐被直接用作PBKDF2的输入(是的,我从SSID输入变量跟踪它)。不幸的是,这意味着您不能直接将PBKDF2用于小于8字节的盐;盐直接在PBKDF2内多次迭代混合。

不幸的是,Rfc2898DeriveBytes (. net中的PBKDF2 API)的设计者认为将安全约束构建到API中是他任务的一部分。在他们实现PBKDF1之后,这并不奇怪,但这可能有点过于热心了。


作为一种替代方法,您可以使用Rfc2898DeriveBytes的Mono实现并删除对盐大小的约束(尽管,如果我没有弄错的话,该约束仅存在于setter上)。