Repository navigation
feat: hash algorithm, RSA padding (RS*), CBOR-valued headers, and Azure credential caching - #212
Conversation
Adds four signing options and removes a hardcoded padding choice. - --HashAlgorithm / --aas-hash-algorithm select SHA256, SHA384 or SHA512 for the local and Azure Artifact Signing paths. The indirect signature path already supported SHA384; the direct sign path did not. - --CborProtectedHeaders / --CborUnProtectedHeaders carry a header value that is already CBOR-encoded, supplied as base64. The existing int and string header options encode values on the caller's behalf and cannot express a pre-encoded structure such as a vendor signature blob. Each value must decode to exactly one well-formed CBOR data item, so a bad value fails during argument parsing rather than producing a signature with an undecodable header. - --aas-rsa-padding selects PSS (default) or PKCS#1 v1.5. The padding chooses the COSE algorithm family, so this is what makes RS256, RS384 and RS512 reachable; CoseSign1MessageFactory previously hardcoded PSS for every RSA key. Providers that do not implement the new optional ISupportsRsaSignaturePadding interface keep the PSS behavior, and the interface is separate from ICoseSigningKeyProvider because the latter targets netstandard2.0 and cannot carry a default implementation. - --aas-exclude-credentials, and the equivalent ExcludeCredentials JSON array, drop credentials from the DefaultAzureCredential chain so their probe timeouts are not paid on every run. Credentials are now cached per exclusion set instead of being rebuilt per signing call, which previously discarded the token cache each time. Adds CoseSignTool.AzureArtifactSigning.Plugin.Tests and wires it into the build workflow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 47678fda-9dc8-4452-9130-806f921eae8c
| public void CreateHeaderExtender_FromNullConfiguration_Throws() | ||
| { | ||
| Assert.ThrowsException<ArgumentNullException>( | ||
| () => CborHeaderHelper.CreateHeaderExtender((IConfiguration)null!)); |
| foreach (IConfigurationSection child in configuration.GetSection(ExcludeCredentialsSection).GetChildren()) | ||
| { | ||
| if (!string.IsNullOrWhiteSpace(child.Value)) | ||
| { | ||
| exclusions.Add(child.Value.Trim()); | ||
| } | ||
| } |
RgABAgME decodes to 0x46 followed by five bytes, which declares a six-byte CBOR byte string with only five bytes available. Copying the example straight from the help text therefore failed argument parsing with "does not contain well-formed CBOR". RAECAwQ= is 0x44 01 02 03 04, a well-formed four-byte CBOR byte string. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 47678fda-9dc8-4452-9130-806f921eae8c
|
LoadSigningKeyProvider() branches to LoadSigningKeyProviderFromPlugin() , which calls plugin.CreateProvider(configuration, …) and never reads HashAlgorithm . Only the local-certificate branch consumes it. So:
The operator asked for SHA512, got SHA256, and nothing said otherwise. Should it fail when --HashAlgorithm is combined with a plugin provider. |
|
Consider adding an option to specify a CBOR file for the protected header. For file: |
|
Should we consider adding a size check to the cbor header? |
Extend mst_register with an optional --proxy-endpoint mode backed by Azure.ArtifactSigning.MST TransparencyClient.RegisterTransparencyAsync. The existing direct-ledger path remains unchanged when the option is not supplied. Proxy mode retains the existing endpoint, payload, signature, timeout, and output arguments, and adds the Artifact Signing account, certificate profile, and optional correlation ID. The returned application/cose receipt is included in the JSON output as base64. Use the prerelease MST SDK from Prod-RW-ACS and isolate its Azure.Core 1.62 dependency inside the MST plugin. Add proxy-path tests and document the canary endpoint invocation. Also repair the existing workflow test command indentation so the test block remains valid YAML. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e18f1141-bfc7-48a8-b918-4f175d760d72
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e18f1141-bfc7-48a8-b918-4f175d760d72
Copilot-Session: e18f1141-bfc7-48a8-b918-4f175d760d72
Azure.CodeSigning.Sdk previously flowed in transitively at 0.1.135 via Azure.Developer.ArtifactSigning.CryptoProvider. Pin it explicitly to the Prod-RW-ACS build 0.1.186-jaxel-add-artifa0004 and add the feed as a restore source for the Azure Artifact Signing projects so the plugin deploys the newer SDK. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…004" This reverts commit f8f5492.
Use the corrected registerTransparency action route from Azure.ArtifactSigning.MST 0006 and pass the MST instance name required by its updated API. Keep Azure.CodeSigning.Sdk on the compatible transitive 0.1.135 version for signing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 485768f7-c951-4fbc-808b-7ee748e79f92
Use the trailing Azure Artifact Signing customer EKU when generating the SCITT CWT issuer so a statement identifies the selected certificate profile rather than the whole tenant. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 28815e2d-8608-4ab8-b531-d704d6f79085
|
Follow-up fix for COSE statement issuer generation: DawnWang17#2 The Artifact Signing certificate carries both tenant- and profile-scoped EKUs. The current deepest/greatest heuristic selects the tenant EKU, causing MST policy rejection. This PR selects the trailing profile-scoped EKU. Verified with 61 tests and a live MST SDK registration returning HTTP 200. |
…cwt-issuer fix: select profile-scoped Artifact Signing issuer
Keep the credential reuse, MST proxy, and profile-scoped issuer changes while relying on the generic hash, padding, and CBOR support now available in main. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4ccf81dc-70d3-461d-b6ac-04b133cf539c
Expose the proxy flow as aas_mst_register, reuse the Artifact Signing credential cache and exclusions, and restore the generic MST plugin to its main-branch behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4ccf81dc-70d3-461d-b6ac-04b133cf539c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4ccf81dc-70d3-461d-b6ac-04b133cf539c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4ccf81dc-70d3-461d-b6ac-04b133cf539c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4ccf81dc-70d3-461d-b6ac-04b133cf539c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4ccf81dc-70d3-461d-b6ac-04b133cf539c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4ccf81dc-70d3-461d-b6ac-04b133cf539c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4ccf81dc-70d3-461d-b6ac-04b133cf539c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4ccf81dc-70d3-461d-b6ac-04b133cf539c
Keep the workflow scoped to the Azure Artifact Signing plugin, persist the MST receipt in the transparent COSE statement, and cover failure/output behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e6f13c8b-c89e-4200-aa76-4965066f8a8f
Select the trailing profile-scoped Artifact Signing EKU instead of the broader tenant EKU so MST policy validation accepts the generated DID issuer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e6f13c8b-c89e-4200-aa76-4965066f8a8f
Pass the existing --ContentType/--cty value into the COSE message factory instead of always using application/cose. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e6f13c8b-c89e-4200-aa76-4965066f8a8f
Summary Adds four signing options to CoseSignTool and removes a hardcoded RSA padding choice. ### 1. Hash algorithm selection
--HashAlgorithm/--haonsign, and--aas-hash-algorithmfor the Azure Artifact Signing provider. AcceptsSHA256(default),SHA384,SHA512, case-insensitively and with an optional dash (sha-384). The indirect signature path already supported SHA384 end-to-end; the direct sign path was hardcoded to SHA256. ### 2. CBOR-valued custom headers--CborProtectedHeaders/--cbphand--CborUnProtectedHeaders/--cbuhtakelabel=base64pairs and place the decoded bytes into the header verbatim. The existing int and string header options encode values on the caller's behalf, so they cannot express a structure that is already CBOR-encoded — for example an existing vendor signature blob carried alongside the COSE signature. Each decoded value must be exactly one well-formed CBOR data item; malformed CBOR, trailing bytes, invalid base64, and empty values are rejected during argument parsing rather than producing a signature with an undecodable header. Labels that parse as an integer become integer header labels, anything else becomes a string label. ### 3. RSA signature padding (RS* algorithm support)--aas-rsa-paddingselectsPSS(default) orPKCS1. The COSE algorithm prefixesPSandRSare accepted as aliases. This is the part that actually makesRS256/RS384/RS512reachable:CoseSign1MessageFactorypreviously hardcodedRSASignaturePadding.Pssfor every RSA key, so no combination of options could produce an RS* signature. |--aas-hash-algorithm|PSS(default) |PKCS1| |---|---|---| |SHA256|PS256|RS256| |SHA384|PS384|RS384| |SHA512|PS512|RS512| The padding is exposed through a new optional capability interface,ISupportsRsaSignaturePadding, following the existingISupportsScittCompliancepattern. It is deliberately not a member ofICoseSigningKeyProvider: that interface targetsnetstandard2.0, which does not support default interface implementations, so adding it there would be a breaking change for external implementers. Providers that do not implement it keep the previous PSS behavior. ### 4. Credential exclusion and caching--aas-exclude-credentialstakes a comma-separated list, and the same list may be supplied as anExcludeCredentialsJSON array. Names are case-insensitive with an optionalCredentialsuffix. An unrecognized name throws rather than being silently ignored, since silently ignoring it would leave a credential the caller believes is excluded still in the chain.DefaultAzureCredentialprobes its chain in order and a credential that cannot succeed still costs a timeout, so excluding known-inapplicable credentials removes that delay. Credentials are also now cached per distinct exclusion set rather than constructed per signing call.DefaultAzureCredentialcaches tokens for its own lifetime, so the previous per-call construction discarded the token cache and re-authenticated for every artifact. ## Testing Full suite passes: 1281 passed, 0 failed across all 13 test projects. New tests: -HashAlgorithmHelperTests— valid/invalid names, casing, dashes, defaults, configuration binding. -RsaSignaturePaddingHelperTests— all padding spellings and the full hash x padding -> COSE algorithm mapping. -CborHeaderHelperTests— integer vs string labels, protected vs unprotected placement, preservation of existing headers, base64 padding in values, and rejection of malformed specs, invalid base64, empty values, malformed CBOR, and trailing bytes. -RsaSignaturePaddingTests— signs real messages and asserts the COSEalgheader is-257/-258/-259(RS256/RS384/RS512) and-37/-38/-39(PS256/PS384/PS512), plus a regression test that a default provider still produces PS256. -AzureCredentialFactoryTests— cache reuse for equivalent exclusion sets, distinct instances for different sets, name normalization, unknown-name rejection, andGetExclusionsfrom both the CLI value and the JSON array. Also verified end-to-end from the built CLI: signing with--HashAlgorithm SHA384 --CborProtectedHeadersproduced a COSE_Sign1 withalg= PS384 and both CBOR headers present with byte-identical values. New test projectCoseSignTool.AzureArtifactSigning.Plugin.Testsis added to the solution and to.github/workflows/dotnet.yml, matching the existing plugin test projects. ## Docsdocs/CoseSignTool.mdanddocs/CertificateProviders.mdupdated with the new options, the algorithm mapping table, and the credential exclusion list.5. Azure Artifact Signing MST proxy
mst_registernow accepts--proxy-endpoint,--account-name,--cert-profile-name, and optional--correlation-id. When--proxy-endpointis supplied, the command callsAzure.ArtifactSigning.MST.TransparencyClient.RegisterTransparencyAsync; without it, the existing direct-ledger behavior is unchanged.The proxy authenticates with
DefaultAzureCredentialand returns theapplication/cosetransparency receipt in the JSON output. It usesAzure.ArtifactSigning.MST0.1.186-jaxel-add-artifact-signing-mst-sdk.5from theProd-RW-ACSfeed; the package's Azure.Core 1.62 dependency is isolated to the MST plugin.Proxy-path tests cover option wiring, SDK request arguments and COSE body, receipt output, validation, and preservation of the direct path. Full suite: 1285 passed, 5 skipped, 0 failed. Debug and Release solution builds pass with 0 warnings.