将WarpWallet的哈希算法从Javascript转换成C#

9

我正在尝试在C#中实现warpwallet代码。我使用cryptsharp进行scrypt和PBKDF2实现。然而,我似乎得到的结果与真实网站不同。

这是我的代码:

static void Main(string[] args)
{
    string randomString = "mypassword";
    byte[] passwordBytes = Encoding.UTF8.GetBytes(randomString);
    byte[] passwordBytesScrypt = new byte[passwordBytes.Length + 1];
    Array.Copy(passwordBytes, 0, passwordBytesScrypt, 0, passwordBytes.Length);
    passwordBytesScrypt[passwordBytes.Length] = 0x1;

    string salt = "salt@gmail.com";
    byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
    byte[] saltBytesScrypt = new byte[saltBytes.Length + 1];
    Array.Copy(saltBytes, 0, saltBytesScrypt, 0, saltBytes.Length);
    saltBytesScrypt[saltBytes.Length] = 0x1;

    byte[] scryptBytes = CryptSharp.Utility.SCrypt.ComputeDerivedKey(passwordBytesScrypt, saltBytes, 524288, 8, 1, null, 32);

    byte[] passwordBytesPBKDF2 = passwordBytesScrypt;
    passwordBytesPBKDF2[passwordBytes.Length] = 0x2;

    byte[] saltBytesPBKDF2 = saltBytesScrypt;
    saltBytesScrypt[saltBytes.Length] = 0x2;

    byte[] pbkdf2Bytes = CryptSharp.Utility.Pbkdf2.ComputeDerivedKey(new HMACSHA256(passwordBytesPBKDF2), saltBytes, 65536, 32);
}

根据网站(我修改了代码以记录到控制台),scrypt哈希结果应为:
4dfe98afd8f279e856abdcccce09aa54031fbd7fa39a912bb3caf5ce28648fe6

而 PBKDF2 哈希的结果应该是

847c053e66c093927d1f1258b52455675fe6788e537c2073927fbddddfacc0d3

我的 scrypt 结果是

790BE1F92DDDF297CF7BACAA69218BE2C67680C706B2A214081A559B8E0EF43D

和 PBKDF2

CB640D1C8C13B44712EBCF341FA68F22F90D69AA5BC8427CD5ABED37FDFFE4EF

我不明白我做错了什么。是CryptSharp的实现有问题吗?还是我漏掉了某个步骤?我不太懂JavaScript,所以完全有可能。任何帮助都将不胜感激。


什么是warpwallet代码?你是在尝试实现类似的功能吗?还是你已经有了warpwallet代码? - Rathan Naik
我从他们的Github上拿到了WarpWallet代码,但你也可以保存网站源代码,这是一样的东西。 - Aeon2058
你可以使用NodeServices从C#调用JavaScript。这似乎是最简单的方法。 - Heretic Monkey
3个回答

1
我发现你的代码有两个问题:

  1. 2^18 is not 524288 but 262144.
  2. It seems the way you're injecting 0x1 is not working, I've done it in a different way and it works:

        string randomString = "mypassword";
    
        string salt = "salt@gmail.com";
    
        //Setup Lists to take the extra byte of the byte array to the end
        var passArrList = new List<byte>();
        var saltArrList = new List<byte>();
    
        //Get the byte array of incoming passphrase
        byte[] passArr = Encoding.UTF8.GetBytes(randomString);
        //Add the pass byte array to the list
        passArrList.AddRange(passArr);
        //Append the needed 0x1 to the end of the array
        passArrList.Add(1);
    
        //Get the bytes of the salt
        byte[] saltArr = Encoding.UTF8.GetBytes(salt);
        //Add the salt to the list
        saltArrList.AddRange(saltArr);
        //Append the needed salt to the end
        saltArrList.Add(1);
    
        byte[] scryptBytes = CryptSharp.Utility.SCrypt.ComputeDerivedKey(passArrList.ToArray(), saltArrList.ToArray(), 262144, 8, 1, null, 32);
    
        Console.WriteLine(BitConverter.ToString(scryptBytes).Replace("-", ""));
    

0

这行代码有 bug:

byte[] scryptBytes = CryptSharp.Utility.SCrypt.ComputeDerivedKey(passwordBytesScrypt, 
  saltBytes, 524288, 8, 1, null, 32);
  • 正如@knocte所解释的那样,2^18不是524288
  • 你正在使用saltBytes而不是你准备好的saltBytesScrypt

更正后的行应为:

byte[] scryptBytes = CryptSharp.Utility.SCrypt.ComputeDerivedKey(passwordBytesScrypt, 
  saltBytesScrypt, 1 << 18, 8, 1, null, 32);

0

你的代码中有一些错别字,我正在使用LINQ以获得更清晰的代码,你可以按照步骤进行操作而无需操纵数组。

在第15行,你应该使用1 << 18和passwordBytesScrypt:

byte[] scryptBytes = CryptSharp.Utility.SCrypt.ComputeDerivedKey(passwordBytesScrypt, saltBytes, 524288, 8, 1, null, 32);

在第23行,你应该使用saltBytesPBKDF2:

byte[] pbkdf2Bytes = CryptSharp.Utility.Pbkdf2.ComputeDerivedKey(new HMACSHA256(passwordBytesPBKDF2), saltBytes, 65536, 32);

最终代码看起来像这样:
static void Main(string[] args)
{
    List<byte> extend1 = new List<byte> { 0x1 }, extend2 = new List<byte> { 0x2 };

    string randomString = "mypassword";
    IEnumerable<byte> passwordBytesScrypt = Encoding.UTF8.GetBytes(randomString).Concat(extend1);

    string salt = "salt@gmail.com";
    IEnumerable<byte> saltBytesScrypt = Encoding.UTF8.GetBytes(salt).Concat(extend1);

    byte[] scryptBytes = CryptSharp.Utility.SCrypt.ComputeDerivedKey(passwordBytesScrypt.ToArray(), saltBytesScrypt.ToArray(), 1 << 18, 8, 1, null, 32);

    byte[] passwordBytesPBKDF2 = passwordBytesScrypt.Take(passwordBytesScrypt.Count() - 1).Concat(extend2).ToArray();
    byte[] saltBytesPBKDF2 = saltBytesScrypt.Take(saltBytesScrypt.Count() - 1).Concat(extend2).ToArray();

    byte[] pbkdf2Bytes = CryptSharp.Utility.Pbkdf2.ComputeDerivedKey(new HMACSHA256(passwordBytesPBKDF2), saltBytesPBKDF2, 65536, 32);

    Console.WriteLine(BitConverter.ToString(scryptBytes).Replace("-", ""));
    Console.WriteLine(BitConverter.ToString(pbkdf2Bytes).Replace("-", ""));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接