diff options
16 files changed, 616 insertions, 69 deletions
diff --git a/pkg/Microsoft.Private.PackageBaseline/packageIndex.json b/pkg/Microsoft.Private.PackageBaseline/packageIndex.json index b2dcfc0398..c1f0bea3f6 100644 --- a/pkg/Microsoft.Private.PackageBaseline/packageIndex.json +++ b/pkg/Microsoft.Private.PackageBaseline/packageIndex.json @@ -1823,7 +1823,7 @@ "BaselineVersion": "4.0.0", "AssemblyVersionInPackageVersion": { "4.0.0.0": "4.0.0", - "4.0.1.0": "4.3.0" + "4.1.0.0": "4.3.0" } }, "System.Security.Cryptography.OpenSsl": { diff --git a/src/System.Security.Cryptography.Encoding/dir.props b/src/System.Security.Cryptography.Encoding/dir.props index 38aaf93ed7..0769c12aaa 100644 --- a/src/System.Security.Cryptography.Encoding/dir.props +++ b/src/System.Security.Cryptography.Encoding/dir.props @@ -1,7 +1,7 @@ <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="..\dir.props" /> <PropertyGroup> - <AssemblyVersion>4.0.1.0</AssemblyVersion> + <AssemblyVersion>4.1.0.0</AssemblyVersion> </PropertyGroup> </Project> diff --git a/src/System.Security.Cryptography.Encoding/pkg/System.Security.Cryptography.Encoding.pkgproj b/src/System.Security.Cryptography.Encoding/pkg/System.Security.Cryptography.Encoding.pkgproj index b8547733f4..77d2ac2571 100644 --- a/src/System.Security.Cryptography.Encoding/pkg/System.Security.Cryptography.Encoding.pkgproj +++ b/src/System.Security.Cryptography.Encoding/pkg/System.Security.Cryptography.Encoding.pkgproj @@ -3,7 +3,7 @@ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> <ItemGroup> <ProjectReference Include="..\ref\System.Security.Cryptography.Encoding.csproj"> - <SupportedFramework>net46;netcore50;netcoreapp1.0;$(AllXamarinFrameworks)</SupportedFramework> + <SupportedFramework>net463;netcoreapp1.1;$(AllXamarinFrameworks)</SupportedFramework> </ProjectReference> <ProjectReference Include="..\src\System.Security.Cryptography.Encoding.builds" /> diff --git a/src/System.Security.Cryptography.Encoding/ref/System.Security.Cryptography.Encoding.cs b/src/System.Security.Cryptography.Encoding/ref/System.Security.Cryptography.Encoding.cs index 0b3eea4d3f..71e4f64ad5 100644 --- a/src/System.Security.Cryptography.Encoding/ref/System.Security.Cryptography.Encoding.cs +++ b/src/System.Security.Cryptography.Encoding/ref/System.Security.Cryptography.Encoding.cs @@ -20,6 +20,49 @@ namespace System.Security.Cryptography public virtual void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } public virtual string Format(bool multiLine) { return default(string); } } + public sealed partial class AsnEncodedDataCollection : System.Collections.ICollection, System.Collections.IEnumerable + { + public AsnEncodedDataCollection() { } + public AsnEncodedDataCollection(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } + public int Count { get { return default(int); } } + public System.Security.Cryptography.AsnEncodedData this[int index] { get { return default(System.Security.Cryptography.AsnEncodedData); } } + bool System.Collections.ICollection.IsSynchronized { get { return default(bool); } } + object System.Collections.ICollection.SyncRoot { get { return default(object); } } + public int Add(System.Security.Cryptography.AsnEncodedData asnEncodedData) { return default(int); } + public void CopyTo(System.Security.Cryptography.AsnEncodedData[] array, int index) { } + public System.Security.Cryptography.AsnEncodedDataEnumerator GetEnumerator() { return default(System.Security.Cryptography.AsnEncodedDataEnumerator); } + public void Remove(System.Security.Cryptography.AsnEncodedData asnEncodedData) { } + void System.Collections.ICollection.CopyTo(System.Array array, int index) { } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return default(System.Collections.IEnumerator); } + } + public sealed partial class AsnEncodedDataEnumerator : System.Collections.IEnumerator + { + internal AsnEncodedDataEnumerator() { } + public System.Security.Cryptography.AsnEncodedData Current { get { return default(System.Security.Cryptography.AsnEncodedData); } } + object System.Collections.IEnumerator.Current { get { return default(object); } } + public bool MoveNext() { return default(bool); } + public void Reset() { } + } + public partial class FromBase64Transform : System.IDisposable, System.Security.Cryptography.ICryptoTransform + { + public FromBase64Transform() { } + public FromBase64Transform(System.Security.Cryptography.FromBase64TransformMode whitespaces) { } + public virtual bool CanReuseTransform { get { return default(bool); } } + public bool CanTransformMultipleBlocks { get { return default(bool); } } + public int InputBlockSize { get { return default(int); } } + public int OutputBlockSize { get { return default(int); } } + public void Clear() { } + public void Dispose() { } + protected virtual void Dispose(bool disposing) { } + ~FromBase64Transform() { } + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { return default(int); } + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { return default(byte[]); } + } + public enum FromBase64TransformMode + { + DoNotIgnoreWhiteSpaces = 1, + IgnoreWhiteSpaces = 0, + } public sealed partial class Oid { public Oid(System.Security.Cryptography.Oid oid) { } @@ -66,29 +109,18 @@ namespace System.Security.Cryptography SignatureAlgorithm = 4, Template = 9, } - - public sealed class AsnEncodedDataCollection : System.Collections.ICollection, System.Collections.IEnumerable - { - public AsnEncodedDataCollection() { } - public AsnEncodedDataCollection(AsnEncodedData asnEncodedData) { } - public int Count { get { return default(int); } } - bool System.Collections.ICollection.IsSynchronized { get { return default(bool); } } - object System.Collections.ICollection.SyncRoot { get { return default(object); } } - public AsnEncodedData this[int index] { get { return default(AsnEncodedData); } } - public int Add(AsnEncodedData asnEncodedData) { return default(int); } - public void CopyTo(AsnEncodedData[] array, int index) { } - public AsnEncodedDataEnumerator GetEnumerator() { return default(AsnEncodedDataEnumerator); } - public void Remove(AsnEncodedData asnEncodedData) { } - void System.Collections.ICollection.CopyTo(Array array, int index) { } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return default(System.Collections.IEnumerator); } - } - - public sealed class AsnEncodedDataEnumerator : System.Collections.IEnumerator + public partial class ToBase64Transform : System.IDisposable, System.Security.Cryptography.ICryptoTransform { - private AsnEncodedDataEnumerator() { } - public AsnEncodedData Current { get { return default(AsnEncodedData); } } - object System.Collections.IEnumerator.Current { get { return default(object); } } - public bool MoveNext() { return default(bool); } - public void Reset() { } + public ToBase64Transform() { } + public virtual bool CanReuseTransform { get { return default(bool); } } + public bool CanTransformMultipleBlocks { get { return default(bool); } } + public int InputBlockSize { get { return default(int); } } + public int OutputBlockSize { get { return default(int); } } + public void Clear() { } + public void Dispose() { } + protected virtual void Dispose(bool disposing) { } + ~ToBase64Transform() { } + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { return default(int); } + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { return default(byte[]); } } } diff --git a/src/System.Security.Cryptography.Encoding/ref/System.Security.Cryptography.Encoding.csproj b/src/System.Security.Cryptography.Encoding/ref/System.Security.Cryptography.Encoding.csproj index fb9b809089..81f9b4ca59 100644 --- a/src/System.Security.Cryptography.Encoding/ref/System.Security.Cryptography.Encoding.csproj +++ b/src/System.Security.Cryptography.Encoding/ref/System.Security.Cryptography.Encoding.csproj @@ -3,7 +3,7 @@ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> <PropertyGroup> <OutputType>Library</OutputType> - <NuGetTargetMoniker>.NETStandard,Version=v1.3</NuGetTargetMoniker> + <NuGetTargetMoniker>.NETStandard,Version=v1.7</NuGetTargetMoniker> </PropertyGroup> <ItemGroup> <Compile Include="System.Security.Cryptography.Encoding.cs" /> diff --git a/src/System.Security.Cryptography.Encoding/ref/project.json b/src/System.Security.Cryptography.Encoding/ref/project.json index e131fe0dbc..1b1510f8fa 100644 --- a/src/System.Security.Cryptography.Encoding/ref/project.json +++ b/src/System.Security.Cryptography.Encoding/ref/project.json @@ -1,11 +1,12 @@ { "dependencies": { - "System.Runtime": "4.0.0" + "System.Runtime": "4.3.0-beta-24522-03", + "System.Security.Cryptography.Primitives": "4.3.0-beta-24522-03" }, "frameworks": { - "netstandard1.3": { + "netstandard1.7": { "imports": [ - "dotnet5.4" + "dotnet5.8" ] } } diff --git a/src/System.Security.Cryptography.Encoding/src/Resources/Strings.resx b/src/System.Security.Cryptography.Encoding/src/Resources/Strings.resx index c7396653a9..c0d44d9639 100644 --- a/src/System.Security.Cryptography.Encoding/src/Resources/Strings.resx +++ b/src/System.Security.Cryptography.Encoding/src/Resources/Strings.resx @@ -123,13 +123,25 @@ <data name="Cryptography_Oid_InvalidName" xml:space="preserve"> <value>No OID value matches this name.</value> </data> + <data name="Cryptography_SSE_InvalidDataSize" xml:space="preserve"> + <value>NoLength of the data to encrypt is invalid.</value> + </data> <data name="Arg_RankMultiDimNotSupported" xml:space="preserve"> <value>Only single dimensional arrays are supported for the requested action.</value> </data> <data name="ArgumentOutOfRange_Index" xml:space="preserve"> <value>Index was out of range. Must be non-negative and less than the size of the collection.</value> </data> + <data name="ArgumentOutOfRange_NeedNonNegNum" xml:space="preserve"> + <value>Non-negative number required.</value> + </data> <data name="Argument_InvalidOffLen" xml:space="preserve"> <value>Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.</value> </data> + <data name="Argument_InvalidValue" xml:space="preserve"> + <value>Value was invalid.</value> + </data> + <data name="ObjectDisposed_Generic" xml:space="preserve"> + <value>Cannot access a disposed object.</value> + </data> </root>
\ No newline at end of file diff --git a/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.builds b/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.builds index 4ff1613681..2210a34f22 100644 --- a/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.builds +++ b/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.builds @@ -10,7 +10,7 @@ </Project> <Project Include="System.Security.Cryptography.Encoding.csproj"> <OSGroup>Windows_NT</OSGroup> - <TargetGroup>net46</TargetGroup> + <TargetGroup>net463</TargetGroup> </Project> </ItemGroup> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" /> diff --git a/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj b/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj index 65bf5f93b6..cfd7b3fd06 100644 --- a/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj +++ b/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj @@ -8,29 +8,30 @@ <ProjectGuid>{AA81E343-5E54-40B0-9381-C459419BE780}</ProjectGuid> <AssemblyName>System.Security.Cryptography.Encoding</AssemblyName> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net46'">true</IsPartialFacadeAssembly> - <ResourcesSourceOutputDirectory Condition="'$(TargetGroup)' == 'net46'">None</ResourcesSourceOutputDirectory> - <NuGetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.3</NuGetTargetMoniker> + <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'net463'">true</IsPartialFacadeAssembly> + <ResourcesSourceOutputDirectory Condition="'$(TargetGroup)' == 'net463'">None</ResourcesSourceOutputDirectory> + <NuGetTargetMoniker Condition="'$(TargetGroup)' == ''">.NETStandard,Version=v1.7</NuGetTargetMoniker> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Unix_Debug|AnyCPU'" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Unix_Release|AnyCPU'" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Debug|AnyCPU'" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Windows_Release|AnyCPU'" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net46_Debug|AnyCPU'" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net46_Release|AnyCPU'" /> - <ItemGroup Condition="'$(TargetGroup)' != 'net46'"> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Debug|AnyCPU'" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net463_Release|AnyCPU'" /> + <ItemGroup Condition="'$(TargetGroup)' != 'net463'"> <Compile Include="Internal\Cryptography\AsnFormatter.cs" /> <Compile Include="Internal\Cryptography\Helpers.cs" /> <Compile Include="Internal\Cryptography\OidLookup.cs" /> <Compile Include="System\Security\Cryptography\AsnEncodedData.cs" /> <Compile Include="System\Security\Cryptography\AsnEncodedDataCollection.cs" /> <Compile Include="System\Security\Cryptography\AsnEncodedDataEnumerator.cs" /> + <Compile Include="System\Security\Cryptography\Base64Transforms.cs" /> <Compile Include="System\Security\Cryptography\Oid.cs" /> <Compile Include="System\Security\Cryptography\OidCollection.cs" /> <Compile Include="System\Security\Cryptography\OidEnumerator.cs" /> <Compile Include="System\Security\Cryptography\OidGroup.cs" /> </ItemGroup> - <ItemGroup Condition=" '$(TargetsWindows)' == 'true' And '$(TargetGroup)' != 'net46'"> + <ItemGroup Condition=" '$(TargetsWindows)' == 'true' And '$(TargetGroup)' != 'net463'"> <Compile Include="Internal\Cryptography\AsnFormatter.Windows.cs" /> <Compile Include="Internal\Cryptography\CngAsnFormatter.cs" /> <Compile Include="Internal\Cryptography\OidLookup.Windows.cs" /> @@ -88,7 +89,7 @@ <Link>Common\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs</Link> </Compile> </ItemGroup> - <ItemGroup Condition="'$(TargetGroup)' == 'net46'"> + <ItemGroup Condition="'$(TargetGroup)' == 'net463'"> <TargetingPackReference Include="mscorlib" /> <TargetingPackReference Include="System" /> </ItemGroup> diff --git a/src/System.Security.Cryptography.Encoding/src/System/Security/Cryptography/Base64Transforms.cs b/src/System.Security.Cryptography.Encoding/src/System/Security/Cryptography/Base64Transforms.cs new file mode 100644 index 0000000000..afd2f07a13 --- /dev/null +++ b/src/System.Security.Cryptography.Encoding/src/System/Security/Cryptography/Base64Transforms.cs @@ -0,0 +1,265 @@ +// 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. + +// This file contains two ICryptoTransforms: ToBase64Transform and FromBase64Transform +// they may be attached to a CryptoStream in either read or write mode + +using System.Text; + +namespace System.Security.Cryptography +{ + public enum FromBase64TransformMode + { + IgnoreWhiteSpaces = 0, + DoNotIgnoreWhiteSpaces = 1, + } + + public class ToBase64Transform : ICryptoTransform + { + // converting to Base64 takes 3 bytes input and generates 4 bytes output + public int InputBlockSize => 3; + public int OutputBlockSize => 4; + public bool CanTransformMultipleBlocks => false; + public virtual bool CanReuseTransform => true; + + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + ValidateTransformBlock(inputBuffer, inputOffset, inputCount); + + // For now, only convert 3 bytes to 4 + byte[] tempBytes = ConvertToBase64(inputBuffer, inputOffset, 3); + + Buffer.BlockCopy(tempBytes, 0, outputBuffer, outputOffset, tempBytes.Length); + return tempBytes.Length; + } + + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + ValidateTransformBlock(inputBuffer, inputOffset, inputCount); + + // Convert.ToBase64CharArray already does padding, so all we have to check is that + // the inputCount wasn't 0 + if (inputCount == 0) + { + return Array.Empty<byte>(); + } + + // Again, for now only a block at a time + return ConvertToBase64(inputBuffer, inputOffset, inputCount); + } + + private byte[] ConvertToBase64(byte[] inputBuffer, int inputOffset, int inputCount) + { + char[] temp = new char[4]; + Convert.ToBase64CharArray(inputBuffer, inputOffset, inputCount, temp, 0); + byte[] tempBytes = Encoding.ASCII.GetBytes(temp); + if (tempBytes.Length != 4) + throw new CryptographicException(SR.Cryptography_SSE_InvalidDataSize); + + return tempBytes; + } + + private static void ValidateTransformBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + if (inputBuffer == null) throw new ArgumentNullException(nameof(inputBuffer)); + if (inputOffset < 0) throw new ArgumentOutOfRangeException(nameof(inputOffset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (inputCount < 0 || (inputCount > inputBuffer.Length)) throw new ArgumentException(SR.Argument_InvalidValue); + if ((inputBuffer.Length - inputCount) < inputOffset) throw new ArgumentException(SR.Argument_InvalidOffLen); + } + + // Must implement IDisposable, but in this case there's nothing to do. + + public void Dispose() + { + Clear(); + } + + public void Clear() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) { } + + ~ToBase64Transform() + { + // A finalizer is not necessary here, however since we shipped a finalizer that called + // Dispose(false) in desktop v2.0, we need to keep it in case any existing code had subclassed + // this transform and expects to have a base class finalizer call its dispose method. + Dispose(false); + } + } + + public class FromBase64Transform : ICryptoTransform + { + private byte[] _inputBuffer = new byte[4]; + private int _inputIndex; + private FromBase64TransformMode _whitespaces; + + public FromBase64Transform() : this(FromBase64TransformMode.IgnoreWhiteSpaces) { } + public FromBase64Transform(FromBase64TransformMode whitespaces) + { + _whitespaces = whitespaces; + _inputIndex = 0; + } + + // Converting from Base64 generates 3 bytes output from each 4 bytes input block + public int InputBlockSize => 1; + public int OutputBlockSize => 3; + public bool CanTransformMultipleBlocks => false; + public virtual bool CanReuseTransform => true; + + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + ValidateTransformBlock(inputBuffer, inputOffset, inputCount); + if (_inputBuffer == null) throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic); + + int effectiveCount; + byte[] temp = GetTempBuffer(inputBuffer, inputOffset, inputCount, out effectiveCount); + + if (effectiveCount + _inputIndex < 4) + { + Buffer.BlockCopy(temp, 0, _inputBuffer, _inputIndex, effectiveCount); + _inputIndex += effectiveCount; + return 0; + } + + byte[] result = ConvertFromBase64(temp, effectiveCount); + + Buffer.BlockCopy(result, 0, outputBuffer, outputOffset, result.Length); + + return result.Length; + } + + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + ValidateTransformBlock(inputBuffer, inputOffset, inputCount); + if (_inputBuffer == null) throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic); + + int effectiveCount; + byte[] temp = GetTempBuffer(inputBuffer, inputOffset, inputCount, out effectiveCount); + + if (effectiveCount + _inputIndex < 4) + { + Reset(); + return Array.Empty<byte>(); + } + + byte[] result = ConvertFromBase64(temp, effectiveCount); + + // reinitialize the transform + Reset(); + + return result; + } + + private byte[] GetTempBuffer(byte[] inputBuffer, int inputOffset, int inputCount, out int effectiveCount) + { + byte[] temp; + + if (_whitespaces == FromBase64TransformMode.IgnoreWhiteSpaces) + { + temp = DiscardWhiteSpaces(inputBuffer, inputOffset, inputCount); + effectiveCount = temp.Length; + } + else + { + temp = new byte[inputCount]; + Buffer.BlockCopy(inputBuffer, inputOffset, temp, 0, inputCount); + effectiveCount = inputCount; + } + + return temp; + } + + private byte[] ConvertFromBase64(byte[] temp, int effectiveCount) + { + // Get the number of 4 bytes blocks to transform + int numBlocks = (effectiveCount + _inputIndex) / 4; + + byte[] transformBuffer = new byte[_inputIndex + effectiveCount]; + Buffer.BlockCopy(_inputBuffer, 0, transformBuffer, 0, _inputIndex); + Buffer.BlockCopy(temp, 0, transformBuffer, _inputIndex, effectiveCount); + + _inputIndex = (effectiveCount + _inputIndex) % 4; + Buffer.BlockCopy(temp, effectiveCount - _inputIndex, _inputBuffer, 0, _inputIndex); + + char[] tempChar = Encoding.ASCII.GetChars(transformBuffer, 0, 4 * numBlocks); + byte[] tempBytes = Convert.FromBase64CharArray(tempChar, 0, 4 * numBlocks); + return tempBytes; + } + + private byte[] DiscardWhiteSpaces(byte[] inputBuffer, int inputOffset, int inputCount) + { + int i, iCount = 0; + for (i = 0; i < inputCount; i++) + { + if (char.IsWhiteSpace((char)inputBuffer[inputOffset + i])) iCount++; + } + + // If there's nothing to do, leave early + if (iCount == 0 && inputOffset == 0) + { + return inputBuffer; + } + + byte[] rgbOut = new byte[inputCount - iCount]; + iCount = 0; + for (i = 0; i < inputCount; i++) + { + if (!char.IsWhiteSpace((char)inputBuffer[inputOffset + i])) + { + rgbOut[iCount++] = inputBuffer[inputOffset + i]; + } + } + + return rgbOut; + } + + private static void ValidateTransformBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + if (inputBuffer == null) throw new ArgumentNullException(nameof(inputBuffer)); + if (inputOffset < 0) throw new ArgumentOutOfRangeException(nameof(inputOffset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (inputCount < 0 || (inputCount > inputBuffer.Length)) throw new ArgumentException(SR.Argument_InvalidValue); + if ((inputBuffer.Length - inputCount) < inputOffset) throw new ArgumentException(SR.Argument_InvalidOffLen); + } + + // must implement IDisposable, which in this case means clearing the input buffer + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + // Reset the state of the transform so it can be used again + private void Reset() + { + _inputIndex = 0; + } + + public void Clear() + { + Dispose(); + } + + protected virtual void Dispose(bool disposing) + { + // we always want to clear the input buffer + if (disposing) + { + if (_inputBuffer != null) + Array.Clear(_inputBuffer, 0, _inputBuffer.Length); + _inputBuffer = null; + _inputIndex = 0; + } + } + + ~FromBase64Transform() + { + Dispose(false); + } + } +} diff --git a/src/System.Security.Cryptography.Encoding/src/project.json b/src/System.Security.Cryptography.Encoding/src/project.json index 7b9d9a0b6e..eeb30e9c99 100644 --- a/src/System.Security.Cryptography.Encoding/src/project.json +++ b/src/System.Security.Cryptography.Encoding/src/project.json @@ -1,26 +1,27 @@ { "frameworks": { - "netstandard1.3": { + "netstandard1.7": { "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1", - "System.Collections": "4.0.0", - "System.Collections.Concurrent": "4.0.0", - "System.Diagnostics.Contracts": "4.0.0", - "System.Diagnostics.Debug": "4.0.10", - "System.Linq": "4.0.0", - "System.Resources.ResourceManager": "4.0.0", - "System.Runtime": "4.0.20", - "System.Runtime.InteropServices": "4.0.20", - "System.Text.Encoding": "4.0.10", - "System.Security.Cryptography.Primitives": "4.0.0" + "Microsoft.NETCore.Platforms": "1.0.2-beta-24522-03", + "System.Collections": "4.3.0-beta-24522-03", + "System.Collections.Concurrent": "4.3.0-beta-24522-03", + "System.Diagnostics.Contracts": "4.3.0-beta-24522-03", + "System.Diagnostics.Debug": "4.3.0-beta-24522-03", + "System.Linq": "4.3.0-beta-24522-03", + "System.Resources.ResourceManager": "4.3.0-beta-24522-03", + "System.Runtime": "4.3.0-beta-24522-03", + "System.Runtime.Extensions": "4.3.0-beta-24522-03", + "System.Runtime.InteropServices": "4.3.0-beta-24522-03", + "System.Text.Encoding": "4.3.0-beta-24522-03", + "System.Security.Cryptography.Primitives": "4.3.0-beta-24522-03" }, "imports": [ - "dotnet5.4" + "dotnet5.8" ] }, - "net46": { + "net463": { "dependencies": { - "Microsoft.TargetingPack.NETFramework.v4.6": "1.0.1" + "Microsoft.TargetingPack.NETFramework.v4.6.2": "1.0.1" } } } diff --git a/src/System.Security.Cryptography.Encoding/tests/Base64TransformsTests.cs b/src/System.Security.Cryptography.Encoding/tests/Base64TransformsTests.cs new file mode 100644 index 0000000000..c7ced87de5 --- /dev/null +++ b/src/System.Security.Cryptography.Encoding/tests/Base64TransformsTests.cs @@ -0,0 +1,204 @@ +// 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.Collections.Generic; +using System.IO; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Encoding.Tests +{ + public class Base64TransformsTests + { + public static IEnumerable<object[]> TestData_Ascii() + { + // Test data taken from RFC 4648 Test Vectors + yield return new object[] { "", "" }; + yield return new object[] { "f", "Zg==" }; + yield return new object[] { "fo", "Zm8=" }; + yield return new object[] { "foo", "Zm9v" }; + yield return new object[] { "foob", "Zm9vYg==" }; + yield return new object[] { "fooba", "Zm9vYmE=" }; + yield return new object[] { "foobar", "Zm9vYmFy" }; + } + + public static IEnumerable<object[]> TestData_LongBlock_Ascii() + { + yield return new object[] { "fooba", "Zm9vYmE=" }; + yield return new object[] { "foobar", "Zm9vYmFy" }; + } + + public static IEnumerable<object[]> TestData_Ascii_NoPadding() + { + // Test data without padding + yield return new object[] { "Zg" }; + yield return new object[] { "Zm9vYg" }; + yield return new object[] { "Zm9vYmE" }; + } + + public static IEnumerable<object[]> TestData_Ascii_Whitespace() + { + yield return new object[] { "fo", "\tZ\tm8=\n" }; + yield return new object[] { "foo", " Z m 9 v" }; + } + + [Fact] + public void InvalidInput_ToBase64Transform() + { + byte[] data_5bytes = Text.Encoding.ASCII.GetBytes("aaaaa"); + + using (var transform = new ToBase64Transform()) + { + InvalidInput_Base64Transform(transform); + + // These exceptions only thrown in ToBase + Assert.Throws<ArgumentOutOfRangeException>("offsetOut", () => transform.TransformFinalBlock(data_5bytes, 0, 5)); + } + } + + [Fact] + public void InvalidInput_FromBase64Transform() + { + byte[] data_4bytes = Text.Encoding.ASCII.GetBytes("aaaa"); + + ICryptoTransform transform = new FromBase64Transform(); + InvalidInput_Base64Transform(transform); + + // These exceptions only thrown in FromBase + transform.Dispose(); + Assert.Throws<ObjectDisposedException>(() => transform.TransformBlock(data_4bytes, 0, 4, null, 0)); + Assert.Throws<ObjectDisposedException>(() => transform.TransformFinalBlock(Array.Empty<byte>(), 0, 0)); + } + + private void InvalidInput_Base64Transform(ICryptoTransform transform) + { + byte[] data_4bytes = Text.Encoding.ASCII.GetBytes("aaaa"); + + Assert.Throws<ArgumentNullException>("inputBuffer", () => transform.TransformBlock(null, 0, 0, null, 0)); + Assert.Throws<ArgumentOutOfRangeException>("inputOffset", () => transform.TransformBlock(Array.Empty<byte>(), -1, 0, null, 0)); + Assert.Throws<ArgumentNullException>("dst", () => transform.TransformBlock(data_4bytes, 0, 4, null, 0)); + Assert.Throws<ArgumentException>(null, () => transform.TransformBlock(Array.Empty<byte>(), 0, 1, null, 0)); + Assert.Throws<ArgumentException>(null, () => transform.TransformBlock(Array.Empty<byte>(), 1, 0, null, 0)); + + Assert.Throws<ArgumentNullException>("inputBuffer", () => transform.TransformFinalBlock(null, 0, 0)); + Assert.Throws<ArgumentOutOfRangeException>("inputOffset", () => transform.TransformFinalBlock(Array.Empty<byte>(), -1, 0)); + Assert.Throws<ArgumentOutOfRangeException>("inputOffset", () => transform.TransformFinalBlock(Array.Empty<byte>(), -1, 0)); + Assert.Throws<ArgumentException>(null, () => transform.TransformFinalBlock(Array.Empty<byte>(), 1, 0)); + } + + [Theory, MemberData(nameof(TestData_Ascii))] + public static void ValidateToBase64CryptoStream(string data, string encoding) + { + using (var transform = new ToBase64Transform()) + { + ValidateCryptoStream(encoding, data, transform); + } + } + + [Theory, MemberData(nameof(TestData_Ascii))] + public static void ValidateFromBase64CryptoStream(string data, string encoding) + { + using (var transform = new FromBase64Transform()) + { + ValidateCryptoStream(data, encoding, transform); + } + } + + private static void ValidateCryptoStream(string expected, string data, ICryptoTransform transform) + { + byte[] inputBytes = Text.Encoding.ASCII.GetBytes(data); + byte[] outputBytes = new byte[100]; + + using (var ms = new MemoryStream(inputBytes)) + using (var cs = new CryptoStream(ms, transform, CryptoStreamMode.Read)) + { + int bytesRead = cs.Read(outputBytes, 0, outputBytes.Length); + string outputString = Text.Encoding.ASCII.GetString(outputBytes, 0, bytesRead); + Assert.Equal(expected, outputString); + } + } + + [Theory, MemberData(nameof(TestData_LongBlock_Ascii))] + public static void ValidateToBase64TransformFinalBlock(string data, string expected) + { + using (var transform = new ToBase64Transform()) + { + byte[] inputBytes = Text.Encoding.ASCII.GetBytes(data); + Assert.True(inputBytes.Length > 4); + + // Test passing blocks > 4 characters to TransformFinalBlock (not supported) + Assert.Throws<ArgumentOutOfRangeException>("offsetOut", () => transform.TransformFinalBlock(inputBytes, 0, inputBytes.Length)); + } + } + + [Theory, MemberData(nameof(TestData_LongBlock_Ascii))] + public static void ValidateFromBase64TransformFinalBlock(string expected, string encoding) + { + using (var transform = new FromBase64Transform()) + { + byte[] inputBytes = Text.Encoding.ASCII.GetBytes(encoding); + Assert.True(inputBytes.Length > 4); + + // Test passing blocks > 4 characters to TransformFinalBlock (supported) + byte[] outputBytes = transform.TransformFinalBlock(inputBytes, 0, inputBytes.Length); + string outputString = Text.Encoding.ASCII.GetString(outputBytes, 0, outputBytes.Length); + Assert.Equal(expected, outputString); + } + } + + [Theory, MemberData(nameof(TestData_Ascii_NoPadding))] + public static void ValidateFromBase64_NoPadding(string data) + { + using (var transform = new FromBase64Transform()) + { + byte[] inputBytes = Text.Encoding.ASCII.GetBytes(data); + byte[] outputBytes = new byte[100]; + + using (var ms = new MemoryStream(inputBytes)) + using (var cs = new CryptoStream(ms, transform, CryptoStreamMode.Read)) + { + int bytesRead = cs.Read(outputBytes, 0, outputBytes.Length); + + // Missing padding bytes not supported (no exception, however) + Assert.NotEqual(inputBytes.Length, bytesRead); + } + } + } + + [Theory, MemberData(nameof(TestData_Ascii_Whitespace))] + public static void ValidateWhitespace(string expected, string data) + { + byte[] inputBytes = Text.Encoding.ASCII.GetBytes(data); + byte[] outputBytes = new byte[100]; + + // Verify default of FromBase64TransformMode.IgnoreWhiteSpaces + using (var base64Transform = new FromBase64Transform()) + using (var ms = new MemoryStream(inputBytes)) + using (var cs = new CryptoStream(ms, base64Transform, CryptoStreamMode.Read)) + { + int bytesRead = cs.Read(outputBytes, 0, outputBytes.Length); + string outputString = Text.Encoding.ASCII.GetString(outputBytes, 0, bytesRead); + Assert.Equal(expected, outputString); + } + + // Verify explicit FromBase64TransformMode.IgnoreWhiteSpaces + using (var base64Transform = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces)) + using (var ms = new MemoryStream(inputBytes)) + using (var cs = new CryptoStream(ms, base64Transform, CryptoStreamMode.Read)) + { + int bytesRead = cs.Read(outputBytes, 0, outputBytes.Length); + string outputString = Text.Encoding.ASCII.GetString(outputBytes, 0, bytesRead); + Assert.Equal(expected, outputString); + } + + // Verify FromBase64TransformMode.DoNotIgnoreWhiteSpaces + using (var base64Transform = new FromBase64Transform(FromBase64TransformMode.DoNotIgnoreWhiteSpaces)) + using (var ms = new MemoryStream(inputBytes)) + using (var cs = new CryptoStream(ms, base64Transform, CryptoStreamMode.Read)) + { + Assert.Throws<FormatException>(() => cs.Read(outputBytes, 0, outputBytes.Length)); + } + } + } +} diff --git a/src/System.Security.Cryptography.Encoding/tests/Oid.cs b/src/System.Security.Cryptography.Encoding/tests/Oid.cs index 0e89ea7223..bc2f000069 100644 --- a/src/System.Security.Cryptography.Encoding/tests/Oid.cs +++ b/src/System.Security.Cryptography.Encoding/tests/Oid.cs @@ -175,7 +175,7 @@ namespace System.Security.Cryptography.Encoding.Tests [Theory] [MemberData(nameof(ValidOidFriendlyNameHashAlgorithmPairs))] - [PlatformSpecific(PlatformID.Windows)] + [PlatformSpecific(Xunit.PlatformID.Windows)] public static void LookupOidByValue_Method_WrongGroup(string oidValue, string friendlyName) { // Oid group is implemented strictly - no fallback to OidGroup.All as with many other parts of Crypto. @@ -231,7 +231,7 @@ namespace System.Security.Cryptography.Encoding.Tests [Theory] [MemberData(nameof(ValidOidFriendlyNameHashAlgorithmPairs))] - [PlatformSpecific(PlatformID.Windows)] + [PlatformSpecific(Xunit.PlatformID.Windows)] public static void LookupOidByFriendlyName_Method_WrongGroup(string oidValue, string friendlyName) { // Oid group is implemented strictly - no fallback to OidGroup.All as with many other parts of Crypto. @@ -253,7 +253,7 @@ namespace System.Security.Cryptography.Encoding.Tests } [Fact] - [PlatformSpecific(PlatformID.AnyUnix)] + [PlatformSpecific(Xunit.PlatformID.AnyUnix)] public static void LookupOidByValue_Method_UnixOnly() { // This needs to be an OID not in the static lookup table. The purpose is to verify the @@ -267,7 +267,7 @@ namespace System.Security.Cryptography.Encoding.Tests } [Fact] - [PlatformSpecific(PlatformID.AnyUnix)] + [PlatformSpecific(Xunit.PlatformID.AnyUnix)] public static void LookupOidByFriendlyName_Method_UnixOnly() { // This needs to be a name not in the static lookup table. The purpose is to verify the diff --git a/src/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.builds b/src/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.builds index 478303b742..5f029c7d7d 100644 --- a/src/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.builds +++ b/src/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.builds @@ -6,7 +6,16 @@ <OSGroup>Unix</OSGroup> </Project> <Project Include="System.Security.Cryptography.Encoding.Tests.csproj"> - <TestTFMs>netcore50;netcoreapp1.0;net46</TestTFMs> + <TargetGroup>netstandard1.7</TargetGroup> + <TestTFMs>netcoreapp1.1</TestTFMs> + <OSGroup>Unix</OSGroup> + </Project> + <Project Include="System.Security.Cryptography.Encoding.Tests.csproj"> + <OSGroup>Windows_NT</OSGroup> + </Project> + <Project Include="System.Security.Cryptography.Encoding.Tests.csproj"> + <TargetGroup>netstandard1.7</TargetGroup> + <TestTFMs>netcoreapp1.1;net463</TestTFMs> <OSGroup>Windows_NT</OSGroup> </Project> </ItemGroup> diff --git a/src/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.csproj b/src/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.csproj index 76d302590c..03fe8707b9 100644 --- a/src/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.csproj +++ b/src/System.Security.Cryptography.Encoding/tests/System.Security.Cryptography.Encoding.Tests.csproj @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition="'$(Configuration)'==''">Windows_Debug</Configuration> @@ -12,7 +12,7 @@ <AssemblyName>System.Security.Cryptography.Encoding.Tests</AssemblyName> <RootNamespace>System.Security.Cryptography.Encoding.Tests</RootNamespace> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - <NugetTargetMoniker>.NETStandard,Version=v1.3</NugetTargetMoniker> + <NugetTargetMoniker Condition="'$(NugetTargetMoniker)'==''">.NETStandard,Version=v1.3</NugetTargetMoniker> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\pkg\System.Security.Cryptography.Encoding.pkgproj"> @@ -37,8 +37,11 @@ <Link>CommonTest\System\Security\Cryptography\ByteUtils.cs</Link> </Compile> </ItemGroup> + <ItemGroup Condition="'$(TargetGroup)'=='netstandard1.7'"> + <Compile Include="Base64TransformsTests.cs" /> + </ItemGroup> <ItemGroup> <None Include="project.json" /> </ItemGroup> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/src/System.Security.Cryptography.Encoding/tests/project.json b/src/System.Security.Cryptography.Encoding/tests/project.json index 547abd08cc..3e4389806a 100644 --- a/src/System.Security.Cryptography.Encoding/tests/project.json +++ b/src/System.Security.Cryptography.Encoding/tests/project.json @@ -9,17 +9,18 @@ "System.Runtime.Numerics": "4.3.0-beta-24522-03", "System.Security.Cryptography.Primitives": "4.3.0-beta-24522-03", "System.Text.RegularExpressions": "4.3.0-beta-24522-03", - "test-runtime": { - "target": "project", - "exclude": "compile" - }, + "System.Xml.XmlSerializer": "4.3.0-beta-24522-03", "Microsoft.xunit.netcore.extensions": "1.0.0-prerelease-00807-03", "Microsoft.DotNet.BuildTools.TestSuite": "1.0.0-prerelease-00807-03", "Microsoft.DotNet.xunit.performance": "1.0.0-alpha-build0040", - "System.Xml.XmlSerializer": "4.3.0-beta-24522-03" + "test-runtime": { + "target": "project", + "exclude": "compile" + } }, "frameworks": { - "netstandard1.3": {} + "netstandard1.3": {}, + "netstandard1.7": {} }, "supports": { "coreFx.Test.netcore50": {}, @@ -27,6 +28,24 @@ "coreFx.Test.net46": {}, "coreFx.Test.net461": {}, "coreFx.Test.net462": {}, - "coreFx.Test.net463": {} + "coreFx.Test.net463": {}, + "coreFx.Test.netcoreapp1.1-ns17": { + "netstandard1.7": [ + "win7-x86", + "win7-x64", + "win10-arm64", + "osx.10.10-x64", + "centos.7-x64", + "debian.8-x64", + "rhel.7-x64", + "ubuntu.14.04-x64", + "ubuntu.16.04-x64", + "ubuntu.16.10-x64", + "fedora.23-x64", + "linux-x64", + "opensuse.13.2-x64", + "opensuse.42.1-x64" + ] + } } } |