如何模拟从exe文件返回的签名信息?

huangapple go评论77阅读模式
英文:

How can you mock signature information returned from an exe file?

问题

我已经添加了一些验证来检查外部的exe文件。它通过获取FileSignatureInfo来验证文件,如下所示:

public static bool IsSigned(string filePath)
{
    using var fileStream = File.OpenRead(filePath);
    var signatureInfo = FileSignatureInfo.GetFromFileStream(fileStream);
    return signatureInfo.State == SignatureState.SignedAndTrusted;
}

然而,现在我想要测试这个功能。我认为System.IO.Abstractions可能是一个好方法。但是它似乎不完全符合我的要求。为了尝试让它工作,我更新了方法如下:

public static bool IsSigned(IFileSystem fileSystem, string filePath)
{
    using var fileStream = fileSystem.File.OpenRead(filePath) as FileStream;
    var signatureInfo = FileSignatureInfo.GetFromFileStream(fileStream);
    return signatureInfo.State == SignatureState.SignedAndTrusted;
}

然后我开始创建了一个类似这样的测试:

[Test]
public void IsSignedReturnsFalseIfSignatureStateIsNotSignedAndTrusted()
{
    // Arrange
    var mockFileSystem = new MockFileSystem();
    var mockFileData = new MockFileData("Test content");
    var directory = @"C:\testDirectory";
    var fileName = "Test.exe";
    var filePath = Path.Combine(directory, fileName);

    mockFileSystem.AddDirectory(directory);
    mockFileSystem.AddFile(filePath, mockFileData);

    // Act
    var result = MyHelper.IsSigned(mockFileSystem, filePath);

    // Assert
    Assert.IsFalse(result);        
}

我知道在这个阶段,这个测试是有缺陷的,因为我正在测试一个没有证书的模拟文件。我只是想确保它是否按预期通过了验证。然而,我发现它在尝试获取签名信息时失败,因为fileStream为null。事实证明,as FileStream并不起作用,因为Stream不是null。

所以我的第一个问题是,如何将从File.OpenRead()返回的流转换为FileStream?如果这有点笨拙/不推荐,那么在围绕证书签名的验证上进行单元测试的最佳方法是什么?我的想法是以某种方式模拟FileSignatureInfo.GetFromFileStream(),但不确定是否值得这么做。

英文:

I've put in some validation to check an external exe file. It verifies the file by getting the FileSignatureInfo like this:

public static bool IsSigned(string filePath)
{
    using var fileStream = File.OpenRead(filePath);
    var signatureInfo = FileSignatureInfo.GetFromFileStream(fileStream);
    return signatureInfo.State == SignatureState.SignedAndTrusted;
}

However, now I want to test this. I figured System.IO.Abstractions would be the way to go. This doesn't seem to do quite what I want though. To try and get this to work I updated the method as follows:

public static bool IsSigned(IFileSystem fileSystem, string filePath)
{
    using var fileStream = fileSystem.File.OpenRead(filePath) as FileStream;
    var signatureInfo = FileSignatureInfo.GetFromFileStream(fileStream);
    return signatureInfo.State == SignatureState.SignedAndTrusted;
}

I then started to create a test like this:

[Test]
public void IsSignedReturnsFalseIfSignatureStateIsNotSignedAndTrusted()
{
    // Arrange
    var mockFileSystem = new MockFileSystem();
    var mockFileData = new MockFileData("Test content");
    var directory = @"C:\testDirectory";
    var fileName = "Test.exe";
    var filePath = Path.Combine(directory, fileName);

    mockFileSystem.AddDirectory(directory);
    mockFileSystem.AddFile(filePath, mockFileData);

    // Act
    var result = MyHelper.IsSigned(mockFileSystem, filePath);

    // Assert
    Assert.IsFalse(result);        
}

I know at this stage the test is flawed as I'm testing a mocked file with no certificate. I just wanted to make sure it was actually flowing through the validation as expected. However, what I found was that it failed when trying to get the signature info because fileStream was null. Turns out the as FileStream isn't working, as the Stream isn't null.

So my first question is, how can I convert the stream returned from File.OpenRead() to a FileStream? If that's a bit clunky / not recommended, then what's the best way to unit test validation around certificate signatures? My thought was to somehow mock FileSignatureInfo.GetFromFileStream(), but not sure if that's more trouble than it's worth.

答案1

得分: 0

看起来这不是你可以模拟的东西,所以我已经解决了。我已经删除了对文件系统的需求,回到了最初的状态,但我只是通过我创建的一个名为SigningRequirement的记录来注入签名要求:

public static bool IsSigned(string filePath, SigningRequirement requirements)
{
    using var fileStream = File.OpenRead(filePath);
    var signatureInfo = FileSignatureInfo.GetFromFileStream(fileStream);

    if(signatureInfo.State == requirements.SignatureState && signatureInfo.SigningCertifcate is not null)
    {
        // 对证书进行更多的检查,比如指纹等等。
    }
}
英文:

Looks like this isn't something that you can mock, so I've worked around it. I've removed the need for the fileSystem and gone back to the original but I simply inject the signing requirements via a record I created called SigningRequirement:

public static bool IsSigned(string filePath, SigningRequirement requirements)
{
    using var fileStream = File.OpenRead(filePath);
    var signatureInfo = FileSignatureInfo.GetFromFileStream(fileStream);

    if(signatureInfo.State == requirements.SignatureState && signatureInfo.SigningCertifcate is not null)
    {
        // more checks against the certificate like thumbprint etc.
    }
}

huangapple
  • 本文由 发表于 2023年7月27日 18:28:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76778830.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定