# SkillPatch skill: azure-security-keyvault-keys-java

This skill provides comprehensive guidance for managing cryptographic keys and performing cryptographic operations using the Azure Key Vault Keys Java SDK. It covers client creation (sync and async), key types (RSA, EC, HSM-backed), and code examples for creating and working with keys. It is designed to help agents integrate Azure Key Vault key management into Java applications.

You (the agent) were given this URL and asked to use this skill. This is a **public** skill — no SkillPatch account, API key, or prior setup is required. Two ways to use it:

**1. Use it right now** — the skill's complete file tree (SKILL.md + all reference files) is inlined below; read `SKILL.md` first, then follow it, consulting the other files as it directs.

**2. Install the exact package onto disk** (recommended if you can run a shell — this reproduces the skill byte-for-byte, including any binary assets that can't be inlined):

```bash
mkdir -p .claude/skills/azure-security-keyvault-keys-java
curl -sSL https://skillpatch.dev/install_skill/azure-security-keyvault-keys-java | tar -xz -C .claude/skills/
```

(`.claude/skills/` is Claude Code's convention; use whatever directory your agent loads skills from.)


---

## Skill files (2)

- `SKILL.md`
- `references/examples.md`


### `SKILL.md`

````markdown
---
name: azure-security-keyvault-keys-java
description: Azure Key Vault Keys Java SDK for cryptographic key management. Use when creating, managing, or using RSA/EC keys, performing encrypt/decrypt/sign/verify operations, or working with HSM-backed keys.
license: MIT
metadata:
  author: Microsoft
  version: "1.0.0"
  package: com.azure:azure-security-keyvault-keys
---

# Azure Key Vault Keys (Java)

Manage cryptographic keys and perform cryptographic operations in Azure Key Vault and Managed HSM.

## Installation

```xml
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-security-keyvault-keys</artifactId>
    <version>4.9.0</version>
</dependency>
```

## Client Creation

```java
import com.azure.core.credential.TokenCredential;
import com.azure.identity.AzureIdentityEnvVars;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.ManagedIdentityCredentialBuilder;
import com.azure.security.keyvault.keys.KeyClient;
import com.azure.security.keyvault.keys.KeyClientBuilder;
import com.azure.security.keyvault.keys.cryptography.CryptographyClient;
import com.azure.security.keyvault.keys.cryptography.CryptographyClientBuilder;

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
TokenCredential credential = new DefaultAzureCredentialBuilder()
    .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
    .build();
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
// TokenCredential credential = new ManagedIdentityCredentialBuilder().build();

// Key management client
KeyClient keyClient = new KeyClientBuilder()
    .vaultUrl("https://<vault-name>.vault.azure.net")
    .credential(credential)
    .buildClient();

// Async client
KeyAsyncClient keyAsyncClient = new KeyClientBuilder()
    .vaultUrl("https://<vault-name>.vault.azure.net")
    .credential(credential)
    .buildAsyncClient();

// Cryptography client (for encrypt/decrypt/sign/verify)
CryptographyClient cryptoClient = new CryptographyClientBuilder()
    .keyIdentifier("https://<vault-name>.vault.azure.net/keys/<key-name>/<key-version>")
    .credential(credential)
    .buildClient();
```

## Key Types

| Type | Description |
|------|-------------|
| `RSA` | RSA key (2048, 3072, 4096 bits) |
| `RSA_HSM` | RSA key in HSM |
| `EC` | Elliptic Curve key |
| `EC_HSM` | Elliptic Curve key in HSM |
| `OCT` | Symmetric key (Managed HSM only) |
| `OCT_HSM` | Symmetric key in HSM |

## Create Keys

### Create RSA Key

```java
import com.azure.security.keyvault.keys.models.*;

// Simple RSA key
KeyVaultKey rsaKey = keyClient.createRsaKey(new CreateRsaKeyOptions("my-rsa-key")
    .setKeySize(2048));

System.out.println("Key name: " + rsaKey.getName());
System.out.println("Key ID: " + rsaKey.getId());
System.out.println("Key type: " + rsaKey.getKeyType());

// RSA key with options
KeyVaultKey rsaKeyWithOptions = keyClient.createRsaKey(new CreateRsaKeyOptions("my-rsa-key-2")
    .setKeySize(4096)
    .setExpiresOn(OffsetDateTime.now().plusYears(1))
    .setNotBefore(OffsetDateTime.now())
    .setEnabled(true)
    .setKeyOperations(KeyOperation.ENCRYPT, KeyOperation.DECRYPT, 
                       KeyOperation.WRAP_KEY, KeyOperation.UNWRAP_KEY)
    .setTags(Map.of("environment", "production")));

// HSM-backed RSA key
KeyVaultKey hsmKey = keyClient.createRsaKey(new CreateRsaKeyOptions("my-hsm-key")
    .setKeySize(2048)
    .setHardwareProtected(true));
```

### Create EC Key

```java
// EC key with P-256 curve
KeyVaultKey ecKey = keyClient.createEcKey(new CreateEcKeyOptions("my-ec-key")
    .setCurveName(KeyCurveName.P_256));

// EC key with other curves
KeyVaultKey ecKey384 = keyClient.createEcKey(new CreateEcKeyOptions("my-ec-key-384")
    .setCurveName(KeyCurveName.P_384));

KeyVaultKey ecKey521 = keyClient.createEcKey(new CreateEcKeyOptions("my-ec-key-521")
    .setCurveName(KeyCurveName.P_521));

// HSM-backed EC key
KeyVaultKey ecHsmKey = keyClient.createEcKey(new CreateEcKeyOptions("my-ec-hsm-key")
    .setCurveName(KeyCurveName.P_256)
    .setHardwareProtected(true));
```

### Create Symmetric Key (Managed HSM only)

```java
KeyVaultKey octKey = keyClient.createOctKey(new CreateOctKeyOptions("my-symmetric-key")
    .setKeySize(256)
    .setHardwareProtected(true));
```

## Get Key

```java
// Get latest version
KeyVaultKey key = keyClient.getKey("my-key");

// Get specific version
KeyVaultKey keyVersion = keyClient.getKey("my-key", "<version-id>");

// Get only key properties (no key material)
KeyProperties keyProps = keyClient.getKey("my-key").getProperties();
```

## Update Key Properties

```java
KeyVaultKey key = keyClient.getKey("my-key");

// Update properties
key.getProperties()
    .setEnabled(false)
    .setExpiresOn(OffsetDateTime.now().plusMonths(6))
    .setTags(Map.of("status", "archived"));

KeyVaultKey updatedKey = keyClient.updateKeyProperties(key.getProperties(),
    KeyOperation.ENCRYPT, KeyOperation.DECRYPT);
```

## List Keys

```java
import com.azure.core.util.paging.PagedIterable;

// List all keys
for (KeyProperties keyProps : keyClient.listPropertiesOfKeys()) {
    System.out.println("Key: " + keyProps.getName());
    System.out.println("  Enabled: " + keyProps.isEnabled());
    System.out.println("  Created: " + keyProps.getCreatedOn());
}

// List key versions
for (KeyProperties version : keyClient.listPropertiesOfKeyVersions("my-key")) {
    System.out.println("Version: " + version.getVersion());
    System.out.println("Created: " + version.getCreatedOn());
}
```

## Delete Key

```java
import com.azure.core.util.polling.SyncPoller;

// Begin delete (soft-delete enabled vaults)
SyncPoller<DeletedKey, Void> deletePoller = keyClient.beginDeleteKey("my-key");

// Wait for deletion
DeletedKey deletedKey = deletePoller.poll().getValue();
System.out.println("Deleted: " + deletedKey.getDeletedOn());

deletePoller.waitForCompletion();

// Purge deleted key (permanent deletion)
keyClient.purgeDeletedKey("my-key");

// Recover deleted key
SyncPoller<KeyVaultKey, Void> recoverPoller = keyClient.beginRecoverDeletedKey("my-key");
recoverPoller.waitForCompletion();
```

## Cryptographic Operations

### Encrypt/Decrypt

```java
import com.azure.security.keyvault.keys.cryptography.models.*;

CryptographyClient cryptoClient = new CryptographyClientBuilder()
    .keyIdentifier("https://<vault>.vault.azure.net/keys/<key-name>")
    .credential(new DefaultAzureCredentialBuilder().build())
    .buildClient();

byte[] plaintext = "Hello, World!".getBytes(StandardCharsets.UTF_8);

// Encrypt
EncryptResult encryptResult = cryptoClient.encrypt(EncryptionAlgorithm.RSA_OAEP, plaintext);
byte[] ciphertext = encryptResult.getCipherText();
System.out.println("Ciphertext length: " + ciphertext.length);

// Decrypt
DecryptResult decryptResult = cryptoClient.decrypt(EncryptionAlgorithm.RSA_OAEP, ciphertext);
String decrypted = new String(decryptResult.getPlainText(), StandardCharsets.UTF_8);
System.out.println("Decrypted: " + decrypted);
```

### Sign/Verify

```java
import java.security.MessageDigest;

// Create digest of data
byte[] data = "Data to sign".getBytes(StandardCharsets.UTF_8);
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(data);

// Sign
SignResult signResult = cryptoClient.sign(SignatureAlgorithm.RS256, digest);
byte[] signature = signResult.getSignature();

// Verify
VerifyResult verifyResult = cryptoClient.verify(SignatureAlgorithm.RS256, digest, signature);
System.out.println("Valid signature: " + verifyResult.isValid());
```

### Wrap/Unwrap Key

```java
// Key to wrap (e.g., AES key)
byte[] keyToWrap = new byte[32];  // 256-bit key
new SecureRandom().nextBytes(keyToWrap);

// Wrap
WrapResult wrapResult = cryptoClient.wrapKey(KeyWrapAlgorithm.RSA_OAEP, keyToWrap);
byte[] wrappedKey = wrapResult.getEncryptedKey();

// Unwrap
UnwrapResult unwrapResult = cryptoClient.unwrapKey(KeyWrapAlgorithm.RSA_OAEP, wrappedKey);
byte[] unwrappedKey = unwrapResult.getKey();
```

## Backup and Restore

```java
// Backup
byte[] backup = keyClient.backupKey("my-key");

// Save backup to file
Files.write(Paths.get("key-backup.blob"), backup);

// Restore
byte[] backupData = Files.readAllBytes(Paths.get("key-backup.blob"));
KeyVaultKey restoredKey = keyClient.restoreKeyBackup(backupData);
```

## Key Rotation

```java
// Rotate to new version
KeyVaultKey rotatedKey = keyClient.rotateKey("my-key");
System.out.println("New version: " + rotatedKey.getProperties().getVersion());

// Set rotation policy
KeyRotationPolicy policy = new KeyRotationPolicy()
    .setExpiresIn("P90D")  // Expire after 90 days
    .setLifetimeActions(Arrays.asList(
        new KeyRotationLifetimeAction(KeyRotationPolicyAction.ROTATE)
            .setTimeBeforeExpiry("P30D")));  // Rotate 30 days before expiry

keyClient.updateKeyRotationPolicy("my-key", policy);

// Get rotation policy
KeyRotationPolicy currentPolicy = keyClient.getKeyRotationPolicy("my-key");
```

## Import Key

```java
import com.azure.security.keyvault.keys.models.ImportKeyOptions;
import com.azure.security.keyvault.keys.models.JsonWebKey;

// Import existing key material
JsonWebKey jsonWebKey = new JsonWebKey()
    .setKeyType(KeyType.RSA)
    .setN(modulus)
    .setE(exponent)
    .setD(privateExponent)
    // ... other RSA components
    ;

ImportKeyOptions importOptions = new ImportKeyOptions("imported-key", jsonWebKey)
    .setHardwareProtected(false);

KeyVaultKey importedKey = keyClient.importKey(importOptions);
```

## Encryption Algorithms

| Algorithm | Key Type | Description |
|-----------|----------|-------------|
| `RSA1_5` | RSA | RSAES-PKCS1-v1_5 |
| `RSA_OAEP` | RSA | RSAES with OAEP (recommended) |
| `RSA_OAEP_256` | RSA | RSAES with OAEP using SHA-256 |
| `A128GCM` | OCT | AES-GCM 128-bit |
| `A256GCM` | OCT | AES-GCM 256-bit |
| `A128CBC` | OCT | AES-CBC 128-bit |
| `A256CBC` | OCT | AES-CBC 256-bit |

## Signature Algorithms

| Algorithm | Key Type | Hash |
|-----------|----------|------|
| `RS256` | RSA | SHA-256 |
| `RS384` | RSA | SHA-384 |
| `RS512` | RSA | SHA-512 |
| `PS256` | RSA | SHA-256 (PSS) |
| `ES256` | EC P-256 | SHA-256 |
| `ES384` | EC P-384 | SHA-384 |
| `ES512` | EC P-521 | SHA-512 |

## Error Handling

```java
import com.azure.core.exception.HttpResponseException;
import com.azure.core.exception.ResourceNotFoundException;

try {
    KeyVaultKey key = keyClient.getKey("non-existent-key");
} catch (ResourceNotFoundException e) {
    System.out.println("Key not found: " + e.getMessage());
} catch (HttpResponseException e) {
    System.out.println("HTTP error " + e.getResponse().getStatusCode());
    System.out.println("Message: " + e.getMessage());
}
```

## Environment Variables

```bash
AZURE_KEYVAULT_URL=https://<vault-name>.vault.azure.net  # Required for vault URL
AZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production
```

## Best Practices

1. **Use HSM Keys for Production** - Set `setHardwareProtected(true)` for sensitive keys
2. **Enable Soft Delete** - Protects against accidental deletion
3. **Key Rotation** - Set up automatic rotation policies
4. **Least Privilege** - Use separate keys for different operations
5. **Local Crypto When Possible** - Use `CryptographyClient` with local key material to reduce round-trips

## Trigger Phrases

- "Key Vault keys Java", "cryptographic keys Java"
- "encrypt decrypt Java", "sign verify Java"
- "RSA key", "EC key", "HSM key"
- "key rotation", "wrap unwrap key"

````


### `references/examples.md`

````markdown
# Azure Key Vault Keys SDK for Java - Examples

Comprehensive code examples for the Azure Key Vault Keys SDK for Java.

## Table of Contents
- [Maven Dependency](#maven-dependency)
- [Client Creation](#client-creation)
- [Creating Keys](#creating-keys)
- [Getting and Listing Keys](#getting-and-listing-keys)
- [Updating Key Properties](#updating-key-properties)
- [Deleting and Recovering Keys](#deleting-and-recovering-keys)
- [Key Rotation](#key-rotation)
- [Cryptographic Operations](#cryptographic-operations)
- [Async Client Patterns](#async-client-patterns)
- [Error Handling](#error-handling)

## Maven Dependency

```xml
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-security-keyvault-keys</artifactId>
    <version>4.9.0</version>
</dependency>

<!-- Required for authentication -->
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-identity</artifactId>
    <version>1.14.0</version>
</dependency>
```

## Client Creation

### Sync KeyClient

```java
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.security.keyvault.keys.KeyClient;
import com.azure.security.keyvault.keys.KeyClientBuilder;

KeyClient keyClient = new KeyClientBuilder()
    .vaultUrl("<your-key-vault-url>")
    .credential(new DefaultAzureCredentialBuilder().build())
    .buildClient();
```

### Async KeyClient

```java
import com.azure.security.keyvault.keys.KeyAsyncClient;

KeyAsyncClient keyAsyncClient = new KeyClientBuilder()
    .vaultUrl("<your-key-vault-url>")
    .credential(new DefaultAzureCredentialBuilder().build())
    .buildAsyncClient();
```

### Sync CryptographyClient

```java
import com.azure.security.keyvault.keys.cryptography.CryptographyClient;
import com.azure.security.keyvault.keys.cryptography.CryptographyClientBuilder;

CryptographyClient cryptographyClient = new CryptographyClientBuilder()
    .keyIdentifier("<your-key-id>")
    .credential(new DefaultAzureCredentialBuilder().build())
    .buildClient();
```

### Async CryptographyClient

```java
import com.azure.security.keyvault.keys.cryptography.CryptographyAsyncClient;

CryptographyAsyncClient cryptographyAsyncClient = new CryptographyClientBuilder()
    .keyIdentifier("<your-key-id>")
    .credential(new DefaultAzureCredentialBuilder().build())
    .buildAsyncClient();
```

### CryptographyClient with Local JsonWebKey

```java
import com.azure.security.keyvault.keys.models.JsonWebKey;

// For local cryptographic operations without Key Vault call
JsonWebKey jsonWebKey = new JsonWebKey().setId("SampleJsonWebKey");
CryptographyClient cryptographyClient = new CryptographyClientBuilder()
    .jsonWebKey(jsonWebKey)
    .buildClient();
```

## Creating Keys

### Create RSA Key

```java
import com.azure.security.keyvault.keys.models.CreateRsaKeyOptions;
import com.azure.security.keyvault.keys.models.KeyVaultKey;
import java.time.OffsetDateTime;

// Simple RSA key
CreateRsaKeyOptions createRsaKeyOptions = new CreateRsaKeyOptions("myRsaKey")
    .setKeySize(2048)
    .setNotBefore(OffsetDateTime.now().plusDays(1))
    .setExpiresOn(OffsetDateTime.now().plusYears(1));

KeyVaultKey rsaKey = keyClient.createRsaKey(createRsaKeyOptions);
System.out.printf("Created key: %s, ID: %s%n", rsaKey.getName(), rsaKey.getId());

// RSA key with 4096-bit size
keyClient.createRsaKey(new CreateRsaKeyOptions("CloudRsaKey")
    .setExpiresOn(OffsetDateTime.now().plusYears(1))
    .setKeySize(4096));
```

### Create EC (Elliptic Curve) Key

```java
import com.azure.security.keyvault.keys.models.CreateEcKeyOptions;
import com.azure.security.keyvault.keys.models.KeyCurveName;

CreateEcKeyOptions createEcKeyOptions = new CreateEcKeyOptions("myEcKey")
    .setCurveName(KeyCurveName.P_384)
    .setNotBefore(OffsetDateTime.now().plusDays(1))
    .setExpiresOn(OffsetDateTime.now().plusYears(1));

KeyVaultKey ecKey = keyClient.createEcKey(createEcKeyOptions);
System.out.printf("Created EC key: %s%n", ecKey.getName());
```

### Create Symmetric (OCT) Key

```java
import com.azure.security.keyvault.keys.models.CreateOctKeyOptions;

CreateOctKeyOptions createOctKeyOptions = new CreateOctKeyOptions("myOctKey")
    .setNotBefore(OffsetDateTime.now().plusDays(1))
    .setExpiresOn(OffsetDateTime.now().plusYears(1));

KeyVaultKey octKey = keyClient.createOctKey(createOctKeyOptions);
System.out.printf("Created OCT key: %s%n", octKey.getName());
```

### Create Key by Type

```java
import com.azure.security.keyvault.keys.models.CreateKeyOptions;
import com.azure.security.keyvault.keys.models.KeyType;

// Simple key creation
KeyVaultKey key = keyClient.createKey("myKey", KeyType.EC);

// With options
CreateKeyOptions createKeyOptions = new CreateKeyOptions("myKey", KeyType.RSA)
    .setNotBefore(OffsetDateTime.now().plusDays(1))
    .setExpiresOn(OffsetDateTime.now().plusYears(1));

KeyVaultKey optionsKey = keyClient.createKey(createKeyOptions);
```

## Getting and Listing Keys

### Get a Key

```java
// Get latest version
KeyVaultKey key = keyClient.getKey("myKey");
System.out.printf("Key name: %s, ID: %s%n", key.getName(), key.getId());

// Get specific version
String keyVersion = "<key-version>";
KeyVaultKey keyWithVersion = keyClient.getKey("myKey", keyVersion);
```

### Get Key with Response

```java
import com.azure.core.http.rest.Response;
import com.azure.core.util.Context;

Response<KeyVaultKey> getKeyResponse = keyClient.getKeyWithResponse(
    "myKey", 
    keyVersion, 
    new Context("key1", "value1")
);

System.out.printf("Status code: %d%n", getKeyResponse.getStatusCode());
System.out.printf("Key: %s%n", getKeyResponse.getValue().getName());
```

### List All Keys

```java
import com.azure.security.keyvault.keys.models.KeyProperties;

// Simple iteration
for (KeyProperties keyProperties : keyClient.listPropertiesOfKeys()) {
    KeyVaultKey key = keyClient.getKey(keyProperties.getName(), keyProperties.getVersion());
    System.out.printf("Key: %s, Type: %s%n", key.getName(), key.getKeyType());
}

// With pagination
keyClient.listPropertiesOfKeys().iterableByPage().forEach(pagedResponse -> {
    System.out.printf("Page status: %d%n", pagedResponse.getStatusCode());
    pagedResponse.getElements().forEach(keyProperties -> {
        System.out.printf("Key: %s%n", keyProperties.getName());
    });
});
```

### List Key Versions

```java
for (KeyProperties keyProperties : keyClient.listPropertiesOfKeyVersions("myKey")) {
    KeyVaultKey key = keyClient.getKey(keyProperties.getName(), keyProperties.getVersion());
    System.out.printf("Version: %s, Created: %s%n", 
        key.getProperties().getVersion(), 
        key.getProperties().getCreatedOn());
}
```

## Updating Key Properties

```java
import com.azure.security.keyvault.keys.models.KeyOperation;

// Get key first
KeyVaultKey key = keyClient.getKey("myKey");

// Update expiry time
key.getProperties().setExpiresOn(OffsetDateTime.now().plusDays(60));

// Update with allowed operations
KeyVaultKey updatedKey = keyClient.updateKeyProperties(
    key.getProperties(), 
    KeyOperation.ENCRYPT, 
    KeyOperation.DECRYPT
);

System.out.printf("Updated key: %s%n", updatedKey.getName());
```

### Update with Response

```java
Response<KeyVaultKey> updateKeyResponse = keyClient.updateKeyPropertiesWithResponse(
    key.getProperties(), 
    new Context("key1", "value1"),
    KeyOperation.ENCRYPT, 
    KeyOperation.DECRYPT
);

System.out.printf("Update status: %d%n", updateKeyResponse.getStatusCode());
```

## Deleting and Recovering Keys

### Delete a Key

```java
import com.azure.core.util.polling.PollResponse;
import com.azure.core.util.polling.SyncPoller;
import com.azure.security.keyvault.keys.models.DeletedKey;

// Begin delete (long-running operation)
SyncPoller<DeletedKey, Void> deleteKeyPoller = keyClient.beginDeleteKey("myKey");
PollResponse<DeletedKey> deleteKeyPollResponse = deleteKeyPoller.poll();

// Get deleted key info
DeletedKey deletedKey = deleteKeyPollResponse.getValue();
System.out.printf("Delete date: %s%n", deletedKey.getDeletedOn());
System.out.printf("Recovery ID: %s%n", deletedKey.getRecoveryId());

// Wait for deletion to complete
deleteKeyPoller.waitForCompletion();
```

### Get Deleted Key

```java
DeletedKey deletedKey = keyClient.getDeletedKey("myKey");
System.out.printf("Recovery ID: %s%n", deletedKey.getRecoveryId());
```

### List Deleted Keys

```java
for (DeletedKey deletedKey : keyClient.listDeletedKeys()) {
    System.out.printf("Deleted key: %s, Recovery ID: %s%n", 
        deletedKey.getName(), 
        deletedKey.getRecoveryId());
}
```

### Recover Deleted Key

```java
SyncPoller<KeyVaultKey, Void> recoverKeyPoller = keyClient.beginRecoverDeletedKey("myKey");
PollResponse<KeyVaultKey> recoverKeyPollResponse = recoverKeyPoller.poll();

KeyVaultKey recoveredKey = recoverKeyPollResponse.getValue();
System.out.printf("Recovered key: %s%n", recoveredKey.getName());

recoverKeyPoller.waitForCompletion();
```

### Purge Deleted Key

```java
// Permanently delete (cannot be recovered)
keyClient.purgeDeletedKey("myKey");
System.out.println("Key purged permanently");
```

## Key Rotation

### Rotate Key

```java
// Create new version of the key
KeyVaultKey rotatedKey = keyClient.rotateKey("myKey");
System.out.printf("New key version: %s%n", rotatedKey.getProperties().getVersion());
```

### Get Key Rotation Policy

```java
import com.azure.security.keyvault.keys.models.KeyRotationPolicy;

KeyRotationPolicy policy = keyClient.getKeyRotationPolicy("myKey");
System.out.printf("Policy ID: %s%n", policy.getId());
```

### Update Key Rotation Policy

```java
import com.azure.security.keyvault.keys.models.KeyRotationLifetimeAction;
import com.azure.security.keyvault.keys.models.KeyRotationPolicyAction;

KeyRotationPolicy policy = new KeyRotationPolicy()
    .setExpiresIn("P90D")  // Key expires in 90 days
    .setLifetimeActions(Arrays.asList(
        new KeyRotationLifetimeAction(KeyRotationPolicyAction.ROTATE)
            .setTimeBeforeExpiry("P30D")  // Rotate 30 days before expiry
    ));

KeyRotationPolicy updatedPolicy = keyClient.updateKeyRotationPolicy("myKey", policy);
```

## Cryptographic Operations

### Encrypt and Decrypt

```java
import com.azure.security.keyvault.keys.cryptography.models.EncryptionAlgorithm;
import com.azure.security.keyvault.keys.cryptography.models.EncryptResult;
import com.azure.security.keyvault.keys.cryptography.models.DecryptResult;

byte[] plaintext = "Hello, World!".getBytes();

// Encrypt
EncryptResult encryptResult = cryptographyClient.encrypt(
    EncryptionAlgorithm.RSA_OAEP, 
    plaintext
);
byte[] ciphertext = encryptResult.getCipherText();
System.out.printf("Encrypted: %d bytes%n", ciphertext.length);

// Decrypt
DecryptResult decryptResult = cryptographyClient.decrypt(
    EncryptionAlgorithm.RSA_OAEP, 
    ciphertext
);
String decryptedText = new String(decryptResult.getPlainText());
System.out.printf("Decrypted: %s%n", decryptedText);
```

### Sign and Verify

```java
import com.azure.security.keyvault.keys.cryptography.models.SignatureAlgorithm;
import com.azure.security.keyvault.keys.cryptography.models.SignResult;
import com.azure.security.keyvault.keys.cryptography.models.VerifyResult;
import java.security.MessageDigest;

byte[] data = "Data to sign".getBytes();
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(data);

// Sign
SignResult signResult = cryptographyClient.sign(
    SignatureAlgorithm.RS256, 
    digest
);
byte[] signature = signResult.getSignature();
System.out.printf("Signature: %d bytes%n", signature.length);

// Verify
VerifyResult verifyResult = cryptographyClient.verify(
    SignatureAlgorithm.RS256, 
    digest, 
    signature
);
System.out.printf("Signature valid: %s%n", verifyResult.isValid());
```

### Wrap and Unwrap Key

```java
import com.azure.security.keyvault.keys.cryptography.models.KeyWrapAlgorithm;
import com.azure.security.keyvault.keys.cryptography.models.WrapResult;
import com.azure.security.keyvault.keys.cryptography.models.UnwrapResult;

byte[] keyToWrap = new byte[32];  // 256-bit key
new java.security.SecureRandom().nextBytes(keyToWrap);

// Wrap
WrapResult wrapResult = cryptographyClient.wrapKey(
    KeyWrapAlgorithm.RSA_OAEP, 
    keyToWrap
);
byte[] wrappedKey = wrapResult.getEncryptedKey();
System.out.printf("Wrapped key: %d bytes%n", wrappedKey.length);

// Unwrap
UnwrapResult unwrapResult = cryptographyClient.unwrapKey(
    KeyWrapAlgorithm.RSA_OAEP, 
    wrappedKey
);
byte[] unwrappedKey = unwrapResult.getKey();
System.out.printf("Unwrapped key: %d bytes%n", unwrappedKey.length);
```

## Async Client Patterns

### Create Key Async

```java
keyAsyncClient.createRsaKey(new CreateRsaKeyOptions("asyncKey").setKeySize(2048))
    .subscribe(
        key -> System.out.printf("Created key: %s%n", key.getName()),
        error -> System.err.println("Error: " + error.getMessage()),
        () -> System.out.println("Create completed")
    );
```

### List Keys Async

```java
keyAsyncClient.listPropertiesOfKeys()
    .subscribe(keyProperties -> {
        System.out.printf("Key: %s%n", keyProperties.getName());
    });
```

### Encrypt/Decrypt Async

```java
byte[] plaintext = "Hello, async!".getBytes();

cryptographyAsyncClient.encrypt(EncryptionAlgorithm.RSA_OAEP, plaintext)
    .flatMap(encryptResult -> {
        System.out.printf("Encrypted: %d bytes%n", encryptResult.getCipherText().length);
        return cryptographyAsyncClient.decrypt(
            EncryptionAlgorithm.RSA_OAEP, 
            encryptResult.getCipherText()
        );
    })
    .subscribe(
        decryptResult -> System.out.printf("Decrypted: %s%n", 
            new String(decryptResult.getPlainText())),
        error -> System.err.println("Error: " + error.getMessage())
    );
```

## Error Handling

```java
import com.azure.core.exception.HttpResponseException;
import com.azure.core.exception.ResourceNotFoundException;

try {
    KeyVaultKey key = keyClient.getKey("nonexistent-key");
} catch (ResourceNotFoundException e) {
    System.err.println("Key not found: " + e.getMessage());
} catch (HttpResponseException e) {
    System.err.println("HTTP error: " + e.getResponse().getStatusCode());
    System.err.println("Message: " + e.getMessage());
} catch (Exception e) {
    System.err.println("Unexpected error: " + e.getMessage());
}
```

### Async Error Handling

```java
keyAsyncClient.getKey("nonexistent-key")
    .subscribe(
        key -> System.out.println("Key: " + key.getName()),
        error -> {
            if (error instanceof ResourceNotFoundException) {
                System.err.println("Key not found");
            } else if (error instanceof HttpResponseException) {
                HttpResponseException httpError = (HttpResponseException) error;
                System.err.println("HTTP error: " + httpError.getResponse().getStatusCode());
            } else {
                System.err.println("Error: " + error.getMessage());
            }
        }
    );
```

````
