Skip to content

Commit ff566bb

Browse files
Feature: Added Digital Signatures tab to the properties window (#17334)
1 parent 30ae1a3 commit ff566bb

File tree

17 files changed

+1551
-21
lines changed

17 files changed

+1551
-21
lines changed

src/Files.App.CsWin32/NativeMethods.txt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,36 @@ GetMenuItemCount
236236
GetMenuItemInfo
237237
IsWow64Process2
238238
GetCurrentProcess
239+
CertFreeCertificateContext
240+
CryptMsgGetParam
241+
CryptMsgClose
242+
CryptMsgOpenToDecode
243+
CryptMsgUpdate
244+
CertOpenStore
245+
CryptDecodeObject
246+
CertFindCertificateInStore
247+
CertComparePublicKeyInfo
248+
CryptQueryObject
249+
CertCloseStore
250+
WinVerifyTrust
251+
FileTimeToSystemTime
252+
FileTimeToLocalFileTime
253+
SystemTimeToFileTime
254+
CRYPTOAPI_BLOB
255+
CMSG_SIGNER_INFO
256+
SignDataHandle
257+
CRYPT_ATTRIBUTE
258+
FILETIME
259+
CRYPT_BIT_BLOB
260+
CERT_ALT_NAME_INFO
261+
CERT_CONTEXT
262+
CERT_INFO
263+
CRYPT_ALGORITHM_IDENTIFIER
264+
CERT_PUBLIC_KEY_INFO
265+
CATALOG_INFO
266+
WINTRUST_FILE_INFO
267+
WINTRUST_DATA
268+
HCERTSTORE
269+
HCRYPTMSG
270+
CERT_QUERY_ENCODING_TYPE
271+
CertGetNameString

src/Files.App/Data/Enums/PropertiesNavigationViewItemType.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,10 @@ public enum PropertiesNavigationViewItemType
4747
/// Shortcut page type
4848
/// </summary>
4949
Shortcut,
50+
51+
/// <summary>
52+
/// Signatures page type
53+
/// </summary>
54+
Signatures,
5055
}
5156
}

src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,15 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
6161
ItemType = PropertiesNavigationViewItemType.Compatibility,
6262
ThemedIconStyle = (Style)Application.Current.Resources["App.ThemedIcons.Properties.Compatability"],
6363
};
64+
var signaturesItem = new NavigationViewItemButtonStyleItem()
65+
{
66+
Name = Strings.Signatures.GetLocalizedResource(),
67+
ItemType = PropertiesNavigationViewItemType.Signatures,
68+
ThemedIconStyle = (Style)Application.Current.Resources["App.ThemedIcons.Properties.Signatures"],
69+
};
6470

6571
PropertiesNavigationViewItems.Add(generalItem);
72+
PropertiesNavigationViewItems.Add(signaturesItem);
6673
PropertiesNavigationViewItems.Add(securityItem);
6774
PropertiesNavigationViewItems.Add(hashesItem);
6875
PropertiesNavigationViewItems.Add(shortcutItem);
@@ -89,6 +96,7 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
8996
PropertiesNavigationViewItems.Remove(securityItem);
9097
PropertiesNavigationViewItems.Remove(customizationItem);
9198
PropertiesNavigationViewItems.Remove(hashesItem);
99+
PropertiesNavigationViewItems.Remove(signaturesItem);
92100
}
93101
else if (item is ListedItem listedItem)
94102
{
@@ -102,13 +110,21 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
102110
var detailsItemEnabled = !(isFolder && !listedItem.IsArchive) && !isLibrary && !listedItem.IsRecycleBinItem;
103111
var customizationItemEnabled = !isLibrary && (isFolder && !listedItem.IsArchive || isShortcut && !listedItem.IsLinkItem);
104112
var compatibilityItemEnabled = FileExtensionHelpers.IsExecutableFile(listedItem is IShortcutItem sht ? sht.TargetPath : fileExt, true);
113+
var signaturesItemEnabled =
114+
!isFolder &&
115+
!isLibrary &&
116+
!listedItem.IsRecycleBinItem &&
117+
FileExtensionHelpers.IsSignableFile(fileExt, true);
105118

106119
if (!securityItemEnabled)
107120
PropertiesNavigationViewItems.Remove(securityItem);
108121

109122
if (!hashItemEnabled)
110123
PropertiesNavigationViewItems.Remove(hashesItem);
111124

125+
if (!signaturesItemEnabled)
126+
PropertiesNavigationViewItems.Remove(signaturesItem);
127+
112128
if (!isShortcut)
113129
PropertiesNavigationViewItems.Remove(shortcutItem);
114130

@@ -132,6 +148,7 @@ public static ObservableCollection<NavigationViewItemButtonStyleItem> Initialize
132148
PropertiesNavigationViewItems.Remove(detailsItem);
133149
PropertiesNavigationViewItems.Remove(customizationItem);
134150
PropertiesNavigationViewItems.Remove(compatibilityItem);
151+
PropertiesNavigationViewItems.Remove(signaturesItem);
135152
}
136153

