繁体   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