Cert Chain Pinning

This commit is contained in:
DHR60 2025-11-01 11:56:24 +08:00
parent 164277aab3
commit 7ec9659d61
13 changed files with 88 additions and 19 deletions

View file

@ -2797,6 +2797,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Fetch Certificate Chain 的本地化字符串。
/// </summary>
public static string TbFetchCertChain {
get {
return ResourceManager.GetString("TbFetchCertChain", resourceCulture);
}
}
/// <summary>
/// 查找类似 Fingerprint 的本地化字符串。
/// </summary>

View file

@ -1609,4 +1609,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="TbFetchCert" xml:space="preserve">
<value>Fetch Certificate</value>
</data>
<data name="TbFetchCertChain" xml:space="preserve">
<value>Fetch Certificate Chain</value>
</data>
</root>

View file

@ -1606,4 +1606,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="TbFetchCert" xml:space="preserve">
<value>Fetch Certificate</value>
</data>
<data name="TbFetchCertChain" xml:space="preserve">
<value>Fetch Certificate Chain</value>
</data>
</root>

View file

@ -1609,4 +1609,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="TbFetchCert" xml:space="preserve">
<value>Fetch Certificate</value>
</data>
<data name="TbFetchCertChain" xml:space="preserve">
<value>Fetch Certificate Chain</value>
</data>
</root>

View file

@ -1609,4 +1609,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="TbFetchCert" xml:space="preserve">
<value>Fetch Certificate</value>
</data>
<data name="TbFetchCertChain" xml:space="preserve">
<value>Fetch Certificate Chain</value>
</data>
</root>

View file

@ -1609,4 +1609,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="TbFetchCert" xml:space="preserve">
<value>Fetch Certificate</value>
</data>
<data name="TbFetchCertChain" xml:space="preserve">
<value>Fetch Certificate Chain</value>
</data>
</root>

View file

@ -1606,4 +1606,7 @@
<data name="TbFetchCert" xml:space="preserve">
<value>获取证书</value>
</data>
<data name="TbFetchCertChain" xml:space="preserve">
<value>获取证书链</value>
</data>
</root>

View file

@ -1606,4 +1606,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
<data name="TbFetchCert" xml:space="preserve">
<value>Fetch Certificate</value>
</data>
<data name="TbFetchCertChain" xml:space="preserve">
<value>Fetch Certificate Chain</value>
</data>
</root>

View file

@ -12,6 +12,7 @@ public class AddServerViewModel : MyReactiveObject
public string Cert { get; set; }
public ReactiveCommand<Unit, Unit> FetchCertCmd { get; }
public ReactiveCommand<Unit, Unit> FetchCertChainCmd { get; }
public ReactiveCommand<Unit, Unit> SaveCmd { get; }
public AddServerViewModel(ProfileItem profileItem, Func<EViewAction, object?, Task<bool>>? updateView)
@ -23,6 +24,10 @@ public class AddServerViewModel : MyReactiveObject
{
await FetchCert();
});
FetchCertChainCmd = ReactiveCommand.CreateFromTask(async () =>
{
await FetchCertChain();
});
SaveCmd = ReactiveCommand.CreateFromTask(async () =>
{
await SaveServerAsync();
@ -117,4 +122,24 @@ public class AddServerViewModel : MyReactiveObject
}
Cert = await Utils.GetCertPem(domain, serverName);
}
private async Task FetchCertChain()
{
if (SelectedSource.StreamSecurity != Global.StreamSecurity)
{
return;
}
var domain = SelectedSource.Address;
var serverName = SelectedSource.Sni.IsNullOrEmpty() ? SelectedSource.Address : SelectedSource.Sni;
if (!Utils.IsDomain(serverName))
{
return;
}
if (SelectedSource.Port > 0)
{
domain += $":{SelectedSource.Port}";
}
var certs = await Utils.GetCertChainPem(domain, serverName);
Cert = string.Join("\n", certs);
}
}

View file

@ -607,10 +607,10 @@
<Button
x:Name="btnExtra"
Classes="IconButton"
Margin="{StaticResource MarginLr8}">
Margin="{StaticResource MarginLr8}"
Classes="IconButton">
<Button.Content>
<PathIcon Data="{StaticResource SemiIconMore}" >
<PathIcon Data="{StaticResource SemiIconMore}">
<PathIcon.RenderTransform>
<RotateTransform Angle="90" />
</PathIcon.RenderTransform>
@ -778,11 +778,11 @@
<Button
Grid.Row="5"
Grid.Column="1"
Classes="IconButton"
Margin="{StaticResource MarginLr8}"
HorizontalAlignment="Left"
Margin="{StaticResource MarginLr8}">
Classes="IconButton">
<Button.Content>
<PathIcon Data="{StaticResource SemiIconMore}" >
<PathIcon Data="{StaticResource SemiIconMore}">
<PathIcon.RenderTransform>
<RotateTransform Angle="90" />
</PathIcon.RenderTransform>
@ -795,11 +795,16 @@
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbCertPinningTips}" />
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<Button
x:Name="btnFetchCert"
HorizontalAlignment="Left"
Margin="{StaticResource Margin4}"
Content="{x:Static resx:ResUI.TbFetchCert}" />
<Button
x:Name="btnFetchCertChain"
Margin="{StaticResource Margin4}"
Content="{x:Static resx:ResUI.TbFetchCertChain}" />
</StackPanel>
<TextBox
x:Name="txtCert"
Width="400"

View file

@ -195,6 +195,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
});

View file

@ -1018,13 +1018,20 @@
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbCertPinningTips}"
TextWrapping="Wrap" />
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<Button
x:Name="btnFetchCert"
Width="100"
Margin="{StaticResource MarginLeftRight4}"
HorizontalAlignment="Left"
Content="{x:Static resx:ResUI.TbFetchCert}"
Style="{StaticResource DefButton}" />
<Button
x:Name="btnFetchCertChain"
Width="100"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbFetchCertChain}"
Style="{StaticResource DefButton}" />
</StackPanel>
<TextBox
x:Name="txtCert"
Width="400"

View file

@ -190,6 +190,7 @@ public partial class AddServerWindow
this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
});