Imported Upstream version 5.10.0.47

Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-24 17:04:36 +00:00
parent 88ff76fe28
commit e46a49ecf1
5927 changed files with 226314 additions and 129848 deletions

View File

@@ -94,10 +94,13 @@ namespace System.Security.Cryptography
public void Dispose() { }
protected virtual void Dispose(bool disposing) { }
protected abstract void HashCore(byte[] array, int ibStart, int cbSize);
protected virtual void HashCore(ReadOnlySpan<byte> source) { throw null; }
protected abstract byte[] HashFinal();
public abstract void Initialize();
public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { throw null; }
public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { throw null; }
public bool TryComputeHash(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten) { throw null; }
protected virtual bool TryHashFinal(Span<byte> destination, out int bytesWritten) { throw null; }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public partial struct HashAlgorithmName : System.IEquatable<System.Security.Cryptography.HashAlgorithmName>

View File

@@ -115,4 +115,7 @@
<data name="CryptoConfigNotSupported" xml:space="preserve">
<value>Accessing a hash algorithm by manipulating the HashName property is not supported on this platform. Instead, you must instantiate one of the supplied subtypes (such as HMACSHA1.)</value>
</data>
<data name="InvalidOperation_IncorrectImplementation" xml:space="preserve">
<value>The algorithm's implementation is incorrect.</value>
</data>
</root>

View File

@@ -33,6 +33,7 @@
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Buffers" />
<Reference Include="System.Diagnostics.Contracts" />
<Reference Include="System.Diagnostics.Debug" />
<Reference Include="System.Resources.ResourceManager" />

View File

@@ -6,43 +6,30 @@ namespace System.Security.Cryptography
{
public abstract class HMAC : KeyedHashAlgorithm
{
private string _hashName;
private int _blockSizeValue = 64;
protected int BlockSizeValue
{
get
{
return _blockSizeValue;
}
set
{
_blockSizeValue = value;
}
get => _blockSizeValue;
set => _blockSizeValue = value;
}
protected HMAC() { }
public static new HMAC Create()
{
return Create("System.Security.Cryptography.HMAC");
}
public static new HMAC Create() => Create("System.Security.Cryptography.HMAC");
public static new HMAC Create(string algorithmName)
{
throw new PlatformNotSupportedException();
}
public static new HMAC Create(string algorithmName) => throw new PlatformNotSupportedException();
public String HashName
public string HashName
{
get
{
return _hashName;
}
get => _hashName;
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(HashName));
}
// On the desktop, setting the HashName selects (or switches over to) a new hashing algorithm via CryptoConfig.
// Our intended refactoring turns HMAC back into an abstract class with no algorithm-specific implementation.
@@ -52,7 +39,9 @@ namespace System.Security.Cryptography
// Since the set is public, ensure that hmac.HashName = hmac.HashName works without throwing.
if (_hashName != null && value != _hashName)
{
throw new PlatformNotSupportedException(SR.HashNameMultipleSetNotSupported);
}
_hashName = value;
}
@@ -60,38 +49,26 @@ namespace System.Security.Cryptography
public override byte[] Key
{
get
{
return base.Key;
}
set
{
base.Key = value;
}
get => base.Key;
set => base.Key = value;
}
protected override void Dispose(bool disposing)
{
protected override void Dispose(bool disposing) =>
base.Dispose(disposing);
}
protected override void HashCore(byte[] rgb, int ib, int cb)
{
protected override void HashCore(byte[] rgb, int ib, int cb) =>
throw new PlatformNotSupportedException(SR.CryptoConfigNotSupported);
}
protected override byte[] HashFinal()
{
protected override void HashCore(ReadOnlySpan<byte> source) =>
throw new PlatformNotSupportedException(SR.CryptoConfigNotSupported);
}
public override void Initialize()
{
protected override byte[] HashFinal() =>
throw new PlatformNotSupportedException(SR.CryptoConfigNotSupported);
}
private String _hashName;
protected override bool TryHashFinal(Span<byte> destination, out int bytesWritten) =>
throw new PlatformNotSupportedException(SR.CryptoConfigNotSupported);
public override void Initialize() =>
throw new PlatformNotSupportedException(SR.CryptoConfigNotSupported);
}
}

View File

