Skip to content

Feature: Added Digital Signatures tab to the properties window #17334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
33 changes: 33 additions & 0 deletions src/Files.App.CsWin32/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,36 @@
GetMenuItemInfo
IsWow64Process2
GetCurrentProcess
CertFreeCertificateContext
CryptMsgGetParam
CryptMsgClose
CryptMsgOpenToDecode
CryptMsgUpdate
CertOpenStore
CryptDecodeObject
CertFindCertificateInStore
CertComparePublicKeyInfo
CryptQueryObject
CertCloseStore
WinVerifyTrust
FileTimeToSystemTime
FileTimeToLocalFileTime
SystemTimeToFileTime
CRYPTOAPI_BLOB

Check warning on line 254 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, x64)

Method, type or constant "CRYPTOAPI_BLOB" not found

Check warning on line 254 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

Method, type or constant "CRYPTOAPI_BLOB" not found

Check warning on line 254 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

Method, type or constant "CRYPTOAPI_BLOB" not found

Check warning on line 254 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

Method, type or constant "CRYPTOAPI_BLOB" not found
CMSG_SIGNER_INFO
SignDataHandle

Check warning on line 256 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, x64)

Method, type or constant "SignDataHandle" not found

Check warning on line 256 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

Method, type or constant "SignDataHandle" not found

Check warning on line 256 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

Method, type or constant "SignDataHandle" not found

Check warning on line 256 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

Method, type or constant "SignDataHandle" not found
CRYPT_ATTRIBUTE
FILETIME
CRYPT_BIT_BLOB
CERT_ALT_NAME_INFO
CERT_CONTEXT
CERT_INFO
CRYPT_ALGORITHM_IDENTIFIER
CERT_PUBLIC_KEY_INFO
CATALOG_INFO
WINTRUST_FILE_INFO
WINTRUST_DATA
HCERTSTORE
HCRYPTMSG

Check warning on line 269 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, x64)

Method, type or constant "HCRYPTMSG" not found. Did you mean or "CERT_CREATE_CONTEXT_NO_HCRYPTMSG_FLAG"?

Check warning on line 269 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

Method, type or constant "HCRYPTMSG" not found. Did you mean or "CERT_CREATE_CONTEXT_NO_HCRYPTMSG_FLAG"?

Check warning on line 269 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

Method, type or constant "HCRYPTMSG" not found. Did you mean or "CERT_CREATE_CONTEXT_NO_HCRYPTMSG_FLAG"?

Check warning on line 269 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

Method, type or constant "HCRYPTMSG" not found. Did you mean or "CERT_CREATE_CONTEXT_NO_HCRYPTMSG_FLAG"?
CERT_QUERY_ENCODING_TYPE
CertGetNameString
5 changes: 5 additions & 0 deletions src/Files.App/Data/Enums/PropertiesNavigationViewItemType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,10 @@ public enum PropertiesNavigationViewItemType
/// Shortcut page type
/// </summary>
Shortcut,

/// <summary>
/// Signatures page type
/// </summary>
Signatures,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,15 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
ItemType = PropertiesNavigationViewItemType.Compatibility,
ThemedIconStyle = (Style)Application.Current.Resources["App.ThemedIcons.Properties.Compatability"],
};
var signaturesItem = new NavigationViewItemButtonStyleItem()
{
Name = Strings.Signatures.GetLocalizedResource(),
ItemType = PropertiesNavigationViewItemType.Signatures,
ThemedIconStyle = (Style)Application.Current.Resources["App.ThemedIcons.Properties.Signatures"],
};

PropertiesNavigationViewItems.Add(generalItem);
PropertiesNavigationViewItems.Add(signaturesItem);
PropertiesNavigationViewItems.Add(securityItem);
PropertiesNavigationViewItems.Add(hashesItem);
PropertiesNavigationViewItems.Add(shortcutItem);
Expand All @@ -89,6 +96,7 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
PropertiesNavigationViewItems.Remove(securityItem);
PropertiesNavigationViewItems.Remove(customizationItem);
PropertiesNavigationViewItems.Remove(hashesItem);
PropertiesNavigationViewItems.Remove(signaturesItem);
}
else if (item is ListedItem listedItem)
{
Expand All @@ -102,13 +110,21 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
var detailsItemEnabled = !(isFolder && !listedItem.IsArchive) && !isLibrary && !listedItem.IsRecycleBinItem;
var customizationItemEnabled = !isLibrary && (isFolder && !listedItem.IsArchive || isShortcut && !listedItem.IsLinkItem);
var compatibilityItemEnabled = FileExtensionHelpers.IsExecutableFile(listedItem is IShortcutItem sht ? sht.TargetPath : fileExt, true);
var signaturesItemEnabled =
!isFolder &&
!isLibrary &&
!listedItem.IsRecycleBinItem &&
FileExtensionHelpers.IsSignableFile(fileExt, true);

if (!securityItemEnabled)
PropertiesNavigationViewItems.Remove(securityItem);

if (!hashItemEnabled)
PropertiesNavigationViewItems.Remove(hashesItem);

if (!signaturesItemEnabled)
PropertiesNavigationViewItems.Remove(signaturesItem);

if (!isShortcut)
PropertiesNavigationViewItems.Remove(shortcutItem);

Expand All @@ -132,6 +148,7 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
PropertiesNavigationViewItems.Remove(detailsItem);
PropertiesNavigationViewItems.Remove(customizationItem);
PropertiesNavigationViewItems.Remove(compatibilityItem);
PropertiesNavigationViewItems.Remove(signaturesItem);
}

