diff --git a/build/build.proj b/build/build.proj
index 2e995c74373..6504d4ae2c7 100644
--- a/build/build.proj
+++ b/build/build.proj
@@ -225,7 +225,7 @@
Projects="@(SolutionProjects)"
Targets="PackProjects"
Properties="$(CommonMSBuildProperties);
- VisualStudioVersion=$(VisualStudioVersion);" />
+ VisualStudioVersion=$(VisualStudioVersion)" />
@@ -11,6 +11,19 @@
true
+
+ $(DefineConstants);NETCORE5_0
+
+
+
+ true
+ false
+
+
+
+ $(DefineConstants);IS_SIGNING_SUPPORTED
+
+
@@ -333,4 +346,4 @@
-
\ No newline at end of file
+
diff --git a/build/config.props b/build/config.props
index 27ff36a9c0e..283fd605370 100644
--- a/build/config.props
+++ b/build/config.props
@@ -32,12 +32,21 @@
$([MSBuild]::Add(11, $(MajorNuGetVersion)))
master
int.$(VsTargetBranch)
+
+
rel/d$(VsTargetMajorVersion).$(MinorNuGetVersion)
int.d$(VsTargetMajorVersion).$(MinorNuGetVersion)
-
+
+
+
+ true
+
+ master 5.0.100-alpha1-015516
+ master
+ "master 5.0.100-alpha1-015516"
$(OverrideCliBranchForTesting)
- 3.1
+ master
$(OverrideCliTargetBranches)
master
$(OverrideCliTargetBranches)
@@ -95,4 +104,7 @@
+
+
+
diff --git a/build/packages.targets b/build/packages.targets
index 69b21a7858f..6d1ddfcf698 100644
--- a/build/packages.targets
+++ b/build/packages.targets
@@ -7,6 +7,8 @@
16.5.29714.20
16.153.0
16.5.126
+
+ 5.0.0-alpha1.19473.1
@@ -68,6 +70,8 @@
+
+
@@ -100,7 +104,6 @@
-
diff --git a/build/vsts_build.yaml b/build/vsts_build.yaml
index 694bc528af6..ee031683146 100644
--- a/build/vsts_build.yaml
+++ b/build/vsts_build.yaml
@@ -62,6 +62,16 @@ jobs:
Write-Host "##vso[task.setvariable variable=BuildNumber;isOutput=true]$newBuildCounter"
Write-Host "##vso[task.setvariable variable=FullVstsBuildNumber;isOutput=true]$FullBuildNumber"
+ - task: PowerShell@1
+ displayName: "Get SDK Version For Build"
+ name: "getSDKVersionForBuild"
+ inputs:
+ scriptType: "inlineScript"
+ inlineScript: |
+ $msbuildExe = 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\bin\msbuild.exe'
+ $SDKVersionForBuild = & $msbuildExe $env:BUILD_REPOSITORY_LOCALPATH\build\config.props /v:m /nologo /t:GetCliVersionForBuilding
+ Write-Host "##vso[task.setvariable variable=SDKVersionForBuild;isOutput=true]$SDKVersionForBuild"
+
- task: PowerShell@1
displayName: "Add Build Tags"
inputs:
@@ -78,6 +88,7 @@ jobs:
FullVstsBuildNumber: $[dependencies.Initialize_Build.outputs['updatebuildnumber.FullVstsBuildNumber']]
VsTargetChannel: $[dependencies.Initialize_Build.outputs['updatebuildnumber.VsTargetChannel']]
VsTargetMajorVersion: $[dependencies.Initialize_Build.outputs['updatebuildnumber.VsTargetMajorVersion']]
+ SDKVersionForBuild: $[dependencies.Initialize_Build.outputs['getSDKVersionForBuild.SDKVersionForBuild']]
LocalizedLanguageCount: "13"
pool:
@@ -93,6 +104,12 @@ jobs:
BuildRTM: "false"
steps:
+ - task: PowerShell@1
+ inputs:
+ scriptName: "$(Build.Repository.LocalPath)\\scripts\\utils\\InstallCLIforBuild.ps1"
+ arguments: '$(SDKVersionForBuild)'
+ displayName: "Install .NET 5.0 for build"
+
- task: PowerShell@1
displayName: "Update Build Number"
inputs:
@@ -101,6 +118,13 @@ jobs:
Write-Host "##vso[build.updatebuildnumber]$env:FullVstsBuildNumber"
Get-ChildItem Env: | Sort-Object Name | Format-Table -Wrap -AutoSize
+ - task: PowerShell@1
+ displayName: "Define variables"
+ inputs:
+ scriptType: "inlineScript"
+ inlineScript: |
+ Write-Host "##vso[task.setvariable variable=Path]${env:AGENT_TEMPDIRECTORY}\dotnet\;${env:Path}"
+
- task: NuGetToolInstaller@0
displayName: "Use NuGet 5.0.0"
inputs:
@@ -552,6 +576,7 @@ jobs:
variables:
BuildNumber: $[dependencies.Initialize_Build.outputs['updatebuildnumber.BuildNumber']]
FullVstsBuildNumber: $[dependencies.Initialize_Build.outputs['updatebuildnumber.FullVstsBuildNumber']]
+ SDKVersionForBuild: $[dependencies.Initialize_Build.outputs['getSDKVersionForBuild.SDKVersionForBuild']]
condition: "and(succeeded(),eq(variables['RunFunctionalTestsOnWindows'], 'true')) "
pool:
name: VSEng-MicroBuildVS2019
@@ -566,6 +591,19 @@ jobs:
SkipDesktopAssemblies: "true"
steps:
+ - task: PowerShell@1
+ inputs:
+ scriptName: "$(Build.Repository.LocalPath)\\scripts\\utils\\InstallCLIforBuild.ps1"
+ arguments: '$(SDKVersionForBuild)'
+ displayName: "Install .NET 5.0 for build"
+
+ - task: PowerShell@1
+ displayName: "Define variables"
+ inputs:
+ scriptType: "inlineScript"
+ inlineScript: |
+ Write-Host "##vso[task.setvariable variable=Path]${env:AGENT_TEMPDIRECTORY}\dotnet\;${env:Path}"
+
- task: PowerShell@1
displayName: "Print Environment Variables"
inputs:
@@ -634,6 +672,7 @@ jobs:
timeoutInMinutes: 15
variables:
FULLVSTSBUILDNUMBER: $[dependencies.Initialize_Build.outputs['updatebuildnumber.FullVstsBuildNumber']]
+ SDKVersionForBuild: $[dependencies.Initialize_Build.outputs['getSDKVersionForBuild.SDKVersionForBuild']]
MSBUILDDISABLENODEREUSE: 1
condition: "and(succeeded(),eq(variables['RunTestsOnLinux'], 'true')) "
pool:
@@ -641,6 +680,23 @@ jobs:
demands: sh
steps:
+
+ - task: ShellScript@2
+ displayName: "Install .NET 5.0 for build"
+ continueOnError: "true"
+ inputs:
+ scriptPath: "scripts/utils/InstallCLIforBuild.sh"
+ disableAutoCwd: "true"
+ cwd: "$(Build.Repository.LocalPath)"
+ args: '$(SDKVersionForBuild)'
+
+ - task: PowerShell@2
+ displayName: "Define variables"
+ inputs:
+ targetType: "inline"
+ script: |
+ Write-Host "##vso[task.setvariable variable=PATH]${env:AGENT_TEMPDIRECTORY}/dotnet/:${env:PATH}"
+
- task: PowerShell@2
displayName: "Update Build Number"
inputs:
@@ -685,11 +741,21 @@ jobs:
timeoutInMinutes: 75
variables:
FULLVSTSBUILDNUMBER: $[dependencies.Initialize_Build.outputs['updatebuildnumber.FullVstsBuildNumber']]
+ SDKVersionForBuild: $[dependencies.Initialize_Build.outputs['getSDKVersionForBuild.SDKVersionForBuild']]
condition: "and(succeeded(),eq(variables['RunTestsOnMac'], 'true')) "
pool:
vmImage: macos-latest
- steps:
+ steps:
+ - task: ShellScript@2
+ displayName: "Install .NET 5.0 for build"
+ continueOnError: "true"
+ inputs:
+ scriptPath: "scripts/utils/InstallCLIforBuild.sh"
+ disableAutoCwd: "true"
+ cwd: "$(Build.Repository.LocalPath)"
+ args: '$(SDKVersionForBuild)'
+
- task: PowerShell@2
displayName: "Update Build Number"
inputs:
@@ -699,6 +765,13 @@ jobs:
failOnStderr: "true"
condition: "always()"
+ - task: PowerShell@2
+ displayName: "Define variables"
+ inputs:
+ targetType: "inline"
+ script: |
+ Write-Host "##vso[task.setvariable variable=PATH]${env:AGENT_TEMPDIRECTORY}/dotnet/:${env:PATH}"
+
- task: DownloadBuildArtifacts@0
displayName: "Download NuGet.CommandLine.Test artifacts"
inputs:
@@ -741,6 +814,7 @@ jobs:
timeoutInMinutes: 150
variables:
FullVstsBuildNumber: $[dependencies.Initialize_Build.outputs['updatebuildnumber.FullVstsBuildNumber']]
+ SDKVersionForBuild: $[dependencies.Initialize_Build.outputs['getSDKVersionForBuild.SDKVersionForBuild']]
condition: "and(succeeded(),eq(variables['RunEndToEndTests'], 'true')) "
pool:
name: DDNuGet-Windows
@@ -749,6 +823,19 @@ jobs:
- Allow_NuGet_E2E_Tests -equals true
steps:
+ - task: PowerShell@1
+ inputs:
+ scriptName: "$(Build.Repository.LocalPath)\\scripts\\utils\\InstallCLIforBuild.ps1"
+ arguments: '$(SDKVersionForBuild)'
+ displayName: "Install .NET 5.0 for build"
+
+ - task: PowerShell@1
+ displayName: "Define variables"
+ inputs:
+ scriptType: "inlineScript"
+ inlineScript: |
+ Write-Host "##vso[task.setvariable variable=Path]${env:AGENT_TEMPDIRECTORY}\dotnet\;${env:Path}"
+
- task: PowerShell@1
displayName: "Print Environment Variables"
inputs:
@@ -840,6 +927,7 @@ jobs:
variables:
BuildNumber: $[dependencies.Initialize_Build.outputs['updatebuildnumber.BuildNumber']]
FullVstsBuildNumber: $[dependencies.Initialize_Build.outputs['updatebuildnumber.FullVstsBuildNumber']]
+ SDKVersionForBuild: $[dependencies.Initialize_Build.outputs['getSDKVersionForBuild.SDKVersionForBuild']]
condition: "and(succeeded(),eq(variables['RunApexTests'], 'true')) "
pool:
name: DDNuGet-Windows
@@ -866,6 +954,24 @@ jobs:
artifactName: "$(VsixPublishDir)"
downloadPath: "$(Build.Repository.LocalPath)/artifacts"
+ - task: NuGetToolInstaller@0
+ displayName: "Use NuGet 4.5.0"
+ inputs:
+ versionSpec: "4.5.0"
+
+ - task: PowerShell@1
+ inputs:
+ scriptName: "$(Build.Repository.LocalPath)\\scripts\\utils\\InstallCLIforBuild.ps1"
+ arguments: '$(SDKVersionForBuild)'
+ displayName: "Install .NET 5.0 for build"
+
+ - task: PowerShell@1
+ displayName: "Define variables"
+ inputs:
+ scriptType: "inlineScript"
+ inlineScript: |
+ Write-Host "##vso[task.setvariable variable=Path]${env:AGENT_TEMPDIRECTORY}\dotnet\;${env:Path}"
+
- task: MSBuild@1
displayName: "Bootstrap NuGet packages"
inputs:
@@ -906,14 +1012,6 @@ jobs:
# $(System.DefaultWorkingDirectory)\\VSCollect.exe -zip:$(EndToEndResultsDropPath)\\apex-collectlogs.zip
# condition: "failed()"
- - task: MSBuild@1
- displayName: "Restore for VS2019"
- inputs:
- solution: "build\\build.proj"
- msbuildVersion: "16.0"
- configuration: "$(BuildConfiguration)"
- msbuildArguments: "/t:RestoreVS /p:BuildNumber=$(BuildNumber)"
-
- task: NuGetCommand@2
displayName: "Add Apex Feed Source"
inputs:
diff --git a/global.json b/global.json
new file mode 100644
index 00000000000..a32d2892027
--- /dev/null
+++ b/global.json
@@ -0,0 +1,5 @@
+{
+ "sdk": {
+ "version": "5.0.100-alpha1"
+ }
+}
\ No newline at end of file
diff --git a/scripts/funcTests/runFuncTests.sh b/scripts/funcTests/runFuncTests.sh
index 1b228bd0c28..5380ca91360 100755
--- a/scripts/funcTests/runFuncTests.sh
+++ b/scripts/funcTests/runFuncTests.sh
@@ -14,6 +14,10 @@ done
RESULTCODE=0
+# print openssl version
+echo "==================================================================================================="
+openssl version -a
+echo "==================================================================================================="
# move up to the repo root
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
DIR=$SCRIPTDIR/../..
@@ -32,33 +36,43 @@ chmod +x scripts/funcTests/dotnet-install.sh
# Get recommended version for bootstrapping testing version
# Issue 8936 - DISABLED TEMPORARILY cli/dotnet-install.sh -i cli -c 2.2
-scripts/funcTests/dotnet-install.sh -i cli -c 2.2
+scripts/funcTests/dotnet-install.sh -i cli -c 2.2 -NoPath
+# cli/dotnet-install.sh -runtime dotnet -Channel 2.2 -i cli -NoPath
DOTNET="$(pwd)/cli/dotnet"
-echo "initial dotnet cli install finished at `date -u +"%Y-%m-%dT%H:%M:%S"`"
-#restore solution packages
-$DOTNET msbuild -t:restore "$DIR/build/bootstrap.proj"
-if [ $? -ne 0 ]; then
- echo "Restore failed!!"
- exit 1
-fi
-
-echo "bootstrap project restore finished at `date -u +"%Y-%m-%dT%H:%M:%S"`"
+echo "dotnet msbuild build/config.props /v:m /nologo /t:GetCliBranchForTesting"
+
+# run it twice so dotnet cli can expand and decompress without affecting the result of the target
+dotnet msbuild build/config.props /v:m /nologo /t:GetCliBranchForTesting
+DOTNET_BRANCHES="$(dotnet msbuild build/config.props /v:m /nologo /t:GetCliBranchForTesting)"
+echo $DOTNET_BRANCHES | tr ";" "\n" | while read -r DOTNET_BRANCH
+do
+ echo $DOTNET_BRANCH
+ ChannelAndVersion=($DOTNET_BRANCH)
+ Channel=${ChannelAndVersion[0]}
+ if [ ${#ChannelAndVersion[@]} -eq 1 ]
+ then
+ Version="latest"
+ else
+ Version=${ChannelAndVersion[1]}
+ fi
+ echo "Channel is: $Channel"
+ echo "Version is: $Version"
+ scripts/funcTests/dotnet-install.sh -i cli -c $Channel -v $Version -nopath
+
+ # Display current version
+ $DOTNET --version
+ dotnet --info
+done
-echo "$DOTNET msbuild build/config.props /v:m /nologo /t:GetCliBranchForTesting"
-DOTNET_BRANCH="$($DOTNET msbuild build/config.props /v:m /nologo /t:GetCliBranchForTesting)"
+echo "initial dotnet cli install finished at `date -u +"%Y-%m-%dT%H:%M:%S"`"
-echo $DOTNET_BRANCH
-# Issue 8936 - TEMPORARILY using direct path to script
-scripts/funcTests/dotnet-install.sh -i cli -c $DOTNET_BRANCH
+echo "================="
-# Install the 2.x runtime because our tests target netcoreapp2x
-# Issue 8936 - TEMPORARILY using direct path to script
-scripts/funcTests/dotnet-install.sh -runtime dotnet -Channel 2.2 -i cli -NoPath
-# Display current version
-$DOTNET --version
+# install SDK2 runtime as we encounter problems on running dotnet vstest command when only download SDK3.
+cli/dotnet-install.sh -runtime dotnet -Channel 2.2 -i cli -NoPath
echo "Deleting .NET Core temporary files"
rm -rf "/tmp/"dotnet.*
@@ -66,6 +80,15 @@ rm -rf "/tmp/"dotnet.*
echo "second dotnet cli install finished at `date -u +"%Y-%m-%dT%H:%M:%S"`"
echo "================="
+#restore solution packages
+$DOTNET msbuild -t:restore "$DIR/build/bootstrap.proj"
+if [ $? -ne 0 ]; then
+ echo "Restore failed!!"
+ exit 1
+fi
+
+echo "bootstrap project restore finished at `date -u +"%Y-%m-%dT%H:%M:%S"`"
+
# init the repo
git submodule init
@@ -84,8 +107,8 @@ then
fi
# restore packages
-echo "$DOTNET msbuild build/build.proj /t:Restore /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta"
-$DOTNET msbuild build/build.proj /t:Restore /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta
+echo "dotnet msbuild build/build.proj /t:Restore /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta"
+dotnet msbuild build/build.proj /t:Restore /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta
if [ $? -ne 0 ]; then
echo "Restore failed!!"
exit 1
@@ -94,8 +117,8 @@ fi
echo "Restore finished at `date -u +"%Y-%m-%dT%H:%M:%S"`"
# Unit tests
-echo "$DOTNET msbuild build/build.proj /t:CoreUnitTests /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta"
-$DOTNET msbuild build/build.proj /t:CoreUnitTests /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta
+echo "dotnet msbuild build/build.proj /t:CoreUnitTests /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta"
+dotnet msbuild build/build.proj /t:CoreUnitTests /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta
if [ $? -ne 0 ]; then
echo "CoreUnitTests failed!!"
@@ -116,8 +139,8 @@ fi
echo "Core tests finished at `date -u +"%Y-%m-%dT%H:%M:%S"`"
# Func tests
-echo "$DOTNET msbuild build/build.proj /t:CoreFuncTests /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta"
-$DOTNET msbuild build/build.proj /t:CoreFuncTests /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta
+echo "dotnet msbuild build/build.proj /t:CoreFuncTests /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta"
+dotnet msbuild build/build.proj /t:CoreFuncTests /p:VisualStudioVersion=16.0 /p:Configuration=Release /p:BuildNumber=1 /p:ReleaseLabel=beta
if [ $? -ne 0 ]; then
RESULTCODE='1'
diff --git a/scripts/utils/InstallCLIforBuild.ps1 b/scripts/utils/InstallCLIforBuild.ps1
new file mode 100644
index 00000000000..c59900e911d
--- /dev/null
+++ b/scripts/utils/InstallCLIforBuild.ps1
@@ -0,0 +1,48 @@
+# Download the CLI install script to Agent.TempDirectory
+
+#Write-Host "Installing dotnet CLI into $Env:AGENT_TEMPDIRECTORY folder for building"
+
+[CmdletBinding(SupportsShouldProcess=$True)]
+Param (
+ [string]$SDKVersionForBuild
+)
+
+# Get version from SDKVersionForBuild, if only branch name specified, use the latest version for this branch
+$CliBranch = $SDKVersionForBuild.trim()
+$CliChannelAndVersion = $CliBranch -split "\s+"
+
+$Channel = $CliChannelAndVersion[0].trim()
+if ($CliChannelAndVersion.count -eq 1) {
+ $Version = 'latest'
+}else {
+ $Version = $CliChannelAndVersion[1].trim()
+}
+
+Write-Host "Channel is : $Channel Version is : $Version" -ForegroundColor Cyan
+
+$InstallDir = Join-Path $Env:AGENT_TEMPDIRECTORY 'dotnet'
+
+New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
+
+$DotNetInstall = Join-Path $InstallDir 'dotnet-install.ps1'
+
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+
+Invoke-WebRequest 'https://dot.net/v1/dotnet-install.ps1' -OutFile $DotNetInstall
+
+
+if ([Environment]::Is64BitOperatingSystem)
+{
+ $arch = "x64";
+}
+else
+{
+ $arch = "x86";
+}
+
+& $DotNetInstall -Channel $Channel -Version $Version -i $InstallDir -Architecture $arch
+
+$Env:PATH
+
+# Display build info
+& dotnet --info
\ No newline at end of file
diff --git a/scripts/utils/InstallCLIforBuild.sh b/scripts/utils/InstallCLIforBuild.sh
new file mode 100644
index 00000000000..309021a77d4
--- /dev/null
+++ b/scripts/utils/InstallCLIforBuild.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+
+# Download the CLI install script to Agent.TempDirectory
+
+env
+
+installVersion=$1
+
+echo $installVersion
+ChannelAndVersion=($installVersion)
+Channel=${ChannelAndVersion[0]}
+if [ ${#ChannelAndVersion[@]} -eq 1 ]
+then
+ Version="latest"
+else
+ Version=${ChannelAndVersion[1]}
+fi
+echo "Channel is: $Channel Version is: $Version"
+
+echo "Installing dotnet CLI into ${AGENT_TEMPDIRECTORY} folder for building"
+
+installDir="${AGENT_TEMPDIRECTORY}/dotnet"
+
+mkdir -p $installDir
+
+curl -o $installDir/dotnet-install.sh -L https://dot.net/v1/dotnet-install.sh
+
+# Run install.sh for cli
+
+chmod +x $installDir/dotnet-install.sh
+
+
+# install master channel to get latest .NET 5 sdks
+
+# Issue 8936 - DISABLED TEMPORARILY $installDir/dotnet-install.sh -i $installDir -c $Channel -v $Version
+chmod +x scripts/funcTests/dotnet-install.sh
+scripts/funcTests/dotnet-install.sh -i $installDir -c $Channel -v $Version
+#$installDir/dotnet-install.sh -i $installDir -c $Channel -v $Version
+
+echo "Add ${installDir} to PATH"
+PATH=$PATH:${installDir}
+
+echo $PATH
+
+echo "Deleting .NET Core temporary files"
+rm -rf "/tmp/"dotnet.*
+
+
+# Display current version
+
+dotnet --info
+
+
+
+echo "================="
+
diff --git a/src/NuGet.Core/Microsoft.Build.NuGetSdkResolver/Microsoft.Build.NuGetSdkResolver.csproj b/src/NuGet.Core/Microsoft.Build.NuGetSdkResolver/Microsoft.Build.NuGetSdkResolver.csproj
index 436708a75ee..64070ca2a8a 100644
--- a/src/NuGet.Core/Microsoft.Build.NuGetSdkResolver/Microsoft.Build.NuGetSdkResolver.csproj
+++ b/src/NuGet.Core/Microsoft.Build.NuGetSdkResolver/Microsoft.Build.NuGetSdkResolver.csproj
@@ -1,4 +1,8 @@
+
+ true
+
+
diff --git a/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.Sdk2x.targets b/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.Sdk2x.targets
new file mode 100644
index 00000000000..a7b505dca41
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.Sdk2x.targets
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.csproj b/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.csproj
index 53d0286ed8c..49c883a4f4d 100644
--- a/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.csproj
+++ b/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.csproj
@@ -1,4 +1,8 @@
-
+
+
+ true
+
+
@@ -39,7 +43,7 @@
-
+
@@ -150,6 +154,7 @@
+
@@ -159,20 +164,14 @@
Desktop/
-
- Desktop/
-
Desktop/
-
+
CoreCLR/
-
- CoreCLR/
-
CoreCLR/
diff --git a/src/NuGet.Core/NuGet.Build.Tasks/NuGet.Build.Tasks.csproj b/src/NuGet.Core/NuGet.Build.Tasks/NuGet.Build.Tasks.csproj
index 97323363dee..b24d9b0ef88 100644
--- a/src/NuGet.Core/NuGet.Build.Tasks/NuGet.Build.Tasks.csproj
+++ b/src/NuGet.Core/NuGet.Build.Tasks/NuGet.Build.Tasks.csproj
@@ -1,4 +1,8 @@
+
+ true
+
+
@@ -46,7 +50,7 @@
-
+
diff --git a/src/NuGet.Core/NuGet.CommandLine.XPlat/NuGet.CommandLine.XPlat.csproj b/src/NuGet.Core/NuGet.CommandLine.XPlat/NuGet.CommandLine.XPlat.csproj
index 940135ef48c..15dd5fd29f3 100644
--- a/src/NuGet.Core/NuGet.CommandLine.XPlat/NuGet.CommandLine.XPlat.csproj
+++ b/src/NuGet.Core/NuGet.CommandLine.XPlat/NuGet.CommandLine.XPlat.csproj
@@ -1,4 +1,8 @@
-
+
+
+ true
+
+
diff --git a/src/NuGet.Core/NuGet.Commands/NuGet.Commands.csproj b/src/NuGet.Core/NuGet.Commands/NuGet.Commands.csproj
index 56435222644..fdd17a2a28b 100644
--- a/src/NuGet.Core/NuGet.Commands/NuGet.Commands.csproj
+++ b/src/NuGet.Core/NuGet.Commands/NuGet.Commands.csproj
@@ -1,4 +1,8 @@
+
+ true
+
+
@@ -7,7 +11,7 @@
$(TargetFrameworksLibrary)
$(NoWarn);CS1591;CS1574;CS1573;CS1584;CS1658
- $(NoWarn);CS1998
+ $(NoWarn);CS1998
true
true
true
diff --git a/src/NuGet.Core/NuGet.Commands/SignCommand/CertificateProvider.cs b/src/NuGet.Core/NuGet.Commands/SignCommand/CertificateProvider.cs
index d22d3b8d05e..77d8e8a9a80 100644
--- a/src/NuGet.Core/NuGet.Commands/SignCommand/CertificateProvider.cs
+++ b/src/NuGet.Core/NuGet.Commands/SignCommand/CertificateProvider.cs
@@ -233,4 +233,4 @@ private static bool IsValid(X509Certificate2 certificate, X509Certificate2Collec
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Commands/TrustedSignersCommand/TrustedSignerActionsProvider.cs b/src/NuGet.Core/NuGet.Commands/TrustedSignersCommand/TrustedSignerActionsProvider.cs
index ce76f9aa0ae..56171d3440c 100644
--- a/src/NuGet.Core/NuGet.Commands/TrustedSignersCommand/TrustedSignerActionsProvider.cs
+++ b/src/NuGet.Core/NuGet.Commands/TrustedSignersCommand/TrustedSignerActionsProvider.cs
@@ -67,7 +67,7 @@ public async Task SyncTrustedRepositoryAsync(string name, CancellationToken toke
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings.Error_TrustedRepositoryDoesNotExist, name));
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// Adds a trusted signer item to the settings based a signed package.
///
@@ -257,7 +257,7 @@ private void ValidateNoExistingSigner(string name, string serviceIndex, bool val
}
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
private CertificateItem GetCertificateItemForSignature(ISignature signature, bool allowUntrustedRoot = false)
{
var defaultHashAlgorithm = HashAlgorithmName.SHA256;
diff --git a/src/NuGet.Core/NuGet.Credentials/NuGet.Credentials.csproj b/src/NuGet.Core/NuGet.Credentials/NuGet.Credentials.csproj
index da26ae78291..c5fd263a5f9 100644
--- a/src/NuGet.Core/NuGet.Credentials/NuGet.Credentials.csproj
+++ b/src/NuGet.Core/NuGet.Credentials/NuGet.Credentials.csproj
@@ -1,4 +1,8 @@
+
+ true
+
+
@@ -31,7 +35,7 @@
-
+
diff --git a/src/NuGet.Core/NuGet.DependencyResolver.Core/NuGet.DependencyResolver.Core.csproj b/src/NuGet.Core/NuGet.DependencyResolver.Core/NuGet.DependencyResolver.Core.csproj
index afbd845a8a6..c83b56fde1a 100644
--- a/src/NuGet.Core/NuGet.DependencyResolver.Core/NuGet.DependencyResolver.Core.csproj
+++ b/src/NuGet.Core/NuGet.DependencyResolver.Core/NuGet.DependencyResolver.Core.csproj
@@ -1,4 +1,8 @@
+
+ true
+
+
diff --git a/src/NuGet.Core/NuGet.Packaging/NuGet.Packaging.csproj b/src/NuGet.Core/NuGet.Packaging/NuGet.Packaging.csproj
index 08fdf73ad3d..b8dc0be568e 100644
--- a/src/NuGet.Core/NuGet.Packaging/NuGet.Packaging.csproj
+++ b/src/NuGet.Core/NuGet.Packaging/NuGet.Packaging.csproj
@@ -1,4 +1,8 @@
-
+
+
+ true
+
+
@@ -7,7 +11,7 @@
$(TargetFrameworksLibrary)
$(NoWarn);CS1591;CS1574;CS1573;CS1572
- $(NoWarn);CS0414
+ $(NoWarn);CS0414
true
true
true
@@ -45,6 +49,9 @@
+
+
+
diff --git a/src/NuGet.Core/NuGet.Packaging/PackageArchiveReader.cs b/src/NuGet.Core/NuGet.Packaging/PackageArchiveReader.cs
index 1b262a896e1..76c4233795d 100644
--- a/src/NuGet.Core/NuGet.Packaging/PackageArchiveReader.cs
+++ b/src/NuGet.Core/NuGet.Packaging/PackageArchiveReader.cs
@@ -271,7 +271,7 @@ public override async Task GetPrimarySignatureAsync(Cancellati
using (var reader = new BinaryReader(bufferedStream, new UTF8Encoding(), leaveOpen: true))
using (var stream = SignedPackageArchiveUtility.OpenPackageSignatureFileStream(reader))
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
signature = PrimarySignature.Load(stream);
#endif
}
@@ -288,18 +288,15 @@ public override Task IsSignedAsync(CancellationToken token)
var isSigned = false;
-#if IS_DESKTOP
- if (RuntimeEnvironmentHelper.IsWindows)
+#if IS_SIGNING_SUPPORTED
+ using (var zip = new ZipArchive(ZipReadStream, ZipArchiveMode.Read, leaveOpen: true))
{
- using (var zip = new ZipArchive(ZipReadStream, ZipArchiveMode.Read, leaveOpen: true))
- {
- var signatureEntry = zip.GetEntry(SigningSpecifications.SignaturePath);
+ var signatureEntry = zip.GetEntry(SigningSpecifications.SignaturePath);
- if (signatureEntry != null &&
- string.Equals(signatureEntry.Name, SigningSpecifications.SignaturePath, StringComparison.Ordinal))
- {
- isSigned = true;
- }
+ if (signatureEntry != null &&
+ string.Equals(signatureEntry.Name, SigningSpecifications.SignaturePath, StringComparison.Ordinal))
+ {
+ isSigned = true;
}
}
#endif
@@ -322,7 +319,7 @@ public override async Task ValidateIntegrityAsync(SignatureContent signatureCont
throw new SignatureException(Strings.SignedPackageNotSignedOnVerify);
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using (var bufferedStream = new ReadOnlyBufferedStream(ZipReadStream, leaveOpen: true))
using (var reader = new BinaryReader(bufferedStream, new UTF8Encoding(), leaveOpen: true))
using (var hashAlgorithm = signatureContent.HashAlgorithm.GetHashProvider())
@@ -383,8 +380,8 @@ public override Task GetArchiveHashAsync(HashAlgorithmName hashAlgorithm
public override bool CanVerifySignedPackages(SignedPackageVerifierSettings verifierSettings)
{
-#if IS_DESKTOP
- return RuntimeEnvironmentHelper.IsWindows && !RuntimeEnvironmentHelper.IsMono;
+#if IS_SIGNING_SUPPORTED
+ return true;
#else
return false;
#endif
@@ -425,4 +422,4 @@ private string GetContentHashForSignedPackage(CancellationToken token)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Archive/SignedPackageArchiveIOUtility.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Archive/SignedPackageArchiveIOUtility.cs
index b186a53dadd..eaaea961af3 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Archive/SignedPackageArchiveIOUtility.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Archive/SignedPackageArchiveIOUtility.cs
@@ -70,8 +70,6 @@ public static void ReadAndWriteUntilPosition(BinaryReader reader, BinaryWriter w
/// Read bytes from a BinaryReader and hash them with a given HashAlgorithm and stop when the provided position
/// is the current position of the BinaryReader's base stream. It does not hash the byte in the provided position.
///
- /// TODO: Once we start supporting signing in Net core, then we should move to another ReadAndHashUntilPosition api which takes Sha512HashFunction which is wrapper
- /// over HashAlgorithm and works for desktop as well as net core.
///
/// Read bytes from this stream
/// HashAlgorithm used to hash contents
@@ -111,8 +109,6 @@ public static void ReadAndHashUntilPosition(BinaryReader reader, HashAlgorithm h
///
/// Hashes given byte array with a specified HashAlgorithm
///
- /// TODO: Once we start supporting signing in Net core, then we should move to another HashBytes api which takes Sha512HashFunction which is wrapper
- /// over HashAlgorithm and works for desktop as well as net core.
///
/// HashAlgorithm used to hash contents
/// Content to hash
@@ -127,11 +123,8 @@ public static void HashBytes(HashAlgorithm hashAlgorithm, byte[] bytes)
{
throw new ArgumentException(Strings.ArgumentCannotBeNullOrEmpty, nameof(bytes));
}
-#if IS_DESKTOP
+
hashAlgorithm.TransformBlock(bytes, 0, bytes.Length, outputBuffer: null, outputOffset: 0);
-#else
- throw new NotImplementedException();
-#endif
}
@@ -798,4 +791,4 @@ private static uint DateTimeToDosTime(DateTime dateTime)
return (uint)ret;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Archive/SignedPackageArchiveUtility.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Archive/SignedPackageArchiveUtility.cs
index 0a51756df99..629c14744cc 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Archive/SignedPackageArchiveUtility.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Archive/SignedPackageArchiveUtility.cs
@@ -8,7 +8,7 @@
using System.IO;
using System.Linq;
using System.Security.Cryptography;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
using System.Text;
@@ -226,7 +226,7 @@ private static bool HasZip64ExtendedInformationExtraField(LocalFileHeader header
return false;
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// Removes repository primary signature (if it exists) or any repository countersignature (if it exists).
///
@@ -407,8 +407,6 @@ internal static void UnsignZip(BinaryReader reader, BinaryWriter writer)
///
/// Verifies that a signed package archive's signature is valid and it has not been tampered with.
///
- /// TODO: When we work to support signing for netcore then we should use GetPackageContentHash api to calculate package hash
- /// which works for desktop as well as netcore.
///
/// Signed package to verify
/// Hash algorithm to be used to hash data.
@@ -635,4 +633,4 @@ private static bool CompareHash(byte[] expectedHash, byte[] actualHash)
return true;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/ISignatureProvider.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/ISignatureProvider.cs
index 5667abaf8e6..a19b986df4e 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/ISignatureProvider.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/ISignatureProvider.cs
@@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using NuGet.Common;
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/SignPackageRequest.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/SignPackageRequest.cs
index db19f8c3887..f855442fe7d 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/SignPackageRequest.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/SignPackageRequest.cs
@@ -41,7 +41,7 @@ public abstract class SignPackageRequest : IDisposable
internal IX509CertificateChain Chain { get; private set; }
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// PrivateKey is only used in mssign command.
///
@@ -86,7 +86,7 @@ public void Dispose()
Certificate?.Dispose();
Chain?.Dispose();
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
PrivateKey?.Dispose();
#endif
@@ -108,4 +108,4 @@ internal void BuildSigningCertificateChainOnce(ILogger logger)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/X509SignatureProvider.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/X509SignatureProvider.cs
index ee1eed07fc9..7f7a4090a05 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/X509SignatureProvider.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Authoring/X509SignatureProvider.cs
@@ -8,7 +8,7 @@
using System.Threading.Tasks;
using NuGet.Common;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
#endif
@@ -97,7 +97,7 @@ public Task CreateRepositoryCountersignatureAsync(RepositorySi
}
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
private static PrimarySignature CreatePrimarySignature(SignPackageRequest request, SignatureContent signatureContent, ILogger logger)
{
var cmsSigner = SigningUtility.CreateCmsSigner(request, logger);
@@ -152,11 +152,11 @@ private static PrimarySignature CreatePrimarySignature(CmsSigner cmsSigner, Sign
private static PrimarySignature CreateRepositoryCountersignature(CmsSigner cmsSigner, PrimarySignature primarySignature, CngKey privateKey)
{
- using (var primarySignatureNativeCms = NativeCms.Decode(primarySignature.GetBytes()))
+ using (ICms primarySignatureCms = CmsFactory.Create(primarySignature.GetBytes()))
{
- primarySignatureNativeCms.AddCountersignature(cmsSigner, privateKey);
+ primarySignatureCms.AddCountersignature(cmsSigner, privateKey);
- var bytes = primarySignatureNativeCms.Encode();
+ var bytes = primarySignatureCms.Encode();
var updatedCms = new SignedCms();
updatedCms.Decode(bytes);
@@ -239,4 +239,4 @@ private Task TimestampRepositoryCountersignatureAsync(SignPack
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Cms/CmsFactory.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/CmsFactory.cs
new file mode 100644
index 00000000000..88d698f80be
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/CmsFactory.cs
@@ -0,0 +1,34 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Security.Cryptography;
+using System.Security.Cryptography.Pkcs;
+
+namespace NuGet.Packaging.Signing
+{
+ internal static class CmsFactory
+ {
+ internal static ICms Create(byte[] cmsBytes)
+ {
+ if (cmsBytes == null)
+ {
+ throw new ArgumentNullException(nameof(cmsBytes));
+ }
+#if IS_SIGNING_SUPPORTED
+ ICms cms = null;
+#if IS_DESKTOP
+ NativeCms nativeCms = NativeCms.Decode(cmsBytes);
+ cms = new NativeCmsWrapper(nativeCms);
+#else
+ SignedCms signedCms = new SignedCms();
+ signedCms.Decode(cmsBytes);
+ cms = new ManagedCmsWrapper(signedCms);
+#endif
+ return cms;
+#else
+ throw new NotSupportedException();
+#endif
+ }
+ }
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Native/HeapBlockRetainer.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/HeapBlockRetainer.cs
similarity index 100%
rename from src/NuGet.Core/NuGet.Packaging/Signing/Native/HeapBlockRetainer.cs
rename to src/NuGet.Core/NuGet.Packaging/Signing/Cms/HeapBlockRetainer.cs
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Cms/ICms.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/ICms.cs
new file mode 100644
index 00000000000..e05fedb835b
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/ICms.cs
@@ -0,0 +1,28 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Security.Cryptography.Pkcs;
+using System.Security.Cryptography.X509Certificates;
+
+namespace NuGet.Packaging.Signing
+{
+ internal interface ICms : IDisposable
+ {
+ byte[] GetPrimarySignatureSignatureValue();
+
+ byte[] GetRepositoryCountersignatureSignatureValue();
+
+ void AddCertificates(IEnumerable certificates);
+
+ void AddCountersignature(CmsSigner cmsSigner, CngKey privateKey);
+
+ void AddTimestampToRepositoryCountersignature(SignedCms timestamp);
+
+ void AddTimestamp(SignedCms timestamp);
+
+ byte[] Encode();
+ }
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Cms/ManagedCmsWrapper.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/ManagedCmsWrapper.cs
new file mode 100644
index 00000000000..43919669f58
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/ManagedCmsWrapper.cs
@@ -0,0 +1,107 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Security.Cryptography.Pkcs;
+using System.Security.Cryptography.X509Certificates;
+using NuGet.Common;
+
+namespace NuGet.Packaging.Signing
+{
+#if IS_SIGNING_SUPPORTED && IS_CORECLR
+ internal sealed class ManagedCmsWrapper : ICms
+ {
+ private readonly SignedCms _signedCms;
+
+ public ManagedCmsWrapper(SignedCms signedCms)
+ {
+ _signedCms = signedCms;
+ }
+
+ public byte[] GetPrimarySignatureSignatureValue()
+ {
+ if (_signedCms.SignerInfos.Count != 1)
+ {
+ throw new SignatureException(NuGetLogCode.NU3009, Strings.Error_NotOnePrimarySignature);
+ }
+
+ return _signedCms.SignerInfos[0].GetSignature();
+ }
+
+ public byte[] GetRepositoryCountersignatureSignatureValue()
+ {
+ if (_signedCms.SignerInfos.Count != 1)
+ {
+ throw new SignatureException(NuGetLogCode.NU3009, Strings.Error_NotOnePrimarySignature);
+ }
+ else if (_signedCms.SignerInfos[0].CounterSignerInfos.Count == 0)
+ {
+ return null;
+ }
+
+ return _signedCms.SignerInfos[0].CounterSignerInfos[0].GetSignature();
+ }
+
+ public void AddCertificates(IEnumerable certificates)
+ {
+ foreach (var cert in certificates)
+ {
+ _signedCms.AddCertificate(new X509Certificate2(cert));
+ }
+ }
+
+ public void AddCountersignature(CmsSigner cmsSigner, CngKey privateKey)
+ {
+ if (_signedCms.SignerInfos.Count != 1)
+ {
+ throw new SignatureException(NuGetLogCode.NU3009, Strings.Error_NotOnePrimarySignature);
+ }
+
+ _signedCms.SignerInfos[0].ComputeCounterSignature(cmsSigner);
+ }
+
+ public void AddTimestampToRepositoryCountersignature(SignedCms timestamp)
+ {
+ var bytes = timestamp.Encode();
+
+ var unsignedAttribute = new AsnEncodedData(Oids.SignatureTimeStampTokenAttribute, bytes);
+
+ if (_signedCms.SignerInfos.Count != 1)
+ {
+ throw new SignatureException(NuGetLogCode.NU3009, Strings.Error_NotOnePrimarySignature);
+ }
+ else if (_signedCms.SignerInfos[0].CounterSignerInfos.Count != 1)
+ {
+ throw new SignatureException(Strings.Error_NotOneRepositoryCounterSignature);
+ }
+
+ _signedCms.SignerInfos[0].CounterSignerInfos[0].AddUnsignedAttribute(unsignedAttribute);
+ }
+
+ public void AddTimestamp(SignedCms timestamp)
+ {
+ var bytes = timestamp.Encode();
+
+ var unsignedAttribute = new AsnEncodedData(Oids.SignatureTimeStampTokenAttribute, bytes);
+
+ if (_signedCms.SignerInfos.Count != 1)
+ {
+ throw new SignatureException(NuGetLogCode.NU3009, Strings.Error_NotOnePrimarySignature);
+ }
+
+ _signedCms.SignerInfos[0].AddUnsignedAttribute(unsignedAttribute);
+ }
+
+ public byte[] Encode()
+ {
+ return _signedCms.Encode();
+ }
+
+ public void Dispose()
+ {
+ }
+ }
+#endif
+}
+
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Native/NativeCms.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeCms.cs
similarity index 96%
rename from src/NuGet.Core/NuGet.Packaging/Signing/Native/NativeCms.cs
rename to src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeCms.cs
index 9ec63ab503c..793a0d9f60a 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Native/NativeCms.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeCms.cs
@@ -3,12 +3,13 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Runtime.InteropServices;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
#endif
-using NuGet.Common;
+using System.Security.Cryptography.X509Certificates;
namespace NuGet.Packaging.Signing
@@ -232,17 +233,18 @@ internal static NativeCms Decode(byte[] input)
return new NativeCms(handle);
}
- internal void AddCertificates(IEnumerable encodedCertificates)
+ internal void AddCertificates(IEnumerable certificates)
{
- foreach (var cert in encodedCertificates)
+ foreach (var cert in certificates)
{
+ byte[] encodedCert = cert.RawData;
using (var hb = new HeapBlockRetainer())
{
- var unmanagedCert = hb.Alloc(cert.Length);
- Marshal.Copy(cert, 0, unmanagedCert, cert.Length);
+ var unmanagedCert = hb.Alloc(encodedCert.Length);
+ Marshal.Copy(encodedCert, 0, unmanagedCert, encodedCert.Length);
var blob = new CRYPT_INTEGER_BLOB()
{
- cbData = (uint)cert.Length,
+ cbData = (uint)encodedCert.Length,
pbData = unmanagedCert
};
@@ -260,7 +262,8 @@ internal void AddCertificates(IEnumerable encodedCertificates)
}
}
}
-#if IS_DESKTOP
+
+#if IS_SIGNING_SUPPORTED
internal unsafe void AddCountersignature(CmsSigner cmsSigner, CngKey privateKey)
{
using (var hb = new HeapBlockRetainer())
@@ -273,12 +276,10 @@ internal unsafe void AddCountersignature(CmsSigner cmsSigner, CngKey privateKey)
cCountersigners: 1,
rgCountersigners: signerInfo));
- AddCertificates(CertificateUtility.GetRawDataForCollection(cmsSigner.Certificates));
+ AddCertificates(cmsSigner.Certificates.OfType());
}
}
-#endif
-#if IS_DESKTOP
internal unsafe void AddTimestampToRepositoryCountersignature(SignedCms timestamp)
{
using (var hb = new HeapBlockRetainer())
@@ -510,7 +511,10 @@ internal byte[] Encode()
public void Dispose()
{
- _handle.Dispose();
+ if (!_handle.IsInvalid)
+ {
+ _handle.Dispose();
+ }
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeCmsWrapper.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeCmsWrapper.cs
new file mode 100644
index 00000000000..e06706b739f
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeCmsWrapper.cs
@@ -0,0 +1,63 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Security.Cryptography.Pkcs;
+using System.Security.Cryptography.X509Certificates;
+
+namespace NuGet.Packaging.Signing
+{
+#if IS_SIGNING_SUPPORTED && IS_DESKTOP
+ internal sealed class NativeCmsWrapper : ICms
+ {
+ private readonly NativeCms _nativeCms;
+
+ public NativeCmsWrapper(NativeCms nativeCms)
+ {
+ _nativeCms = nativeCms;
+ }
+
+ public byte[] GetPrimarySignatureSignatureValue()
+ {
+ return _nativeCms.GetPrimarySignatureSignatureValue();
+ }
+
+ public byte[] GetRepositoryCountersignatureSignatureValue()
+ {
+ return _nativeCms.GetRepositoryCountersignatureSignatureValue();
+ }
+
+ public void AddCertificates(IEnumerable certificates)
+ {
+ _nativeCms.AddCertificates(certificates);
+ }
+
+ public void AddCountersignature(CmsSigner cmsSigner, CngKey privateKey)
+ {
+ _nativeCms.AddCountersignature(cmsSigner, privateKey);
+ }
+
+ public void AddTimestampToRepositoryCountersignature(SignedCms timestamp)
+ {
+ _nativeCms.AddTimestampToRepositoryCountersignature(timestamp);
+ }
+
+ public void AddTimestamp(SignedCms timestamp)
+ {
+ _nativeCms.AddTimestamp(timestamp);
+ }
+
+ public byte[] Encode()
+ {
+ return _nativeCms.Encode();
+ }
+
+ public void Dispose()
+ {
+ _nativeCms.Dispose();
+ }
+ }
+#endif
+}
+
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Native/NativeMethods.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeMethods.cs
similarity index 100%
rename from src/NuGet.Core/NuGet.Packaging/Signing/Native/NativeMethods.cs
rename to src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeMethods.cs
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Native/NativeUtility.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeUtility.cs
similarity index 99%
rename from src/NuGet.Core/NuGet.Packaging/Signing/Native/NativeUtility.cs
rename to src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeUtility.cs
index 498baeddae0..9c49d0a5e9e 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Native/NativeUtility.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Cms/NativeUtility.cs
@@ -3,7 +3,7 @@
using System;
using System.Runtime.InteropServices;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
#endif
@@ -28,7 +28,7 @@ internal static void ThrowIfFailed(bool result)
}
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
internal static SignedCms NativeSign(CmsSigner cmsSigner, byte[] data, CngKey privateKey)
{
using (var hb = new HeapBlockRetainer())
@@ -206,4 +206,4 @@ internal unsafe static CMSG_SIGNER_ENCODE_INFO CreateSignerInfo(
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Package/ISignedPackageWriter.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Package/ISignedPackageWriter.cs
index d7e12e5620a..d8fcaf2cd43 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Package/ISignedPackageWriter.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Package/ISignedPackageWriter.cs
@@ -14,7 +14,7 @@ namespace NuGet.Packaging.Signing
///
public interface ISignedPackageWriter
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// Removes a signature if it exists.
///
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/AuthorPrimarySignature.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/AuthorPrimarySignature.cs
index f3e3a9dad97..92d94b5ccc8 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/AuthorPrimarySignature.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/AuthorPrimarySignature.cs
@@ -4,7 +4,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
#endif
@@ -14,8 +14,7 @@ namespace NuGet.Packaging.Signing
{
public sealed class AuthorPrimarySignature : PrimarySignature
{
-#if IS_DESKTOP
-
+#if IS_SIGNING_SUPPORTED
public AuthorPrimarySignature(SignedCms signedCms)
: base(signedCms, SignatureType.Author)
{
@@ -46,4 +45,4 @@ public override SignatureVerificationSummary Verify(
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/IRepositorySignature.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/IRepositorySignature.cs
index 5484db85993..0d1b8bd8352 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/IRepositorySignature.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/IRepositorySignature.cs
@@ -8,7 +8,7 @@ namespace NuGet.Packaging.Signing
{
public interface IRepositorySignature : ISignature
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
Uri V3ServiceIndexUrl { get; }
IReadOnlyList PackageOwners { get; }
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/ISignature.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/ISignature.cs
index 6d8dd83e3e4..78f91b437de 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/ISignature.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/ISignature.cs
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
@@ -9,7 +9,7 @@ namespace NuGet.Packaging.Signing
{
public interface ISignature
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
SignatureType Type { get; }
SignerInfo SignerInfo { get; }
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/PrimarySignature.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/PrimarySignature.cs
index a3c72454f90..5ae8a65f7c6 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/PrimarySignature.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/PrimarySignature.cs
@@ -4,7 +4,7 @@
using System;
using System.IO;
using System.Security.Cryptography;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
using NuGet.Common;
@@ -13,7 +13,7 @@ namespace NuGet.Packaging.Signing
{
public abstract class PrimarySignature : Signature
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// A SignedCms object holding the signature and SignerInfo.
///
@@ -105,9 +105,9 @@ public static PrimarySignature Load(Stream stream)
public override byte[] GetSignatureValue()
{
- using (var nativeCms = NativeCms.Decode(SignedCms.Encode()))
+ using (ICms cms = CmsFactory.Create(SignedCms.Encode()))
{
- return nativeCms.GetPrimarySignatureSignatureValue();
+ return cms.GetPrimarySignatureSignatureValue();
}
}
@@ -128,7 +128,6 @@ protected static void ThrowForInvalidPrimarySignature()
throw new SignatureException(NuGetLogCode.NU3011, Strings.InvalidPrimarySignature);
}
-
private static void VerifySigningCertificate(
SignedCms signedCms,
SignerInfo signerInfo,
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/PrimarySignatureFactory.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/PrimarySignatureFactory.cs
index 9996b73d86e..7ba4392cb3e 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/PrimarySignatureFactory.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/PrimarySignatureFactory.cs
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
using NuGet.Common;
#endif
@@ -10,7 +10,7 @@ namespace NuGet.Packaging.Signing
{
public static class PrimarySignatureFactory
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
public static PrimarySignature CreateSignature(SignedCms signedCms)
{
var signatureType = AttributeUtility.GetSignatureType(signedCms.SignerInfos[0].SignedAttributes);
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/RepositoryCountersignature.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/RepositoryCountersignature.cs
index 6ec17d963c3..bb4ad146ce9 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/RepositoryCountersignature.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/RepositoryCountersignature.cs
@@ -5,7 +5,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
#endif
@@ -15,7 +15,7 @@ namespace NuGet.Packaging.Signing
{
public sealed class RepositoryCountersignature : Signature, IRepositorySignature
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
private readonly PrimarySignature _primarySignature;
public Uri V3ServiceIndexUrl { get; }
@@ -78,9 +78,9 @@ public static RepositoryCountersignature GetRepositoryCountersignature(PrimarySi
public override byte[] GetSignatureValue()
{
- using (var nativeCms = NativeCms.Decode(_primarySignature.GetBytes()))
+ using (ICms cms = CmsFactory.Create(_primarySignature.GetBytes()))
{
- return nativeCms.GetRepositoryCountersignatureSignatureValue();
+ return cms.GetRepositoryCountersignatureSignatureValue();
}
}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/RepositoryPrimarySignature.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/RepositoryPrimarySignature.cs
index 975c3ba559d..b1dd3fecf9d 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/RepositoryPrimarySignature.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/RepositoryPrimarySignature.cs
@@ -5,7 +5,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
#endif
@@ -15,7 +15,7 @@ namespace NuGet.Packaging.Signing
{
public sealed class RepositoryPrimarySignature : PrimarySignature, IRepositorySignature
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
public Uri V3ServiceIndexUrl { get; }
public IReadOnlyList PackageOwners { get; }
@@ -57,4 +57,4 @@ public override SignatureVerificationSummary Verify(
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/Signature.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/Signature.cs
index 2ad15893563..d61d62426f5 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/Signature.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/Signature.cs
@@ -5,7 +5,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
@@ -20,7 +20,7 @@ namespace NuGet.Packaging.Signing
///
public abstract class Signature : ISignature
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
private readonly Lazy> _timestamps;
///
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/UnknownPrimarySignature.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/UnknownPrimarySignature.cs
index 3b3e943c019..96e473da74c 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/UnknownPrimarySignature.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Signatures/UnknownPrimarySignature.cs
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
@@ -9,7 +9,7 @@ namespace NuGet.Packaging.Signing
{
public sealed class UnknownPrimarySignature : PrimarySignature
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
public UnknownPrimarySignature(SignedCms signedCms)
: base(signedCms, SignatureType.Unknown)
{
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/IRfc3161TimestampRequest.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/IRfc3161TimestampRequest.cs
new file mode 100644
index 00000000000..5c0b661cdee
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/IRfc3161TimestampRequest.cs
@@ -0,0 +1,13 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Threading.Tasks;
+
+namespace NuGet.Packaging.Signing
+{
+ internal interface IRfc3161TimestampRequest
+ {
+ Task SubmitRequestAsync(Uri timestampUri, TimeSpan timeout);
+ }
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/IRfc3161TimestampToken.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/IRfc3161TimestampToken.cs
new file mode 100644
index 00000000000..c6f381483b4
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/IRfc3161TimestampToken.cs
@@ -0,0 +1,17 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Security.Cryptography.Pkcs;
+
+namespace NuGet.Packaging.Signing
+{
+ internal interface IRfc3161TimestampToken
+ {
+#if IS_SIGNING_SUPPORTED
+ IRfc3161TimestampTokenInfo TokenInfo { get; }
+
+ SignedCms AsSignedCms();
+#endif
+ }
+}
+
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/IRfc3161TimestampTokenInfo.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/IRfc3161TimestampTokenInfo.cs
new file mode 100644
index 00000000000..d38f39bf25f
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/IRfc3161TimestampTokenInfo.cs
@@ -0,0 +1,25 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Security.Cryptography;
+
+namespace NuGet.Packaging.Signing
+{
+ internal interface IRfc3161TimestampTokenInfo
+ {
+#if IS_SIGNING_SUPPORTED
+ string PolicyId { get; }
+
+ DateTimeOffset Timestamp { get; }
+
+ long? AccuracyInMicroseconds { get; }
+
+ Oid HashAlgorithmId { get; }
+
+ bool HasMessageHash(byte[] hash);
+
+ byte[] GetNonce();
+#endif
+ }
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampProvider.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampProvider.cs
index 09b8d6bbced..e5494db1b57 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampProvider.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampProvider.cs
@@ -7,7 +7,7 @@
using System.Linq;
using System.Security.Cryptography;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
@@ -26,11 +26,11 @@ public class Rfc3161TimestampProvider : ITimestampProvider
{
// Url to an RFC 3161 timestamp server
private readonly Uri _timestamperUrl;
- private const int _rfc3161RequestTimeoutSeconds = 10;
+ private static readonly TimeSpan RequestTimeout = TimeSpan.FromSeconds(10);
public Rfc3161TimestampProvider(Uri timeStampServerUrl)
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
// Uri.UriSchemeHttp and Uri.UriSchemeHttps are not available in netstandard 1.3
if (!string.Equals(timeStampServerUrl.Scheme, Uri.UriSchemeHttp, StringComparison.Ordinal) &&
!string.Equals(timeStampServerUrl.Scheme, Uri.UriSchemeHttps, StringComparison.Ordinal))
@@ -46,32 +46,32 @@ public Rfc3161TimestampProvider(Uri timeStampServerUrl)
_timestamperUrl = timeStampServerUrl ?? throw new ArgumentNullException(nameof(timeStampServerUrl));
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// Timestamps data present in the TimestampRequest.
///
- public Task TimestampSignatureAsync(PrimarySignature primarySignature, TimestampRequest request, ILogger logger, CancellationToken token)
+ public async Task TimestampSignatureAsync(PrimarySignature primarySignature, TimestampRequest request, ILogger logger, CancellationToken token)
{
- var timestampCms = GetTimestamp(request, logger, token);
- using (var signatureNativeCms = NativeCms.Decode(primarySignature.GetBytes()))
+ SignedCms timestampCms = await GetTimestampAsync(request, logger, token);
+ using (ICms signatureCms = CmsFactory.Create(primarySignature.GetBytes()))
{
if (request.Target == SignaturePlacement.Countersignature)
{
- signatureNativeCms.AddTimestampToRepositoryCountersignature(timestampCms);
+ signatureCms.AddTimestampToRepositoryCountersignature(timestampCms);
}
else
{
- signatureNativeCms.AddTimestamp(timestampCms);
+ signatureCms.AddTimestamp(timestampCms);
}
- return Task.FromResult(PrimarySignature.Load(signatureNativeCms.Encode()));
+ return PrimarySignature.Load(signatureCms.Encode());
}
}
///
/// Timestamps data present in the TimestampRequest.
///
- public SignedCms GetTimestamp(TimestampRequest request, ILogger logger, CancellationToken token)
+ public async Task GetTimestampAsync(TimestampRequest request, ILogger logger, CancellationToken token)
{
token.ThrowIfCancellationRequested();
@@ -87,17 +87,19 @@ public SignedCms GetTimestamp(TimestampRequest request, ILogger logger, Cancella
// Allows us to track the request.
var nonce = GenerateNonce();
- var rfc3161TimestampRequest = new Rfc3161TimestampRequest(
+ var rfc3161TimestampRequest = Rfc3161TimestampRequestFactory.Create(
request.HashedMessage,
request.HashAlgorithm.ConvertToSystemSecurityHashAlgorithmName(),
+ requestedPolicyId: null,
nonce: nonce,
- requestSignerCertificates: true);
+ requestSignerCertificates: true,
+ extensions: null);
// Request a timestamp
// The response status need not be checked here as lower level api will throw if the response is invalid
- var timestampToken = rfc3161TimestampRequest.SubmitRequest(
+ IRfc3161TimestampToken timestampToken = await rfc3161TimestampRequest.SubmitRequestAsync(
_timestamperUrl,
- TimeSpan.FromSeconds(_rfc3161RequestTimeoutSeconds));
+ RequestTimeout);
// quick check for response validity
ValidateTimestampResponse(nonce, request.HashedMessage, timestampToken);
@@ -124,16 +126,15 @@ public SignedCms GetTimestamp(TimestampRequest request, ILogger logger, Cancella
}
private static SignedCms EnsureCertificatesInCertificatesCollection(
- SignedCms timestampCms,
+ SignedCms timestamp,
IReadOnlyList chain)
{
- using (var timestampNativeCms = NativeCms.Decode(timestampCms.Encode()))
+ using (ICms timestampCms = CmsFactory.Create(timestamp.Encode()))
{
- timestampNativeCms.AddCertificates(
- chain.Where(certificate => !timestampCms.Certificates.Contains(certificate))
- .Select(certificate => certificate.RawData));
+ timestampCms.AddCertificates(
+ chain.Where(certificate => !timestamp.Certificates.Contains(certificate)));
- var bytes = timestampNativeCms.Encode();
+ var bytes = timestampCms.Encode();
var updatedCms = new SignedCms();
updatedCms.Decode(bytes);
@@ -142,7 +143,7 @@ private static SignedCms EnsureCertificatesInCertificatesCollection(
}
}
- private static void ValidateTimestampCms(SigningSpecifications spec, SignedCms timestampCms, Rfc3161TimestampToken timestampToken)
+ private static void ValidateTimestampCms(SigningSpecifications spec, SignedCms timestampCms, IRfc3161TimestampToken timestampToken)
{
var signerInfo = timestampCms.SignerInfos[0];
try
@@ -203,7 +204,7 @@ private static void ValidateTimestampCms(SigningSpecifications spec, SignedCms t
}
}
- private static void ValidateTimestampResponse(byte[] nonce, byte[] messageHash, Rfc3161TimestampToken timestampToken)
+ private static void ValidateTimestampResponse(byte[] nonce, byte[] messageHash, IRfc3161TimestampToken timestampToken)
{
if (!nonce.SequenceEqual(timestampToken.TokenInfo.GetNonce()))
{
@@ -233,6 +234,17 @@ private static byte[] GenerateNonce()
rng.GetBytes(nonce);
}
+ EnsureValidNonce(nonce);
+
+ return nonce;
+ }
+
+ ///
+ /// Non-private for testing purposes only.
+ ///
+ internal static void EnsureValidNonce(byte[] nonce)
+ {
+#if IS_DESKTOP
// Eventually, CryptEncodeObjectEx(...) is called on a CRYPT_TIMESTAMP_REQUEST with this nonce,
// and CryptEncodeObjectEx(...) interprets the nonce as a little endian, DER-encoded integer value
// (without tag and length), and may even strip leading bytes from the big endian representation
@@ -247,8 +259,12 @@ private static byte[] GenerateNonce()
nonce[nonce.Length - 1] &= 0x7f;
nonce[nonce.Length - 1] |= 0x01;
-
- return nonce;
+#else
+ // Per documentation on Rfc3161TimestampRequest.CreateFromHash(...) the nonce "value is interpreted
+ // as an unsigned big-endian integer and may be normalized to the encoding format." Clear the sign bit on
+ // the most significant byte to ensure the nonce represents an unsigned big endian integer.
+ nonce[0] &= 0x7f;
+#endif
}
#else
@@ -262,4 +278,4 @@ public Task TimestampSignatureAsync(PrimarySignature primarySi
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequest.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequest.cs
index 4ae973efcc5..2a84e39ba69 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequest.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequest.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
@@ -180,7 +179,7 @@ public Rfc3161TimestampRequest(
public X509ExtensionCollection GetExtensions() =>
Rfc3161TimestampTokenInfo.ShallowCopy(Data._extensions, preserveNull: false);
- public unsafe Rfc3161TimestampToken SubmitRequest(Uri timestampUri, TimeSpan timeout)
+ public unsafe IRfc3161TimestampToken SubmitRequest(Uri timestampUri, TimeSpan timeout)
{
if (timestampUri == null)
throw new ArgumentNullException(nameof(timestampUri));
@@ -239,7 +238,7 @@ public unsafe Rfc3161TimestampToken SubmitRequest(Uri timestampUri, TimeSpan tim
byte[] encoded = new byte[content.cbEncoded];
Marshal.Copy(content.pbEncoded, encoded, 0, content.cbEncoded);
- Rfc3161TimestampTokenInfo tstInfo = new Rfc3161TimestampTokenInfo(pTsContext);
+ var tstInfo = new Rfc3161TimestampTokenInfoNet472Wrapper(new Rfc3161TimestampTokenInfo(pTsContext));
X509Certificate2 signerCert = new X509Certificate2(pTsSigner);
using (X509Store extraCerts = new X509Store(hStore))
@@ -254,7 +253,7 @@ public unsafe Rfc3161TimestampToken SubmitRequest(Uri timestampUri, TimeSpan tim
}
}
- return new Rfc3161TimestampToken(
+ return Rfc3161TimestampTokenFactory.Create(
tstInfo,
signerCert,
additionalCertsColl,
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequestFactory.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequestFactory.cs
new file mode 100644
index 00000000000..3e291d7bb40
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequestFactory.cs
@@ -0,0 +1,49 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+
+namespace NuGet.Packaging.Signing
+{
+ internal sealed class Rfc3161TimestampRequestFactory
+ {
+ public static IRfc3161TimestampRequest Create(
+ byte[] messageHash,
+ HashAlgorithmName hashAlgorithm,
+ Oid requestedPolicyId,
+ byte[] nonce,
+ bool requestSignerCertificates,
+ X509ExtensionCollection extensions)
+ {
+ if (messageHash == null)
+ {
+ throw new ArgumentNullException(nameof(messageHash));
+ }
+#if IS_SIGNING_SUPPORTED
+ IRfc3161TimestampRequest iRfc3161TimestampRequest = null;
+#if IS_DESKTOP
+ iRfc3161TimestampRequest = new Rfc3161TimestampRequestNet472Wrapper(
+ messageHash,
+ hashAlgorithm,
+ requestedPolicyId,
+ nonce,
+ requestSignerCertificates,
+ extensions);
+#else
+ iRfc3161TimestampRequest = new Rfc3161TimestampRequestNetstandard21Wrapper(
+ messageHash,
+ hashAlgorithm,
+ requestedPolicyId,
+ nonce,
+ requestSignerCertificates,
+ extensions);
+#endif
+ return iRfc3161TimestampRequest;
+#else
+ throw new NotSupportedException();
+#endif
+ }
+ }
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequestNet472Wrapper.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequestNet472Wrapper.cs
new file mode 100644
index 00000000000..3df66efde6a
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequestNet472Wrapper.cs
@@ -0,0 +1,39 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Threading.Tasks;
+
+namespace NuGet.Packaging.Signing
+{
+#if IS_SIGNING_SUPPORTED && IS_DESKTOP
+ internal sealed class Rfc3161TimestampRequestNet472Wrapper : IRfc3161TimestampRequest
+ {
+ private readonly Rfc3161TimestampRequest _rfc3161TimestampRequest;
+
+ public Rfc3161TimestampRequestNet472Wrapper(
+ byte[] messageHash,
+ HashAlgorithmName hashAlgorithm,
+ Oid requestedPolicyId,
+ byte[] nonce,
+ bool requestSignerCertificates,
+ X509ExtensionCollection extensions)
+ {
+ _rfc3161TimestampRequest = new Rfc3161TimestampRequest(
+ messageHash,
+ hashAlgorithm,
+ requestedPolicyId,
+ nonce,
+ requestSignerCertificates,
+ extensions);
+ }
+
+ public Task SubmitRequestAsync(Uri timestampUri, TimeSpan timeout)
+ {
+ return Task.FromResult(_rfc3161TimestampRequest.SubmitRequest(timestampUri, timeout));
+ }
+ }
+#endif
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequestNetstandard21Wrapper.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequestNetstandard21Wrapper.cs
new file mode 100644
index 00000000000..6bbf67cab7c
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampRequestNetstandard21Wrapper.cs
@@ -0,0 +1,90 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Globalization;
+#if IS_SIGNING_SUPPORTED && IS_CORECLR
+using System.Net.Http;
+using System.Net.Http.Headers;
+#endif
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using System.Threading.Tasks;
+
+namespace NuGet.Packaging.Signing
+{
+#if IS_SIGNING_SUPPORTED && IS_CORECLR
+ internal sealed class Rfc3161TimestampRequestNetstandard21Wrapper : IRfc3161TimestampRequest
+ {
+ private static readonly HttpClient HttpClient = new HttpClient();
+ private readonly System.Security.Cryptography.Pkcs.Rfc3161TimestampRequest _rfc3161TimestampRequest;
+
+ public Rfc3161TimestampRequestNetstandard21Wrapper(
+ byte[] messageHash,
+ HashAlgorithmName hashAlgorithm,
+ Oid requestedPolicyId,
+ byte[] nonce,
+ bool requestSignerCertificates,
+ X509ExtensionCollection extensions)
+ {
+ _rfc3161TimestampRequest = System.Security.Cryptography.Pkcs.Rfc3161TimestampRequest.CreateFromHash(
+ new ReadOnlyMemory(messageHash),
+ hashAlgorithm,
+ requestedPolicyId,
+ nonce,
+ requestSignerCertificates,
+ extensions);
+ }
+
+ public async Task SubmitRequestAsync(Uri timestampUri, TimeSpan timeout)
+ {
+ if (timestampUri == null)
+ {
+ throw new ArgumentNullException(nameof(timestampUri));
+ }
+
+ if (!timestampUri.IsAbsoluteUri)
+ {
+ throw new ArgumentException(
+ Strings.AnAbsoluteUriIsRequired, nameof(timestampUri));
+ }
+
+ if (timestampUri.Scheme != Uri.UriSchemeHttp && timestampUri.Scheme != Uri.UriSchemeHttps)
+ {
+ throw new ArgumentException(
+ Strings.HttpOrHttpsIsRequired, nameof(timestampUri));
+ }
+
+ using (var content = new ReadOnlyMemoryContent(_rfc3161TimestampRequest.Encode()))
+ {
+ content.Headers.ContentType = new MediaTypeHeaderValue("application/timestamp-query");
+ using (HttpResponseMessage httpResponse = await HttpClient.PostAsync(timestampUri, content))
+ {
+ if (!httpResponse.IsSuccessStatusCode)
+ {
+ throw new CryptographicException(
+ string.Format(
+ CultureInfo.CurrentCulture,
+ Strings.TimestampServiceRespondedError,
+ (int)httpResponse.StatusCode,
+ httpResponse.ReasonPhrase));
+ }
+
+ if (!string.Equals(httpResponse.Content.Headers.ContentType.MediaType, "application/timestamp-response", StringComparison.OrdinalIgnoreCase))
+ {
+ throw new CryptographicException(Strings.TimestampServiceRespondedInvalidFormat);
+ }
+
+ var data = await httpResponse.Content.ReadAsByteArrayAsync();
+
+ System.Security.Cryptography.Pkcs.Rfc3161TimestampToken response = _rfc3161TimestampRequest.ProcessResponse(data, out var _);
+
+ var timestampToken = new Rfc3161TimestampTokenNetstandard21Wrapper(response);
+
+ return timestampToken;
+ }
+ }
+ }
+ }
+#endif
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampToken.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampToken.cs
index 39eb96dea43..0031ff3c0f3 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampToken.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampToken.cs
@@ -26,12 +26,12 @@ internal sealed class Rfc3161TimestampToken
private readonly byte[] _encoded;
- public Rfc3161TimestampTokenInfo TokenInfo { get; }
+ public IRfc3161TimestampTokenInfo TokenInfo { get; }
public X509Certificate2 SignerCertificate { get; }
public X509Certificate2Collection AdditionalCerts { get; }
internal Rfc3161TimestampToken(
- Rfc3161TimestampTokenInfo tstInfo,
+ IRfc3161TimestampTokenInfo tstInfo,
X509Certificate2 signerCertificate,
X509Certificate2Collection additionalCerts,
byte[] encoded)
@@ -121,7 +121,7 @@ private static Rfc3161TimestampToken CryptVerifyTimeStampSignature(byte[] encode
throw new CryptographicException(Marshal.GetLastWin32Error());
}
- Rfc3161TimestampTokenInfo tstInfo = new Rfc3161TimestampTokenInfo(pTsContext);
+ IRfc3161TimestampTokenInfo tstInfo = new Rfc3161TimestampTokenInfoNet472Wrapper(new Rfc3161TimestampTokenInfo(pTsContext));
X509Certificate2 signerCert = new X509Certificate2(pTsSigner);
using (X509Store extraCerts = new X509Store(hStore))
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenFactory.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenFactory.cs
new file mode 100644
index 00000000000..02aa3e9d42f
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenFactory.cs
@@ -0,0 +1,57 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Security.Cryptography.X509Certificates;
+
+namespace NuGet.Packaging.Signing
+{
+ internal sealed class Rfc3161TimestampTokenFactory
+ {
+ public static IRfc3161TimestampToken Create(
+ IRfc3161TimestampTokenInfo tstInfo,
+ X509Certificate2 signerCertificate,
+ X509Certificate2Collection additionalCerts,
+ byte[] encoded)
+ {
+ if (tstInfo == null)
+ {
+ throw new ArgumentNullException(nameof(tstInfo));
+ }
+
+ if (signerCertificate == null)
+ {
+ throw new ArgumentNullException(nameof(signerCertificate));
+ }
+
+ if (additionalCerts == null)
+ {
+ throw new ArgumentNullException(nameof(additionalCerts));
+ }
+
+ if (encoded == null)
+ {
+ throw new ArgumentNullException(nameof(encoded));
+ }
+#if IS_SIGNING_SUPPORTED
+ IRfc3161TimestampToken iRfc3161TimestampToken = null;
+#if IS_DESKTOP
+ iRfc3161TimestampToken = new Rfc3161TimestampTokenNet472Wrapper(
+ tstInfo,
+ signerCertificate,
+ additionalCerts,
+ encoded);
+#else
+ iRfc3161TimestampToken = new Rfc3161TimestampTokenNetstandard21Wrapper(
+ tstInfo,
+ signerCertificate,
+ additionalCerts,
+ encoded);
+#endif
+ return iRfc3161TimestampToken;
+#else
+ throw new NotSupportedException();
+#endif
+ }
+ }
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenInfoFactory.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenInfoFactory.cs
new file mode 100644
index 00000000000..e5c86bb4815
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenInfoFactory.cs
@@ -0,0 +1,30 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Security.Cryptography;
+
+namespace NuGet.Packaging.Signing
+{
+ internal sealed class Rfc3161TimestampTokenInfoFactory
+ {
+ public static IRfc3161TimestampTokenInfo Create(byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ throw new ArgumentNullException(nameof(bytes));
+ }
+#if IS_SIGNING_SUPPORTED
+ IRfc3161TimestampTokenInfo iRfc3161TimestampTokenInfo = null;
+#if IS_DESKTOP
+ iRfc3161TimestampTokenInfo = new Rfc3161TimestampTokenInfoNet472Wrapper(bytes);
+#else
+ iRfc3161TimestampTokenInfo = new Rfc3161TimestampTokenInfoNetstandard21Wrapper(bytes);
+#endif
+ return iRfc3161TimestampTokenInfo;
+#else
+ throw new NotSupportedException();
+#endif
+ }
+ }
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenInfoNet472Wrapper.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenInfoNet472Wrapper.cs
new file mode 100644
index 00000000000..9bdb1a6c47d
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenInfoNet472Wrapper.cs
@@ -0,0 +1,43 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Security.Cryptography;
+
+namespace NuGet.Packaging.Signing
+{
+#if IS_SIGNING_SUPPORTED && IS_DESKTOP
+ internal sealed class Rfc3161TimestampTokenInfoNet472Wrapper : IRfc3161TimestampTokenInfo
+ {
+ private Rfc3161TimestampTokenInfo _rfc3161TimestampTokenInfo;
+
+ public Rfc3161TimestampTokenInfoNet472Wrapper(byte[] timestampTokenInfo)
+ {
+ _rfc3161TimestampTokenInfo = new Rfc3161TimestampTokenInfo(timestampTokenInfo);
+ }
+
+ public Rfc3161TimestampTokenInfoNet472Wrapper(Rfc3161TimestampTokenInfo timestampTokenInfo)
+ {
+ _rfc3161TimestampTokenInfo = timestampTokenInfo;
+ }
+
+ public string PolicyId => _rfc3161TimestampTokenInfo.PolicyId;
+
+ public DateTimeOffset Timestamp => _rfc3161TimestampTokenInfo.Timestamp;
+
+ public long? AccuracyInMicroseconds => _rfc3161TimestampTokenInfo.AccuracyInMicroseconds;
+
+ public Oid HashAlgorithmId => _rfc3161TimestampTokenInfo.HashAlgorithmId;
+
+ public bool HasMessageHash(byte[] hash)
+ {
+ return _rfc3161TimestampTokenInfo.HasMessageHash(hash);
+ }
+
+ public byte[] GetNonce()
+ {
+ return _rfc3161TimestampTokenInfo.GetNonce();
+ }
+ }
+#endif
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenInfoNetstandard21Wrapper.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenInfoNetstandard21Wrapper.cs
new file mode 100644
index 00000000000..cedd8fc2f91
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenInfoNetstandard21Wrapper.cs
@@ -0,0 +1,69 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Linq;
+using System.Security.Cryptography;
+
+namespace NuGet.Packaging.Signing
+{
+#if IS_SIGNING_SUPPORTED && IS_CORECLR
+ internal sealed class Rfc3161TimestampTokenInfoNetstandard21Wrapper : IRfc3161TimestampTokenInfo
+ {
+ private System.Security.Cryptography.Pkcs.Rfc3161TimestampTokenInfo _rfc3161TimestampTokenInfo;
+
+ public Rfc3161TimestampTokenInfoNetstandard21Wrapper(byte[] timestampTokenInfo)
+ {
+ bool success = System.Security.Cryptography.Pkcs.Rfc3161TimestampTokenInfo.TryDecode(
+ new ReadOnlyMemory(timestampTokenInfo),
+ out _rfc3161TimestampTokenInfo,
+ out var _);
+
+ if (!success)
+ {
+ throw new CryptographicException(Strings.InvalidAsn1);
+ }
+ }
+
+ public Rfc3161TimestampTokenInfoNetstandard21Wrapper(System.Security.Cryptography.Pkcs.Rfc3161TimestampTokenInfo timestampTokenInfo)
+ {
+ _rfc3161TimestampTokenInfo = timestampTokenInfo;
+ }
+
+ public string PolicyId => _rfc3161TimestampTokenInfo.PolicyId.ToString();
+
+ public DateTimeOffset Timestamp => _rfc3161TimestampTokenInfo.Timestamp;
+
+ public long? AccuracyInMicroseconds => _rfc3161TimestampTokenInfo.AccuracyInMicroseconds;
+
+ public Oid HashAlgorithmId => _rfc3161TimestampTokenInfo.HashAlgorithmId;
+
+ public bool HasMessageHash(byte[] hash)
+ {
+ if (hash == null)
+ {
+ return false;
+ }
+
+ var value = _rfc3161TimestampTokenInfo.GetMessageHash().ToArray();
+
+ if (hash.Length != value.Length)
+ {
+ return false;
+ }
+
+ return value.SequenceEqual(hash);
+ }
+
+ public byte[] GetNonce()
+ {
+ ReadOnlyMemory? nonce = _rfc3161TimestampTokenInfo.GetNonce();
+ if (nonce.HasValue)
+ {
+ return nonce.Value.ToArray();
+ }
+ return Array.Empty();
+ }
+ }
+#endif
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenNet472Wrapper.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenNet472Wrapper.cs
new file mode 100644
index 00000000000..39178d7d06d
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenNet472Wrapper.cs
@@ -0,0 +1,36 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Security.Cryptography.Pkcs;
+using System.Security.Cryptography.X509Certificates;
+
+namespace NuGet.Packaging.Signing
+{
+#if IS_SIGNING_SUPPORTED && IS_DESKTOP
+ internal sealed class Rfc3161TimestampTokenNet472Wrapper : IRfc3161TimestampToken
+ {
+ private readonly Rfc3161TimestampToken _rfc3161TimestampToken;
+
+ public Rfc3161TimestampTokenNet472Wrapper(
+ IRfc3161TimestampTokenInfo tstInfo,
+ X509Certificate2 signerCertificate,
+ X509Certificate2Collection additionalCerts,
+ byte[] encoded)
+ {
+ _rfc3161TimestampToken = new Rfc3161TimestampToken(
+ tstInfo,
+ signerCertificate,
+ additionalCerts,
+ encoded);
+ }
+
+ public IRfc3161TimestampTokenInfo TokenInfo => _rfc3161TimestampToken.TokenInfo;
+
+ public SignedCms AsSignedCms()
+ {
+ return _rfc3161TimestampToken.AsSignedCms();
+ }
+ }
+#endif
+}
+
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenNetstandard21Wrapper.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenNetstandard21Wrapper.cs
new file mode 100644
index 00000000000..7b017e6336b
--- /dev/null
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampTokenNetstandard21Wrapper.cs
@@ -0,0 +1,51 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Security.Cryptography;
+using System.Security.Cryptography.Pkcs;
+using System.Security.Cryptography.X509Certificates;
+
+namespace NuGet.Packaging.Signing
+{
+#if IS_SIGNING_SUPPORTED && IS_CORECLR
+ internal sealed class Rfc3161TimestampTokenNetstandard21Wrapper : IRfc3161TimestampToken
+ {
+ private readonly System.Security.Cryptography.Pkcs.Rfc3161TimestampToken _rfc3161TimestampToken;
+ public IRfc3161TimestampTokenInfo TokenInfo { get; }
+
+ public Rfc3161TimestampTokenNetstandard21Wrapper(
+ IRfc3161TimestampTokenInfo tstInfo,
+ X509Certificate2 signerCertificate,
+ X509Certificate2Collection additionalCerts,
+ byte[] encoded)
+ {
+ bool success = System.Security.Cryptography.Pkcs.Rfc3161TimestampToken.TryDecode(
+ new ReadOnlyMemory(encoded),
+ out _rfc3161TimestampToken,
+ out var _);
+
+ if (!success)
+ {
+ throw new CryptographicException(Strings.InvalidAsn1);
+ }
+
+ TokenInfo = new Rfc3161TimestampTokenInfoNetstandard21Wrapper(_rfc3161TimestampToken.TokenInfo);
+ }
+
+ public Rfc3161TimestampTokenNetstandard21Wrapper(
+ System.Security.Cryptography.Pkcs.Rfc3161TimestampToken rfc3161TimestampToken)
+ {
+ _rfc3161TimestampToken = rfc3161TimestampToken;
+
+ TokenInfo = new Rfc3161TimestampTokenInfoNetstandard21Wrapper(_rfc3161TimestampToken.TokenInfo);
+ }
+
+ public SignedCms AsSignedCms()
+ {
+ return _rfc3161TimestampToken.AsSignedCms();
+ }
+ }
+#endif
+}
+
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampVerificationUtility.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampVerificationUtility.cs
index 44217fb01e5..46a63c47775 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampVerificationUtility.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Rfc3161TimestampVerificationUtility.cs
@@ -4,7 +4,7 @@
using System;
using System.IO;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
@@ -19,7 +19,7 @@ internal static class Rfc3161TimestampVerificationUtility
{
private const double _millisecondsPerMicrosecond = 0.001;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
internal static bool ValidateSignerCertificateAgainstTimestamp(
X509Certificate2 signerCertificate,
@@ -34,19 +34,19 @@ internal static bool ValidateSignerCertificateAgainstTimestamp(
internal static bool TryReadTSTInfoFromSignedCms(
SignedCms timestampCms,
- out Rfc3161TimestampTokenInfo tstInfo)
+ out IRfc3161TimestampTokenInfo tstInfo)
{
tstInfo = null;
if (timestampCms.ContentInfo.ContentType.Value.Equals(Oids.TSTInfoContentType))
{
- tstInfo = new Rfc3161TimestampTokenInfo(timestampCms.ContentInfo.Content);
+ tstInfo = Rfc3161TimestampTokenInfoFactory.Create(timestampCms.ContentInfo.Content);
return true;
}
// return false if the signedCms object does not contain the right ContentType
return false;
}
- internal static double GetAccuracyInMilliseconds(Rfc3161TimestampTokenInfo tstInfo)
+ internal static double GetAccuracyInMilliseconds(IRfc3161TimestampTokenInfo tstInfo)
{
double accuracyInMilliseconds;
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Timestamp.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Timestamp.cs
index 2fcccda9225..d2b9857995e 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Timestamp.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Timestamp/Timestamp.cs
@@ -8,7 +8,7 @@
using System.Security.Cryptography.X509Certificates;
using System.Linq;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
@@ -16,7 +16,7 @@ namespace NuGet.Packaging.Signing
{
public sealed class Timestamp
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// Upper limit of Timestamp.
@@ -46,7 +46,7 @@ public sealed class Timestamp
///
/// Timestamp token info for this timestamp.
///
- internal Rfc3161TimestampTokenInfo TstInfo { get; }
+ internal IRfc3161TimestampTokenInfo TstInfo { get; }
///
/// Default constructor. Limits are set to current time.
@@ -273,4 +273,4 @@ internal SignatureVerificationStatusFlags Verify(
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Utility/AttributeUtility.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Utility/AttributeUtility.cs
index eeac36e7532..d9e2f9a8ff6 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Utility/AttributeUtility.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Utility/AttributeUtility.cs
@@ -6,7 +6,7 @@
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
using System.Security.Cryptography.X509Certificates;
@@ -15,7 +15,7 @@ namespace NuGet.Packaging.Signing
{
public static class AttributeUtility
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// Create a CommitmentTypeIndication attribute.
/// https://tools.ietf.org/html/rfc5126.html#section-5.11.1
@@ -394,4 +394,4 @@ public static IEnumerable GetAttributes(this Crypt
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Utility/SignatureUtility.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Utility/SignatureUtility.cs
index 99539a0893e..bb82ef9b000 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Utility/SignatureUtility.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Utility/SignatureUtility.cs
@@ -5,7 +5,7 @@
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
using System.Security.Cryptography.X509Certificates;
@@ -23,7 +23,7 @@ private enum SigningCertificateRequirement
EitherOrBoth
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// Gets certificates in the certificate chain for the primary signature.
///
@@ -680,4 +680,4 @@ internal Errors(
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Utility/SigningUtility.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Utility/SigningUtility.cs
index 564231babe4..a23f18de80c 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Utility/SigningUtility.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Utility/SigningUtility.cs
@@ -6,7 +6,7 @@
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
using System.Security.Cryptography.X509Certificates;
@@ -56,7 +56,7 @@ public static void Verify(SignPackageRequest request, ILogger logger)
request.BuildSigningCertificateChainOnce(logger);
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
public static CryptographicAttributeObjectCollection CreateSignedAttributes(
SignPackageRequest request,
IReadOnlyList chainList)
@@ -293,4 +293,4 @@ private static SignatureContent GenerateSignatureContent(Common.HashAlgorithmNam
public static Task SignAsync(SigningOptions options, SignPackageRequest signRequest, CancellationToken token) => throw new NotImplementedException();
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Utility/VerificationUtility.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Utility/VerificationUtility.cs
index 40ef762d94a..8f96ca0f974 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Utility/VerificationUtility.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Utility/VerificationUtility.cs
@@ -95,7 +95,7 @@ internal static SignatureVerificationStatusFlags ValidateSigningCertificate(X509
return validationFlags;
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
internal static SignatureVerificationStatusFlags ValidateTimestamp(Timestamp timestamp, Signature signature, bool treatIssuesAsErrors, List issues, SigningSpecifications spec)
{
if (timestamp == null)
@@ -189,4 +189,4 @@ internal static SignatureVerificationStatusFlags ValidateTimestamp(Timestamp tim
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Verification/AllowListVerificationProvider.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Verification/AllowListVerificationProvider.cs
index 056bc0a88e3..1bf728c7a9a 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Verification/AllowListVerificationProvider.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Verification/AllowListVerificationProvider.cs
@@ -31,7 +31,7 @@ public Task GetTrustResultAsync(ISignedPackageReader
return Task.FromResult(VerifyAllowList(package, signature, settings));
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
private PackageVerificationResult VerifyAllowList(ISignedPackageReader package, PrimarySignature signature, SignedPackageVerifierSettings settings)
{
var treatIssuesAsErrors = !settings.AllowUntrusted;
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Verification/IntegrityVerificationProvider.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Verification/IntegrityVerificationProvider.cs
index 09c928521db..a851abc39af 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Verification/IntegrityVerificationProvider.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Verification/IntegrityVerificationProvider.cs
@@ -18,7 +18,7 @@ public Task GetTrustResultAsync(ISignedPackageReader
return VerifyPackageIntegrityAsync(package, signature, settings);
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
private async Task VerifyPackageIntegrityAsync(ISignedPackageReader package, PrimarySignature signature, SignedPackageVerifierSettings settings)
{
var status = SignatureVerificationStatus.Unknown;
@@ -57,4 +57,4 @@ private Task VerifyPackageIntegrityAsync(ISignedPacka
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Verification/SignatureTrustAndValidityVerificationProvider.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Verification/SignatureTrustAndValidityVerificationProvider.cs
index c5191a976c7..4b9c6e32c6c 100644
--- a/src/NuGet.Core/NuGet.Packaging/Signing/Verification/SignatureTrustAndValidityVerificationProvider.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Signing/Verification/SignatureTrustAndValidityVerificationProvider.cs
@@ -51,7 +51,7 @@ public Task GetTrustResultAsync(
return Task.FromResult(result);
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
private PackageVerificationResult Verify(
PrimarySignature signature,
SignedPackageVerifierSettings settings)
@@ -292,4 +292,4 @@ private PackageVerificationResult Verify(
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs b/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs
index e28f583bc06..d460ca5bf9b 100644
--- a/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs
+++ b/src/NuGet.Core/NuGet.Packaging/Strings.Designer.cs
@@ -60,6 +60,15 @@ internal Strings() {
}
}
+ ///
+ /// Looks up a localized string similar to An absolute URI is required..
+ ///
+ internal static string AnAbsoluteUriIsRequired {
+ get {
+ return ResourceManager.GetString("AnAbsoluteUriIsRequired", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to The argument cannot be null or empty..
///
@@ -555,6 +564,15 @@ internal static string FallbackFolderNotFound {
}
}
+ ///
+ /// Looks up a localized string similar to HTTP or HTTPS is required..
+ ///
+ internal static string HttpOrHttpsIsRequired {
+ get {
+ return ResourceManager.GetString("HttpOrHttpsIsRequired", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to The argument is invalid..
///
@@ -1572,6 +1590,24 @@ internal static string TimestampResponseExceptionGeneral {
}
}
+ ///
+ /// Looks up a localized string similar to The timestamp service responded with HTTP status code '{0}' ('{1}')..
+ ///
+ internal static string TimestampServiceRespondedError {
+ get {
+ return ResourceManager.GetString("TimestampServiceRespondedError", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The reply from the timestamp server was invalid..
+ ///
+ internal static string TimestampServiceRespondedInvalidFormat {
+ get {
+ return ResourceManager.GetString("TimestampServiceRespondedInvalidFormat", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to The timestamp signature has an unsupported digest algorithm ({0}). The following algorithms are supported: {1}..
///
diff --git a/src/NuGet.Core/NuGet.Packaging/Strings.resx b/src/NuGet.Core/NuGet.Packaging/Strings.resx
index fd2eaed6bd6..a21c87ff1c8 100644
--- a/src/NuGet.Core/NuGet.Packaging/Strings.resx
+++ b/src/NuGet.Core/NuGet.Packaging/Strings.resx
@@ -829,4 +829,17 @@ Valid from:
Path: {0}
0 - folder path
+
+ An absolute URI is required.
+
+
+ HTTP or HTTPS is required.
+
+
+ The timestamp service responded with HTTP status code '{0}' ('{1}').
+ {0} is the httpResponse.StatusCode, {1} is the httpResponse.ReasonPhrase.
+
+
+ The reply from the timestamp server was invalid.
+
diff --git a/src/NuGet.Core/NuGet.ProjectModel/NuGet.ProjectModel.csproj b/src/NuGet.Core/NuGet.ProjectModel/NuGet.ProjectModel.csproj
index 0515216cfc2..d452115ccca 100644
--- a/src/NuGet.Core/NuGet.ProjectModel/NuGet.ProjectModel.csproj
+++ b/src/NuGet.Core/NuGet.ProjectModel/NuGet.ProjectModel.csproj
@@ -1,4 +1,8 @@
+
+ true
+
+
@@ -22,7 +26,7 @@
-
+
diff --git a/src/NuGet.Core/NuGet.Protocol/NuGet.Protocol.csproj b/src/NuGet.Core/NuGet.Protocol/NuGet.Protocol.csproj
index 7f08b3da644..c3d3c399b4e 100644
--- a/src/NuGet.Core/NuGet.Protocol/NuGet.Protocol.csproj
+++ b/src/NuGet.Core/NuGet.Protocol/NuGet.Protocol.csproj
@@ -1,4 +1,8 @@
+
+ true
+
+
@@ -46,7 +50,7 @@
-
+
diff --git a/src/NuGet.Core/NuGet.Resolver/NuGet.Resolver.csproj b/src/NuGet.Core/NuGet.Resolver/NuGet.Resolver.csproj
index 9874ca1f6bf..09d75f97877 100644
--- a/src/NuGet.Core/NuGet.Resolver/NuGet.Resolver.csproj
+++ b/src/NuGet.Core/NuGet.Resolver/NuGet.Resolver.csproj
@@ -1,4 +1,8 @@
+
+ true
+
+
diff --git a/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/SignCommandTestFixture.cs b/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/SignCommandTestFixture.cs
index dedefadcf36..6202c3d5cc7 100644
--- a/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/SignCommandTestFixture.cs
+++ b/test/NuGet.Clients.FuncTests/NuGet.CommandLine.FuncTest/Commands/SignCommandTestFixture.cs
@@ -55,7 +55,7 @@ public TrustedTestCert TrustedTestCertificate
// Code Sign EKU needs trust to a root authority
// Add the cert to Root CA list in LocalMachine as it does not prompt a dialog
// This makes all the associated tests to require admin privilege
- _trustedTestCert = TestCertificate.Generate(actionGenerator).WithPrivateKeyAndTrust(StoreName.Root, StoreLocation.LocalMachine);
+ _trustedTestCert = TestCertificate.Generate(actionGenerator).WithPrivateKeyAndTrust(StoreName.Root);
}
return _trustedTestCert;
@@ -72,7 +72,7 @@ public TrustedTestCert TrustedTestCertificateWithInvalidEku
// Add the cert to Root CA list in LocalMachine as it does not prompt a dialog
// This makes all the associated tests to require admin privilege
- _trustedTestCertWithInvalidEku = TestCertificate.Generate(actionGenerator).WithPrivateKeyAndTrust(StoreName.Root, StoreLocation.LocalMachine);
+ _trustedTestCertWithInvalidEku = TestCertificate.Generate(actionGenerator).WithPrivateKeyAndTrust(StoreName.Root);
}
return _trustedTestCertWithInvalidEku;
@@ -90,7 +90,7 @@ public TrustedTestCert TrustedTestCertificateExpired
// Code Sign EKU needs trust to a root authority
// Add the cert to Root CA list in LocalMachine as it does not prompt a dialog
// This makes all the associated tests to require admin privilege
- _trustedTestCertExpired = TestCertificate.Generate(actionGenerator).WithPrivateKeyAndTrust(StoreName.Root, StoreLocation.LocalMachine);
+ _trustedTestCertExpired = TestCertificate.Generate(actionGenerator).WithPrivateKeyAndTrust(StoreName.Root);
}
return _trustedTestCertExpired;
@@ -108,7 +108,7 @@ public TrustedTestCert TrustedTestCertificateNotYetValid
// Code Sign EKU needs trust to a root authority
// Add the cert to Root CA list in LocalMachine as it does not prompt a dialog
// This makes all the associated tests to require admin privilege
- _trustedTestCertNotYetValid = TestCertificate.Generate(actionGenerator).WithPrivateKeyAndTrust(StoreName.Root, StoreLocation.LocalMachine);
+ _trustedTestCertNotYetValid = TestCertificate.Generate(actionGenerator).WithPrivateKeyAndTrust(StoreName.Root);
}
return _trustedTestCertNotYetValid;
@@ -394,4 +394,4 @@ private async Task CreateDefaultTrustedTimestampServiceAsync()
return timestampService;
}
}
-}
\ No newline at end of file
+}
diff --git a/test/NuGet.Clients.FuncTests/NuGet.MSSigning.Extensions.FuncTest/MSSignCommandTestFixture.cs b/test/NuGet.Clients.FuncTests/NuGet.MSSigning.Extensions.FuncTest/MSSignCommandTestFixture.cs
index 25ae64e800b..870b04e1a3d 100644
--- a/test/NuGet.Clients.FuncTests/NuGet.MSSigning.Extensions.FuncTest/MSSignCommandTestFixture.cs
+++ b/test/NuGet.Clients.FuncTests/NuGet.MSSigning.Extensions.FuncTest/MSSignCommandTestFixture.cs
@@ -6,7 +6,6 @@
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
-using NuGet.CommandLine.Test;
using Test.Utility.Signing;
namespace NuGet.MSSigning.Extensions.FuncTest.Commands
@@ -46,7 +45,7 @@ public TrustedTestCert TrustedTestCertificateWithPrivateKey
// Code Sign EKU needs trust to a root authority
// Add the cert to Root CA list in LocalMachine as it does not prompt a dialog
// This makes all the associated tests to require admin privilege
- _trustedTestCertWithPrivateKey = TestCertificate.Generate(actionGenerator).WithPrivateKeyAndTrust(StoreName.Root, StoreLocation.LocalMachine);
+ _trustedTestCertWithPrivateKey = TestCertificate.Generate(actionGenerator).WithPrivateKeyAndTrust(StoreName.Root);
}
return _trustedTestCertWithPrivateKey;
@@ -64,7 +63,7 @@ public TrustedTestCert TrustedTestCertificateWithoutPrivateKey
// Code Sign EKU needs trust to a root authority
// Add the cert to Root CA list in LocalMachine as it does not prompt a dialog
// This makes all the associated tests to require admin privilege
- _trustedTestCertWithoutPrivateKey = TestCertificate.Generate(actionGenerator).WithTrust(StoreName.Root, StoreLocation.LocalMachine);
+ _trustedTestCertWithoutPrivateKey = TestCertificate.Generate(actionGenerator).WithTrust();
}
return _trustedTestCertWithoutPrivateKey;
@@ -102,11 +101,12 @@ private async Task CreateDefaultTrustedCertificateAuthorit
var rootCa = CertificateAuthority.Create(testServer.Url);
var intermediateCa = rootCa.CreateIntermediateCertificateAuthority();
var rootCertificate = new X509Certificate2(rootCa.Certificate.GetEncoded());
+ StoreLocation storeLocation = CertificateStoreUtilities.GetTrustedCertificateStoreLocation();
_trustedTimestampRoot = TrustedTestCert.Create(
rootCertificate,
StoreName.Root,
- StoreLocation.LocalMachine);
+ storeLocation);
var ca = intermediateCa;
diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs
index e1866a7ea93..f6806aff1e9 100644
--- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs
+++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/RestoreNETCoreTest.cs
@@ -6775,6 +6775,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
solution.Projects.Add(projectA);
solution.Create(pathContext.SolutionRoot);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
// Act
var r = Util.RestoreSolution(pathContext);
@@ -6829,6 +6831,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
solution.Projects.Add(projectA);
solution.Create(pathContext.SolutionRoot);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
// Act
var r = Util.RestoreSolution(pathContext);
@@ -6898,6 +6902,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
xml.Save(projectA.ProjectPath);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
// Act
var r = Util.RestoreSolution(pathContext);
@@ -6958,6 +6964,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
solution.Projects.Add(projectA);
solution.Create(pathContext.SolutionRoot);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
// Act
var r = Util.RestoreSolution(pathContext);
@@ -7023,6 +7031,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
solution.Projects.Add(projectA);
solution.Create(pathContext.SolutionRoot);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
// Act
var r = Util.RestoreSolution(pathContext);
@@ -7136,6 +7146,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
solution.Projects.Add(projectA);
solution.Create(pathContext.SolutionRoot);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
var r = Util.RestoreSolution(pathContext);
// Preconditions
@@ -7153,6 +7165,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
Assert.False(Directory.Exists(packagePath), $"{packageX.ToString()} should not be installed anymore.");
+
// Act
r = Util.RestoreSolution(pathContext);
Assert.True(r.Success, r.AllOutput);
@@ -7193,6 +7206,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
solution.Projects.Add(projectA);
solution.Create(pathContext.SolutionRoot);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
var r = Util.RestoreSolution(pathContext);
// Preconditions
@@ -7207,6 +7222,7 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
Assert.True(Directory.Exists(packagePath), $"{packageX.ToString()} is not installed");
Assert.Contains("Writing cache file", r.Item2);
+
// Act
r = Util.RestoreSolution(pathContext);
Assert.True(r.Success, r.AllOutput);
@@ -7252,6 +7268,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
solution.Projects.Add(projectA);
solution.Create(pathContext.SolutionRoot);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
// Act
var r = Util.RestoreSolution(pathContext);
@@ -7316,6 +7334,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
solution.Projects.Add(projectA);
solution.Create(pathContext.SolutionRoot);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
// Act
var r = Util.RestoreSolution(pathContext);
@@ -7390,6 +7410,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
xml.Save(projectB.ProjectPath);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
// Act
var r = Util.RestoreSolution(pathContext);
@@ -7481,6 +7503,8 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
xml.Save(projectA.ProjectPath);
+ Util.CreateTempGlobalJson(pathContext.SolutionRoot);
+
// Act
var r = Util.RestoreSolution(pathContext);
diff --git a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/Util.cs b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/Util.cs
index 4c0a61527f1..ddd6ca2b3b8 100644
--- a/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/Util.cs
+++ b/test/NuGet.Clients.Tests/NuGet.CommandLine.Test/Util.cs
@@ -1246,5 +1246,29 @@ public static void TestCommandInvalidArguments(string command)
// Verify traits of help message in stdout
Assert.Contains("usage:", result.Item2);
}
+
+ //This is a temporary change since the VS on CI doesn't have the latest hostfxr, it could not resolve the preview SDK.
+ //Will be removed when CI has the latest version of VS, or SDK3.0 released RTM version.
+ //Create a global.json file in temporary testing folder, to make sure msbuild could choose preview version of SDK.
+ public static void CreateTempGlobalJson(string solutionRoot)
+ {
+ //put the global.json at one level up to solutionRoot path
+ var pathToPlaceGlobalJsonFile = solutionRoot.Substring(0, solutionRoot.Length - 1 - solutionRoot.Split(Path.DirectorySeparatorChar).Last().Length);
+
+ var globalJsonFile =
+@"{
+ ""sdk"": {
+ ""version"": ""5.0.100-alpha1""
+ }
+}";
+
+ using (var outputFile = new StreamWriter(Path.Combine(pathToPlaceGlobalJsonFile, "global.json")))
+ {
+ outputFile.WriteLine(globalJsonFile);
+ outputFile.Close();
+ }
+
+ }
+
}
}
diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/Dotnet.Integration.Test.csproj b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/Dotnet.Integration.Test.csproj
index 0651fac5d73..62dd434cd28 100644
--- a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/Dotnet.Integration.Test.csproj
+++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/Dotnet.Integration.Test.csproj
@@ -1,13 +1,18 @@
-
+
+
+ true
+ true
+
+
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
Integration tests for NuGet-powered dotnet CLI commands such as pack/restore/list package and dotnet nuget.
-
+
@@ -22,7 +27,6 @@
-
diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetRestoreTests.cs b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetRestoreTests.cs
index 852c7e02e38..e5c180abedd 100644
--- a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetRestoreTests.cs
+++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetRestoreTests.cs
@@ -230,7 +230,6 @@ public async Task DotnetRestore_ProjectMovedDoesNotRunRestore()
ProjectFileUtils.SetTargetFrameworkForProject(xml, "TargetFrameworks", tfm);
var attributes = new Dictionary() { { "Version", "1.0.0" } };
-
ProjectFileUtils.AddItem(
xml,
"PackageReference",
diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/MsbuildIntegrationTestFixture.cs b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/MsbuildIntegrationTestFixture.cs
index 17186bfb9c4..17124d115f3 100644
--- a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/MsbuildIntegrationTestFixture.cs
+++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/MsbuildIntegrationTestFixture.cs
@@ -6,9 +6,13 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Reflection;
+using System.Text;
using System.Threading;
+using Newtonsoft.Json.Linq;
using NuGet.Common;
using NuGet.Packaging.Core;
+using NuGet.Protocol;
using NuGet.Test.Utility;
using NuGet.XPlat.FuncTest;
using Xunit;
@@ -29,9 +33,18 @@ public MsbuildIntegrationTestFixture()
_cliDirectory = CopyLatestCliForPack();
var dotnetExecutableName = RuntimeEnvironmentHelper.IsWindows ? "dotnet.exe" : "dotnet";
TestDotnetCli = Path.Combine(_cliDirectory, dotnetExecutableName);
- MsBuildSdksPath = Path.Combine(Directory.GetDirectories
- (Path.Combine(_cliDirectory, "sdk"))
- .First(), "Sdks");
+
+ var sdkPaths = Directory.GetDirectories(Path.Combine(_cliDirectory, "sdk"));
+
+ // TODO - remove when shipping. See https://github.com/NuGet/Home/issues/8508
+ // const string dotnetMajorVersion = "3.";
+ const string dotnetMajorVersion = "5.";
+ PatchSDKWithCryptographyDlls(dotnetMajorVersion, sdkPaths);
+
+ MsBuildSdksPath = Path.Combine(
+ sdkPaths.Where(path => path.Split(Path.DirectorySeparatorChar).Last().StartsWith(dotnetMajorVersion)).First()
+ , "Sdks");
+
_templateDirectory = TestDirectory.Create();
_processEnvVars.Add("MSBuildSDKsPath", MsBuildSdksPath);
@@ -75,7 +88,7 @@ internal void CreateDotnetNewProject(string solutionRoot, string projectName, st
private static void CopyFromTemplate(string projectName, string args, string workingDirectory, DirectoryInfo templateDirectoryInfo)
{
- foreach(var file in templateDirectoryInfo.GetFiles())
+ foreach (var file in templateDirectoryInfo.GetFiles())
{
File.Copy(file.FullName, Path.Combine(workingDirectory, file.Name));
}
@@ -98,7 +111,8 @@ internal void CreateDotnetToolProject(string solutionRoot, string projectName, s
var restoreSolutionDirectory = workingDirectory;
var msbuildProjectExtensionsPath = Path.Combine(workingDirectory);
var packageReference = string.Empty;
- foreach (var package in packages) {
+ foreach (var package in packages)
+ {
packageReference = string.Concat(packageReference, Environment.NewLine, $@"");
}
@@ -170,7 +184,7 @@ private void RestoreProjectOrSolution(string workingDirectory, string fileName,
///
/// dotnet.exe args
///
- internal CommandRunnerResult RunDotnet(string workingDirectory, string args, bool ignoreExitCode=false)
+ internal CommandRunnerResult RunDotnet(string workingDirectory, string args, bool ignoreExitCode = false)
{
var result = CommandRunner.Run(TestDotnetCli,
workingDirectory,
@@ -280,24 +294,28 @@ private void CopyRestoreArtifacts(string artifactsDirectory, string pathToSdkInC
foreach (var projectName in sdkDependencies)
{
var projectArtifactsFolder = new DirectoryInfo(Path.Combine(artifactsDirectory, projectName, toolsetVersion, "bin", configuration));
- foreach (var frameworkArtifactsFolder in projectArtifactsFolder.EnumerateDirectories())
+
+ IEnumerable frameworkArtifactFolders = projectArtifactsFolder.EnumerateDirectories().Where(folder => folder.FullName.Contains("netstandard2.1") || folder.FullName.Contains("netcoreapp5.0"));
+
+ if (!frameworkArtifactFolders.Any())
+ {
+ frameworkArtifactFolders = projectArtifactsFolder.EnumerateDirectories().Where(folder => folder.FullName.Contains("netstandard2.0"));
+ }
+
+ foreach (var frameworkArtifactsFolder in frameworkArtifactFolders)
{
- if (frameworkArtifactsFolder.FullName.Contains("netstandard") ||
- frameworkArtifactsFolder.FullName.Contains("netcoreapp"))
+ var fileName = projectName + ".dll";
+ File.Copy(
+ sourceFileName: Path.Combine(frameworkArtifactsFolder.FullName, fileName),
+ destFileName: Path.Combine(pathToSdkInCli, fileName),
+ overwrite: true);
+ // Copy the restore targets.
+ if (projectName.Equals(restoreProjectName))
{
- var fileName = projectName + ".dll";
File.Copy(
- sourceFileName: Path.Combine(frameworkArtifactsFolder.FullName, fileName),
- destFileName: Path.Combine(pathToSdkInCli, fileName),
- overwrite: true);
- // Copy the restore targets.
- if (projectName.Equals(restoreProjectName))
- {
- File.Copy(
- sourceFileName: Path.Combine(frameworkArtifactsFolder.FullName, restoreTargetsName),
- destFileName: Path.Combine(pathToSdkInCli, restoreTargetsName),
- overwrite: true);
- }
+ sourceFileName: Path.Combine(frameworkArtifactsFolder.FullName, restoreTargetsName),
+ destFileName: Path.Combine(pathToSdkInCli, restoreTargetsName),
+ overwrite: true);
}
}
}
@@ -310,7 +328,8 @@ private void CopyPackSdkArtifacts(string artifactsDirectory, string pathToSdkInC
const string packProjectName = "NuGet.Build.Tasks.Pack";
const string packTargetsName = "NuGet.Build.Tasks.Pack.targets";
// Copy the pack SDK.
- var packProjectCoreArtifactsDirectory = new DirectoryInfo(Path.Combine(artifactsDirectory, packProjectName, toolsetVersion, "bin", configuration)).EnumerateDirectories("netstandard*").Single();
+ //Order by fullname so that we can get the latest nestandard version. E.g. if we have both netstandard2.0 and netstandard2.1, netstandard2.1 will be selected.
+ var packProjectCoreArtifactsDirectory = new DirectoryInfo(Path.Combine(artifactsDirectory, packProjectName, toolsetVersion, "bin", configuration)).EnumerateDirectories("netstandard*").OrderBy(x => x.FullName).Last();
var packAssemblyDestinationDirectory = Path.Combine(pathToPackSdk, "CoreCLR");
// Be smart here so we don't have to call ILMerge in the VS build. It takes ~15s total.
// In VisualStudio, simply use the non il merged version.
@@ -410,7 +429,7 @@ private static void DeleteDirectory(string path)
for (var i = 0; i < MaxTries; i++)
{
-
+
try
{
Directory.Delete(path, recursive: true);
@@ -427,5 +446,111 @@ private static void DeleteDirectory(string path)
}
}
+
+ // Temporary added methods for processing deps.json files for patching
+
+ ///
+ /// Temporary patching process to bring in Cryptography DLLs for testing while SDK gets around to including them in 5.0.
+ /// See also: https://github.com/NuGet/Home/issues/8508
+ ///
+ private void PatchSDKWithCryptographyDlls(string dotnetMajorVersion, string[] sdkPaths)
+ {
+ string directoryToPatch = sdkPaths.Where(path => path.Split(Path.DirectorySeparatorChar).Last().StartsWith(dotnetMajorVersion)).First();
+ var assemblyNames = new string[1] { "System.Security.Cryptography.Pkcs.dll" };
+ PatchDepsJsonFiles(assemblyNames, directoryToPatch);
+
+ string userProfilePath = Environment.GetEnvironmentVariable(RuntimeEnvironmentHelper.IsWindows ? "USERPROFILE" : "HOME");
+ string globalPackagesPath = Path.Combine(userProfilePath, ".nuget", "packages");
+
+ CopyNewlyAddedDlls(assemblyNames, Directory.GetCurrentDirectory(), directoryToPatch);
+ }
+
+ private void PatchDepsJsonFiles(string[] assemblyNames, string patchDir)
+ {
+ string[] fileNames = new string[3] { "dotnet.deps.json", "MSBuild.deps.json", "NuGet.CommandLine.XPlat.deps.json" };
+ string[] fullNames = fileNames.Select(filename => Path.Combine(patchDir, filename)).ToArray();
+ PatchDepsJsonWithNewlyAddedDlls(assemblyNames, fullNames);
+ }
+
+ private void CopyNewlyAddedDlls(string[] assemblyNames, string copyFromPath, string copyToPath)
+ {
+ foreach (var assemblyName in assemblyNames)
+ {
+ File.Copy(
+ Path.Combine(copyFromPath, assemblyName),
+ Path.Combine(copyToPath, assemblyName)
+ );
+ }
+ }
+
+ private void PatchDepsJsonWithNewlyAddedDlls(string[] assemblyNames, string[] filePaths)
+ {
+ string nugetBuildTasksName = "NuGet.Build.Tasks/5.3.0-rtm.6251";
+ foreach (string assemblyName in assemblyNames)
+ {
+ foreach (string filePath in filePaths)
+ {
+ JObject jsonFile = GetJson(filePath);
+
+ JObject targets = jsonFile.GetJObjectProperty("targets");
+
+ JObject netcoreapp50 = targets.GetJObjectProperty(".NETCoreApp,Version=v5.0");
+
+ JObject nugetBuildTasks = netcoreapp50.GetJObjectProperty(nugetBuildTasksName);
+
+ JObject runtime = nugetBuildTasks.GetJObjectProperty("runtime");
+
+ var assemblyPath = Path.Combine(Directory.GetCurrentDirectory(), assemblyName);
+ var assemblyVersion = Assembly.LoadFile(assemblyPath).GetName().Version.ToString();
+ var assemblyFileVersion = FileVersionInfo.GetVersionInfo(assemblyPath).FileVersion;
+ var jproperty = new JProperty("lib/netstandard2.1/" + assemblyName,
+ new JObject
+ {
+ new JProperty("assemblyVersion", assemblyVersion),
+ new JProperty("fileVersion", assemblyFileVersion),
+ }
+ );
+ runtime.Add(jproperty);
+ nugetBuildTasks["runtime"] = runtime;
+ netcoreapp50[nugetBuildTasksName] = nugetBuildTasks;
+ targets[".NETCoreApp,Version=v5.0"] = netcoreapp50;
+ jsonFile["targets"] = targets;
+ SaveJson(jsonFile, filePath);
+ }
+ }
+ }
+
+ private JObject GetJson(string jsonFilePath)
+ {
+ try
+ {
+ return FileUtility.SafeRead(jsonFilePath, (stream, filePath) =>
+ {
+ using (var reader = new StreamReader(stream))
+ {
+ return JObject.Parse(reader.ReadToEnd());
+ }
+ });
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException(
+ string.Format("Failed to read json file at {0}: {1}", jsonFilePath, ex.Message),
+ ex
+ );
+ }
+ }
+
+ private void SaveJson(JObject json, string jsonFilePath)
+ {
+ FileUtility.Replace((outputPath) =>
+ {
+ using (var writer = new StreamWriter(outputPath, append: false, encoding: Encoding.UTF8))
+ {
+ writer.Write(json.ToString());
+ }
+ },
+ jsonFilePath);
+ }
}
}
diff --git a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs
index 16ff99052d8..5bf196d9920 100644
--- a/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs
+++ b/test/NuGet.Core.FuncTests/Dotnet.Integration.Test/PackCommandTests.cs
@@ -16,6 +16,8 @@
using NuGet.Test.Utility;
using NuGet.Versioning;
using Xunit;
+using NuGet.XPlat.FuncTest;
+
namespace Dotnet.Integration.Test
@@ -616,6 +618,7 @@ public void PackCommand_PackProject_AddsProjectRefsAsPackageRefs()
Assert.Equal(framework,
dependencyGroups[0].TargetFramework);
+
var packagesA = dependencyGroups[0].Packages.ToList();
Assert.Equal(1,
packagesA.Count);
@@ -4047,7 +4050,7 @@ public void PackCommand_PackProject_PacksFrameworkReferences(string frameworkRef
}
ProjectFileUtils.SetTargetFrameworkForProject(xml, frameworkProperty, targetFrameworks);
- foreach(var frameworkRef in frameworkReftoPack)
+ foreach (var frameworkRef in frameworkReftoPack)
{
var attributes = new Dictionary();
@@ -4464,4 +4467,5 @@ public void PackCommand_DoesNotGenerateOwnersElement()
}
}
}
+
}
diff --git a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/NuGet.Commands.FuncTest.csproj b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/NuGet.Commands.FuncTest.csproj
index 9fde40b1991..598d2774a06 100644
--- a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/NuGet.Commands.FuncTest.csproj
+++ b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/NuGet.Commands.FuncTest.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
functional
Integration tests for the more involved NuGet.Commands, such as restore.
diff --git a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs
index 9953d71fead..0b099cef719 100644
--- a/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs
+++ b/test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs
@@ -1857,8 +1857,6 @@ public async Task RestoreCommand_LockedLockFileWithOutOfDateProjectAsync()
}
}
-#if IS_DESKTOP
- // TODO: To work on coreclr we need to address https://github.com/NuGet/Home/issues/7588
[Fact]
public void RestoreCommand_PathTooLongException()
{
@@ -1868,9 +1866,9 @@ public void RestoreCommand_PathTooLongException()
new PackageSource(NuGetConstants.V3FeedUrl)
};
- using(var packagesDir = TestDirectory.Create())
- using(var projectDir = TestDirectory.Create())
- using(var cacheContext = new SourceCacheContext())
+ using (var packagesDir = TestDirectory.Create())
+ using (var projectDir = TestDirectory.Create())
+ using (var cacheContext = new SourceCacheContext())
{
var configJson = JObject.Parse(@"
{
@@ -1886,7 +1884,18 @@ public void RestoreCommand_PathTooLongException()
var spec = JsonPackageSpecReader.GetPackageSpec(configJson.ToString(), "TestProject", specPath);
var logger = new TestLogger();
- var request = new TestRestoreRequest(spec, sources, packagesDir + new string('_', 300), cacheContext, logger)
+ string longPath = packagesDir + new string('_', 300);
+ try
+ {
+ // This test is pointless if the machine has long paths enabled.
+ Path.GetFullPath(longPath);
+ return;
+ }
+ catch (PathTooLongException)
+ {
+ }
+
+ var request = new TestRestoreRequest(spec, sources, longPath, cacheContext, logger)
{
LockFilePath = Path.Combine(projectDir, "project.lock.json")
};
@@ -1897,7 +1906,6 @@ public void RestoreCommand_PathTooLongException()
new Func(async () => await command.ExecuteAsync()).ShouldThrow();
}
}
-#endif
[Fact]
public async Task RestoreCommand_RestoreExactVersionWithFailingSourceAsync()
diff --git a/test/NuGet.Core.FuncTests/NuGet.Core.FuncTest/NuGet.Core.FuncTest.csproj b/test/NuGet.Core.FuncTests/NuGet.Core.FuncTest/NuGet.Core.FuncTest.csproj
index e2ebcd2f1ff..11066ddf6d2 100644
--- a/test/NuGet.Core.FuncTests/NuGet.Core.FuncTest/NuGet.Core.FuncTest.csproj
+++ b/test/NuGet.Core.FuncTests/NuGet.Core.FuncTest/NuGet.Core.FuncTest.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Integration tests for various functionality from the src/NuGet.Core projects.
@@ -19,7 +23,7 @@
-
+
diff --git a/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/NuGet.Packaging.FuncTest.csproj b/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/NuGet.Packaging.FuncTest.csproj
index 9a38e298766..b1042cd539a 100644
--- a/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/NuGet.Packaging.FuncTest.csproj
+++ b/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/NuGet.Packaging.FuncTest.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Integration tests for the more involved NuGet.Packaging functionality, such as signing.
diff --git a/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/SigningTests/AllowListVerificationProviderTests.cs b/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/SigningTests/AllowListVerificationProviderTests.cs
index bca9c5819d6..eb192fd6357 100644
--- a/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/SigningTests/AllowListVerificationProviderTests.cs
+++ b/test/NuGet.Core.FuncTests/NuGet.Packaging.FuncTest/SigningTests/AllowListVerificationProviderTests.cs
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System;
using System.Collections.Generic;
@@ -1101,4 +1101,4 @@ public static IEnumerable
-
+
diff --git a/test/NuGet.Core.Tests/NuGet.Configuration.Test/NuGet.Configuration.Test.csproj b/test/NuGet.Core.Tests/NuGet.Configuration.Test/NuGet.Configuration.Test.csproj
index 713f533ca27..5c31b9e81fa 100644
--- a/test/NuGet.Core.Tests/NuGet.Configuration.Test/NuGet.Configuration.Test.csproj
+++ b/test/NuGet.Core.Tests/NuGet.Configuration.Test/NuGet.Configuration.Test.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Unit tests for NuGet.Configuration.
@@ -14,7 +18,7 @@
-
+
diff --git a/test/NuGet.Core.Tests/NuGet.DependencyResolver.Core.Tests/NuGet.DependencyResolver.Core.Tests.csproj b/test/NuGet.Core.Tests/NuGet.DependencyResolver.Core.Tests/NuGet.DependencyResolver.Core.Tests.csproj
index 1c405fc7734..572bddca237 100644
--- a/test/NuGet.Core.Tests/NuGet.DependencyResolver.Core.Tests/NuGet.DependencyResolver.Core.Tests.csproj
+++ b/test/NuGet.Core.Tests/NuGet.DependencyResolver.Core.Tests/NuGet.DependencyResolver.Core.Tests.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Unit tests for NuGet.DependencyResolver.Core.
diff --git a/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGet.Frameworks.Test.csproj b/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGet.Frameworks.Test.csproj
index e6865f78f09..c413deb77c6 100644
--- a/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGet.Frameworks.Test.csproj
+++ b/test/NuGet.Core.Tests/NuGet.Frameworks.Test/NuGet.Frameworks.Test.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Unit tests for NuGet.Frameworks.
@@ -14,7 +18,7 @@
-
+
diff --git a/test/NuGet.Core.Tests/NuGet.LibraryModel.Tests/NuGet.LibraryModel.Tests.csproj b/test/NuGet.Core.Tests/NuGet.LibraryModel.Tests/NuGet.LibraryModel.Tests.csproj
index 964dd2a5895..5c8bb7bdc79 100644
--- a/test/NuGet.Core.Tests/NuGet.LibraryModel.Tests/NuGet.LibraryModel.Tests.csproj
+++ b/test/NuGet.Core.Tests/NuGet.LibraryModel.Tests/NuGet.LibraryModel.Tests.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Unit tests for NuGet.LibraryModel.
diff --git a/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/NuGet.PackageManagement.Test.csproj b/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/NuGet.PackageManagement.Test.csproj
index 828d0f4c461..fe3daa3dbc9 100644
--- a/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/NuGet.PackageManagement.Test.csproj
+++ b/test/NuGet.Core.Tests/NuGet.PackageManagement.Test/NuGet.PackageManagement.Test.csproj
@@ -4,7 +4,7 @@
$(NETFXTargetFramework)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Unit tests for NuGet.PackageManagement.
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/NuGet.Packaging.Test.csproj b/test/NuGet.Core.Tests/NuGet.Packaging.Test/NuGet.Packaging.Test.csproj
index 548757bf916..20c8d1bcd69 100644
--- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/NuGet.Packaging.Test.csproj
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/NuGet.Packaging.Test.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Unit tests for NuGet.Packaging.
@@ -15,7 +19,7 @@
-
+
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageArchiveReaderTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageArchiveReaderTests.cs
index 35f69c143fa..f379f70d151 100644
--- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageArchiveReaderTests.cs
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageArchiveReaderTests.cs
@@ -1597,7 +1597,7 @@ await Assert.ThrowsAsync(
}
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
[Fact]
public async Task ValidateIntegrityAsync_WhenSignatureContentNull_Throws()
{
@@ -1835,7 +1835,7 @@ public void GetContentHash_UnsignedPackage_WhenGivingAFallbackFunctionThatReturn
}
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
[CIOnlyFact]
public async Task GetContentHash_IsSameForUnsignedAndSignedPackageAsync()
{
@@ -1956,18 +1956,11 @@ public void CanVerifySignedPackages_ReturnsValueBasedOnOperatingSystemAndFramewo
// Act
var result = packageArchiveReader.CanVerifySignedPackages(null);
// Assert
-#if IS_DESKTOP
- // Verify package signature when running in full frameworks
- if (RuntimeEnvironmentHelper.IsWindows && !RuntimeEnvironmentHelper.IsMono)
- {
- Assert.True(result);
- }
- else
- {
- Assert.False(result);
- }
+#if IS_SIGNING_SUPPORTED
+ // Verify package signature when signing is supported
+ Assert.True(result);
#else
- // Cannot verify package signature in not-full frameworks
+ // Cannot verify package signature when signing is not supported
Assert.False(result);
#endif
}
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageExtractorTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageExtractorTests.cs
index b4ed8d47cb0..616bbaa5e9e 100644
--- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageExtractorTests.cs
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/PackageExtractorTests.cs
@@ -2362,7 +2362,7 @@ public async Task ExtractPackageAsync_RequireMode_UnsignedPackage_PluginPackageR
}
#endif
-#if IS_CORECLR
+#if IS_CORECLR && !IS_SIGNING_SUPPORTED
[Fact]
public async Task ExtractPackageAsync_RequireMode_UnsignedPackage_InCoreCLR_SkipsSigningVerificationAsync()
{
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/AttributeUtilityTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/AttributeUtilityTests.cs
index 382231920b7..c4eb8b83871 100644
--- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/AttributeUtilityTests.cs
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/AttributeUtilityTests.cs
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System;
using System.Linq;
using System.Security.Cryptography;
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/CertificateChainUtilityTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/CertificateChainUtilityTests.cs
index 9813fc797fd..29f4c1aaad2 100644
--- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/CertificateChainUtilityTests.cs
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/CertificateChainUtilityTests.cs
@@ -73,7 +73,7 @@ public void GetCertificateChain_WhenCertificateTypeUndefined_Throws()
Assert.Equal("certificateType", exception.ParamName);
}
- [PlatformFact(Platform.Windows, Platform.Linux)] // https://github.com/NuGet/Home/issues/8047
+ [Fact]
public void GetCertificateChain_WithUntrustedRoot_Throws()
{
using (var chainHolder = new X509ChainHolder())
@@ -100,19 +100,26 @@ public void GetCertificateChain_WithUntrustedRoot_Throws()
if (RuntimeEnvironmentHelper.IsWindows || RuntimeEnvironmentHelper.IsLinux)
{
+#if NETCORE5_0
+ Assert.Equal(2, logger.Warnings);
+#else
Assert.Equal(RuntimeEnvironmentHelper.IsWindows ? 2 : 1, logger.Warnings);
-
+#endif
SigningTestUtility.AssertOfflineRevocation(logger.LogMessages, LogLevel.Warning);
+#if NETCORE5_0
+ SigningTestUtility.AssertRevocationStatusUnknown(logger.LogMessages, LogLevel.Warning);
+#else
if (RuntimeEnvironmentHelper.IsWindows)
{
SigningTestUtility.AssertRevocationStatusUnknown(logger.LogMessages, LogLevel.Warning);
}
+#endif
}
}
}
- [PlatformFact(Platform.Windows, Platform.Linux)] // https://github.com/NuGet/Home/issues/8047
+ [Fact]
public void GetCertificateChain_WithUntrustedSelfIssuedCertificate_ReturnsChain()
{
using (var certificate = _fixture.GetDefaultCertificate())
@@ -131,14 +138,19 @@ public void GetCertificateChain_WithUntrustedSelfIssuedCertificate_ReturnsChain(
}
Assert.Equal(0, logger.Errors);
+#if (IS_DESKTOP || NETCORE5_0)
+ Assert.Equal(1, logger.Warnings);
+#else
Assert.Equal(RuntimeEnvironmentHelper.IsLinux ? 2 : 1, logger.Warnings);
-
+#endif
SigningTestUtility.AssertUntrustedRoot(logger.LogMessages, LogLevel.Warning);
+#if !NETCORE5_0
if (RuntimeEnvironmentHelper.IsLinux)
{
SigningTestUtility.AssertOfflineRevocation(logger.LogMessages, LogLevel.Warning);
}
+#endif
}
}
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/EssCertIdTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/EssCertIdTests.cs
index c63c07cb875..25e39bf9cb7 100644
--- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/EssCertIdTests.cs
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/EssCertIdTests.cs
@@ -36,7 +36,7 @@ public void Read_WithInvalidAsn1_Throws()
() => EssCertId.Read(new byte[] { 0x30, 0x0b }));
}
-#if !IS_CORECLR
+#if IS_SIGNING_SUPPORTED
[Fact]
public void Read_WithValidInput_ReturnsEssCertId()
{
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/EssCertIdV2Tests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/EssCertIdV2Tests.cs
index 7969df8bfd9..9d005a41aac 100644
--- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/EssCertIdV2Tests.cs
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/EssCertIdV2Tests.cs
@@ -168,7 +168,7 @@ public void Read_WithNonDefaultAlgorithmIdentifier_ReturnsEssCertIdV2()
SigningTestUtility.VerifyByteArrays(bcIssuerSerial.Serial.Value.ToByteArray(), essCertIdV2.IssuerSerial.SerialNumber);
}
-#if !IS_CORECLR
+#if IS_SIGNING_SUPPORTED
[Fact]
public void Read_WithValidInput_ReturnsEssCertId()
{
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/PrimarySignatureTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/PrimarySignatureTests.cs
index 39199bc84e9..6a16317678a 100644
--- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/PrimarySignatureTests.cs
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/PrimarySignatureTests.cs
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/ReadOnlyBufferedStreamTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/ReadOnlyBufferedStreamTests.cs
index e693f00c2d1..020abfd9bdf 100644
--- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/ReadOnlyBufferedStreamTests.cs
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/ReadOnlyBufferedStreamTests.cs
@@ -249,7 +249,7 @@ public void WriteTimeout_Setter_SetsValueOnUnderlyingStream()
}
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
[Fact]
public void Close_WhenLeaveOpenFalse_DisposesUnderlyingStream()
{
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/RepositoryCountersignatureTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/RepositoryCountersignatureTests.cs
index 20a18861eb0..8c34ef7f080 100644
--- a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/RepositoryCountersignatureTests.cs
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/RepositoryCountersignatureTests.cs
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/Rfc3161TimestampProviderTests.cs b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/Rfc3161TimestampProviderTests.cs
new file mode 100644
index 00000000000..48815d74fcc
--- /dev/null
+++ b/test/NuGet.Core.Tests/NuGet.Packaging.Test/SigningTests/Rfc3161TimestampProviderTests.cs
@@ -0,0 +1,43 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+#if IS_SIGNING_SUPPORTED
+using System.Collections.Generic;
+using NuGet.Packaging.Signing;
+using Xunit;
+
+namespace NuGet.Packaging.Test.SigningTests
+{
+ public class Rfc3161TimestampProviderTests
+ {
+ public static IEnumerable
-
+
diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/WindowsEmbeddedSignatureVerifierTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/WindowsEmbeddedSignatureVerifierTests.cs
index d8d68d30f84..f7eb743ad4e 100644
--- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/WindowsEmbeddedSignatureVerifierTests.cs
+++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/Plugins/WindowsEmbeddedSignatureVerifierTests.cs
@@ -22,10 +22,17 @@ public WindowsEmbeddedSignatureVerifierTests()
[InlineData("")]
public void IsValid_ThrowsForNullOrEmpty(string filePath)
{
- var expectedMessage = $"Argument cannot be null or empty.{Environment.NewLine}Parameter name: filePath";
+ var expectedMessage = "Argument cannot be null or empty.";
+ var expectedParam = "filePath";
var exception = Assert.Throws(() => _verifier.IsValid(filePath));
- Assert.Equal(expectedMessage, exception.Message);
+ Assert.Contains(expectedMessage, exception.Message);
+ Assert.Equal(expectedParam, exception.ParamName);
+ //Remove the expected message from the exception message, the rest part should have param info.
+ //Background of this change: System.ArgumentException(string message, string paramName) used to generate two lines of message before, but changed to generate one line
+ //in PR: https://github.com/dotnet/coreclr/pull/25185/files#diff-0365d5690376ef849bf908dfc225b8e8
+ var paramPart = exception.Message.Substring(exception.Message.IndexOf(expectedMessage) + expectedMessage.Length);
+ Assert.Contains(expectedParam, paramPart);
}
[PlatformFact(Platform.Windows)]
diff --git a/test/NuGet.Core.Tests/NuGet.Resolver.Test/NuGet.Resolver.Test.csproj b/test/NuGet.Core.Tests/NuGet.Resolver.Test/NuGet.Resolver.Test.csproj
index 19faf2c11ed..657af7a5aca 100644
--- a/test/NuGet.Core.Tests/NuGet.Resolver.Test/NuGet.Resolver.Test.csproj
+++ b/test/NuGet.Core.Tests/NuGet.Resolver.Test/NuGet.Resolver.Test.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Unit tests for NuGet.Resolver.
diff --git a/test/NuGet.Core.Tests/NuGet.Shared.Tests/NuGet.Shared.Tests.csproj b/test/NuGet.Core.Tests/NuGet.Shared.Tests/NuGet.Shared.Tests.csproj
index 6c68d67269a..8027ab1948a 100644
--- a/test/NuGet.Core.Tests/NuGet.Shared.Tests/NuGet.Shared.Tests.csproj
+++ b/test/NuGet.Core.Tests/NuGet.Shared.Tests/NuGet.Shared.Tests.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Unit tests for the utilities included using shared compilation.
diff --git a/test/NuGet.Core.Tests/NuGet.Versioning.Test/ExceptionAssert.cs b/test/NuGet.Core.Tests/NuGet.Versioning.Test/ExceptionAssert.cs
index 1a36c13e902..69f55a060f4 100644
--- a/test/NuGet.Core.Tests/NuGet.Versioning.Test/ExceptionAssert.cs
+++ b/test/NuGet.Core.Tests/NuGet.Versioning.Test/ExceptionAssert.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
@@ -75,13 +75,16 @@ public static void ThrowsArgumentException(Action act, string paramName, string
public static void ThrowsArgumentException(Action act, string paramName, string message) where TArgException : ArgumentException
{
Throws(act, ex =>
- {
- Assert.Equal(paramName, ex.ParamName);
- var lines = ex.Message.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
- Assert.Equal(2, lines.Length);
- Assert.Equal(message, lines[0]);
- Assert.True(lines[1].EndsWith(paramName));
- });
+ {
+ Assert.Equal(paramName, ex.ParamName);
+ Assert.Contains(message, ex.Message);
+ //Remove the expected message from the exception message, the rest part should have param info.
+ //Background of this change: System.ArgumentException(string message, string paramName) used to generate two lines of message before, but changed to generate one line
+ //in PR: https://github.com/dotnet/coreclr/pull/25185/files#diff-0365d5690376ef849bf908dfc225b8e8
+ var paramPart = ex.Message.Substring(ex.Message.IndexOf(message) + message.Length);
+ Assert.Contains("Parameter", paramPart);
+ Assert.Contains(paramName, paramPart);
+ });
}
}
}
diff --git a/test/NuGet.Core.Tests/NuGet.Versioning.Test/NuGet.Versioning.Test.csproj b/test/NuGet.Core.Tests/NuGet.Versioning.Test/NuGet.Versioning.Test.csproj
index f831dae9b1a..05224e60d88 100644
--- a/test/NuGet.Core.Tests/NuGet.Versioning.Test/NuGet.Versioning.Test.csproj
+++ b/test/NuGet.Core.Tests/NuGet.Versioning.Test/NuGet.Versioning.Test.csproj
@@ -1,10 +1,14 @@
+
+ true
+
+
$(TargetFrameworksExe)
- $(NETCoreTargetFramework)
+ $(NETCoreTargetFrameworks)
true
true
Unit tests for NuGet.Versioning.
diff --git a/test/TestExtensions/TestablePlugin/TestablePlugin.csproj b/test/TestExtensions/TestablePlugin/TestablePlugin.csproj
index e0da25d37b0..1569a572872 100644
--- a/test/TestExtensions/TestablePlugin/TestablePlugin.csproj
+++ b/test/TestExtensions/TestablePlugin/TestablePlugin.csproj
@@ -1,4 +1,8 @@
+
+ true
+
+
diff --git a/test/TestUtilities/Test.Utility/Signing/CertificateAuthority.cs b/test/TestUtilities/Test.Utility/Signing/CertificateAuthority.cs
index 3a3ee685c1c..ba9a917d312 100644
--- a/test/TestUtilities/Test.Utility/Signing/CertificateAuthority.cs
+++ b/test/TestUtilities/Test.Utility/Signing/CertificateAuthority.cs
@@ -152,7 +152,7 @@ public void Revoke(X509Certificate certificate, RevocationReason reason, DateTim
new RevocationInfo(certificate.SerialNumber, revocationDate, reason));
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
public override void Respond(HttpListenerContext context)
{
if (context == null)
@@ -332,4 +332,4 @@ internal RevocationInfo(BigInteger serialNumber, DateTimeOffset revocationDate,
}
}
}
-}
\ No newline at end of file
+}
diff --git a/test/TestUtilities/Test.Utility/Signing/CertificateStoreUtilities.cs b/test/TestUtilities/Test.Utility/Signing/CertificateStoreUtilities.cs
new file mode 100644
index 00000000000..07887bfff5d
--- /dev/null
+++ b/test/TestUtilities/Test.Utility/Signing/CertificateStoreUtilities.cs
@@ -0,0 +1,22 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Security.Cryptography.X509Certificates;
+using NuGet.Common;
+
+namespace Test.Utility.Signing
+{
+ public static class CertificateStoreUtilities
+ {
+ public static StoreLocation GetTrustedCertificateStoreLocation(bool readOnly = false)
+ {
+ // According to https://github.com/dotnet/runtime/blob/master/docs/design/features/cross-platform-cryptography.md#x509store
+ // use different approaches for Windows, Mac and Linux.
+ if(readOnly)
+ {
+ return StoreLocation.LocalMachine;
+ }
+ return (RuntimeEnvironmentHelper.IsWindows || RuntimeEnvironmentHelper.IsMacOSX) ? StoreLocation.LocalMachine : StoreLocation.CurrentUser;
+ }
+ }
+}
diff --git a/test/TestUtilities/Test.Utility/Signing/CertificateUtilities.cs b/test/TestUtilities/Test.Utility/Signing/CertificateUtilities.cs
index c7441a3fe92..eec3c134151 100644
--- a/test/TestUtilities/Test.Utility/Signing/CertificateUtilities.cs
+++ b/test/TestUtilities/Test.Utility/Signing/CertificateUtilities.cs
@@ -2,15 +2,19 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
using NuGet.Common;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
-using Org.BouncyCastle.X509;
+using Xunit;
+using X509Certificate = Org.BouncyCastle.X509.X509Certificate;
namespace Test.Utility.Signing
{
- internal static class CertificateUtilities
+ public static class CertificateUtilities
{
internal static AsymmetricCipherKeyPair CreateKeyPair(int strength = 2048)
{
@@ -35,5 +39,33 @@ internal static string GenerateRandomId()
{
return Guid.NewGuid().ToString();
}
+
+ public static X509Certificate2 GetCertificateWithPrivateKey(X509Certificate bcCertificate, AsymmetricCipherKeyPair keyPair)
+ {
+ Assert.IsType(keyPair.Private);
+
+ var privateKeyParameters = (RsaPrivateCrtKeyParameters)keyPair.Private;
+#if IS_DESKTOP
+ RSA privateKey = DotNetUtilities.ToRSA(privateKeyParameters);
+
+ var certificate = new X509Certificate2(bcCertificate.GetEncoded());
+
+ certificate.PrivateKey = privateKey;
+#else
+ RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(privateKeyParameters);
+
+ var privateKey = new RSACryptoServiceProvider();
+
+ privateKey.ImportParameters(rsaParameters);
+
+ X509Certificate2 certificate;
+
+ using (var certificateTmp = new X509Certificate2(bcCertificate.GetEncoded()))
+ {
+ certificate = RSACertificateExtensions.CopyWithPrivateKey(certificateTmp, privateKey);
+ }
+#endif
+ return certificate;
+ }
}
-}
\ No newline at end of file
+}
diff --git a/test/TestUtilities/Test.Utility/Signing/HttpResponder.cs b/test/TestUtilities/Test.Utility/Signing/HttpResponder.cs
index 45f7a357086..92719ad214d 100644
--- a/test/TestUtilities/Test.Utility/Signing/HttpResponder.cs
+++ b/test/TestUtilities/Test.Utility/Signing/HttpResponder.cs
@@ -11,7 +11,7 @@ public abstract class HttpResponder : IHttpResponder
{
public abstract Uri Url { get; }
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
public abstract void Respond(HttpListenerContext context);
protected static bool IsGet(HttpListenerRequest request)
@@ -43,4 +43,4 @@ protected static void WriteResponseBody(HttpListenerResponse response, byte[] by
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/test/TestUtilities/Test.Utility/Signing/IHttpResonder.cs b/test/TestUtilities/Test.Utility/Signing/IHttpResonder.cs
index 50f9827794b..b834929206c 100644
--- a/test/TestUtilities/Test.Utility/Signing/IHttpResonder.cs
+++ b/test/TestUtilities/Test.Utility/Signing/IHttpResonder.cs
@@ -10,8 +10,8 @@ public interface IHttpResponder
{
Uri Url { get; }
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
void Respond(HttpListenerContext context);
#endif
}
-}
\ No newline at end of file
+}
diff --git a/test/TestUtilities/Test.Utility/Signing/ISigningTestServer.cs b/test/TestUtilities/Test.Utility/Signing/ISigningTestServer.cs
index ed17fd07b47..98b5800f4b7 100644
--- a/test/TestUtilities/Test.Utility/Signing/ISigningTestServer.cs
+++ b/test/TestUtilities/Test.Utility/Signing/ISigningTestServer.cs
@@ -9,8 +9,8 @@ public interface ISigningTestServer
{
Uri Url { get; }
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
IDisposable RegisterResponder(IHttpResponder responder);
#endif
}
-}
\ No newline at end of file
+}
diff --git a/test/TestUtilities/Test.Utility/Signing/OcspResponder.cs b/test/TestUtilities/Test.Utility/Signing/OcspResponder.cs
index 7f562e864c2..016a256e04c 100644
--- a/test/TestUtilities/Test.Utility/Signing/OcspResponder.cs
+++ b/test/TestUtilities/Test.Utility/Signing/OcspResponder.cs
@@ -49,7 +49,7 @@ public static OcspResponder Create(
return new OcspResponder(certificateAuthority, options);
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
public override void Respond(HttpListenerContext context)
{
if (context == null)
@@ -174,4 +174,4 @@ private X509Certificate[] GetCertificateChain()
return certificates.ToArray();
}
}
-}
\ No newline at end of file
+}
diff --git a/test/TestUtilities/Test.Utility/Signing/SignatureTestUtility.cs b/test/TestUtilities/Test.Utility/Signing/SignatureTestUtility.cs
index 7d674c7b05b..cd99bdbfe03 100644
--- a/test/TestUtilities/Test.Utility/Signing/SignatureTestUtility.cs
+++ b/test/TestUtilities/Test.Utility/Signing/SignatureTestUtility.cs
@@ -15,7 +15,7 @@ namespace Test.Utility.Signing
{
public static class SignatureTestUtility
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
// Central Directory file header size excluding signature, file name, extra field and file comment
private const uint CentralDirectoryFileHeaderSizeWithoutSignature = 46;
diff --git a/test/TestUtilities/Test.Utility/Signing/SignedArchiveTestUtility.cs b/test/TestUtilities/Test.Utility/Signing/SignedArchiveTestUtility.cs
index d763b71e35d..3e12bd30f36 100644
--- a/test/TestUtilities/Test.Utility/Signing/SignedArchiveTestUtility.cs
+++ b/test/TestUtilities/Test.Utility/Signing/SignedArchiveTestUtility.cs
@@ -6,7 +6,7 @@
using System.IO;
using System.IO.Compression;
using System.Linq;
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
using System.Security.Cryptography.Pkcs;
#endif
using System.Security.Cryptography.X509Certificates;
@@ -22,7 +22,7 @@ namespace Test.Utility.Signing
{
public static class SignedArchiveTestUtility
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// Generates an author signed copy of a package and returns the path to that package
/// This method can timestamp a package and should only be used with tests marked with [CIOnlyFact]
@@ -53,7 +53,8 @@ public static async Task AuthorSignPackageAsync(
return await AuthorSignPackageAsync(certificate, timestampService, signatureHashAlgorithm, timestampHashAlgorithm, signedPackagePath, tempPath);
}
-
+#endif
+#if IS_SIGNING_SUPPORTED
///
/// Generates an author signed copy of a package and returns the path to that package
/// This method can timestamp a package and should only be used with tests marked with [CIOnlyFact]
@@ -89,7 +90,8 @@ public static async Task AuthorSignPackageAsync(
return await AuthorSignPackageAsync(certificate, timestampService, signatureHashAlgorithm, timestampHashAlgorithm, signedPackagePath, tempPath);
}
-
+#endif
+#if IS_SIGNING_SUPPORTED
private static async Task AuthorSignPackageAsync(
X509Certificate2 certificate,
Uri timestampService,
@@ -286,7 +288,7 @@ public static async Task RepositoryCountersignPrimarySignature
return await signatureProvider.CreateRepositoryCountersignatureAsync(request, signature, testLogger, CancellationToken.None);
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
// This generates a package with a basic signed CMS.
// The signature MUST NOT have any signed or unsigned attributes.
public static async Task SignPackageFileWithBasicSignedCmsAsync(
@@ -371,7 +373,7 @@ public static async Task IsRepositoryCountersignedAsync(Stream package)
var primarySignature = await reader.GetPrimarySignatureAsync(CancellationToken.None);
if (primarySignature != null)
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
return SignatureUtility.HasRepositoryCountersignature(primarySignature);
#endif
}
diff --git a/test/TestUtilities/Test.Utility/Signing/SigningTestServer.cs b/test/TestUtilities/Test.Utility/Signing/SigningTestServer.cs
index 6edfbb9fd93..526249e1d29 100644
--- a/test/TestUtilities/Test.Utility/Signing/SigningTestServer.cs
+++ b/test/TestUtilities/Test.Utility/Signing/SigningTestServer.cs
@@ -14,14 +14,14 @@ namespace Test.Utility.Signing
public sealed class SigningTestServer : ISigningTestServer, IDisposable
{
private readonly ConcurrentDictionary _responders = new ConcurrentDictionary();
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
private readonly HttpListener _listener;
private bool _isDisposed;
#endif
public Uri Url { get; }
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
private SigningTestServer(HttpListener listener, Uri url)
{
_listener = listener;
@@ -31,7 +31,7 @@ private SigningTestServer(HttpListener listener, Uri url)
public void Dispose()
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
if (!_isDisposed)
{
_listener.Stop();
@@ -56,7 +56,7 @@ public IDisposable RegisterResponder(IHttpResponder responder)
public static Task CreateAsync()
{
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
var portReserver = new PortReserver();
return portReserver.ExecuteAsync(
@@ -87,14 +87,16 @@ public static Task CreateAsync()
#endif
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
private static string GetBaseAbsolutePath(Uri url)
{
var path = url.PathAndQuery;
return path.Substring(0, path.IndexOf('/', 1) + 1);
}
+#endif
+#if IS_SIGNING_SUPPORTED
private void HandleRequest(ManualResetEventSlim mutex, CancellationToken cancellationToken)
{
mutex.Set();
@@ -168,4 +170,4 @@ public void Dispose()
}
}
}
-}
\ No newline at end of file
+}
diff --git a/test/TestUtilities/Test.Utility/Signing/SigningTestUtility.cs b/test/TestUtilities/Test.Utility/Signing/SigningTestUtility.cs
index e1af25638ec..df49a9d4cde 100644
--- a/test/TestUtilities/Test.Utility/Signing/SigningTestUtility.cs
+++ b/test/TestUtilities/Test.Utility/Signing/SigningTestUtility.cs
@@ -147,7 +147,7 @@ public static IList> GenerateCertificateChain(i
IsCA = true
};
- cert = TestCertificate.Generate(actionGenerator, chainCertificateRequest).WithPrivateKeyAndTrust(StoreName.Root, StoreLocation.LocalMachine);
+ cert = TestCertificate.Generate(actionGenerator, chainCertificateRequest).WithPrivateKeyAndTrust(StoreName.Root);
issuer = cert;
}
else if (i < length - 1) // intermediate CA cert
@@ -161,7 +161,7 @@ public static IList> GenerateCertificateChain(i
Issuer = issuer.Source.Cert
};
- cert = TestCertificate.Generate(actionGenerator, chainCertificateRequest).WithPrivateKeyAndTrust(StoreName.CertificateAuthority, StoreLocation.LocalMachine);
+ cert = TestCertificate.Generate(actionGenerator, chainCertificateRequest).WithPrivateKeyAndTrust(StoreName.CertificateAuthority);
issuer = cert;
}
else // leaf cert
@@ -175,7 +175,7 @@ public static IList> GenerateCertificateChain(i
Issuer = issuer.Source.Cert
};
- cert = TestCertificate.Generate(actionGenerator, chainCertificateRequest).WithPrivateKeyAndTrust(StoreName.My, StoreLocation.LocalMachine);
+ cert = TestCertificate.Generate(actionGenerator, chainCertificateRequest).WithPrivateKeyAndTrust(StoreName.My);
}
certChain.Add(cert);
@@ -243,7 +243,12 @@ private static X509Certificate2 GenerateCertificate(
var keyUsage = X509KeyUsageFlags.DigitalSignature;
- if (chainCertificateRequest != null)
+ if (chainCertificateRequest == null)
+ {
+ // Self-signed certificates should have this flag set.
+ keyUsage |= X509KeyUsageFlags.KeyCertSign;
+ }
+ else
{
if (chainCertificateRequest.Issuer != null)
{
@@ -286,6 +291,7 @@ private static X509Certificate2 GenerateCertificate(
var padding = paddingMode.ToPadding();
var request = new CertificateRequest(subjectDN, rsa, hashAlgorithm.ConvertToSystemSecurityHashAlgorithmName(), padding);
+ bool isCa = isSelfSigned ? true : (chainCertificateRequest?.IsCA ?? false);
certGen.NotAfter = notAfter ?? DateTime.UtcNow.Add(TimeSpan.FromMinutes(30));
certGen.NotBefore = DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(30));
@@ -301,7 +307,7 @@ private static X509Certificate2 GenerateCertificate(
certGen.Extensions.Add(
new X509KeyUsageExtension(keyUsage, critical: false));
certGen.Extensions.Add(
- new X509BasicConstraintsExtension(certificateAuthority: chainCertificateRequest?.IsCA ?? false, hasPathLengthConstraint: false, pathLengthConstraint: 0, critical: true));
+ new X509BasicConstraintsExtension(certificateAuthority: isCa, hasPathLengthConstraint: false, pathLengthConstraint: 0, critical: true));
// Allow changes
modifyGenerator?.Invoke(certGen);
@@ -490,7 +496,7 @@ public static SignedCms GenerateSignedCms(X509Certificate2 cert, byte[] content)
return cms;
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
///
/// Generates a SignedCMS object for some content.
///
@@ -541,7 +547,7 @@ public static TrustedTestCert GenerateTrustedTestCertificate()
// Code Sign EKU needs trust to a root authority
// Add the cert to Root CA list in LocalMachine as it does not prompt a dialog
// This makes all the associated tests to require admin privilege
- return TestCertificate.Generate(actionGenerator).WithTrust(StoreName.Root, StoreLocation.LocalMachine);
+ return TestCertificate.Generate(actionGenerator).WithTrust();
}
public static TrustedTestCert GenerateTrustedTestCertificateExpired()
@@ -551,7 +557,7 @@ public static TrustedTestCert GenerateTrustedTestCertificateExp
// Code Sign EKU needs trust to a root authority
// Add the cert to Root CA list in LocalMachine as it does not prompt a dialog
// This makes all the associated tests to require admin privilege
- return TestCertificate.Generate(actionGenerator).WithTrust(StoreName.Root, StoreLocation.LocalMachine);
+ return TestCertificate.Generate(actionGenerator).WithTrust();
}
public static TrustedTestCert GenerateTrustedTestCertificateNotYetValid()
@@ -561,7 +567,7 @@ public static TrustedTestCert GenerateTrustedTestCertificateNot
// Code Sign EKU needs trust to a root authority
// Add the cert to Root CA list in LocalMachine as it does not prompt a dialog
// This makes all the associated tests to require admin privilege
- return TestCertificate.Generate(actionGenerator).WithTrust(StoreName.Root, StoreLocation.LocalMachine);
+ return TestCertificate.Generate(actionGenerator).WithTrust();
}
public static TrustedTestCert GenerateTrustedTestCertificateThatWillExpireSoon(TimeSpan expiresIn)
@@ -571,7 +577,7 @@ public static TrustedTestCert GenerateTrustedTestCertificateTha
// Code Sign EKU needs trust to a root authority
// Add the cert to Root CA list in LocalMachine as it does not prompt a dialog
// This makes all the associated tests to require admin privilege
- return TestCertificate.Generate(actionGenerator).WithTrust(StoreName.Root, StoreLocation.LocalMachine);
+ return TestCertificate.Generate(actionGenerator).WithTrust();
}
public static bool AreVerifierSettingsEqual(SignedPackageVerifierSettings first, SignedPackageVerifierSettings second)
@@ -654,6 +660,8 @@ public static void VerifyByteArrays(byte[] expected, byte[] actual)
Assert.Equal(expectedHex, actualHex);
}
+ //We will not change the original X509ChainStatus.StatusInformation of OfflineRevocation if we directly call API CertificateChainUtility.GetCertificateChain (or SigningUtility.Verify)
+ //So if we use APIs above to verify the results of chain.build, we should use AssertOfflineRevocation
public static void AssertOfflineRevocation(IEnumerable issues, LogLevel logLevel)
{
string offlineRevocation;
@@ -677,7 +685,30 @@ public static void AssertOfflineRevocation(IEnumerable issues, LogL
issue.Message.Contains(offlineRevocation));
}
+ //We will change the original X509ChainStatus.StatusInformation of OfflineRevocation to VerifyCertTrustOfflineWhileRevocationModeOffline or VerifyCertTrustOfflineWhileRevocationModeOnline in Signature.cs and Timestamp.cs
+ //So if we use APIs above to verify the results of chain.build, we should use assert AssertOfflineRevocationOnlineMode and AssertOfflineRevocationOfflineMode
+ public static void AssertOfflineRevocationOnlineMode(IEnumerable issues, LogLevel logLevel)
+ {
+ Assert.Contains(issues, issue =>
+ issue.Code == NuGetLogCode.NU3018 &&
+ issue.Level == logLevel &&
+ issue.Message.Contains("The revocation function was unable to check revocation because the revocation server could not be reached. For more information, visit https://aka.ms/certificateRevocationMode."));
+ }
+
+ public static void AssertOfflineRevocationOfflineMode(IEnumerable issues)
+ {
+ Assert.Contains(issues, issue =>
+ issue.Code == NuGetLogCode.Undefined &&
+ issue.Level == LogLevel.Information &&
+ issue.Message.Contains("The revocation function was unable to check revocation because the certificate is not available in the cached certificate revocation list and NUGET_CERT_REVOCATION_MODE environment variable has been set to offline. For more information, visit https://aka.ms/certificateRevocationMode."));
+ }
+
public static void AssertRevocationStatusUnknown(IEnumerable issues, LogLevel logLevel)
+ {
+ AssertRevocationStatusUnknown(issues, logLevel, NuGetLogCode.NU3018);
+ }
+
+ public static void AssertRevocationStatusUnknown(IEnumerable issues, LogLevel logLevel, NuGetLogCode code)
{
string revocationStatusUnknown;
@@ -693,9 +724,9 @@ public static void AssertRevocationStatusUnknown(IEnumerable issues
{
revocationStatusUnknown = "unable to get certificate CRL";
}
-
+
Assert.Contains(issues, issue =>
- issue.Code == NuGetLogCode.NU3018 &&
+ issue.Code == code &&
issue.Level == logLevel &&
issue.Message.Contains(revocationStatusUnknown));
}
@@ -710,7 +741,7 @@ public static void AssertUntrustedRoot(IEnumerable issues, LogLevel
}
else if (RuntimeEnvironmentHelper.IsMacOSX)
{
- untrustedRoot = "The trust policy was not trusted.";
+ untrustedRoot = "The certificate was not trusted.";
}
else
{
@@ -739,7 +770,7 @@ public static void AssertNotTimeValid(IEnumerable issues, LogLevel
{
notTimeValid = "certificate has expired";
}
-
+
Assert.Contains(issues, issue =>
issue.Code == NuGetLogCode.NU3018 &&
issue.Level == logLevel &&
diff --git a/test/TestUtilities/Test.Utility/Signing/TestCertificate.cs b/test/TestUtilities/Test.Utility/Signing/TestCertificate.cs
index 37830910c44..e69dbf1bc73 100644
--- a/test/TestUtilities/Test.Utility/Signing/TestCertificate.cs
+++ b/test/TestUtilities/Test.Utility/Signing/TestCertificate.cs
@@ -3,6 +3,7 @@
using System;
using System.Security.Cryptography.X509Certificates;
+using NuGet.Common;
namespace Test.Utility.Signing
{
@@ -36,17 +37,23 @@ public class TestCertificate
/// Trust the PublicCert cert for the life of the object.
///
/// Dispose of the object returned!
- public TrustedTestCert WithTrust(StoreName storeName = StoreName.TrustedPeople, StoreLocation storeLocation = StoreLocation.CurrentUser)
+ /// According to https://github.com/dotnet/corefx/blob/master/Documentation/architecture/cross-platform-cryptography.md#x509store
+ /// Linux could not read/write LocalMachine\Root , but could only read/write CurrentUser\Root
+ public TrustedTestCert WithTrust()
{
- return new TrustedTestCert(this, e => PublicCert, storeName, storeLocation);
+ StoreLocation storeLocation = CertificateStoreUtilities.GetTrustedCertificateStoreLocation();
+
+ return new TrustedTestCert(this, e => PublicCert, StoreName.Root, storeLocation);
}
///
/// Trust the PublicCert cert for the life of the object.
///
/// Dispose of the object returned!
- public TrustedTestCert WithPrivateKeyAndTrust(StoreName storeName = StoreName.TrustedPeople, StoreLocation storeLocation = StoreLocation.CurrentUser)
+ public TrustedTestCert WithPrivateKeyAndTrust(StoreName storeName = StoreName.TrustedPeople)
{
+ StoreLocation storeLocation = CertificateStoreUtilities.GetTrustedCertificateStoreLocation();
+
return new TrustedTestCert(this, e => PublicCertWithPrivateKey, storeName, storeLocation);
}
diff --git a/test/TestUtilities/Test.Utility/Signing/TimestampService.cs b/test/TestUtilities/Test.Utility/Signing/TimestampService.cs
index a79b7d2e93d..eb211b0486e 100644
--- a/test/TestUtilities/Test.Utility/Signing/TimestampService.cs
+++ b/test/TestUtilities/Test.Utility/Signing/TimestampService.cs
@@ -136,7 +136,7 @@ void customizeCertificate(X509V3CertificateGenerator generator)
return new TimestampService(certificateAuthority, certificate, issueCertificateOptions.KeyPair, uri, serviceOptions);
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
public override void Respond(HttpListenerContext context)
{
if (context == null)
diff --git a/test/TestUtilities/Test.Utility/Signing/TrustedTestCert.cs b/test/TestUtilities/Test.Utility/Signing/TrustedTestCert.cs
index 8c5133c09cd..cf063f37eec 100644
--- a/test/TestUtilities/Test.Utility/Signing/TrustedTestCert.cs
+++ b/test/TestUtilities/Test.Utility/Signing/TrustedTestCert.cs
@@ -2,7 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.IO;
using System.Security.Cryptography.X509Certificates;
+using System.Threading;
+using NuGet.Common;
+using NuGet.Test.Utility;
namespace Test.Utility.Signing
{
@@ -40,6 +44,8 @@ public class TrustedTestCert : IDisposable
private bool _isDisposed;
+ private const string KeychainForMac = "/Library/Keychains/System.keychain";
+
public TrustedTestCert(T source,
Func getCert,
StoreName storeName = StoreName.TrustedPeople,
@@ -54,15 +60,23 @@ public TrustedTestCert(T source,
maximumValidityPeriod = TimeSpan.FromHours(2);
}
-#if IS_DESKTOP
+#if IS_SIGNING_SUPPORTED
if (TrustedCert.NotAfter - TrustedCert.NotBefore > maximumValidityPeriod.Value)
{
throw new InvalidOperationException($"The certificate used is valid for more than {maximumValidityPeriod}.");
}
#endif
- StoreName = storeName;
- StoreLocation = storeLocation;
- AddCertificateToStore();
+ if (RuntimeEnvironmentHelper.IsMacOSX)
+ {
+ AddCertificateToStoreForMacOSX();
+ }
+ else
+ {
+ StoreName = storeName;
+ StoreLocation = storeLocation;
+ AddCertificateToStore();
+ }
+
ExportCrl();
}
@@ -71,6 +85,88 @@ private void AddCertificateToStore()
_store = new X509Store(StoreName, StoreLocation);
_store.Open(OpenFlags.ReadWrite);
_store.Add(TrustedCert);
+
+ //Add wait for Linux, as https://github.com/dotnet/runtime/issues/32608
+ //Windows has a live-synchronized model, and on Linux, there is a filesystem/rescan delay problem.
+ //For performance reasons, dotnet/runtime only check to see if the store has been modified once a second.
+ if (RuntimeEnvironmentHelper.IsLinux)
+ {
+ Thread.Sleep(1500);
+
+ var MaxTries = 30;
+
+ for (var i = 0; i < MaxTries; i++)
+ {
+ using (var chain = new X509Chain())
+ {
+ chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
+
+ if (chain.Build(TrustedCert))
+ {
+ break;
+ }
+ else
+ {
+ Thread.Sleep(1000);
+ }
+ }
+ }
+ }
+ }
+
+ //According to https://github.com/dotnet/runtime/blob/master/docs/design/features/cross-platform-cryptography.md#x509store,
+ //on macOS the X509Store class is a projection of system trust decisions (read-only), user trust decisions (read-only), and user key storage (read-write).
+ //So we have to run command to add certificate to System.keychain to make it trusted.
+ private void AddCertificateToStoreForMacOSX()
+ {
+ var certFile = new FileInfo(Path.Combine("/tmp", $"{TrustedCert.Thumbprint}.cer"));
+
+ File.WriteAllBytes(certFile.FullName, TrustedCert.RawData);
+
+ string addToKeyChainCmd = $"sudo security add-trusted-cert -d -r trustRoot " +
+ $"-k \"{KeychainForMac}\" " +
+ $"\"{certFile.FullName}\"";
+
+ RunMacCommand(addToKeyChainCmd);
+ }
+
+ //According to https://github.com/dotnet/runtime/blob/master/docs/design/features/cross-platform-cryptography.md#x509store,
+ //on macOS the X509Store class is a projection of system trust decisions (read-only), user trust decisions (read-only), and user key storage (read-write).
+ //So we have to run command to remove certificate from System.keychain to make it untrusted.
+ private void RemoveTrustedCert()
+ {
+ var certFile = new FileInfo(Path.Combine("/tmp", $"{TrustedCert.Thumbprint}.cer"));
+
+ string removeFromKeyChainCmd = $"sudo security delete-certificate -Z {TrustedCert.Thumbprint} \"{KeychainForMac}\"";
+
+ try
+ {
+ RunMacCommand(removeFromKeyChainCmd);
+ }
+ finally
+ {
+ certFile.Delete();
+ }
+ }
+
+ private static void RunMacCommand(string cmd)
+ {
+ string workingDirectory = "/bin";
+ string args = "-c \"" + cmd + "\"";
+
+ CommandRunnerResult result = CommandRunner.Run("/bin/bash",
+ workingDirectory,
+ args,
+ waitForExit: true,
+ timeOutInMilliseconds: 60000);
+
+ if (!result.Success)
+ {
+ throw new SystemToolException($"Run security command failed with following log information :\n" +
+ $"exit code = {result.ExitCode} \n" +
+ $"exit output = {result.Output} \n" +
+ $"exit error = {result.Errors} \n");
+ }
}
private void ExportCrl()
@@ -97,9 +193,16 @@ public void Dispose()
{
if (!_isDisposed)
{
- using (_store)
+ if (RuntimeEnvironmentHelper.IsMacOSX)
+ {
+ RemoveTrustedCert();
+ }
+ else
{
- _store.Remove(TrustedCert);
+ using (_store)
+ {
+ _store.Remove(TrustedCert);
+ }
}
DisposeCrl();
@@ -110,4 +213,4 @@ public void Dispose()
}
}
}
-}
\ No newline at end of file
+}
diff --git a/test/TestUtilities/Test.Utility/SystemToolException.cs b/test/TestUtilities/Test.Utility/SystemToolException.cs
new file mode 100644
index 00000000000..a4b55ae2282
--- /dev/null
+++ b/test/TestUtilities/Test.Utility/SystemToolException.cs
@@ -0,0 +1,30 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Globalization;
+
+namespace Test.Utility
+{
+ internal sealed class SystemToolException : Exception
+ {
+ public SystemToolException()
+ {
+ }
+
+ public SystemToolException(string message)
+ : base(message)
+ {
+ }
+
+ public SystemToolException(string format, params object[] args)
+ : base(string.Format(CultureInfo.CurrentCulture, format, args))
+ {
+ }
+
+ public SystemToolException(string message, Exception exception)
+ : base(message, exception)
+ {
+ }
+ }
+}
diff --git a/test/TestUtilities/Test.Utility/Test.Utility.csproj b/test/TestUtilities/Test.Utility/Test.Utility.csproj
index 86312f8495b..96ed273aa5a 100644
--- a/test/TestUtilities/Test.Utility/Test.Utility.csproj
+++ b/test/TestUtilities/Test.Utility/Test.Utility.csproj
@@ -1,11 +1,15 @@
+
+ true
+
+
$(TargetFrameworksExe)
$(NoWarn);CS1591
- $(NoWarn);CS1998
+ $(NoWarn);CS1998
true
true
true
@@ -64,14 +68,14 @@
-
+
-
+