@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Buffers;
using System.IO;
namespace System.Security.Cryptography
@@ -15,15 +16,9 @@ namespace System.Security.Cryptography
protected HashAlgorithm() { }
public static HashAlgorithm Create()
{
return Create("System.Security.Cryptography.HashAlgorithm");
}
public static HashAlgorithm Create() => Create("System.Security.Cryptography.HashAlgorithm");
public static HashAlgorithm Create(string hashName)
{
throw new PlatformNotSupportedException();
}
public static HashAlgorithm Create(string hashName) => throw new PlatformNotSupportedException();
public virtual int HashSize => HashSizeValue;
@@ -36,7 +31,7 @@ namespace System.Security.Cryptography
if (State != 0)
throw new CryptographicUnexpectedOperationException(SR.Cryptography_HashNotYetFinalized);
return (byte[])HashValue.Clone();
return (byte[])HashValue?.Clone();
}
}
@@ -51,6 +46,32 @@ namespace System.Security.Cryptography
return CaptureHashCodeAndReinitialize();
}
public bool TryComputeHash(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten)
{
if (_disposed)
{
throw new ObjectDisposedException(null);
}
if (destination.Length < HashSizeValue/8)
{
bytesWritten = 0;
return false;
}
HashCore(source);
if (!TryHashFinal(destination, out bytesWritten))
{
// The only reason for failure should be that the destination isn't long enough,
// but we checked the size earlier.
throw new InvalidOperationException(SR.InvalidOperation_IncorrectImplementation);
}
HashValue = null;
Initialize();
return true;
}
public byte[] ComputeHash(byte[] buffer, int offset, int count)
{
if (buffer == null)
@@ -121,25 +142,10 @@ namespace System.Security.Cryptography
// ICryptoTransform methods
// We assume any HashAlgorithm can take input a byte at a time
public virtual int InputBlockSize
{
get { return (1); }
}
public virtual int OutputBlockSize
{
get { return (1); }
}
public virtual bool CanTransformMultipleBlocks
{
get { return true; }
}
public virtual bool CanReuseTransform
{
get { return true; }
}
public virtual int InputBlockSize => 1;
public virtual int OutputBlockSize => 1;
public virtual bool CanTransformMultipleBlocks => true;
public virtual bool CanReuseTransform => true;
public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
@@ -198,5 +204,41 @@ namespace System.Security.Cryptography
protected abstract void HashCore(byte[] array, int ibStart, int cbSize);
protected abstract byte[] HashFinal();
public abstract void Initialize();
protected virtual void HashCore(ReadOnlySpan<byte> source)
{
byte[] array = ArrayPool<byte>.Shared.Rent(source.Length);
try
{
source.CopyTo(array);
HashCore(array, 0, source.Length);
}
finally
{
Array.Clear(array, 0, source.Length);
ArrayPool<byte>.Shared.Return(array);
}
}
protected virtual bool TryHashFinal(Span<byte> destination, out int bytesWritten)
{
int hashSizeInBytes = HashSizeValue / 8;
if (destination.Length >= hashSizeInBytes)
{
byte[] final = HashFinal();
if (final.Length == hashSizeInBytes)
{
new ReadOnlySpan<byte>(final).CopyTo(destination);
bytesWritten = final.Length;
return true;
}
throw new InvalidOperationException(SR.InvalidOperation_IncorrectImplementation);
}
bytesWritten = 0;
return false;
}
}
}

View File

@@ -0,0 +1,52 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Linq;
using Xunit;
namespace System.Security.Cryptography.Hashing.Tests
{
public partial class HashAlgorithmTest
{
[Fact]
public void SpanMethodsUsed_NotOverridden_ArrayMethodsInvoked()
{
byte[] input = Enumerable.Range(0, 1024).Select(i => (byte)i).ToArray();
byte[] output;
int bytesWritten;
var testAlgorithm = new SummingTestHashAlgorithm();
output = new byte[sizeof(long) - 1];
Assert.False(testAlgorithm.TryComputeHash(input, output, out bytesWritten));
Assert.Equal(0, bytesWritten);
Assert.Equal<byte>(new byte[sizeof(long) - 1], output);
output = new byte[sizeof(long)];
Assert.True(testAlgorithm.TryComputeHash(input, output, out bytesWritten));
Assert.Equal(sizeof(long), bytesWritten);
Assert.Equal(input.Sum(b => (long)b), BitConverter.ToInt64(output, 0));
}
private sealed class SummingTestHashAlgorithm : HashAlgorithm
{
private long _sum;
public SummingTestHashAlgorithm() => HashSizeValue = sizeof(long)*8;
public override void Initialize() => _sum = 0;
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
for (int i = ibStart; i < ibStart + cbSize; i++) _sum += array[i];
}
protected override byte[] HashFinal() => BitConverter.GetBytes(_sum);
// Do not override HashCore(ReadOnlySpan) and TryHashFinal. Consuming
// test verifies that calling the base implementations invokes the array
// implementations by verifying the right value is produced.
}
}
}

View File

@@ -24,12 +24,10 @@
<Compile Include="$(CommonTestPath)\System\IO\PositionValueStream.cs">
<Link>CommonTest\System\IO\PositionValueStream.cs</Link>
</Compile>
<Compile Include="$(CommonTestPath)\System\PlatformDetection.cs">
<Link>CommonTest\System\PlatformDetection.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)'=='netcoreapp'">
<Compile Include="CryptoConfigTests.cs" />
<Compile Include="HashAlgorithmTest.netcoreapp.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>