return PropertiesNavigationViewItems;
Expand Down
18 changes: 18 additions & 0 deletions src/Files.App/Data/Items/CertNodeInfoItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

namespace Files.App.Data.Items
{
public class CertNodeInfoItem
{
public string IssuedTo { get; set; } = string.Empty;

public string IssuedBy { get; set; } = string.Empty;

public string Version { get; set; } = string.Empty;

public string ValidFrom { get; set; } = string.Empty;

public string ValidTo { get; set; } = string.Empty;
}
}
92 changes: 92 additions & 0 deletions src/Files.App/Data/Models/SignatureInfoItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using Files.App.Utils.Signatures;
using System.Windows.Input;
using Windows.Win32.Foundation;

namespace Files.App.Data.Models
{
public sealed partial class SignatureInfoItem : ObservableObject
{
private readonly string _fileName;

private readonly HWND _hwndParent;

private readonly int _index;

private string _Version = string.Empty;
public string Version
{
get => _Version;
set => SetProperty(ref _Version, value);
}

private string _IssuedBy = string.Empty;
public string IssuedBy
{
get => _IssuedBy;
set => SetProperty(ref _IssuedBy, value);
}

private string _IssuedTo = string.Empty;
public string IssuedTo
{
get => _IssuedTo;
set => SetProperty(ref _IssuedTo, value);
}

private string _ValidFromTimestamp = string.Empty;
public string ValidFromTimestamp
{
get => _ValidFromTimestamp;
set => SetProperty(ref _ValidFromTimestamp, value);
}

private string _ValidToTimestamp = string.Empty;
public string ValidToTimestamp
{
get => _ValidToTimestamp;
set => SetProperty(ref _ValidToTimestamp, value);
}

private string _VerifiedTimestamp = string.Empty;
public string VerifiedTimestamp
{
get => _VerifiedTimestamp;
set => SetProperty(ref _VerifiedTimestamp, value);
}

private bool _Verified = false;
public bool Verified
{
get => _Verified;
set
{
if (SetProperty(ref _Verified, value))
OnPropertyChanged(nameof(Glyph));
}
}

public List<CertNodeInfoItem> SignChain { get; }

public string Glyph => Verified ? "\uE930" : "\uEA39";

public ICommand OpenDetailsCommand { get; }

public SignatureInfoItem(string fileName, int index, HWND hWnd, List<CertNodeInfoItem> chain)
{
_fileName = fileName;
_hwndParent = hWnd;
_index = index;
SignChain = chain ?? new List<CertNodeInfoItem>();
OpenDetailsCommand = new AsyncRelayCommand(DoOpenDetails);
}

private Task DoOpenDetails()
{
DigitalSignaturesUtil.DisplaySignerInfoDialog(_fileName, _hwndParent, _index);
return Task.CompletedTask;
}
}
}
4 changes: 2 additions & 2 deletions src/Files.App/Helpers/Win32/Win32Helper.Storage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -902,13 +902,13 @@ public static SafeFileHandle OpenFileForRead(string filePath, bool readWrite = f
(uint)FILE_ACCESS_RIGHTS.FILE_GENERIC_READ | (uint)(readWrite ? FILE_ACCESS_RIGHTS.FILE_GENERIC_WRITE : 0u), (uint)(Win32PInvoke.FILE_SHARE_READ | (readWrite ? 0 : Win32PInvoke.FILE_SHARE_WRITE)), IntPtr.Zero, Win32PInvoke.OPEN_EXISTING, (uint)Win32PInvoke.File_Attributes.BackupSemantics | flags, IntPtr.Zero), true);
}

public static bool GetFileDateModified(string filePath, out FILETIME dateModified)
public static bool GetFileDateModified(string filePath, out System.Runtime.InteropServices.ComTypes.FILETIME dateModified)
{
using var hFile = new SafeFileHandle(Win32PInvoke.CreateFileFromApp(filePath, (uint)FILE_ACCESS_RIGHTS.FILE_GENERIC_READ, Win32PInvoke.FILE_SHARE_READ, IntPtr.Zero, Win32PInvoke.OPEN_EXISTING, (uint)Win32PInvoke.File_Attributes.BackupSemantics, IntPtr.Zero), true);
return Win32PInvoke.GetFileTime(hFile.DangerousGetHandle(), out _, out _, out dateModified);
}

