Skip to content

Commit 1b25d5c

Browse files
authored
Add Key Vault signing sample back in (Azure#2480)
Now that we install the openssl dependency in Windows via vpkg, I can put this sample back into the Key Vault certificates README
1 parent 28c3cc8 commit 1b25d5c

File tree

1 file changed

+117
-0
lines changed
  • sdk/keyvault/azure_security_keyvault_certificates

1 file changed

+117
-0
lines changed

sdk/keyvault/azure_security_keyvault_certificates/README.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ The following section provides several code snippets using the `CertificateClien
7373
* [Update an existing certificate](#update-an-existing-certificate)
7474
* [Delete a certificate](#delete-a-certificate)
7575
* [List certificates](#list-certificates)
76+
* [Key operations using certificates](#key-operations-using-certificates)
7677

7778
### Create a certificate
7879

@@ -283,6 +284,122 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
283284
}
284285
```
285286

287+
### Key operations using certificates
288+
289+
You can use a `KeyClient` to perform key operations on a certificate created with a `CertificateClient`.
290+
The following example shows how to sign data using an EC certificate key.
291+
292+
```rust no_run
293+
use azure_core::base64;
294+
use azure_identity::DefaultAzureCredential;
295+
use azure_security_keyvault_certificates::{
296+
models::{
297+
CertificatePolicy, CreateCertificateParameters, CurveName, IssuerParameters, KeyProperties,
298+
KeyType, KeyUsageType, X509CertificateProperties,
299+
},
300+
CertificateClient, ResourceExt, ResourceId,
301+
};
302+
use azure_security_keyvault_keys::{
303+
models::{SignParameters, SignatureAlgorithm},
304+
KeyClient,
305+
};
306+
use openssl::sha::sha256;
307+
use std::{env, time::Duration};
308+
use tokio::time::sleep;
309+
310+
#[tokio::main]
311+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
312+
// Pass data to sign as the first argument.
313+
let plaintext = env::args().nth(1).ok_or("plaintext required")?;
314+
315+
let certificate_client = CertificateClient::new(
316+
"https://tcac7e9c41ef52cec.vault.azure.net/",
317+
DefaultAzureCredential::new()?,
318+
None,
319+
)?;
320+
321+
// Create an EC certificate policy for signing.
322+
let policy = CertificatePolicy {
323+
x509_certificate_properties: Some(X509CertificateProperties {
324+
subject: Some("CN=DefaultPolicy".into()),
325+
key_usage: vec![KeyUsageType::DigitalSignature],
326+
..Default::default()
327+
}),
328+
issuer_parameters: Some(IssuerParameters {
329+
name: Some("Self".into()),
330+
..Default::default()
331+
}),
332+
key_properties: Some(KeyProperties {
333+
key_type: Some(KeyType::EC),
334+
curve: Some(CurveName::P256),
335+
..Default::default()
336+
}),
337+
..Default::default()
338+
};
339+
340+
// Create a self-signed certificate.
341+
let body = CreateCertificateParameters {
342+
certificate_policy: Some(policy),
343+
..Default::default()
344+
};
345+
let mut operation = certificate_client
346+
.create_certificate("ec-signing-certificate", body.try_into()?, None)
347+
.await?
348+
.into_body()
349+
.await?;
350+
let ResourceId {
351+
vault_url,
352+
name: certificate_name,
353+
..
354+
} = operation.resource_id()?;
355+
356+
// Wait for the certificate operation to complete.
357+
loop {
358+
if matches!(operation.status, Some(ref status) if status == "completed") {
359+
break;
360+
}
361+
362+
if let Some(err) = operation.error {
363+
Err(azure_core::Error::new(
364+
azure_core::error::ErrorKind::Other,
365+
err.message
366+
.unwrap_or_else(|| "failed to create certificate".into()),
367+
))?;
368+
}
369+
370+
sleep(Duration::from_secs(3)).await;
371+
372+
operation = certificate_client
373+
.get_certificate_operation(&certificate_name, None)
374+
.await?
375+
.into_body()
376+
.await?;
377+
}
378+
379+
// Hash the plaintext to be signed.
380+
let digest = sha256(plaintext.as_bytes()).to_vec();
381+
382+
// Create a KeyClient using the certificate to sign the digest.
383+
let key_client = KeyClient::new(&vault_url, DefaultAzureCredential::new()?, None)?;
384+
let body = SignParameters {
385+
algorithm: Some(SignatureAlgorithm::ES256),
386+
value: Some(digest),
387+
};
388+
389+
let signature = key_client
390+
.sign(&certificate_name, "", body.try_into()?, None)
391+
.await?
392+
.into_body()
393+
.await?;
394+
395+
if let Some(signature) = signature.result.map(base64::encode_url_safe) {
396+
println!("Signature: {}", signature);
397+
}
398+
399+
Ok(())
400+
}
401+
```
402+
286403
## Troubleshooting
287404

288405
### General

0 commit comments

Comments
 (0)