C# 的pbkdf2可以调用多次, go的怎么弄?

https://dotnetfiddle.net/Widg...

C#调用多次每次结果都不一样

using System;
using System.Text;
using System.Security.Cryptography;


public class Program
{
    public static void Main()
    {
        byte[] bytes = Encoding.UTF8.GetBytes("salt salt salt");
        Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes("some password", bytes);
        rfc2898DeriveBytes.IterationCount = 1000;
        for (var i = 0; i < 10; i++) {
            var a = rfc2898DeriveBytes.GetBytes(16);
            Console.WriteLine("Encoded string: " + BitConverter.ToString(a));
        }
        
    }
}
Encoded string: 2B-E7-51-50-97-74-2E-4A-E5-AE-D3-6D-21-12-A8-EE
Encoded string: 85-C7-42-8E-A3-BA-DE-C9-0A-E2-5F-EF-07-95-EA-B3
Encoded string: 95-61-DE-B9-8D-C7-07-CD-6B-15-1B-3E-F8-54-18-78
Encoded string: AD-F1-19-67-78-DC-87-3F-4C-FB-81-CF-5F-72-5B-11
Encoded string: 37-74-4B-34-54-F5-48-CB-DE-5D-04-C7-C2-CC-69-55
Encoded string: FA-FF-2B-BF-F9-3B-D4-BC-5F-31-80-CE-B0-55-1B-BB
Encoded string: CC-E2-5D-8A-91-51-47-F4-93-C2-6C-DD-2E-87-DB-2B
Encoded string: 2D-4B-E0-8B-9E-1D-95-9E-E9-1B-E8-A9-7B-EC-DC-C6
Encoded string: 9A-4E-1C-31-92-9D-05-18-38-16-D7-DA-35-E5-3C-57
Encoded string: 77-E1-3A-FB-C2-99-D6-57-06-4D-98-29-2D-14-B1-FE

golang的只能生成一个

package main

import (
    "crypto/sha1"
    "fmt"
    "golang.org/x/crypto/pbkdf2"
)

func main() {
    dk1 := pbkdf2.Key([]byte("test"), []byte("test"), 1000, 16, sha1.New)
    dk2 := pbkdf2.Key([]byte("test"), []byte("test"), 1000, 16, sha1.New)
    fmt.Println(dk1)
    fmt.Println(dk2)
}

调用两次的结果是一样的

[120 95 112 156 17 50 179 67 179 47 155 230 71 243 135 24]
[120 95 112 156 17 50 179 67 179 47 155 230 71 243 135 24]

golang的能生成多个不一样的吗?

阅读 3.3k
1 个回答

首先这不是go的问题, 你没明白c#中Rfc2898DeriveBytes生成pbkdf2的原理是什么.看一下官方文档的描述:
https://docs.microsoft.com/en...

其中下面的remark很有意思

The Rfc2898DeriveBytes class implements PBKDF2 functionality by using a pseudorandom number 
generator based on HMACSHA1. The Rfc2898DeriveBytes class takes a password, a salt, and an 
iteration count, and then generates keys through calls to the GetBytes method. Repeated calls 
to this method will not generate the same key; instead, appending two calls of the GetBytes 
method with a cb parameter value of 20 is the equivalent of calling the GetBytes method once
with a cb parameter value of 40.

看明白了么, 你在for循环中每次调用

a = rfc2898DeriveBytes.GetBytes(16);

rfc2898DeriveBytes对象的状态是不同的,举例来说

a = rfc2898DeriveBytes.GetBytes(16);
b = rfc2898DeriveBytes.GetBytes(16);

a 和b两个最终拼接的效果和下面c的结果是相同的

c = rfc2898DeriveBytes.GetBytes(32);

因此在你for循环的代码里面, 效果等同于

using System;
using System.Text;
using System.Security.Cryptography;


public class Program
{
    public static void Main()
    {
        byte[] bytes = Encoding.UTF8.GetBytes("salt salt salt");
        Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes("some password", bytes);
        rfc2898DeriveBytes.IterationCount = 1000;
        var d = rfc2898DeriveBytes.GetBytes(160);
        var a = new byte[16];
        for (var i = 0; i < 10; i++) {
            Array.Copy(d, i*16, a, 0, 16);
            Console.WriteLine("Encoded string: " + BitConverter.ToString(a));
        }
        
    }
}

因此在go里面也是一样的:

package main

import (
    "crypto/sha1"
    "fmt"
    "encoding/hex"
    "golang.org/x/crypto/pbkdf2"
)

func main() {
    dk := pbkdf2.Key([]byte("some password"), []byte("salt salt salt"), 1000, 16 * 10, sha1.New)
    for i := 0; i < 10; i++ {
        fmt.Println(hex.EncodeToString(dk[i*16: (i+1)*16]))
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题