137154
return PropertiesNavigationViewItems;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
namespace Files.App.Data.Items
5+
{
6+
public class CertNodeInfoItem
7+
{
8+
public string IssuedTo { get; set; } = string.Empty;
9+
10+
public string IssuedBy { get; set; } = string.Empty;
11+
12+
public string Version { get; set; } = string.Empty;
13+
14+
public string ValidFrom { get; set; } = string.Empty;
15+
16+
public string ValidTo { get; set; } = string.Empty;
17+
}
18+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
using Files.App.Utils.Signatures;
5+
using System.Windows.Input;
6+
using Windows.Win32.Foundation;
7+
8+
namespace Files.App.Data.Models
9+
{
10+
public sealed partial class SignatureInfoItem : ObservableObject
11+
{
12+
private readonly string _fileName;
13+
14+
private readonly HWND _hwndParent;
15+
16+
private readonly int _index;
17+
18+
private string _Version = string.Empty;
19+
public string Version
20+
{
21+
get => _Version;
22+
set => SetProperty(ref _Version, value);
23+
}
24+
25+
private string _IssuedBy = string.Empty;
26+
public string IssuedBy
27+
{
28+
get => _IssuedBy;
29+
set => SetProperty(ref _IssuedBy, value);
30+
}
31+
32+
private string _IssuedTo = string.Empty;
33+
public string IssuedTo
34+
{
35+
get => _IssuedTo;
36+
set => SetProperty(ref _IssuedTo, value);
37+
}
38+
39+
private string _ValidFromTimestamp = string.Empty;
40+
public string ValidFromTimestamp
41+
{
42+
get => _ValidFromTimestamp;
43+
set => SetProperty(ref _ValidFromTimestamp, value);
44+
}
45+
46+
private string _ValidToTimestamp = string.Empty;
47+
public string ValidToTimestamp
48+
{
49+
get => _ValidToTimestamp;
50+
set => SetProperty(ref _ValidToTimestamp, value);
51+
}
52+
53+
private string _VerifiedTimestamp = string.Empty;
54+
public string VerifiedTimestamp
55+
{
56+
get => _VerifiedTimestamp;
57+
set => SetProperty(ref _VerifiedTimestamp, value);
58+
}
59+
60+
private bool _Verified = false;
61+
public bool Verified
62+
{
63+
get => _Verified;
64+
set
65+
{
66+
if (SetProperty(ref _Verified, value))
67+
OnPropertyChanged(nameof(Glyph));
68+
}
69+
}
70+
71+
public List<CertNodeInfoItem> SignChain { get; }
72+
73+
public string Glyph => Verified ? "\uE930" : "\uEA39";
74+
75+
public ICommand OpenDetailsCommand { get; }
76+
77+
public SignatureInfoItem(string fileName, int index, HWND hWnd, List<CertNodeInfoItem> chain)
78+
{
79+
_fileName = fileName;
80+
_hwndParent = hWnd;
81+
_index = index;
82+
SignChain = chain ?? new List<CertNodeInfoItem>();
83+
OpenDetailsCommand = new AsyncRelayCommand(DoOpenDetails);
84+
}
85+
86+
private Task DoOpenDetails()
87+
{
88+
DigitalSignaturesUtil.DisplaySignerInfoDialog(_fileName, _hwndParent, _index);
89+
return Task.CompletedTask;
90+
}
91+
}
92+
}

src/Files.App/Helpers/Win32/Win32Helper.Storage.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -902,13 +902,13 @@ public static SafeFileHandle OpenFileForRead(string filePath, bool readWrite = f
902902
(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);
903903
}
904904

905-
public static bool GetFileDateModified(string filePath, out FILETIME dateModified)
905+
public static bool GetFileDateModified(string filePath, out System.Runtime.InteropServices.ComTypes.FILETIME dateModified)
906906
{
907907
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);
908908
return Win32PInvoke.GetFileTime(hFile.DangerousGetHandle(), out _, out _, out dateModified);
909909
}
910910

911-
public static bool SetFileDateModified(string filePath, FILETIME dateModified)
911+
public static bool SetFileDateModified(string filePath, System.Runtime.InteropServices.ComTypes.FILETIME dateModified)
912912
{
913913
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);
914914
return Win32PInvoke.SetFileTime(hFile.DangerousGetHandle(), new(), new(), dateModified);

src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
// Copyright (c) 2024 Files Community
2-
// Licensed under the MIT License. See the LICENSE.
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
33