public static bool SetFileDateModified(string filePath, FILETIME dateModified)
public static bool SetFileDateModified(string filePath, System.Runtime.InteropServices.ComTypes.FILETIME dateModified)
{
using var hFile = new SafeFileHandle(Win32PInvoke.CreateFileFromApp(filePath, (uint)FILE_ACCESS_RIGHTS.FILE_WRITE_ATTRIBUTES, 0, IntPtr.Zero, Win32PInvoke.OPEN_EXISTING, (uint)Win32PInvoke.File_Attributes.BackupSemantics, IntPtr.Zero), true);
return Win32PInvoke.SetFileTime(hFile.DangerousGetHandle(), new(), new(), dateModified);
Expand Down
23 changes: 13 additions & 10 deletions src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.
// Copyright (c) Files Community
// Licensed under the MIT License.

using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;
Expand Down Expand Up @@ -232,17 +231,17 @@ public static extern bool WriteFileEx(
[DllImport("api-ms-win-core-file-l1-2-1.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern bool GetFileTime(
[In] IntPtr hFile,
out FILETIME lpCreationTime,
out FILETIME lpLastAccessTime,
out FILETIME lpLastWriteTime
out System.Runtime.InteropServices.ComTypes.FILETIME lpCreationTime,
out System.Runtime.InteropServices.ComTypes.FILETIME lpLastAccessTime,
out System.Runtime.InteropServices.ComTypes.FILETIME lpLastWriteTime
);

[DllImport("api-ms-win-core-file-l1-2-1.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern bool SetFileTime(
[In] IntPtr hFile,
in FILETIME lpCreationTime,
in FILETIME lpLastAccessTime,
in FILETIME lpLastWriteTime
in System.Runtime.InteropServices.ComTypes.FILETIME lpCreationTime,
in System.Runtime.InteropServices.ComTypes.FILETIME lpLastAccessTime,
in System.Runtime.InteropServices.ComTypes.FILETIME lpLastWriteTime
);

[DllImport("api-ms-win-core-file-l2-1-1.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
Expand Down Expand Up @@ -288,7 +287,7 @@ IntPtr hFindFile

[DllImport("api-ms-win-core-timezone-l1-1-0.dll", SetLastError = true)]
public static extern bool FileTimeToSystemTime(
ref FILETIME lpFileTime,
ref System.Runtime.InteropServices.ComTypes.FILETIME lpFileTime,
out SYSTEMTIME lpSystemTime
);

Expand Down Expand Up @@ -347,5 +346,9 @@ public static extern int SHGetKnownFolderPath(
IntPtr hToken,
out IntPtr pszPath
);

// cryptui.dll
[DllImport("cryptui.dll", SetLastError = true, CharSet = CharSet.Auto)]
public unsafe static extern bool CryptUIDlgViewSignerInfo(CRYPTUI_VIEWSIGNERINFO_STRUCT* pViewInfo);
}
}
47 changes: 40 additions & 7 deletions src/Files.App/Helpers/Win32/Win32PInvoke.Structs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Windows.Win32.Foundation;
using Windows.Win32.Security.Cryptography;

namespace Files.App.Helpers
{
Expand Down Expand Up @@ -90,9 +91,9 @@ public struct REPARSE_DATA_BUFFER
public struct WIN32_FILE_ATTRIBUTE_DATA
{
public FileAttributes dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
}
Expand Down Expand Up @@ -183,9 +184,9 @@ public struct WIN32_FIND_DATA
{
public uint dwFileAttributes;

public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;

public uint nFileSizeHigh;
public uint nFileSizeLow;
Expand All @@ -198,5 +199,37 @@ public struct WIN32_FIND_DATA
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}

[StructLayout(LayoutKind.Sequential)]
public unsafe struct SignDataHandle
{
public uint dwObjSize;
public CMSG_SIGNER_INFO* pSignerInfo;
public HCERTSTORE hCertStoreHandle;
}

[StructLayout(LayoutKind.Sequential)]
public unsafe struct CRYPTOAPI_BLOB
{
public uint cbData;
public void* pbData;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public unsafe struct CRYPTUI_VIEWSIGNERINFO_STRUCT
{
public uint dwSize;
public HWND hwndParent;
public uint dwFlags;
public PCSTR szTitle;
public CMSG_SIGNER_INFO* pSignerInfo;
public void* hMsg;
public PCSTR pszOID;
public uint? dwReserved;
public uint cStores;
public HCERTSTORE* rghStores;
public uint cPropPages;
public void* rgPropPages;
}
}
}
21 changes: 21 additions & 0 deletions src/Files.App/Strings/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -4273,6 +4273,27 @@
<data name="Filename" xml:space="preserve">
<value>Filename</value>
</data>
<data name="Signatures" xml:space="preserve">
<value>Signatures</value>
</data>
<data name="SignatureList" xml:space="preserve">
<value>Signature list</value>
</data>
<data name="IssuedBy" xml:space="preserve">
<value>Issued by:</value>
</data>
<data name="IssuedTo" xml:space="preserve">
<value>Issued to:</value>
</data>
<data name="ValidFrom" xml:space="preserve">
<value>Valid from:</value>
</data>
<data name="ValidTo" xml:space="preserve">
<value>Valid to:</value>
</data>
<data name="NoSignatureFound" xml:space="preserve">
<value>No signature was found.</value>
</data>
<data name="ShowOpenTerminal" xml:space="preserve">
<value>Show option to open folders in Windows Terminal</value>
</data>
Expand Down
Loading
Loading