簡體   English   中英

如何在 java 中使用 SecureRandom.getInstance("SHA1PRNG") 在 c# 中獲得相同的結果

[英]How to get the same result in c# with SecureRandom.getInstance("SHA1PRNG") in java

我在 java 中使用 SHA1PRNG 生成了長度為 32 的隨機字節數組,如何在 c# 中獲得相同的結果?

Java 代碼:

String seed = "Test";
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(seed.getBytes(StandardCharsets.UTF_8));
byte[] password = new byte[32];
random.nextBytes(password);
var encoder = java.util.Base64.getEncoder();
System.out.println(new String(encoder.encode(password), StandardCharsets.UTF_8));

我嘗試使用 SHA1CryptoServiceProvider,但它的 HashSize 只有 160(長度為 20)

C# 代碼:

string seed = "Test";
byte[] keyArray = new byte[32];
using (var sha1 = new SHA1CryptoServiceProvider())
{
  byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(seed));
  var rd = sha1.ComputeHash(hash);
  keyArray = rd.ToArray();
}
Console.WriteLine(Convert.ToBase64String(keyArray));

我將 SHA1PRNG 的代碼從 java 復制到 c#。 但我不確定它是否適用於所有場景。

public sealed class SHA1PRNG
{
    private const int DIGEST_SIZE = 20;

    private SHA1PRNG()
    {

    }

    private static void updateState(byte[] state, byte[] output)
    {
        int last = 1;
        int v;
        byte t;
        bool zf = false;

        // state(n + 1) = (state(n) + output(n) + 1) % 2^160;
        for (int i = 0; i < state.Length; i++)
        {
            // Add two bytes
            v = (int)(sbyte)state[i] + (int)(sbyte)output[i] + last;
            // Result is lower 8 bits
            t = (byte)(sbyte)v;
            // Store result. Check for state collision.
            zf = zf | (state[i] != t);
            state[i] = t;
            // High 8 bits are carry. Store for next iteration.
            last = v >> 8;
        }

        // Make sure at least one bit changes!
        if (!zf)
        {
            state[0] = (byte)(sbyte)(state[0]+1);
        }
    }

    public static void GetBytes(byte[] seed, byte[] result)
    {
        byte[] state;
        byte[] remainder = null;
        int remCount;
        int index = 0;
        int todo;
        byte[] output = remainder;

        using (var sha1 = new SHA1CryptoServiceProvider())
        {
            state = sha1.ComputeHash(seed);
            remCount = 0;

            // Use remainder from last time
            int r = remCount;
            if (r > 0)
            {
                // How many bytes?
                todo = (result.Length - index) < (DIGEST_SIZE - r) ?
                            (result.Length - index) : (DIGEST_SIZE - r);
                // Copy the bytes, zero the buffer
                for (int i = 0; i < todo; i++)
                {
                    result[i] = output[r];
                    output[r++] = 0;
                }
                remCount += todo;
                index += todo;
            }

            // If we need more bytes, make them.
            while (index < result.Length)
            {
                // Step the state
                output = sha1.ComputeHash(state);
                updateState(state, output);

                // How many bytes?
                todo = (result.Length - index) > DIGEST_SIZE ?
                    DIGEST_SIZE : result.Length - index;
                // Copy the bytes, zero the buffer
                for (int i = 0; i < todo; i++)
                {
                    result[index++] = output[i];
                    output[i] = 0;
                }
                remCount += todo;
            }

            // Store remainder for next time
            remainder = output;
            remCount %= DIGEST_SIZE;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM