Skip to content

Commit b3d33ab

Browse files
authored
Merge pull request #177 from CycloneDX/signing
2 parents 4233afe + b48801b commit b3d33ab

29 files changed

+1224
-27
lines changed

.github/workflows/dotnetcore.yml

+8-19
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,18 @@ on: [pull_request, workflow_dispatch]
66
jobs:
77
# Fail if there are build warnings
88
#
9-
# As a general code quality check we use FxCop analyzers.
10-
#
119
# To check for build warnings locally you may need to run a clean build.
1210
#
1311
# This can be done by running `dotnet clean` before running `dotnet build`
14-
# build-warnings:
15-
# name: Build warnings check
16-
# runs-on: ubuntu-20.04
17-
# timeout-minutes: 30
18-
# steps:
19-
# - uses: actions/[email protected]
20-
# - uses: actions/[email protected]
21-
# with:
22-
# dotnet-version: '5.0.100-rc.2.20479.15'
12+
build-warnings:
13+
name: Build warnings check
14+
runs-on: ubuntu-20.04
15+
timeout-minutes: 30
16+
steps:
17+
- uses: actions/[email protected]
2318

24-
# - name: Build
25-
# run: dotnet build /WarnAsError
19+
- name: Build
20+
run: dotnet build /WarnAsError
2621

2722
# We end up targeting a range of runtimes, make sure they all build
2823
build:
@@ -34,9 +29,6 @@ jobs:
3429
timeout-minutes: 30
3530
steps:
3631
- uses: actions/[email protected]
37-
- uses: actions/[email protected]
38-
with:
39-
dotnet-version: '5.0.100-rc.2.20479.15'
4032

4133
- name: Build
4234
run: dotnet build cyclonedx/cyclonedx.csproj -r ${{ matrix.runtime }}
@@ -56,9 +48,6 @@ jobs:
5648

5749
steps:
5850
- uses: actions/[email protected]
59-
- uses: actions/[email protected]
60-
with:
61-
dotnet-version: '5.0.100-rc.2.20479.15'
6251

6352
- name: Tests
6453
run: |

README.md

