Skip to content

Commit c6ae2e6

Browse files
authored
Merge pull request #88 from jmhardison/full-update-attempt
first batch update
2 parents 1f1c555 + 38f62bd commit c6ae2e6

5 files changed

Lines changed: 199 additions & 74 deletions

File tree

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
name: Build and Release
2+
3+
on:
4+
push:
5+
branches: [ master, main ]
6+
pull_request:
7+
branches: [ master, main ]
8+
9+
jobs:
10+
build:
11+
runs-on: windows-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
with:
16+
fetch-depth: 1
17+
18+
- name: Setup .NET
19+
uses: actions/setup-dotnet@v4
20+
with:
21+
dotnet-version: '8.0.x'
22+
23+
- name: Restore dependencies
24+
run: dotnet restore
25+
26+
- name: Build and publish for multiple platforms
27+
run: |
28+
dotnet publish -c Release --self-contained -r osx-x64
29+
dotnet publish -c Release --self-contained -r centos-x64
30+
dotnet publish -c Release --self-contained -r rhel-x64
31+
dotnet publish -c Release --self-contained -r linux-x64
32+
dotnet publish -c Release --self-contained -r win-x64
33+
34+
- name: Create artifacts
35+
uses: actions/upload-artifact@v4
36+
with:
37+
name: centos-x64-binaries
38+
path: cli-exakvdocsign/bin/Release/net8.0/centos-x64/publish/
39+
40+
- name: Upload Linux x64 artifacts
41+
uses: actions/upload-artifact@v4
42+
with:
43+
name: linux-x64-binaries
44+
path: cli-exakvdocsign/bin/Release/net8.0/linux-x64/publish/
45+
46+
- name: Upload RHEL x64 artifacts
47+
uses: actions/upload-artifact@v4
48+
with:
49+
name: rhel-x64-binaries
50+
path: cli-exakvdocsign/bin/Release/net8.0/rhel-x64/publish/
51+
52+
- name: Upload macOS x64 artifacts
53+
uses: actions/upload-artifact@v4
54+
with:
55+
name: osx-x64-binaries
56+
path: cli-exakvdocsign/bin/Release/net8.0/osx-x64/publish/
57+
58+
- name: Upload Windows x64 artifacts
59+
uses: actions/upload-artifact@v4
60+
with:
61+
name: win-x64-binaries
62+
path: cli-exakvdocsign/bin/Release/net8.0/win-x64/publish/
63+
64+
release:
65+
needs: build
66+
runs-on: ubuntu-latest
67+
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main'
68+
69+
steps:
70+
- uses: actions/checkout@v4
71+
72+
- name: Download all artifacts
73+
uses: actions/download-artifact@v4
74+
75+
- name: Create Release
76+
id: create_release
77+
uses: actions/create-release@v1
78+
env:
79+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
80+
with:
81+
tag_name: v${{ github.run_number }}
82+
release_name: Release v${{ github.run_number }}
83+
body: ${{ github.event.head_commit.message }}
84+
draft: true
85+
prerelease: false
86+
87+
- name: Upload centos-x64 Release Asset
88+
uses: actions/upload-release-asset@v1
89+
env:
90+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
91+
with:
92+
upload_url: ${{ steps.create_release.outputs.upload_url }}
93+
asset_path: ./centos-x64-binaries
94+
asset_name: centos-x64-binaries.zip
95+
asset_content_type: application/zip
96+
97+
- name: Upload linux-x64 Release Asset
98+
uses: actions/upload-release-asset@v1
99+
env:
100+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
101+
with:
102+
upload_url: ${{ steps.create_release.outputs.upload_url }}
103+
asset_path: ./linux-x64-binaries
104+
asset_name: linux-x64-binaries.zip
105+
asset_content_type: application/zip
106+
107+
- name: Upload rhel-x64 Release Asset
108+
uses: actions/upload-release-asset@v1
109+
env:
110+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
111+
with:
112+
upload_url: ${{ steps.create_release.outputs.upload_url }}
113+
asset_path: ./rhel-x64-binaries
114+
asset_name: rhel-x64-binaries.zip
115+
asset_content_type: application/zip
116+
117+
- name: Upload osx-x64 Release Asset
118+
uses: actions/upload-release-asset@v1
119+
env:
120+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
121+
with:
122+
upload_url: ${{ steps.create_release.outputs.upload_url }}
123+
asset_path: ./osx-x64-binaries
124+
asset_name: osx-x64-binaries.zip
125+
asset_content_type: application/zip
126+
127+
- name: Upload win-x64 Release Asset
128+
uses: actions/upload-release-asset@v1
129+
env:
130+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
131+
with:
132+
upload_url: ${{ steps.create_release.outputs.upload_url }}
133+
asset_path: ./win-x64-binaries
134+
asset_name: win-x64-binaries.zip
135+
asset_content_type: application/zip

