Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Keyvault] az keyvault key sign/verify: Fix --digest to accept base64 encoded string #30521

Merged
merged 2 commits into from
Dec 23, 2024

Conversation

evelyn-ys
Copy link
Member

Related command

az keyvault key sign/verify

Description

Fix #27631, #28027

--digest now accepts base64 encoded string

Testing Guide

> echo "HelloWorld" | openssl dgst -sha256 -binary | openssl base64
Pz8hPx8/Pz9mP11RFj8/Mz8/bj91PwRhPz8JQ2k/eGMNCg==
> az keyvault key sign -n $rsaKey --vault-name $testVault -a RS256 --digest Pz8hPx8/Pz9mP11RFj8/Mz8/bj91PwRhP
{
  "algorithm": "RS256",
  "keyId": "https://$testVault.vault.azure.net/keys/......",
  "signature": "UZmopfF5fHtGs+qu8............=="
}
> az keyvault key verify -n $rsaKey --vault-name $testVault -a RS256 --digest Pz8hPx8/Pz9mP11RFj8/Mz8/bj91PwRhP --signature "UZmopfF5fHtGs+qu8............=="
{
  "algorithm": "RS256",
  "isValid": true,
  "keyId": "https://$testVault.vault.azure.net/keys/......"
}
> az keyvault key sign -n $ecKey --vault-name $testVault -a ES256 --digest Pz8hPx8/Pz9mP11RFj8/Mz8/bj91PwRhP
> az keyvault key verify -n $ecKey --vault-name $testVault -a ES256 --digest Pz8hPx8/Pz9mP11RFj8/Mz8 --signature "......"

History Notes

[Component Name 1] BREAKING CHANGE: az command a: Make some customer-facing breaking change
[Component Name 2] az command b: Add some customer-facing feature


This checklist is used to make sure that common guidelines for a pull request are followed.

Copy link

azure-client-tools-bot-prd bot commented Dec 16, 2024

️✔️AzureCLI-FullTest
️✔️acr
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️acs
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️advisor
️✔️latest
️✔️3.12
️✔️3.9
️✔️ams
️✔️latest
️✔️3.12
️✔️3.9
️✔️apim
️✔️latest
️✔️3.12
️✔️3.9
️✔️appconfig
️✔️latest
️✔️3.12
️✔️3.9
️✔️appservice
️✔️latest
️✔️3.12
️✔️3.9
️✔️aro
️✔️latest
️✔️3.12
️✔️3.9
️✔️backup
️✔️latest
️✔️3.12
️✔️3.9
️✔️batch
️✔️latest
️✔️3.12
️✔️3.9
️✔️batchai
️✔️latest
️✔️3.12
️✔️3.9
️✔️billing
️✔️latest
️✔️3.12
️✔️3.9
️✔️botservice
️✔️latest
️✔️3.12
️✔️3.9
️✔️cdn
️✔️latest
️✔️3.12
️✔️3.9
️✔️cloud
️✔️latest
️✔️3.12
️✔️3.9
️✔️cognitiveservices
️✔️latest
️✔️3.12
️✔️3.9
️✔️compute_recommender
️✔️latest
️✔️3.12
️✔️3.9
️✔️computefleet
️✔️latest
️✔️3.12
️✔️3.9
️✔️config
️✔️latest
️✔️3.12
️✔️3.9
️✔️configure
️✔️latest
️✔️3.12
️✔️3.9
️✔️consumption
️✔️latest
️✔️3.12
️✔️3.9
️✔️container
️✔️latest
️✔️3.12
️✔️3.9
️✔️containerapp
️✔️latest
️✔️3.12
️✔️3.9
️✔️core
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️cosmosdb
️✔️latest
️✔️3.12
️✔️3.9
️✔️databoxedge
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️dls
️✔️latest
️✔️3.12
️✔️3.9
️✔️dms
️✔️latest
️✔️3.12
️✔️3.9
️✔️eventgrid
️✔️latest
️✔️3.12
️✔️3.9
️✔️eventhubs
️✔️latest
️✔️3.12
️✔️3.9
️✔️feedback
️✔️latest
️✔️3.12
️✔️3.9
️✔️find
️✔️latest
️✔️3.12
️✔️3.9
️✔️hdinsight
️✔️latest
️✔️3.12
️✔️3.9
️✔️identity
️✔️latest
️✔️3.12
️✔️3.9
️✔️iot
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️keyvault
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️lab
️✔️latest
️✔️3.12
️✔️3.9
️✔️managedservices
️✔️latest
️✔️3.12
️✔️3.9
️✔️maps
️✔️latest
️✔️3.12
️✔️3.9
️✔️marketplaceordering
️✔️latest
️✔️3.12
️✔️3.9
️✔️monitor
️✔️latest
️✔️3.12
️✔️3.9
️✔️mysql
️✔️latest
️✔️3.12
️✔️3.9
️✔️netappfiles
️✔️latest
️✔️3.12
️✔️3.9
️✔️network
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️policyinsights
️✔️latest
️✔️3.12
️✔️3.9
️✔️privatedns
️✔️latest
️✔️3.12
️✔️3.9
️✔️profile
️✔️latest
️✔️3.12
️✔️3.9
️✔️rdbms
️✔️latest
️✔️3.12
️✔️3.9
️✔️redis
️✔️latest
️✔️3.12
️✔️3.9
️✔️relay
️✔️latest
️✔️3.12
️✔️3.9
️✔️resource
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️role
️✔️latest
️✔️3.12
️✔️3.9
️✔️search
️✔️latest
️✔️3.12
️✔️3.9
️✔️security
️✔️latest
️✔️3.12
️✔️3.9
️✔️servicebus
️✔️latest
️✔️3.12
️✔️3.9
️✔️serviceconnector
️✔️latest
️✔️3.12
️✔️3.9
️✔️servicefabric
️✔️latest
️✔️3.12
️✔️3.9
️✔️signalr
️✔️latest
️✔️3.12
️✔️3.9
️✔️sql
️✔️latest
️✔️3.12
️✔️3.9
️✔️sqlvm
️✔️latest
️✔️3.12
️✔️3.9
️✔️storage
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️synapse
️✔️latest
️✔️3.12
️✔️3.9
️✔️telemetry
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️util
️✔️latest
️✔️3.12
️✔️3.9
️✔️vm
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9

