diff --git a/src/arcade/Arcade.slnx b/src/arcade/Arcade.slnx
index cc381104afc..a4c51eaafd6 100644
--- a/src/arcade/Arcade.slnx
+++ b/src/arcade/Arcade.slnx
@@ -45,6 +45,7 @@
+
@@ -71,7 +72,6 @@
-
diff --git a/src/arcade/eng/Version.Details.props b/src/arcade/eng/Version.Details.props
index 39ca5e519b3..74f32236a9c 100644
--- a/src/arcade/eng/Version.Details.props
+++ b/src/arcade/eng/Version.Details.props
@@ -14,8 +14,8 @@ This file should be imported by eng/Versions.props
10.0.100-preview.4.25220.1
- 10.0.0-beta.25469.2
- 10.0.0-beta.25469.2
+ 10.0.0-beta.25507.1
+ 10.0.0-beta.25507.1
1.1.0-beta.25424.1
1.1.0-beta.25424.1
diff --git a/src/arcade/eng/Version.Details.xml b/src/arcade/eng/Version.Details.xml
index b108dd09482..8e4ff3e2e9b 100644
--- a/src/arcade/eng/Version.Details.xml
+++ b/src/arcade/eng/Version.Details.xml
@@ -20,13 +20,13 @@
https://github.com/dotnet/templating
43b5827697e501c442eb75ffff832cd4df2514fe
-
+
https://github.com/dotnet/arcade
- 6275af47ebda0d394d4a5a401b77bc6f2304204a
+ 4eaa220ea860cee9fa61df42411bbf79394edd23
-
+
https://github.com/dotnet/arcade
- 6275af47ebda0d394d4a5a401b77bc6f2304204a
+ 4eaa220ea860cee9fa61df42411bbf79394edd23
https://github.com/dotnet/arcade-services
diff --git a/src/arcade/global.json b/src/arcade/global.json
index a90a1ab74f6..b8b866ce354 100644
--- a/src/arcade/global.json
+++ b/src/arcade/global.json
@@ -12,8 +12,8 @@
"dotnet": "10.0.100-rc.1.25451.107"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25469.2",
- "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25469.2",
+ "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25507.1",
+ "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25507.1",
"Microsoft.Build.NoTargets": "3.7.0"
}
}
diff --git a/src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/build/wix5/bundle/bundle.wxs b/src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/build/wix5/bundle/bundle.wxs
index b7fb42ee99b..1c5db2ade1d 100644
--- a/src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/build/wix5/bundle/bundle.wxs
+++ b/src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/build/wix5/bundle/bundle.wxs
@@ -61,7 +61,15 @@
-
+
+
+
+
+
+
+
+
+
diff --git a/src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/build/wix5/wix.targets b/src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/build/wix5/wix.targets
index 8632bcf50af..742bf80955f 100644
--- a/src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/build/wix5/wix.targets
+++ b/src/arcade/src/Microsoft.DotNet.Build.Tasks.Installers/build/wix5/wix.targets
@@ -340,7 +340,7 @@
-
+
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool.Tests/Resources/InnerZipFile.zip b/src/arcade/src/Microsoft.DotNet.SignTool.Tests/Resources/InnerZipFile.zip
new file mode 100644
index 00000000000..333b5199c4e
Binary files /dev/null and b/src/arcade/src/Microsoft.DotNet.SignTool.Tests/Resources/InnerZipFile.zip differ
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool.Tests/SignToolTests.cs b/src/arcade/src/Microsoft.DotNet.SignTool.Tests/SignToolTests.cs
index cacd084dab3..3b4cd8581ea 100644
--- a/src/arcade/src/Microsoft.DotNet.SignTool.Tests/SignToolTests.cs
+++ b/src/arcade/src/Microsoft.DotNet.SignTool.Tests/SignToolTests.cs
@@ -1281,6 +1281,93 @@ public void SignZipFile()
});
}
+ [Fact]
+ public void SignArchivesUsingDetachedSignature()
+ {
+ // List of files to be considered for signing
+ var itemsToSign = new List()
+ {
+ new ItemToSign(GetResourcePath("test.zip")),
+ new ItemToSign(GetResourcePath("test.tgz")),
+ new ItemToSign(GetResourcePath("NestedZip.zip")),
+ new ItemToSign(GetResourcePath("InnerZipFile.zip"))
+ };
+
+ var strongNameSignInfo = new Dictionary>();
+
+ // Overriding information
+ var explicitCertKeys = new Dictionary()
+ {
+ { new ExplicitCertificateKey("test.zip"), "ArchiveCert" },
+ { new ExplicitCertificateKey("test.tgz"), "ArchiveCert" },
+ { new ExplicitCertificateKey("InnerZipFile.zip"), "ArchiveCert" }
+ };
+
+ var additionalCertificateInfo = new Dictionary>()
+ {
+ { "ArchiveCert",
+ new List() {
+ new AdditionalCertificateInformation() { GeneratesDetachedSignature = true }
+ }
+ }
+ };
+
+ ValidateFileSignInfos(itemsToSign, strongNameSignInfo, explicitCertKeys, s_fileExtensionSignInfo, new[]
+ {
+ "File 'NativeLibrary.dll' Certificate='Microsoft400'",
+ "File 'SOS.NETCore.dll' TargetFramework='.NETCoreApp,Version=v1.0' Certificate='Microsoft400'",
+ "File 'Nested.NativeLibrary.dll' Certificate='Microsoft400'",
+ "File 'Nested.SOS.NETCore.dll' TargetFramework='.NETCoreApp,Version=v1.0' Certificate='Microsoft400'",
+ "File 'test.zip' Certificate='ArchiveCert'",
+ "File 'test.tgz' Certificate='ArchiveCert'",
+ "File 'InnerZipFile.zip' Certificate='ArchiveCert'",
+ "File 'Mid.SOS.NETCore.dll' TargetFramework='.NETCoreApp,Version=v1.0' Certificate='Microsoft400'",
+ "File 'MidNativeLibrary.dll' Certificate='Microsoft400'",
+ "File 'NestedZip.zip'",
+ },
+ additionalCertificateInfo: additionalCertificateInfo,
+ expectedCopyFiles: new[]
+ {
+ $"{Path.Combine(_tmpDir, "ContainerSigning", "6", "InnerZipFile.zip")} -> {Path.Combine(_tmpDir, "InnerZipFile.zip")}",
+ $"{Path.Combine(_tmpDir, "ContainerSigning", "6", "InnerZipFile.zip.sig")} -> {Path.Combine(_tmpDir, "InnerZipFile.zip.sig")}"
+ });
+
+ ValidateGeneratedProject(itemsToSign, strongNameSignInfo, explicitCertKeys, s_fileExtensionSignInfo, new[]
+ {
+$@"
+
+ Microsoft400
+
+
+ Microsoft400
+
+
+ Microsoft400
+
+
+ Microsoft400
+
+
+ Microsoft400
+
+
+ Microsoft400
+
+",
+$@"
+
+ ArchiveCert
+
+
+ ArchiveCert
+
+
+ ArchiveCert
+
+"
+ }, additionalCertificateInfo: additionalCertificateInfo);
+ }
+
///
/// Verifies that signing of pkgs can be done on Windows, even though
/// we will not unpack or repack them.
@@ -2590,6 +2677,11 @@ public void ValidateSignToolTaskParsing()
}),
// Signed pe file
new TaskItem(GetResourcePath("SignedLibrary.dll"), new Dictionary
+ {
+ { SignToolConstants.CollisionPriorityId, "123" }
+ }),
+ // Sign a test.zip
+ new TaskItem(GetResourcePath("test.zip"), new Dictionary
{
{ SignToolConstants.CollisionPriorityId, "123" }
})
@@ -2621,6 +2713,11 @@ public void ValidateSignToolTaskParsing()
{ "CertificateName", "DualSignCertificate" },
{ "PublicKeyToken", "31bf3856ad364e35" },
{ "CollisionPriorityId", "123" }
+ }),
+ new TaskItem("test.zip", new Dictionary
+ {
+ { "CertificateName", "DetachedArchiveCert" },
+ { "CollisionPriorityId", "123" }
})
};
@@ -2637,7 +2734,11 @@ public void ValidateSignToolTaskParsing()
{ "MacCertificate", "MacDeveloperHarden" },
{ "MacNotarizationAppName", "com.microsoft.dotnet" },
{ "CollisionPriorityId", "123" }
- })
+ }),
+ new TaskItem("DetachedArchiveCert", new Dictionary
+ {
+ { "DetachedSignature", "true" }
+ }),
};
var task = new SignToolTask
@@ -2670,7 +2771,11 @@ public void ValidateSignToolTaskParsing()
"File 'ProjectOne.dll' TargetFramework='.NETCoreApp,Version=v2.1' Certificate='3PartySHA2' StrongName='ArcadeStrongTest'",
"File 'ProjectOne.dll' TargetFramework='.NETStandard,Version=v2.0' Certificate='OverrideCertificateName' StrongName='ArcadeStrongTest'",
"File 'ContainerOne.1.0.0.nupkg' Certificate='NuGet'",
- "File 'SignedLibrary.dll' TargetFramework='.NETCoreApp,Version=v2.0' Certificate='DualSignCertificate'"
+ "File 'SignedLibrary.dll' TargetFramework='.NETCoreApp,Version=v2.0' Certificate='DualSignCertificate'",
+ "File 'SOS.NETCore.dll' TargetFramework='.NETCoreApp,Version=v1.0' Certificate='Microsoft400'",
+ "File 'Nested.NativeLibrary.dll' Certificate='Microsoft400'",
+ "File 'Nested.SOS.NETCore.dll' TargetFramework='.NETCoreApp,Version=v1.0' Certificate='Microsoft400'",
+ "File 'test.zip' Certificate='DetachedArchiveCert'"
};
task.ParsedSigningInput.FilesToSign.Select(f => f.ToString()).Should().BeEquivalentTo(expected);
}
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool/src/AdditionalCertificateInformation.cs b/src/arcade/src/Microsoft.DotNet.SignTool/src/AdditionalCertificateInformation.cs
index e7e2ed2f4a2..06f87035dee 100644
--- a/src/arcade/src/Microsoft.DotNet.SignTool/src/AdditionalCertificateInformation.cs
+++ b/src/arcade/src/Microsoft.DotNet.SignTool/src/AdditionalCertificateInformation.cs
@@ -21,6 +21,10 @@ public class AdditionalCertificateInformation
/// If the certificate name represents a sign+notarize operation, this is the name of the notarize operation.
///
public string MacNotarizationAppName { get; set; }
+ ///
+ /// If true, this certificate should generate detached signatures instead of in-place signing.
+ ///
+ public bool GeneratesDetachedSignature { get; set; }
public string CollisionPriorityId { get; set; }
}
}
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool/src/BatchSignUtil.cs b/src/arcade/src/Microsoft.DotNet.SignTool/src/BatchSignUtil.cs
index 1eaca00b273..ecd63cf0009 100644
--- a/src/arcade/src/Microsoft.DotNet.SignTool/src/BatchSignUtil.cs
+++ b/src/arcade/src/Microsoft.DotNet.SignTool/src/BatchSignUtil.cs
@@ -554,9 +554,10 @@ private void VerifyCertificates(TaskLoggingHelper log)
}
else if (fileName.IsZip())
{
- if (fileName.SignInfo.Certificate != null)
+ // Zip files can't be signed without a detached signature. If a certificate is provided but the signature is not detached.
+ if (!fileName.SignInfo.GeneratesDetachedSignature && fileName.SignInfo.Certificate != null)
{
- log.LogError($"Zip {fileName} should not be signed with this certificate: {fileName.SignInfo.Certificate}");
+ log.LogError($"'{fileName}' may only be signed with a detached signature. '{fileName.SignInfo.Certificate}' does not produce a detached signature");
}
if (fileName.SignInfo.StrongName != null)
@@ -564,6 +565,19 @@ private void VerifyCertificates(TaskLoggingHelper log)
log.LogError($"Zip {fileName} cannot be strong name signed.");
}
}
+ else if (fileName.IsTarGZip())
+ {
+ // Tar.gz files can't be signed without a detached signature. If a certificate is provided but the signature is not detached.
+ if (!fileName.SignInfo.GeneratesDetachedSignature && fileName.SignInfo.Certificate != null)
+ {
+ log.LogError($"'{fileName}' may only be signed with a detached signature. '{fileName.SignInfo.Certificate}' does not produce a detached signature");
+ }
+
+ if (fileName.SignInfo.StrongName != null)
+ {
+ log.LogError($"TarGZip {fileName} cannot be strong name signed.");
+ }
+ }
if (fileName.IsExecutableWixContainer())
{
if (isInvalidEmptyCertificate)
@@ -589,7 +603,28 @@ private void VerifyAfterSign(TaskLoggingHelper log, FileSignInfo file)
// No need to check if the file should not have been signed.
if (file.SignInfo.ShouldSign)
{
- if (file.IsPEFile())
+ // For files with detached signatures, verify the .sig file exists
+ if (file.SignInfo.GeneratesDetachedSignature)
+ {
+ string sigFilePath = file.DetachedSignatureFullPath;
+ if (!File.Exists(sigFilePath))
+ {
+ _log.LogError($"Detached signature file {sigFilePath} does not exist for {file.FullPath}");
+ }
+ else
+ {
+ var fileInfo = new FileInfo(sigFilePath);
+ if (fileInfo.Length == 0)
+ {
+ _log.LogError($"Detached signature file {sigFilePath} is empty.");
+ }
+ else
+ {
+ _log.LogMessage(MessageImportance.Low, $"Detached signature file {sigFilePath} exists and is non-empty.");
+ }
+ }
+ }
+ else if (file.IsPEFile())
{
using (var stream = File.OpenRead(file.FullPath))
{
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool/src/Configuration.cs b/src/arcade/src/Microsoft.DotNet.SignTool/src/Configuration.cs
index 8a48211bb31..1eb5b38408c 100644
--- a/src/arcade/src/Microsoft.DotNet.SignTool/src/Configuration.cs
+++ b/src/arcade/src/Microsoft.DotNet.SignTool/src/Configuration.cs
@@ -224,6 +224,14 @@ private FileSignInfo TrackFile(PathWithHash file, PathWithHash parentContainer,
// Copy the signed content to the destination path.
_filesToCopy.Add(new KeyValuePair(existingSignInfo.FullPath, file.FullPath));
+
+ // If this is a top-level file that uses detached signatures, also copy the detached signature file
+ if (existingSignInfo.SignInfo.GeneratesDetachedSignature)
+ {
+ _filesToCopy.Add(new KeyValuePair(existingSignInfo.DetachedSignatureFullPath, fileSignInfo.DetachedSignatureFullPath));
+ _log.LogMessage(MessageImportance.Low, $"Will copy detached signature from '{existingSignInfo.DetachedSignatureFullPath}' to '{fileSignInfo.DetachedSignatureFullPath}'");
+ }
+
return fileSignInfo;
}
@@ -262,7 +270,7 @@ private FileSignInfo TrackFile(PathWithHash file, PathWithHash parentContainer,
// Only sign containers if the file itself is unsigned, or
// an item in the container is unsigned.
hasSignableParts = _zipDataMap[fileSignInfo.FileContentKey].NestedParts.Values.Any(b => b.FileSignInfo.SignInfo.ShouldSign || b.FileSignInfo.HasSignableParts);
- if(hasSignableParts)
+ if (hasSignableParts)
{
// If the file has contents that need to be signed, then re-evaluate the signing info
fileSignInfo = fileSignInfo.WithSignableParts();
@@ -529,6 +537,12 @@ private FileSignInfo ExtractSignInfo(
Check3rdPartyMicrosoftSignatureMismatch(file, peInfo, signInfo);
+ // Check if this cert should use detached signatures instead of in-place signing
+ if (ShouldUseDetachedSignature(file, signInfo))
+ {
+ signInfo = signInfo.WithDetachedSignature(signInfo.Certificate);
+ }
+
return new FileSignInfo(file, signInfo, (peInfo != null && peInfo.TargetFramework != "") ? peInfo.TargetFramework : null, wixContentFilePath: wixContentFilePath);
}
@@ -864,5 +878,27 @@ private bool ShouldSkip3rdPartyCheck(string fileName)
{
return _itemsToSkip3rdPartyCheck != null && _itemsToSkip3rdPartyCheck.Contains(Path.GetFileName(fileName));
}
+
+ ///
+ /// Determines if a file should use detached signatures based on certificate configuration.
+ ///
+ /// The file to check
+ /// True if the file should use detached signatures
+ private bool ShouldUseDetachedSignature(PathWithHash file, SignInfo signInfo)
+ {
+ // Check if the certificate is configured for detached signatures
+ if (signInfo.Certificate != null && _additionalCertificateInformation.TryGetValue(signInfo.Certificate, out var additionalInfo))
+ {
+ var additionalCertInfo = additionalInfo.FirstOrDefault(a => string.IsNullOrEmpty(a.CollisionPriorityId) ||
+ a.CollisionPriorityId == signInfo.CollisionPriorityId);
+ if (additionalCertInfo != null && additionalCertInfo.GeneratesDetachedSignature)
+ {
+ _log.LogMessage(MessageImportance.Low, $"File {file.FileName} will use detached signatures based on certificate configuration");
+ return true;
+ }
+ }
+
+ return false;
+ }
}
}
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool/src/ExplicitCertificateKey.cs b/src/arcade/src/Microsoft.DotNet.SignTool/src/ExplicitCertificateKey.cs
index b8c775ddb36..14f4531cbcf 100644
--- a/src/arcade/src/Microsoft.DotNet.SignTool/src/ExplicitCertificateKey.cs
+++ b/src/arcade/src/Microsoft.DotNet.SignTool/src/ExplicitCertificateKey.cs
@@ -25,20 +25,6 @@ public ExplicitCertificateKey(string fileName, string publicKeyToken = null, str
ExecutableType = executableType;
}
- private static ExecutableType ParseExecutableType(string executableType)
- {
- if (string.IsNullOrEmpty(executableType))
- return ExecutableType.None;
-
- return executableType switch
- {
- "PE" => ExecutableType.PE,
- "MachO" => ExecutableType.MachO,
- "ELF" => ExecutableType.ELF,
- _ => ExecutableType.None
- };
- }
-
public override bool Equals(object obj)
=> obj is ExplicitCertificateKey key && Equals(key);
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool/src/FileSignInfo.cs b/src/arcade/src/Microsoft.DotNet.SignTool/src/FileSignInfo.cs
index 62e5c8636f6..47062c119c6 100644
--- a/src/arcade/src/Microsoft.DotNet.SignTool/src/FileSignInfo.cs
+++ b/src/arcade/src/Microsoft.DotNet.SignTool/src/FileSignInfo.cs
@@ -17,6 +17,9 @@ internal readonly struct FileSignInfo
internal readonly SignInfo SignInfo;
internal ImmutableArray ContentHash => File.ContentHash;
internal readonly string WixContentFilePath;
+ internal string DetachedSignatureFilePath => $"{FileName}.sig";
+ internal string DetachedSignatureFullPath => $"{FullPath}.sig";
+
internal readonly PathWithHash File;
// optional file information that allows to disambiguate among multiple files with the same name:
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool/src/SignInfo.cs b/src/arcade/src/Microsoft.DotNet.SignTool/src/SignInfo.cs
index a6bb1087218..2f618337432 100644
--- a/src/arcade/src/Microsoft.DotNet.SignTool/src/SignInfo.cs
+++ b/src/arcade/src/Microsoft.DotNet.SignTool/src/SignInfo.cs
@@ -18,6 +18,11 @@ internal readonly struct SignInfo
///
public static readonly SignInfo AlreadySigned = new SignInfo(ignoreThisFile: false, alreadySigned: true, isAlreadyStrongNamed: false);
+ ///
+ /// Used to flag that the file should generate a detached signature.
+ ///
+ public static readonly SignInfo DetachedSignature = new SignInfo(ignoreThisFile: false, alreadySigned: false, isAlreadyStrongNamed: false, generatesDetachedSignature: true);
+
///
/// The authenticode certificate which should be used to sign the binary. This can be null
/// in cases where we have a zip container where the contents are signed but not the actual
@@ -42,6 +47,11 @@ internal readonly struct SignInfo
internal bool IsAlreadySigned { get; }
+ ///
+ /// True if this file should generate a detached signature rather than being signed in-place.
+ ///
+ internal bool GeneratesDetachedSignature { get; }
+
///
/// This is used to decide what SignInfos to use in the case of a collision. In case of a collision
/// we'll use the lower value since it would map a lower node in the graph and has precedence
@@ -57,7 +67,7 @@ internal readonly struct SignInfo
public bool ShouldNotarize => !string.IsNullOrEmpty(NotarizationAppName) && !ShouldIgnore;
- public SignInfo(string certificate, string strongName, string notarizationAppName, string collisionPriorityId, bool shouldIgnore, bool isAlreadySigned, bool isAlreadyStrongNamed)
+ private SignInfo(string certificate, string strongName, string notarizationAppName, string collisionPriorityId, bool shouldIgnore, bool isAlreadySigned, bool isAlreadyStrongNamed, bool generatesDetachedSignature = false)
{
ShouldIgnore = shouldIgnore;
IsAlreadySigned = isAlreadySigned;
@@ -66,10 +76,11 @@ public SignInfo(string certificate, string strongName, string notarizationAppNam
CollisionPriorityId = collisionPriorityId;
IsAlreadyStrongNamed = isAlreadyStrongNamed;
NotarizationAppName = notarizationAppName;
+ GeneratesDetachedSignature = generatesDetachedSignature;
}
- private SignInfo(bool ignoreThisFile, bool alreadySigned, bool isAlreadyStrongNamed)
- : this(certificate: null, strongName: null, notarizationAppName: null, collisionPriorityId: null, ignoreThisFile, alreadySigned, isAlreadyStrongNamed)
+ private SignInfo(bool ignoreThisFile, bool alreadySigned, bool isAlreadyStrongNamed, bool generatesDetachedSignature = false)
+ : this(certificate: null, strongName: null, notarizationAppName: null, collisionPriorityId: null, ignoreThisFile, alreadySigned, isAlreadyStrongNamed, generatesDetachedSignature)
{
}
@@ -79,20 +90,23 @@ internal SignInfo(string certificate, string strongName = null, string notarizat
}
internal SignInfo WithCertificateName(string value, string collisionPriorityId)
- => new SignInfo(value, StrongName, NotarizationAppName, collisionPriorityId, false, false, IsAlreadyStrongNamed);
+ => new SignInfo(value, StrongName, NotarizationAppName, collisionPriorityId, false, false, IsAlreadyStrongNamed, GeneratesDetachedSignature);
internal SignInfo WithNotarization(string appName, string collisionPriorityId)
- => new SignInfo(Certificate, StrongName, appName, collisionPriorityId, false, false, IsAlreadyStrongNamed);
+ => new SignInfo(Certificate, StrongName, appName, collisionPriorityId, false, false, IsAlreadyStrongNamed, GeneratesDetachedSignature);
internal SignInfo WithCollisionPriorityId(string collisionPriorityId)
- => new SignInfo(Certificate, StrongName, NotarizationAppName, collisionPriorityId, ShouldIgnore, IsAlreadySigned, IsAlreadyStrongNamed);
+ => new SignInfo(Certificate, StrongName, NotarizationAppName, collisionPriorityId, ShouldIgnore, IsAlreadySigned, IsAlreadyStrongNamed, GeneratesDetachedSignature);
internal SignInfo WithIsAlreadySigned(bool value = false)
=> Certificate != null ?
- new SignInfo(Certificate, StrongName, NotarizationAppName, CollisionPriorityId, value, value, IsAlreadyStrongNamed) :
- new SignInfo(Certificate, StrongName, NotarizationAppName, CollisionPriorityId, true, value, IsAlreadyStrongNamed);
+ new SignInfo(Certificate, StrongName, NotarizationAppName, CollisionPriorityId, value, value, IsAlreadyStrongNamed, GeneratesDetachedSignature) :
+ new SignInfo(Certificate, StrongName, NotarizationAppName, CollisionPriorityId, true, value, IsAlreadyStrongNamed, GeneratesDetachedSignature);
internal SignInfo WithIsAlreadyStrongNamed(bool value = false) =>
- new SignInfo(Certificate, StrongName, NotarizationAppName, CollisionPriorityId, ShouldIgnore, IsAlreadySigned, value);
+ new SignInfo(Certificate, StrongName, NotarizationAppName, CollisionPriorityId, ShouldIgnore, IsAlreadySigned, value, GeneratesDetachedSignature);
+
+ internal SignInfo WithDetachedSignature(string certificate)
+ => new SignInfo(certificate, StrongName, NotarizationAppName, CollisionPriorityId, false, false, IsAlreadyStrongNamed, true);
}
}
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool/src/SignTool.cs b/src/arcade/src/Microsoft.DotNet.SignTool/src/SignTool.cs
index 6aa74d2ccc1..6b88e6d156b 100644
--- a/src/arcade/src/Microsoft.DotNet.SignTool/src/SignTool.cs
+++ b/src/arcade/src/Microsoft.DotNet.SignTool/src/SignTool.cs
@@ -13,6 +13,7 @@
using Microsoft.Build.Utilities;
using NuGet.Packaging;
using Microsoft.DotNet.StrongName;
+using System.ComponentModel;
namespace Microsoft.DotNet.SignTool
{
@@ -148,15 +149,37 @@ private bool AuthenticodeSignAndNotarize(IBuildEngine buildEngine, int round, IE
var zippedPaths = ZipMacFiles(filesToSign);
- // First the signing pass
- var signProjectPath = Path.Combine(dir, $"Round{round}-Sign.proj");
- File.WriteAllText(signProjectPath, GenerateBuildFileContent(filesToSign, zippedPaths, false));
- string signingLogName = $"SigningRound{round}";
- status = RunMSBuild(buildEngine, signProjectPath, Path.Combine(_args.LogDir, $"{signingLogName}.binlog"), Path.Combine(_args.LogDir, $"{signingLogName}.log"), Path.Combine(_args.LogDir, $"{signingLogName}.error.log"));
+ // Identify files that need detached signatures
+ var detachedSignatureFiles = filesToSign.Where(f => f.SignInfo.GeneratesDetachedSignature).ToList();
+ var originalFileBackups = new Dictionary();
- if (!status)
+ try
{
- return false;
+ PrepareDetachedSignatureFiles(detachedSignatureFiles, originalFileBackups);
+
+ var signProjectPath = Path.Combine(dir, $"Round{round}-Sign.proj");
+ File.WriteAllText(signProjectPath, GenerateBuildFileContent(filesToSign, zippedPaths, false));
+ string signingLogName = $"SigningRound{round}";
+ status = RunMSBuild(buildEngine, signProjectPath, Path.Combine(_args.LogDir, $"{signingLogName}.binlog"), Path.Combine(_args.LogDir, $"{signingLogName}.log"), Path.Combine(_args.LogDir, $"{signingLogName}.error.log"));
+
+ if (!status)
+ {
+ return false;
+ }
+
+ // After signing, handle detached signatures
+ CompleteDetachedSignatures(detachedSignatureFiles, originalFileBackups);
+ }
+ finally
+ {
+ // Delete any original detached signature files
+ foreach (var backupPath in originalFileBackups.Values)
+ {
+ if (File.Exists(backupPath))
+ {
+ File.Delete(backupPath);
+ }
+ }
}
// Now unzip. Notarization does not expect zipped packages.
@@ -175,6 +198,47 @@ private bool AuthenticodeSignAndNotarize(IBuildEngine buildEngine, int round, IE
return status;
}
+ ///
+ /// Copies the signed content to the .sig file and restores the original file.
+ ///
+ ///
+ ///
+ private void CompleteDetachedSignatures(List detachedSignatureFiles, Dictionary originalFileBackups)
+ {
+ foreach (var fileInfo in detachedSignatureFiles)
+ {
+ // Copy the signed content to .sig file
+ File.Copy(fileInfo.FullPath, fileInfo.DetachedSignatureFullPath);
+ _log.LogMessage($"Created detached signature file: {fileInfo.DetachedSignatureFullPath}");
+
+ // Restore the original file
+ string backupPath = originalFileBackups[fileInfo.FullPath];
+ File.Copy(backupPath, fileInfo.FullPath, overwrite: true);
+ _log.LogMessage($"Restored original file: {fileInfo.FullPath}");
+ }
+ }
+
+ ///
+ /// Creates backup copies of the specified files to prepare for detached signature operations.
+ ///
+ /// Each file is backed up by copying it to a new file with the ".original" extension
+ /// appended to its path. The method updates the provided dictionary to allow later restoration of the original
+ /// files if needed.
+ /// A list of file information objects representing the files for which detached signature backups will be
+ /// created. Each file in the list will be copied to a backup location.
+ /// A dictionary that will be populated with mappings from the original file paths to their corresponding backup
+ /// file paths. The dictionary is updated in place.
+ private void PrepareDetachedSignatureFiles(List detachedSignatureFiles, Dictionary originalFileBackups)
+ {
+ foreach (var fileInfo in detachedSignatureFiles)
+ {
+ string backupPath = fileInfo.FullPath + ".original";
+ File.Copy(fileInfo.FullPath, backupPath);
+ originalFileBackups[fileInfo.FullPath] = backupPath;
+ _log.LogMessage($"Backed up original file for detached signature: {fileInfo.FullPath} -> {backupPath}");
+ }
+ }
+
private string GenerateBuildFileContent(IEnumerable filesToSign, Dictionary zippedPaths, bool notarize)
{
var builder = new StringBuilder();
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool/src/SignToolTask.cs b/src/arcade/src/Microsoft.DotNet.SignTool/src/SignToolTask.cs
index b999bbd6502..14d65f5bf0f 100644
--- a/src/arcade/src/Microsoft.DotNet.SignTool/src/SignToolTask.cs
+++ b/src/arcade/src/Microsoft.DotNet.SignTool/src/SignToolTask.cs
@@ -336,6 +336,8 @@ private Dictionary> ParseAddition
var macSigningOperation = certificateSignInfo.GetMetadata("MacCertificate");
var macNotarizationAppName = certificateSignInfo.GetMetadata("MacNotarizationAppName");
var collisionPriorityId = certificateSignInfo.GetMetadata(SignToolConstants.CollisionPriorityId);
+ var detachedSignatureCertificate = certificateSignInfo.GetMetadata("DetachedSignature");
+ bool detachedSignatureCertificateValue = false;
if (string.IsNullOrEmpty(macSigningOperation) != string.IsNullOrEmpty(macNotarizationAppName))
{
@@ -348,11 +350,18 @@ private Dictionary> ParseAddition
continue;
}
+ if (!string.IsNullOrEmpty(detachedSignatureCertificate) && !bool.TryParse(detachedSignatureCertificate, out detachedSignatureCertificateValue))
+ {
+ Log.LogError($"DetachedSignature must be 'true' or 'false");
+ continue;
+ }
+
var additionalCertInfo = new AdditionalCertificateInformation
{
DualSigningAllowed = dualSignAllowedValue,
MacSigningOperation = macSigningOperation,
MacNotarizationAppName = macNotarizationAppName,
+ GeneratesDetachedSignature = detachedSignatureCertificateValue,
CollisionPriorityId = collisionPriorityId
};
diff --git a/src/nuget-client/build/DotNetSdkTestVersions.txt b/src/nuget-client/build/DotNetSdkTestVersions.txt
index 041f89b91b4..d4a2109c8e2 100644
--- a/src/nuget-client/build/DotNetSdkTestVersions.txt
+++ b/src/nuget-client/build/DotNetSdkTestVersions.txt
@@ -2,4 +2,4 @@
# To make sure that the right version of dotnet.exe (and maybe other files) is used, always install from lowest version to highest version
-Channel 8.0 -Runtime dotnet
-Channel 9.0 -Runtime dotnet
--Channel 10.0.1xx -Version 10.0.100-rc.2.25465.104
+-Channel 10.0.1xx -Quality daily
diff --git a/src/nuget-client/build/common.project.props b/src/nuget-client/build/common.project.props
index 5f7af2d3650..ab90d04409a 100644
--- a/src/nuget-client/build/common.project.props
+++ b/src/nuget-client/build/common.project.props
@@ -142,8 +142,6 @@
- $(SemanticVersion).$(PreReleaseVersion)
- $(SemanticVersion).0
$(SemanticVersion).$(PreReleaseVersion)
$(SemanticVersion)$(PreReleaseInformationVersion)
$(SemanticVersion)$(PreReleaseInformationVersion)+$(BUILD_SOURCEVERSION)
diff --git a/src/nuget-client/build/common.targets b/src/nuget-client/build/common.targets
index b0ea719307b..14934090e62 100644
--- a/src/nuget-client/build/common.targets
+++ b/src/nuget-client/build/common.targets
@@ -2,7 +2,7 @@
-
+
$(SemanticVersion).$(PreReleaseVersion)
$(SemanticVersion).0
diff --git a/src/nuget-client/build/config.props b/src/nuget-client/build/config.props
index 83fcdc328ce..26e1ba81e9b 100644
--- a/src/nuget-client/build/config.props
+++ b/src/nuget-client/build/config.props
@@ -22,7 +22,7 @@
rc
- false
+ true
$([MSBuild]::Add(11, $(MajorNuGetVersion)))
diff --git a/src/nuget-client/eng/Version.Details.props b/src/nuget-client/eng/Version.Details.props
index 02eb28a0001..1092349c1de 100644
--- a/src/nuget-client/eng/Version.Details.props
+++ b/src/nuget-client/eng/Version.Details.props
@@ -21,8 +21,8 @@ This file should be imported by eng/Versions.props
4.5.0
- 10.0.0-beta.25420.109
- 10.0.0-beta.25420.109
+ 10.0.0-beta.25468.104
+ 10.0.0-beta.25468.104
diff --git a/src/nuget-client/eng/Version.Details.xml b/src/nuget-client/eng/Version.Details.xml
index 90dcf3571a7..328e46c38da 100644
--- a/src/nuget-client/eng/Version.Details.xml
+++ b/src/nuget-client/eng/Version.Details.xml
@@ -1,6 +1,6 @@
-
+
- 10.0.0-rc.2.25466.2
+ 10.0.0-rtm.25502.1
4.9.0-rc2.21473.1
@@ -100,12 +100,12 @@ This file should be imported by eng/Versions.props
10.0.0-prerelease.25475.1
10.0.0-prerelease.25475.1
- 1.0.0-prerelease.25467.1
- 1.0.0-prerelease.25467.1
- 1.0.0-prerelease.25467.1
- 1.0.0-prerelease.25467.1
- 1.0.0-prerelease.25467.1
- 1.0.0-prerelease.25467.1
+ 1.0.0-prerelease.25502.1
+ 1.0.0-prerelease.25502.1
+ 1.0.0-prerelease.25502.1
+ 1.0.0-prerelease.25502.1
+ 1.0.0-prerelease.25502.1
+ 1.0.0-prerelease.25502.1
10.0.0-alpha.0.25479.2
diff --git a/src/runtime/eng/Version.Details.xml b/src/runtime/eng/Version.Details.xml
index e40ce5b17dd..1f28d582d03 100644
--- a/src/runtime/eng/Version.Details.xml
+++ b/src/runtime/eng/Version.Details.xml
@@ -1,9 +1,9 @@
-
+
https://github.com/dotnet/icu
- 4c504bd8f75919cc512c456551f4229847da9e21
+ a91b254e70decd379d76338b7bb171ee98301aef
https://github.com/dotnet/wcf
@@ -307,21 +307,21 @@
https://github.com/dotnet/dotnet
e72b5bbe719d747036ce9c36582a205df9f1c361
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- 59dc6a9bf1b3e3ab71c73d94160c2049fb104cd1
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- 59dc6a9bf1b3e3ab71c73d94160c2049fb104cd1
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- 59dc6a9bf1b3e3ab71c73d94160c2049fb104cd1
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- 59dc6a9bf1b3e3ab71c73d94160c2049fb104cd1
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
https://github.com/dotnet/hotreload-utils
@@ -355,13 +355,13 @@
https://github.com/dotnet/dotnet
e72b5bbe719d747036ce9c36582a205df9f1c361
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- 59dc6a9bf1b3e3ab71c73d94160c2049fb104cd1
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
- 59dc6a9bf1b3e3ab71c73d94160c2049fb104cd1
+ 71ce9774e9875270b80faaac1d6b60568a80e1fa
diff --git a/src/runtime/src/mono/mono/mini/aot-compiler.c b/src/runtime/src/mono/mono/mini/aot-compiler.c
index 5349e634ed9..9598e9d3f20 100644
--- a/src/runtime/src/mono/mono/mini/aot-compiler.c
+++ b/src/runtime/src/mono/mono/mini/aot-compiler.c
@@ -638,7 +638,7 @@ is_direct_pinvoke_enabled (const MonoAotCompile *acfg)
/* Wrappers around the image writer functions */
-#define MAX_SYMBOL_SIZE 256
+#define MAX_SYMBOL_SIZE 1024
#if defined(TARGET_WIN32) && defined(TARGET_X86)
static const char *
diff --git a/src/source-manifest.json b/src/source-manifest.json
index 9e6b331554a..a988ed957bc 100644
--- a/src/source-manifest.json
+++ b/src/source-manifest.json
@@ -1,10 +1,10 @@
{
"repositories": [
{
- "barId": 285108,
+ "barId": 286215,
"path": "arcade",
"remoteUri": "https://github.com/dotnet/arcade",
- "commitSha": "e6f510cb87812d56ad781d93ff0513cdcccd0eb4"
+ "commitSha": "7ff6478d902606d65aa33cb8cedc2730e1843fe1"
},
{
"barId": 286219,
@@ -61,10 +61,10 @@
"commitSha": "dc755eb75a2a1f6a82036588da128eb859d96e8e"
},
{
- "barId": 284434,
+ "barId": 286446,
"path": "nuget-client",
"remoteUri": "https://github.com/nuget/nuget.client",
- "commitSha": "28eeb0947095a716b98b5c34454625708cb3ac76"
+ "commitSha": "5514d935e3e77d90d931758cf9e2589735b905a3"
},
{
"barId": 286084,
@@ -79,10 +79,10 @@
"commitSha": "23d275e30097136b12a68d1bab4997148361d116"
},
{
- "barId": 285920,
+ "barId": 286218,
"path": "runtime",
"remoteUri": "https://github.com/dotnet/runtime",
- "commitSha": "05a3a9ba8860b076afc88a6bf0d455f2c3b522d3"
+ "commitSha": "d321bc6abef02ed27790e8da3740d253976b9ac6"
},
{
"barId": 277711,