cli-exakvdocsign/CustomR256Signature.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,16 @@ public class RSAPKCS1SHA256SignatureDescription : SignatureDescription
7777
/// Construct an RSAPKCS1SHA256SignatureDescription object. The default settings for this object
7878
/// are:
7979
/// <list type="bullet">
80-
/// <item>Digest algorithm - <see cref="SHA256Managed" /></item>
81-
/// <item>Key algorithm - <see cref="RSACryptoServiceProvider" /></item>
80+
/// <item>Digest algorithm - <see cref="SHA256" /></item>
81+
/// <item>Key algorithm - <see cref="RSA" /></item>
8282
/// <item>Formatter algorithm - <see cref="RSAPKCS1SignatureFormatter" /></item>
8383
/// <item>Deformatter algorithm - <see cref="RSAPKCS1SignatureDeformatter" /></item>
8484
/// </list>
8585
/// </summary>
8686
public RSAPKCS1SHA256SignatureDescription()
8787
{
88-
KeyAlgorithm = typeof(RSACryptoServiceProvider).FullName;
89-
DigestAlgorithm = typeof(SHA256Managed).FullName; // Note - SHA256CryptoServiceProvider is not registered with CryptoConfig
88+
KeyAlgorithm = typeof(RSA).FullName; // Updated from RSACryptoServiceProvider
89+
DigestAlgorithm = typeof(SHA256).FullName; // Updated from SHA256Managed
9090
FormatterAlgorithm = typeof(RSAPKCS1SignatureFormatter).FullName;
9191
DeformatterAlgorithm = typeof(RSAPKCS1SignatureDeformatter).FullName;
9292
}

cli-exakvdocsign/CustomSigner.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,24 @@
77
using System.Security.Cryptography.Xml;
88
using System.Text;
99
using System.Reflection;
10-
using Microsoft.Azure.KeyVault;
11-
using Microsoft.Azure.KeyVault.Models;
12-
10+
using Azure.Security.KeyVault.Keys;
11+
using Azure.Security.KeyVault.Keys.Cryptography;
1312

