diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 0000000..1194c80 --- /dev/null +++ b/.github/workflows/build-release.yml @@ -0,0 +1,135 @@ +name: Build and Release + +on: + push: + branches: [ master, main ] + pull_request: + branches: [ master, main ] + +jobs: + build: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Restore dependencies + run: dotnet restore + + - name: Build and publish for multiple platforms + run: | + dotnet publish -c Release --self-contained -r osx-x64 + dotnet publish -c Release --self-contained -r centos-x64 + dotnet publish -c Release --self-contained -r rhel-x64 + dotnet publish -c Release --self-contained -r linux-x64 + dotnet publish -c Release --self-contained -r win-x64 + + - name: Create artifacts + uses: actions/upload-artifact@v4 + with: + name: centos-x64-binaries + path: cli-exakvdocsign/bin/Release/net8.0/centos-x64/publish/ + + - name: Upload Linux x64 artifacts + uses: actions/upload-artifact@v4 + with: + name: linux-x64-binaries + path: cli-exakvdocsign/bin/Release/net8.0/linux-x64/publish/ + + - name: Upload RHEL x64 artifacts + uses: actions/upload-artifact@v4 + with: + name: rhel-x64-binaries + path: cli-exakvdocsign/bin/Release/net8.0/rhel-x64/publish/ + + - name: Upload macOS x64 artifacts + uses: actions/upload-artifact@v4 + with: + name: osx-x64-binaries + path: cli-exakvdocsign/bin/Release/net8.0/osx-x64/publish/ + + - name: Upload Windows x64 artifacts + uses: actions/upload-artifact@v4 + with: + name: win-x64-binaries + path: cli-exakvdocsign/bin/Release/net8.0/win-x64/publish/ + + release: + needs: build + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' + + steps: + - uses: actions/checkout@v4 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: v${{ github.run_number }} + release_name: Release v${{ github.run_number }} + body: ${{ github.event.head_commit.message }} + draft: true + prerelease: false + + - name: Upload centos-x64 Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./centos-x64-binaries + asset_name: centos-x64-binaries.zip + asset_content_type: application/zip + + - name: Upload linux-x64 Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./linux-x64-binaries + asset_name: linux-x64-binaries.zip + asset_content_type: application/zip + + - name: Upload rhel-x64 Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./rhel-x64-binaries + asset_name: rhel-x64-binaries.zip + asset_content_type: application/zip + + - name: Upload osx-x64 Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./osx-x64-binaries + asset_name: osx-x64-binaries.zip + asset_content_type: application/zip + + - name: Upload win-x64 Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./win-x64-binaries + asset_name: win-x64-binaries.zip + asset_content_type: application/zip \ No newline at end of file diff --git a/cli-exakvdocsign/CustomR256Signature.cs b/cli-exakvdocsign/CustomR256Signature.cs index e98bc99..4712cb7 100644 --- a/cli-exakvdocsign/CustomR256Signature.cs +++ b/cli-exakvdocsign/CustomR256Signature.cs @@ -77,16 +77,16 @@ public class RSAPKCS1SHA256SignatureDescription : SignatureDescription /// Construct an RSAPKCS1SHA256SignatureDescription object. The default settings for this object /// are: /// - /// Digest algorithm - - /// Key algorithm - + /// Digest algorithm - + /// Key algorithm - /// Formatter algorithm - /// Deformatter algorithm - /// /// public RSAPKCS1SHA256SignatureDescription() { - KeyAlgorithm = typeof(RSACryptoServiceProvider).FullName; - DigestAlgorithm = typeof(SHA256Managed).FullName; // Note - SHA256CryptoServiceProvider is not registered with CryptoConfig + KeyAlgorithm = typeof(RSA).FullName; // Updated from RSACryptoServiceProvider + DigestAlgorithm = typeof(SHA256).FullName; // Updated from SHA256Managed FormatterAlgorithm = typeof(RSAPKCS1SignatureFormatter).FullName; DeformatterAlgorithm = typeof(RSAPKCS1SignatureDeformatter).FullName; } diff --git a/cli-exakvdocsign/CustomSigner.cs b/cli-exakvdocsign/CustomSigner.cs index bd96126..d542e8f 100644 --- a/cli-exakvdocsign/CustomSigner.cs +++ b/cli-exakvdocsign/CustomSigner.cs @@ -7,9 +7,8 @@ using System.Security.Cryptography.Xml; using System.Text; using System.Reflection; -using Microsoft.Azure.KeyVault; -using Microsoft.Azure.KeyVault.Models; - +using Azure.Security.KeyVault.Keys; +using Azure.Security.KeyVault.Keys.Cryptography; namespace cli_exakvdocsign { @@ -17,7 +16,15 @@ public class CustomSigner: CustomSignedXml.ISignerProvider { public byte[] Sign(byte[] data) { - 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; + // Create cryptography client for the key + var cryptographyClient = new CryptographyClient(cli_exakvdocsign.Program.secretKey.Id, new Azure.Identity.ClientSecretCredential( + tenantId: Environment.GetEnvironmentVariable("AZURE_TENANT_ID"), + clientId: Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"), // You'll need to expose this from Program + clientSecret: Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET"))); // You'll need to expose this from Program + + // Sign the data using RS256 algorithm + var signResult = cryptographyClient.SignAsync(SignatureAlgorithm.RS256, data).Result; + return signResult.Signature; } } } diff --git a/cli-exakvdocsign/Program.cs b/cli-exakvdocsign/Program.cs index 9e821b8..12b4a57 100644 --- a/cli-exakvdocsign/Program.cs +++ b/cli-exakvdocsign/Program.cs @@ -3,29 +3,25 @@ Example Azure KeyVault HSM Protected Key XML Signing */ using System; -using System.Net.Http; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using System.Xml; using System.Security.Cryptography; using System.Security.Cryptography.Xml; -using Microsoft.Azure.KeyVault; -using Microsoft.Azure.KeyVault.Models; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Configuration.AzureKeyVault; -using Microsoft.IdentityModel.Clients.ActiveDirectory; +using Azure.Security.KeyVault.Keys; +using Azure.Security.KeyVault.Certificates; +using Azure.Identity; using System.Text; - namespace cli_exakvdocsign { -class Program + class Program { // AAD Application ID - Create a new application registration and grant it appropriate rights to the KeyVault. private static string AADClientID; // AAD Application Secret/Key - Create a "password key" that lives for the desired validity period before expiring. private static string AADClientSecret; - // KeyVault Address - Full address of deployed KeyVault. + // KeyVault Address - Full address of deployed KeyVault. internal static string KeyVaultAddress; //certificate name - Provided in creation of cert, also visible in key identifier. (*.vault.azure.net/keys/ GetAccessToken(string authority, string resource, string scope) - { - ClientCredential clientCredential = new ClientCredential(AADClientID, AADClientSecret); - - var context = new AuthenticationContext(authority, TokenCache.DefaultShared); - var result = await context.AcquireTokenAsync(resource, clientCredential); - - return result.AccessToken; - } - private static void ProcessArgs(string[] args){ if(args.Length > 0){ for(int i =0; i < args.Length; i++){ @@ -114,6 +105,10 @@ private static void ProcessArgs(string[] args){ else if(args[i].StartsWith("-xmlfiletosave")){ XMLFileOutputName = args[i+1]; } + else if(args[i].StartsWith("-tenantid")) + { + TenantID = args[i].Substring(10); + } } } else{ @@ -147,8 +142,8 @@ public static void SignDoc(){ // Load an XML file into the XmlDocument object. xmlDoc.PreserveWhitespace = true; xmlDoc.Load(XMLFileName); - - // Sign the XML document. + + // Sign the XML document. SignXml(xmlDoc); } @@ -164,19 +159,15 @@ public static void VerifyDoc(){ // Load an XML file into the XmlDocument object. xmlDoc.PreserveWhitespace = true; xmlDoc.Load(ValidateFile); - - // Sign the XML document. + + // Sign the XML document. Console.WriteLine("The file validation results in: " + Verify(xmlDoc)); } - //sourced https://docs.microsoft.com/en-us/dotnet/standard/security/how-to-sign-xml-documents-with-digital-signatures - // Sign an XML file. - // This document cannot be verified unless the verifying - // code has the key with which it was signed. public static void SignXml(XmlDocument xmlDoc) { - RSA key = secretKeyBundle.Key.ToRSA(); - + RSA key = secretKey.Key.ToRSA(); + // Check arguments. if (xmlDoc == null) throw new ArgumentException("xmlDoc"); @@ -192,14 +183,12 @@ public static void SignXml(XmlDocument xmlDoc) // add key info KeyInfo importKeyInfo = new KeyInfo(); KeyInfoX509Data importKeyInfoData = new KeyInfoX509Data(); - X509Certificate tempCert = new X509Certificate(publicCertBundle.Cer); + X509Certificate tempCert = new X509Certificate(publicCert.Cer); importKeyInfoData.AddCertificate(tempCert); importKeyInfoData.AddIssuerSerial(tempCert.Issuer, tempCert.GetSerialNumberString()); importKeyInfo.AddClause(importKeyInfoData); signedXml.KeyInfo = importKeyInfo; - - // Create a reference to be signed. Reference reference = new Reference(); @@ -225,8 +214,7 @@ public static void SignXml(XmlDocument xmlDoc) xmlDoc.Save(XMLFileOutputName); var test = Verify(xmlDoc); - Console.WriteLine("XML Signed and validated as: " + test.ToString()); - + Console.WriteLine("XML Signed and validated as: " + test.ToString()); } public static bool Verify(XmlDocument document) @@ -251,9 +239,6 @@ public static bool Verify(XmlDocument document) } } return signed.CheckSignature(new X509Certificate2(cer), true); - } - - } } diff --git a/cli-exakvdocsign/cli-exakvdocsign.csproj b/cli-exakvdocsign/cli-exakvdocsign.csproj index 8262300..bd3ea5f 100644 --- a/cli-exakvdocsign/cli-exakvdocsign.csproj +++ b/cli-exakvdocsign/cli-exakvdocsign.csproj @@ -2,15 +2,13 @@ Exe true - netcoreapp2.0 - linux-x64;centos-x64;rhel-x64;osx-x64;win-x64;win-x86 + net8.0 + linux-x64;centos-x64;rhel-x64;osx-x64;win-x64;win-x86 - - - - - + + +