+96-7
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,18 @@ Options:
2121
-?, -h, --help Show help and usage information
2222
2323
Commands:
24-
add Add information to a BOM (currently supports files)
25-
analyze Analyze a BOM file
26-
convert Convert between different BOM formats
27-
diff <from-file> <to-file> Generate a BOM diff
28-
merge Merge two or more BOMs
29-
validate Validate a BOM
24+
add Add information to a BOM (currently supports files)
25+
analyze Analyze a BOM file
26+
convert Convert between different BOM formats
27+
diff <from-file> <to-file> Generate a BOM diff
28+
keygen Generates an RSA public/private key pair for BOM signing
29+
merge Merge two or more BOMs
30+
sign Sign a BOM or file
31+
validate Validate a BOM
32+
verify Verify signatures in a BOM
3033
```
3134

32-
The CycloneDX CLI tool currently supports BOM analysis, diffing, merging and format conversions.
35+
The CycloneDX CLI tool currently supports BOM analysis, modification, diffing, merging, format conversion, signing and verification.
3336

3437
Conversion from all CycloneDX BOM versions and CSV is supported.
3538

@@ -157,6 +160,19 @@ Options:
157160
Reporting on components with version changes:
158161
`cyclonedx-cli diff sbom-from.xml sbom-to.xml --component-versions`
159162

163+
## Keygen Command
164+
165+
```
166+
keygen
167+
Generates an RSA public/private key pair for BOM signing
168+
169+
Usage:
170+
cyclonedx [options] keygen
171+
172+
Options:
173+
--private-key-file <private-key-file> Filename for generated private key file (defaults to "private.key")
174+
--public-key-file <public-key-file> Filename for generated public key file (defaults to "public.key")
175+
```
160176

161177
## Merge Command
162178

@@ -189,6 +205,42 @@ Merge two XML formatted BOMs:
189205
Merging two BOMs and piping output to additional tools:
190206
`cyclonedx-cli merge --input-files sbom1.xml sbom2.xml --output-format json | grep "something"`
191207

208+
## Sign Command
209+
210+
Sign a BOM or file
211+
212+
### Sign Bom Subcommand
213+
214+
```
215+
bom
216+
Sign the entire BOM document
217+
218+
Usage:
219+
cyclonedx [options] sign bom <bom-file>
220+
221+
Arguments:
222+
<bom-file> BOM filename
223+
224+
Options:
225+
--key-file <key-file> Signing key filename (RSA private key in PEM format, defaults to "private.key")
226+
```
227+
228+
### Sign File Subcommand
229+
230+
```
231+
file
232+
Sign arbitrary files and generate a PKCS1 RSA SHA256 signature file
233+
234+
Usage:
235+
cyclonedx [options] sign file <file>
236+
237+
Arguments:
238+
<file> Filename of the file the signature will be created for
239+
240+
Options:
241+
--key-file <key-file> Signing key filename (RSA private key in PEM format, defaults to "private.key")
242+
--signature-file <signature-file> Filename of the generated signature file (defaults to the filename with ".sig" appended)
243+
```
192244

193245
## Validate Command
194246

@@ -210,6 +262,43 @@ Options:
210262
Validate BOM and return non-zero exit code (handy for automatically "breaking" a build, etc)
211263
`cyclonedx-cli validate --input-file sbom.xml --fail-on-errors`
212264

265+
## Verify Command
266+
267+
Verify signatures for BOMs and files
268+
269+
### Verify All Subcommand
270+
271+
```
272+
all
273+
Verify all signatures in a BOM
274+
275+
Usage:
276+
cyclonedx [options] verify all <bom-file>
277+
278+
Arguments:
279+
<bom-file> BOM filename
280+
281+
Options:
282+
--key-file <key-file> Public key filename (RSA public key in PEM format, defaults to "public.key")
283+
```
284+
285+
### Verify File Subcommand
286+
287+
```
288+
file
289+
Verifies a PKCS1 RSA SHA256 signature file for an abritrary file
290+
291+
Usage:
292+
cyclonedx [options] verify file <file>
293+
294+
Arguments:
295+
<file> File the signature file is for
296+
297+
Options:
298+
--key-file <key-file> Public key filename (RSA public key in PEM format, defaults to "public.key")
299+
--signature-file <signature-file> Signature file to be verified (defaults to the filename with ".sig" appended)
300+
```
301+
213302
# Docker Image
214303

215304
The CycloneDX CLI tool can also be run using docker `docker run cyclonedx/cyclonedx-cli`.
256 Bytes
Binary file not shown.
256 Bytes
Binary file not shown.

cyclonedx.tests/Resources/private.key

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEpAIBAAKCAQEArEVXY6FwqCMWq7HID0rLGs8gym5prQLzlQIdJSBIJjN5X/Uw
3+
UTwy30vEKc2ENgmHrek1rOtiNLxXzmPC2KWyDSUKt4BUdjVWm/PlAduBZP2ZLKlX
4+
WORVu6g3+S0/uCXP66c7u1jGdHaLdGAoMGWLFcQi+lmPIEFLXOAkxSX58tVrDYgt
5+
u6RaOQGeeuV8cYmy3Db6flMbT6/bI7tsXwMoYQ7vjTN2U+MxrSlflfqri2q+R616
6+
oxgvIRbAz4BYJgxK3xw7IZFBC/hr6fwKJ/frvUD7tLzYR4Ap91pjB0x8FPR3tUEN
7+
dR8EyMU48vUr3xNWROpIsrCOdmiRVm0Xkdc+3wIDAQABAoIBAGG3O2iiDDrzHErr
8+
nuU9sZNVZe4tTvf6MpyVBF8ovoQcsn5Bn9SUZu7OFUj48EOOiE2XeQDKy3vKUawa
9+
Xk1xP1vBZSDNRBuBCc2QPJgfIHheeOIidA9SBWdaddV7WydjG1s6EuGj633oOBYc
10+
7O72yjvgc066Ojs7jjnyUikZ73tTsIo110wKGR/LhvIhwW4FERfTzlaHYP/iiMbO
11+
oFxLqS6gb3Rv4QoPa5gQTmLBeusFKSoy9hzSVAy5u7wq/9EA/yTpFTzGupJVvt+q
12+
CW4uFUNvF/KpX2WgeJu38KS6x1qUvvk+3j3xGNBFyB/SkBIg8h5psn6JQD4BAqz7
13+
JN3lJQECgYEA4LaGYRiG40sUsV4V1OdqhtXpje6IcXUwcS76834GmH2irRuTv2jB
14+
T0SzTuDUe77Ga9x5F+lU3e0ohkO9UOeMv0RAM912fePShHIJkZs0KiDWwg7RPl5v
15+
q6fqWSzmt8+6Y8kbAWMSVZyxctCVUU0fpHhx4PTt718UhLesjsGIix8CgYEAxEGd
16+
Zagh9dlUjLeaEQPmWbQnVyRrNKLRAECXKKFv/2uyPWyoCX0Kg452NrM/2SLDqw2I
17+
e1p2zUNtQShezUJuhVM13nwluu1OrYsHxTILefsIkItJssqc8xO6RdgPYaVZMbo4
18+
63bN2Kk3GWGkpqeYoBPC0JuXTL9BM/vN3iiClEECgYArgSrjAWyb9J08+Yogfe0R
19+
zbg50kR4Msf+IapUGcINI8Wq3fvswssqHZLZYo3Ap16i4zxOdM4JaTC/Tb4JO8rz
20+
/LKxV97o4IKRQcK4fePLhDAPwe6gtIfKI+gq+5ZvX7gmOXkQ+61BBeUU5W0DIHtP
21+
zEG/26t0/GNsjmLKAI3+4QKBgQCuzx8quFsfiCi2eqfBti6NAln0Vd0j8k6loeLC
22+
byG6aixGaC043mbqDZAgYwNhHoUZLKG/9jFR3lhHrHTc8epN2XNnLD/TQ6NME0Wl
23+
kVEFouPbFCZeGfk4zv6hTbVNraFIGO6wVY8/CGKquf2V8DyTgWaKt7xJwSWL7yNN
24+
WdoNwQKBgQDWkg2qvuRUbXtc696FkCdhfNqmSLD+py+ZihsrHcp0HyETMWg+sNwu
25+
+Nz6Bgcihm8GOwP5jOroD3oEkit/bvcG6FWpmxBajxsWfFU5Cpgp0DVxY/RzES+F
26+
wqIB7SN/nfcjeTCYM3Z0m3KvyflBgP6UO0dFJjJYGm16bd95VSOXrQ==
27+
-----END RSA PRIVATE KEY-----

cyclonedx.tests/Resources/public.key

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEpAIBAAKCAQEArEVXY6FwqCMWq7HID0rLGs8gym5prQLzlQIdJSBIJjN5X/Uw
3+
UTwy30vEKc2ENgmHrek1rOtiNLxXzmPC2KWyDSUKt4BUdjVWm/PlAduBZP2ZLKlX
4+
WORVu6g3+S0/uCXP66c7u1jGdHaLdGAoMGWLFcQi+lmPIEFLXOAkxSX58tVrDYgt
5+
u6RaOQGeeuV8cYmy3Db6flMbT6/bI7tsXwMoYQ7vjTN2U+MxrSlflfqri2q+R616
6+
oxgvIRbAz4BYJgxK3xw7IZFBC/hr6fwKJ/frvUD7tLzYR4Ap91pjB0x8FPR3tUEN
7+
dR8EyMU48vUr3xNWROpIsrCOdmiRVm0Xkdc+3wIDAQABAoIBAGG3O2iiDDrzHErr
8+
nuU9sZNVZe4tTvf6MpyVBF8ovoQcsn5Bn9SUZu7OFUj48EOOiE2XeQDKy3vKUawa
9+
Xk1xP1vBZSDNRBuBCc2QPJgfIHheeOIidA9SBWdaddV7WydjG1s6EuGj633oOBYc
10+
7O72yjvgc066Ojs7jjnyUikZ73tTsIo110wKGR/LhvIhwW4FERfTzlaHYP/iiMbO
11+
oFxLqS6gb3Rv4QoPa5gQTmLBeusFKSoy9hzSVAy5u7wq/9EA/yTpFTzGupJVvt+q
12+
CW4uFUNvF/KpX2WgeJu38KS6x1qUvvk+3j3xGNBFyB/SkBIg8h5psn6JQD4BAqz7
13+
JN3lJQECgYEA4LaGYRiG40sUsV4V1OdqhtXpje6IcXUwcS76834GmH2irRuTv2jB
14+
T0SzTuDUe77Ga9x5F+lU3e0ohkO9UOeMv0RAM912fePShHIJkZs0KiDWwg7RPl5v
15+
q6fqWSzmt8+6Y8kbAWMSVZyxctCVUU0fpHhx4PTt718UhLesjsGIix8CgYEAxEGd
16+
Zagh9dlUjLeaEQPmWbQnVyRrNKLRAECXKKFv/2uyPWyoCX0Kg452NrM/2SLDqw2I
17+
e1p2zUNtQShezUJuhVM13nwluu1OrYsHxTILefsIkItJssqc8xO6RdgPYaVZMbo4
18+
63bN2Kk3GWGkpqeYoBPC0JuXTL9BM/vN3iiClEECgYArgSrjAWyb9J08+Yogfe0R
19+
zbg50kR4Msf+IapUGcINI8Wq3fvswssqHZLZYo3Ap16i4zxOdM4JaTC/Tb4JO8rz
20+
/LKxV97o4IKRQcK4fePLhDAPwe6gtIfKI+gq+5ZvX7gmOXkQ+61BBeUU5W0DIHtP
21+
zEG/26t0/GNsjmLKAI3+4QKBgQCuzx8quFsfiCi2eqfBti6NAln0Vd0j8k6loeLC
22+
byG6aixGaC043mbqDZAgYwNhHoUZLKG/9jFR3lhHrHTc8epN2XNnLD/TQ6NME0Wl
23+
kVEFouPbFCZeGfk4zv6hTbVNraFIGO6wVY8/CGKquf2V8DyTgWaKt7xJwSWL7yNN
24+
WdoNwQKBgQDWkg2qvuRUbXtc696FkCdhfNqmSLD+py+ZihsrHcp0HyETMWg+sNwu
25+
+Nz6Bgcihm8GOwP5jOroD3oEkit/bvcG6FWpmxBajxsWfFU5Cpgp0DVxY/RzES+F
26+
wqIB7SN/nfcjeTCYM3Z0m3KvyflBgP6UO0dFJjJYGm16bd95VSOXrQ==
27+
-----END RSA PRIVATE KEY-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<bom xmlns="http://cyclonedx.org/schema/bom/1.3" serialNumber="urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" version="1">
3+
<components>
4+
<component type="library">
5+
<publisher>Not-Apache</publisher>
6+
<group>org.apache.tomcat</group>
7+
<name>tomcat-catalina</name>
8+
<version>9.0.14</version>
9+
<hashes>
10+
<hash alg="MD5">3942447fac867ae5cdb3229b658f4d48</hash>
11+
<hash alg="SHA-1">e6b1000b94e835ffd37f4c6dcbdad43f4b48a02a</hash>
12+
<hash alg="SHA-256">f498a8ff2dd007e29c2074f5e4b01a9a01775c3ff3aeaf6906ea503bc5791b7b</hash>
13+
<hash alg="SHA-512">e8f33e424f3f4ed6db76a482fde1a5298970e442c531729119e37991884bdffab4f9426b7ee11fccd074eeda0634d71697d6f88a460dce0ac8d627a29f7d1282</hash>
14+
</hashes>
15+
<licenses>
16+
<license>
17+
<id>Apache-2.0</id>
18+
</license>
19+
</licenses>
20+
<purl>pkg:maven/org.apache.tomcat/[email protected]</purl>
21+
</component>
22+
</components>
23+
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>/dv/4234OrWJ3z0ytdv86AGtDFjiPYNSamZRRWrOFSQ=</DigestValue></Reference></SignedInfo><SignatureValue>lpUmguCCoJVe+AXaHarzR8l2Uvk7spE0L0yV/d54IGU7vn1dh2IFLrZvhxK2lVLlLV2qQtaFs89UWmXPKyRlzU0N/AEZTWHaxJh/5DTy3w7iyOcqKf1U4j9nSRkCtwiBF3rc8u/Oi4XdvmnzNDaIfIdu/vZlkWRvsh1HZZtKtb1ZFnRrmKr+HHzGqtA4nAI5yqzq0g28M9Q2x2Rqd5K0wFGAusWMNcLR6lAcglEg5I8CW9ILzhqXsu91+YMax41wyZ1FZEQwX+Jj4xsgf8xRMr1nGkO0+FV0km6zc0EWl7uJGFCVFXTChQJUZ53hWZVzsGs66UL4jxEF4DfnWIxMzA==</SignatureValue></Signature></bom>
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<bom xmlns="http://cyclonedx.org/schema/bom/1.3" serialNumber="urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" version="1">
3+
<components>
4+
<component type="library">
5+
<publisher>Apache</publisher>
6+
<group>org.apache.tomcat</group>
7+
<name>tomcat-catalina</name>
8+
<version>9.0.14</version>
9+
<hashes>
10+
<hash alg="MD5">3942447fac867ae5cdb3229b658f4d48</hash>
11+
<hash alg="SHA-1">e6b1000b94e835ffd37f4c6dcbdad43f4b48a02a</hash>
12+
<hash alg="SHA-256">f498a8ff2dd007e29c2074f5e4b01a9a01775c3ff3aeaf6906ea503bc5791b7b</hash>
13+
<hash alg="SHA-512">e8f33e424f3f4ed6db76a482fde1a5298970e442c531729119e37991884bdffab4f9426b7ee11fccd074eeda0634d71697d6f88a460dce0ac8d627a29f7d1282</hash>
14+
</hashes>
15+
<licenses>
16+
<license>
17+
<id>Apache-2.0</id>
18+
</license>
19+
</licenses>
20+
<purl>pkg:maven/org.apache.tomcat/[email protected]</purl>
21+
</component>
22+
</components>
23+
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>/dv/4234OrWJ3z0ytdv86AGtDFjiPYNSamZRRWrOFSQ=</DigestValue></Reference></SignedInfo><SignatureValue>lpUmguCCoJVe+AXaHarzR8l2Uvk7spE0L0yV/d54IGU7vn1dh2IFLrZvhxK2lVLlLV2qQtaFs89UWmXPKyRlzU0N/AEZTWHaxJh/5DTy3w7iyOcqKf1U4j9nSRkCtwiBF3rc8u/Oi4XdvmnzNDaIfIdu/vZlkWRvsh1HZZtKtb1ZFnRrmKr+HHzGqtA4nAI5yqzq0g28M9Q2x2Rqd5K0wFGAusWMNcLR6lAcglEg5I8CW9ILzhqXsu91+YMax41wyZ1FZEQwX+Jj4xsgf8xRMr1nGkO0+FV0km6zc0EWl7uJGFCVFXTChQJUZ53hWZVzsGs66UL4jxEF4DfnWIxMzA==</SignatureValue></Signature></bom>

cyclonedx.tests/SignBomTests.cs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// This file is part of CycloneDX CLI Tool
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the “License”);
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an “AS IS” BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
// SPDX-License-Identifier: Apache-2.0
16+
// Copyright (c) OWASP Foundation. All Rights Reserved.
17+
18+
using System;
19+
using System.IO;
20+
using System.Threading.Tasks;
21+
using Xunit;
22+
using Snapshooter;
23+
using Snapshooter.Xunit;
24+
using CycloneDX.Cli.Commands.Sign;
25+
26+
namespace CycloneDX.Cli.Tests
27+
{
28+
public class SignBomTests
29+
{
30+
[Fact]
31+
public async Task SignXmlBom()
32+
{
33+
using (var tempDirectory = new TempDirectory())
34+
{
35+
var testFilename = Path.Combine(tempDirectory.DirectoryPath, "bom.xml");
36+
File.Copy(Path.Combine("Resources", "bom-1.3.xml"), testFilename);
37+
38+
var exitCode = await SignBomCommand.SignBom(new SignBomCommandOptions
39+
{
40+
BomFile = testFilename,
41+
KeyFile = Path.Combine("Resources", "private.key"),
42+
}).ConfigureAwait(false);
43+
44+
Assert.Equal(ExitCode.Ok, (ExitCode)exitCode);
45+
46+
var bom = File.ReadAllText(testFilename);
47+
Snapshot.Match(bom);
48+
}
49+
}
50+
}
51+
}

cyclonedx.tests/SignFileTests.cs

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// This file is part of CycloneDX CLI Tool
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the “License”);
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an “AS IS” BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
// SPDX-License-Identifier: Apache-2.0
16+
// Copyright (c) OWASP Foundation. All Rights Reserved.
17+
18+
using System;
19+
using System.IO;
20+
using System.Threading.Tasks;
21+
using Xunit;
22+
using Snapshooter;
23+
using Snapshooter.Xunit;
24+
using CycloneDX.Cli.Commands.Sign;
25+
26+
namespace CycloneDX.Cli.Tests
27+
{
28+
public class SignFileTests
29+
{
30+
[Fact]
31+
public async Task SignFile()
32+
{
33+
using (var tempDirectory = new TempDirectory())
34+
{
35+
var testFilename = Path.Combine(tempDirectory.DirectoryPath, "bom.xml");
36+
var fileContents = await File.ReadAllTextAsync(Path.Combine("Resources", "bom-1.3.xml")).ConfigureAwait(false);
37+
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
38+
{
39+
fileContents = fileContents.Replace("\r\n", "\n");
40+
}
41+
await File.WriteAllTextAsync(testFilename, fileContents).ConfigureAwait(false);
42+
43+
var exitCode = await SignFileCommand.SignFile(new SignFileCommandOptions
44+
{
45+
File = testFilename,
46+
KeyFile = Path.Combine("Resources", "private.key"),
47+
}).ConfigureAwait(false);
48+
49+
Assert.Equal(ExitCode.Ok, (ExitCode)exitCode);
50+
51+
var signature = File.ReadAllText(testFilename + ".sig");
52+
Snapshot.Match(signature);
53+
}
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)