1413
namespace cli_exakvdocsign
1514
{
1615
public class CustomSigner: CustomSignedXml.ISignerProvider
1716
{
1817
public byte[] Sign(byte[] data)
1918
{
20-
return cli_exakvdocsign.Program.keyVault.SignAsync(cli_exakvdocsign.Program.KeyVaultAddress, cli_exakvdocsign.Program.publicCertBundle.KeyIdentifier.Name, cli_exakvdocsign.Program.publicCertBundle.KeyIdentifier.Version, Microsoft.Azure.KeyVault.WebKey.JsonWebKeySignatureAlgorithm.RS256, data).Result.Result;
19+
// Create cryptography client for the key
20+
var cryptographyClient = new CryptographyClient(cli_exakvdocsign.Program.secretKey.Id, new Azure.Identity.ClientSecretCredential(
21+
tenantId: Environment.GetEnvironmentVariable("AZURE_TENANT_ID"),
22+
clientId: Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"), // You'll need to expose this from Program
23+
clientSecret: Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET"))); // You'll need to expose this from Program
24+
25+
// Sign the data using RS256 algorithm
26+
var signResult = cryptographyClient.SignAsync(SignatureAlgorithm.RS256, data).Result;
27+
return signResult.Signature;
2128
}
2229
}
2330
}

cli-exakvdocsign/Program.cs

Lines changed: 44 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,25 @@ Example Azure KeyVault HSM Protected Key XML Signing
33
*/
44

55
using System;
6-
using System.Net.Http;
76
using System.Security.Cryptography.X509Certificates;
87
using System.Threading.Tasks;
98
using System.Xml;
109
using System.Security.Cryptography;
1110
using System.Security.Cryptography.Xml;
12-
using Microsoft.Azure.KeyVault;
13-
using Microsoft.Azure.KeyVault.Models;
14-
using Microsoft.Extensions.Configuration;
15-
using Microsoft.Extensions.Configuration.AzureKeyVault;
16-
using Microsoft.IdentityModel.Clients.ActiveDirectory;
11+
using Azure.Security.KeyVault.Keys;
12+
using Azure.Security.KeyVault.Certificates;
13+
using Azure.Identity;
1714
using System.Text;
1815

19-
2016
namespace cli_exakvdocsign
2117
{
22-
class Program
18+
class Program
2319
{
2420
// AAD Application ID - Create a new application registration and grant it appropriate rights to the KeyVault.
2521
private static string AADClientID;
2622
// AAD Application Secret/Key - Create a "password key" that lives for the desired validity period before expiring.
2723
private static string AADClientSecret;
28-
// KeyVault Address - Full address of deployed KeyVault.
24+
// KeyVault Address - Full address of deployed KeyVault.
2925
internal static string KeyVaultAddress;
3026
//certificate name - Provided in creation of cert, also visible in key identifier. (*.vault.azure.net/keys/<certnamehere/*)
3127
internal static string CertName;
@@ -34,41 +30,46 @@ class Program
3430
//file name and path of where to save the signed xml document.
3531
private static string XMLFileOutputName;
3632

37-
//instantiated KeyVault client used through the example.
38-
internal static KeyVaultClient keyVault;
39-
//retrieved keybundle (private key). Note, the actual private key is never returned by Azure KeyVault HSM.
40-
internal static KeyBundle secretKeyBundle;
41-
//retrieved public certificate bundle. This will also hold a reference the the appropriate private key information.
42-
internal static CertificateBundle publicCertBundle;
43-
33+
//instantiated KeyVault clients used through the example.
34+
internal static KeyClient keyClient;
35+
internal static CertificateClient certificateClient;
36+
//retrieved key
37+
internal static KeyVaultKey secretKey;
38+
//retrieved public certificate
39+
internal static KeyVaultCertificateWithPolicy publicCert;
40+
4441
//holds file name of signed xml to check. When populated, no other actions are ran.
4542
private static string ValidateFile = null;
4643

47-
48-
49-
static void Main(string[] args)
44+
// Add these static properties to the Program class:
45+
internal static string TenantID;
46+
47+
static async Task Main(string[] args)
5048
{
5149
try{
5250
//run through the arguments and break them into variables.
5351
ProcessArgs(args);
5452

55-
//if user is requesting validaiton of a file, only run verifydoc and exit.
53+
//if user is requesting validation of a file, only run verifydoc and exit.
5654
if(ValidateFile != null)
5755
{
5856
VerifyDoc();
5957
}
6058
else{
61-
62-
//create KeyVault Client and authenticate with AAD. (GetAccessToken method.)
63-
keyVault = new KeyVaultClient(
64-
new KeyVaultClient.AuthenticationCallback(GetAccessToken),
65-
new HttpClient());
66-
67-
//get cert bundle from supplied certificate name.
68-
publicCertBundle = keyVault.GetCertificateAsync(KeyVaultAddress, CertName).Result;
69-
//get secret (private key) bundle from information in public cert bundle pointing to current key and version associated to cert.
70-
secretKeyBundle = keyVault.GetKeyAsync(publicCertBundle.KeyIdentifier.Vault, publicCertBundle.KeyIdentifier.Name).Result;
71-
59+
60+
//create KeyVault Clients with Azure Identity
61+
var credential = new ClientSecretCredential(
62+
tenantId: Environment.GetEnvironmentVariable("AZURE_TENANT_ID"), // You'll need to add this
63+
clientId: AADClientID,
64+
clientSecret: AADClientSecret);
65+
66+
keyClient = new KeyClient(new Uri(KeyVaultAddress), credential);
67+
certificateClient = new CertificateClient(new Uri(KeyVaultAddress), credential);
68+
69+
//get cert from supplied certificate name.
70+
publicCert = await certificateClient.GetCertificateAsync(CertName);
71+
//get key from certificate
72+
secretKey = await keyClient.GetKeyAsync(CertName);
7273

7374
//sign the doc yo!
7475
SignDoc();
@@ -79,16 +80,6 @@ static void Main(string[] args)
7980
}
8081
}
8182

82-
public static async Task<string> GetAccessToken(string authority, string resource, string scope)
83-
{
84-
ClientCredential clientCredential = new ClientCredential(AADClientID, AADClientSecret);
85-
86-
var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
87-
var result = await context.AcquireTokenAsync(resource, clientCredential);
88-
89-
return result.AccessToken;
90-
}
91-
9283
private static void ProcessArgs(string[] args){
9384
if(args.Length > 0){
9485
for(int i =0; i < args.Length; i++){
@@ -114,6 +105,10 @@ private static void ProcessArgs(string[] args){
114105
else if(args[i].StartsWith("-xmlfiletosave")){
115106
XMLFileOutputName = args[i+1];
116107
}
108+
else if(args[i].StartsWith("-tenantid"))
109+
{
110+
TenantID = args[i].Substring(10);
111+
}
117112
}
118113
}
119114
else{
@@ -147,8 +142,8 @@ public static void SignDoc(){
147142
// Load an XML file into the XmlDocument object.
148143
xmlDoc.PreserveWhitespace = true;
149144
xmlDoc.Load(XMLFileName);
150-
151-
// Sign the XML document.
145+
146+
// Sign the XML document.
152147
SignXml(xmlDoc);
153148

154149
}
@@ -164,19 +159,15 @@ public static void VerifyDoc(){
164159
// Load an XML file into the XmlDocument object.
165160
xmlDoc.PreserveWhitespace = true;
166161
xmlDoc.Load(ValidateFile);
167-
168-
// Sign the XML document.
162+
163+
// Sign the XML document.
169164
Console.WriteLine("The file validation results in: " + Verify(xmlDoc));
170165
}
171166

172-
//sourced https://docs.microsoft.com/en-us/dotnet/standard/security/how-to-sign-xml-documents-with-digital-signatures
173-
// Sign an XML file.
174-
// This document cannot be verified unless the verifying
175-
// code has the key with which it was signed.
176167
public static void SignXml(XmlDocument xmlDoc)
177168
{
178-
RSA key = secretKeyBundle.Key.ToRSA();
179-
169+
RSA key = secretKey.Key.ToRSA();
170+
180171
// Check arguments.
181172
if (xmlDoc == null)
182173
throw new ArgumentException("xmlDoc");
@@ -192,14 +183,12 @@ public static void SignXml(XmlDocument xmlDoc)
192183
// add key info
193184
KeyInfo importKeyInfo = new KeyInfo();
194185
KeyInfoX509Data importKeyInfoData = new KeyInfoX509Data();
195-
X509Certificate tempCert = new X509Certificate(publicCertBundle.Cer);
186+
X509Certificate tempCert = new X509Certificate(publicCert.Cer);
196187
importKeyInfoData.AddCertificate(tempCert);
197188
importKeyInfoData.AddIssuerSerial(tempCert.Issuer, tempCert.GetSerialNumberString());
198189

199190
importKeyInfo.AddClause(importKeyInfoData);
200191
signedXml.KeyInfo = importKeyInfo;
201-
202-
203192

204193
// Create a reference to be signed.
205194
Reference reference = new Reference();
@@ -225,8 +214,7 @@ public static void SignXml(XmlDocument xmlDoc)
225214
xmlDoc.Save(XMLFileOutputName);
226215

227216
var test = Verify(xmlDoc);
228-
Console.WriteLine("XML Signed and validated as: " + test.ToString());
229-
217+
Console.WriteLine("XML Signed and validated as: " + test.ToString());
230218
}
231219

232220
public static bool Verify(XmlDocument document)
@@ -251,9 +239,6 @@ public static bool Verify(XmlDocument document)
251239
}
252240
}
253241
return signed.CheckSignature(new X509Certificate2(cer), true);
254-
255242
}
256-
257-
258243
}
259244
}

0 commit comments

Comments
 (0)