如何使用HashAlgorithm.TransformBlock/TransformFinalBlock?

tig*_*rou 4 c# hash cryptography sha

我想使用TransformBlock()/ 在几个步骤中计算SHA1哈希TransformFinalBlock():

byte[] block1 = Encoding.ASCII.GetBytes("This");
byte[] block2 = Encoding.ASCII.GetBytes("is");
byte[] block3 = Encoding.ASCII.GetBytes("Sparta");

SHA1 sha = new SHA1Managed();
sha.TransformBlock(block1, 0, block1.Length, block1, 0);
sha.TransformBlock(block2, 0, block2.Length, block2, 0);
sha.TransformFinalBlock(block3, 0, block3.Length);

byte[] result = sha.Hash;
Run Code Online (Sandbox Code Playgroud)

我知道还有其他方法来计算SHA1(例如:HashAlgorithm.ComputeHash()CryptoStream).以上是更复杂代码的简化版本.

对我来说完全不清楚的是为outputBuffer数组传递什么(TransformBlock方法的第四个参数) :

int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, 
                   byte[] outputBuffer, int outputOffset);
Run Code Online (Sandbox Code Playgroud)

MSDN页说:

计算输入字节数组的指定区域的哈希值,并将输入字节数组的指定区域复制到输出字节数组的指定区域

如果我不需要该阵列副本怎么办?我应该通过null吗?(为了避免每次都复制输入数组?)

这有什么典型的用途吗?

同样,似乎TransformFinalBlock()也将输入数组复制到输出数组.AFAIKm这是方法返回的内容:

byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount);
Run Code Online (Sandbox Code Playgroud)

xan*_*tos 6

您链接的页面和示例非常清楚:

使用不同的输入和输出数组调用TransformBlock方法会导致IOException.

甚至在使用上的例子很清楚:

offset += sha.TransformBlock(input, offset, size, input, offset);
Run Code Online (Sandbox Code Playgroud)

SHA1并不真的需要那个参数.但它是ICryptoTransform具有此签名的接口的实现.所以SHA1.TransformBlock()有(无用)参数.请注意,您可以将输出设置为null(未记录但有效).

请注意,在HashAlgorithm(即SHA1该实现的基类ICryptoTransform)中,TransformBlock一行如下:

if ((outputBuffer != null) && ((inputBuffer != outputBuffer) || (inputOffset != outputOffset)))
    Buffer.BlockCopy(inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount);
Run Code Online (Sandbox Code Playgroud)

因此,如果您将其设置为nullinput == output之后将不会复制任何内容.

  • 我认为,这是.NET团队的可怕设计决定。显然,他们有这样的想法,因为*已经不正确的`ICryptoTransform`设计(再次将输入和输出进行合并),他们不得不对`outputBuffer`做一些事情。但是,复制输入会导致信息泄漏。而且由于哈希函数始终不会更改输入,那么为什么要复制它呢?它违反了干净的设计原则:1.一次且更重要的是做两件事。2.最不令人惊讶的原则。使用流接口,至少它不需要您处理不存在的输出。 (5认同)