Visual Studio
You can update the MAUI .csproj file to include the following. This will allow signing in either developer mode or with an EV certificate. I have not specifically used a YubiKey, but it should be the same. Be sure to replace A1B2C3... with your Developer Certificate thumbprint and D4E5F6... with your EV Code Certificate thumbprint.
<PropertyGroup>
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<PackageCertificateThumbprint>A1B2C3...</PackageCertificateThumbprint>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<PackageCertificateThumbprint>D4E5F6...</PackageCertificateThumbprint>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.Contains('-windows')) and '$(Configuration)' == 'Release'">
<GenerateAppxPackageOnBuild>true</GenerateAppxPackageOnBuild>
</PropertyGroup>
PowerShell
Or you can use this PowerShell script to fully automate the publish process and avoid having the EV Code Certificate dialog for the password pop up. This is my preferred method.
There are several replacements here to customize to your project; and if you are using plain text password files please ensure they are saved on some form of secure storage such as a BitLocker VHD.
Some notes:
- If you have trouble with signing, check this post
- You will need to replace all of the paths such as
C:\MyProject
, C:\Logs
, or D:\EncryptedStorage
with real paths
- While it is outside of the scope of this answer, it is very easy to extract the version from a .csproj file and replace the
1.0.0.0
with the current version
- I realize MAUI can target other OSes, but I have not done the work to figure out what needs to change for them
# Update manifest file
$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 "D:\EncryptedStorage\MyCertificate.cer"
$file = "C:\MyProject\Platforms\Windows\Package.appxmanifest"
$xml = [Xml] (Get-Content $file)
$xml.Package.Identity.Publisher = $certificate.Subject
$xml.Package.Properties.PublisherDisplayName = $certificate.Subject -replace "(CN=)(.*?),.*", '$2'
$xml.Save($file)
# Publish
$dotnet = "C:\Program Files\dotnet\dotnet.exe"
$arguments = New-Object System.Collections.Generic.List[System.String]
$arguments.Add("publish")
$arguments.Add("C:\MyProject\MyProject.csproj")
$arguments.Add("-c Release")
$arguments.Add("-f net6.0-windows10.0.19041.0")
$publish = Start-Process -NoNewWindow -FilePath $dotnet -PassThru -ArgumentList $arguments.ToArray() -RedirectStandardOutput "C:\Logs\PublishLog.txt"
Wait-Process -InputObject $publish
# Sign
$container = Get-Content "D:\EncryptedStorage\MyCertificateContainer.txt"
$pw = Get-Content "D:\EncryptedStorage\MyCertificatePassword.txt"
$arguments = New-Object System.Collections.Generic.List[System.String]
$arguments.Add("sign")
$arguments.Add("/tr http://timestamp.sectigo.com")
$arguments.Add("/td SHA256")
$arguments.Add("/f D:\EncryptedStorage\MyCertificate.cer")
$arguments.Add("/fd SHA256")
$arguments.Add("/csp ""eToken Base Cryptographic Provider""")
$arguments.Add("/kc ""[{{${pw}}}]=${container}""")
$arguments.Add("C:\MyProject\bin\Release\net6.0-windows10.0.19041.0\win10-x64\AppPackages\MyProject_1.0.0.0_Test\MyProject_1.0.0.0_x64.msix"))
Copy-Item "D:\EncryptedStorage\MyCertificate.cer" -Destination "C:\MyProject\bin\Release\net6.0-windows10.0.19041.0\win10-x64\AppPackages\MyProject_1.0.0.0_Test\MyProject_1.0.0.0_x64.cer"
$sign = Start-Process -NoNewWindow -FilePath $SignTool -PassThru -ArgumentList $arguments.ToArray() -RedirectStandardOutput "C:\Logs\SignLog.txt"
Wait-Process -InputObject $sign
CLI
Or you can use the dotnet publish
command on the command line to publish your application. Again, replace D4E5F6... with your EV Code Certificate thumbprint. And replace CertificatePassword with the password for your certificate (although I would advise using the PowerShell method above to make sure the password is not in your CLI history)
A couple notes:
- This is currently for Windows, you can change that by updating the
-f
and removing the /p:GenerateAppxPackageOnBuild=true
- I have not yet found out how to get the
/p:PackageCertificatePassword
to bypass popups for EV Code Certificates (such as the SafeNet Authentication Client). Use the PowerShell method for this
dotnet publish C:\MyProject\MyProject.csproj -c Release -f net6.0-windows10.0.19041.0 /p:GenerateAppxPackageOnBuild=true /p:AppxPackageSigningEnabled=true /p:PackageCertificateThumbprint="D4E5F6..." /p:PackageCertificatePassword="CertificatePassword"