Copy link

azure-client-tools-bot-prd bot commented Dec 16, 2024

️✔️AzureCLI-BreakingChangeTest
️✔️Non Breaking Changes

@yonzhan
Copy link
Collaborator

yonzhan commented Dec 16, 2024

Thank you for your contribution! We will review the pull request and get back to you soon.

Copy link

⚠️Your changes in this PR will be released on Jan 14, 2025 due to CCOA (extend to Jan 6, 2025)

SignatureAlgorithm = cmd.loader.get_sdk('SignatureAlgorithm', mod='crypto._enums',
resource_type=ResourceType.DATA_KEYVAULT_KEYS)
crypto_client = client.get_cryptography_client(name, key_version=version)
return crypto_client.sign(SignatureAlgorithm(algorithm), digest.encode('utf-8'))
return crypto_client.sign(SignatureAlgorithm(algorithm),
hash_func(base64.b64decode(digest.encode('utf-8'))).digest())
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the argument is called digest, it's already a hash of the data. This is computing a hash of hash.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evelyn-ys best to confirm what crypto_client.sign() does specifically (does it digest again internall), but re-digesting the digest before calling sign() is definitely unnecessary.

@@ -1127,19 +1128,31 @@ def decrypt_key(cmd, client, algorithm, value, iv=None, tag=None, aad=None,


def sign_key(cmd, client, algorithm, digest, name=None, version=None):
if '256' in algorithm:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should really be matching a list of precise allowed identifiers for the digest functions that are supported. Someone passing 'sha-224' for example will get a signature using sha-512, and that's not going to be what they want.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the options for algorithm are ES256, ES256K, ES384, ES512, PS256, PS384, PS512, RS256, RS384, RS512, so it's either sha256, sha384 or sha512

Copy link

@achamayou achamayou Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but this list is presumably checked elsewhere, and may get extended in the future, at which point this can become unsafe. Something like:

signing_algo_to_digest_algo = {
  "ES256": hashlib.sha256,
  ...
}

hash_func = signing_algo_to_digest_algo[algorithm]

would be clearer and reduce the chance that the function can be used in an unsafe manner.



def verify_key(cmd, client, algorithm, digest, signature, name=None, version=None):
import base64
if '256' in algorithm:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, this is worse because it has the potential to create confusion about what's being verified. It's really important to have a precise mapping.

SignatureAlgorithm = cmd.loader.get_sdk('SignatureAlgorithm', mod='crypto._enums',
resource_type=ResourceType.DATA_KEYVAULT_KEYS)
crypto_client = client.get_cryptography_client(name, key_version=version)
return crypto_client.verify(SignatureAlgorithm(algorithm),
digest.encode('utf-8'),
hash_func(base64.b64decode(digest.encode('utf-8'))).digest(),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extra round of digest is going to be an unwelcome surprise for users, who won't expect it, if they try to verify using their own code. There needs to be a testcase that checks that signatures created using the REST API directly can be verified with this call.

Copy link
Member Author

@evelyn-ys evelyn-ys Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that CLI shouldn't make extra undocumented logic above REST API. Will revert additional hash

@freedge
Copy link
Contributor

freedge commented Dec 17, 2024

the patch applied cleanly, I tested OK with az keyvault key sign -a RS384 and az keyvault key verify -a RS384, also downloading the public key and verifying it with openssl dgst -verify rsa.pub -sha384 , this looks great, thanks!

@evelyn-ys evelyn-ys merged commit 683c286 into Azure:dev Dec 23, 2024
53 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Auto-Assign Auto assign by bot KeyVault az keyvault
Projects
None yet
Development

Successfully merging this pull request may close these issues.

signing of arbitrary 32 byte digest not working with az keyvault key sign
5 participants