44
using System.IO;
55
using System.Runtime.InteropServices;
6-
using System.Runtime.InteropServices.ComTypes;
76
using System.Text;
87
using Windows.Win32.Foundation;
98
using Windows.Win32.System.Com;
@@ -232,17 +231,17 @@ public static extern bool WriteFileEx(
232231
[DllImport("api-ms-win-core-file-l1-2-1.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
233232
public static extern bool GetFileTime(
234233
[In] IntPtr hFile,
235-
out FILETIME lpCreationTime,
236-
out FILETIME lpLastAccessTime,
237-
out FILETIME lpLastWriteTime
234+
out System.Runtime.InteropServices.ComTypes.FILETIME lpCreationTime,
235+
out System.Runtime.InteropServices.ComTypes.FILETIME lpLastAccessTime,
236+
out System.Runtime.InteropServices.ComTypes.FILETIME lpLastWriteTime
238237
);
239238

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

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

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

@@ -347,5 +346,9 @@ public static extern int SHGetKnownFolderPath(
347346
IntPtr hToken,
348347
out IntPtr pszPath
349348
);
349+
350+
// cryptui.dll
351+
[DllImport("cryptui.dll", SetLastError = true, CharSet = CharSet.Auto)]
352+
public unsafe static extern bool CryptUIDlgViewSignerInfo(CRYPTUI_VIEWSIGNERINFO_STRUCT* pViewInfo);
350353
}
351354
}

src/Files.App/Helpers/Win32/Win32PInvoke.Structs.cs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
using System.IO;
55
using System.Runtime.InteropServices;
6-
using System.Runtime.InteropServices.ComTypes;
6+
using Windows.Win32.Foundation;
7+
using Windows.Win32.Security.Cryptography;
78

89
namespace Files.App.Helpers
910
{
@@ -90,9 +91,9 @@ public struct REPARSE_DATA_BUFFER
9091
public struct WIN32_FILE_ATTRIBUTE_DATA
9192
{
9293
public FileAttributes dwFileAttributes;
93-
public FILETIME ftCreationTime;
94-
public FILETIME ftLastAccessTime;
95-
public FILETIME ftLastWriteTime;
94+
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
95+
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
96+
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
9697
public uint nFileSizeHigh;
9798
public uint nFileSizeLow;
9899
}
@@ -183,9 +184,9 @@ public struct WIN32_FIND_DATA
183184
{
184185
public uint dwFileAttributes;
185186

186-
public FILETIME ftCreationTime;
187-
public FILETIME ftLastAccessTime;
188-
public FILETIME ftLastWriteTime;
187+
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
188+
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
189+
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
189190

190191
public uint nFileSizeHigh;
191192
public uint nFileSizeLow;
@@ -198,5 +199,37 @@ public struct WIN32_FIND_DATA
198199
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
199200
public string cAlternateFileName;
200201
}
202+
203+
[StructLayout(LayoutKind.Sequential)]
204+
public unsafe struct SignDataHandle
205+
{
206+
public uint dwObjSize;
207+
public CMSG_SIGNER_INFO* pSignerInfo;
208+
public HCERTSTORE hCertStoreHandle;
209+
}
210+
211+
[StructLayout(LayoutKind.Sequential)]
212+
public unsafe struct CRYPTOAPI_BLOB
213+
{
214+
public uint cbData;
215+
public void* pbData;
216+
}
217+
218+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
219+
public unsafe struct CRYPTUI_VIEWSIGNERINFO_STRUCT
220+
{
221+
public uint dwSize;
222+
public HWND hwndParent;
223+
public uint dwFlags;
224+
public PCSTR szTitle;
225+
public CMSG_SIGNER_INFO* pSignerInfo;
226+
public void* hMsg;
227+
public PCSTR pszOID;
228+
public uint? dwReserved;
229+
public uint cStores;
230+
public HCERTSTORE* rghStores;
231+
public uint cPropPages;
232+
public void* rgPropPages;
233+
}
201234
}
202235
}

src/Files.App/Strings/en-US/Resources.resw

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4273,6 +4273,27 @@
42734273
<data name="Filename" xml:space="preserve">
42744274
<value>Filename</value>
42754275
</data>
4276+
<data name="Signatures" xml:space="preserve">
4277+
<value>Signatures</value>
4278+
</data>
4279+
<data name="SignatureList" xml:space="preserve">
4280+
<value>Signature list</value>
4281+
</data>
4282+
<data name="IssuedBy" xml:space="preserve">
4283+
<value>Issued by:</value>
4284+
</data>
4285+
<data name="IssuedTo" xml:space="preserve">
4286+
<value>Issued to:</value>
4287+
</data>
4288+
<data name="ValidFrom" xml:space="preserve">
4289+
<value>Valid from:</value>
4290+
</data>
4291+
<data name="ValidTo" xml:space="preserve">
4292+
<value>Valid to:</value>
4293+
</data>
4294+
<data name="NoSignatureFound" xml:space="preserve">
4295+
<value>No signature was found.</value>
4296+
</data>
42764297
<data name="ShowOpenTerminal" xml:space="preserve">
42774298
<value>Show option to open folders in Windows Terminal</value>
42784299
</data>

0 commit comments

Comments
 (0)