@@ -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