Issue
I generated a random byte array of length 32 using SHA1PRNG in java, how can I get the same result in c#?
Java Code:
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));
I tried to use SHA1CryptoServiceProvider, but its HashSize is only 160(Length of 20)
C# Code:
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));
Solution
I copied the code of SHA1PRNG from java to c#. But I'm not sure it will work in all scenarios.
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;
}
}
}
Answered By - Fantasy0v0
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.