> ## Documentation Index
> Fetch the complete documentation index at: https://docs.controlplane.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Keypair

> Create a keypair secret to store asymmetric public and private keys for SSH authentication, JWT signing, or encryption.

Keypair secrets store asymmetric key pairs (public and private keys) with optional passphrase protection. Use them for SSH authentication, JWT signing, encryption, or any cryptographic operation requiring public-key infrastructure.

## Use Cases

* **SSH Authentication**: Store SSH keys for accessing remote servers or Git repositories
* **JWT Signing**: Sign and verify JSON Web Tokens for API authentication
* **Encryption/Decryption**: Encrypt data with the public key, decrypt with the private key
* **Code Signing**: Sign artifacts to verify authenticity and integrity
* **Secure Communication**: Establish encrypted channels between services

## Configuration Options

| Field        | Description                           | Required |
| :----------- | :------------------------------------ | :------- |
| `secretKey`  | Private key in PEM format             | Yes      |
| `publicKey`  | Public key in PEM format              | Yes      |
| `passphrase` | Passphrase for encrypted private keys | No       |

<Note>
  Both keys must be PEM-encoded. The private key can be encrypted with a passphrase—if so, provide the passphrase so your workload can use the key.
</Note>

***

## Create a Keypair Secret

<Tabs>
  <Tab title="Console UI">
    <Steps>
      <Step title="Navigate to Secrets">
        In the Console, navigate to **Secrets** and click **New**, or use the **Create** dropdown in the top-right corner and select **Secret**.
      </Step>

      <Step title="Enter basic information">
        Enter a **Name** and optional **Description**.
      </Step>

      <Step title="Select secret type">
        Select **Keypair** as the secret type.
      </Step>

      <Step title="Configure key data">
        Click **Data** in the left pane. For **Secret Key**, drag and drop your private key file or click to import. For **Public Key**, drag and drop your public key file or click to import. Enter the **Passphrase** if the private key is encrypted (optional).
      </Step>

      <Step title="Create the secret">
        Click **Create**.
      </Step>
    </Steps>
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    cpln secret create-keypair \
      --name my-keypair \
      --secret private_key.pem \
      --public public_key.pem \
      --passphrase 'my-passphrase' \
      --org my-org
    ```

    Without a passphrase (for unencrypted private keys):

    ```bash theme={null}
    cpln secret create-keypair \
      --name my-keypair \
      --secret private_key.pem \
      --public public_key.pem \
      --org my-org
    ```
  </Tab>

  <Tab title="Terraform">
    ```hcl theme={null}
    resource "cpln_secret" "keypair" {
      name        = "my-keypair"
      description = "RSA keypair for JWT signing"

      keypair {
        secret_key = file("private_key.pem")
        public_key = file("public_key.pem")
        passphrase = "my-passphrase"  # Optional
      }
    }
    ```

    <Warning>
      This example uses a hardcoded passphrase for testing. In production, use Terraform variables or integrate with a secrets manager. Never commit private keys to version control.
    </Warning>
  </Tab>

  <Tab title="Pulumi">
    <Tabs>
      <Tab title="TypeScript">
        ```typescript theme={null}
        import * as cpln from "@pulumiverse/cpln";
        import * as fs from "fs";

        const keypairSecret = new cpln.Secret("my-keypair", {
          name: "my-keypair",
          description: "RSA keypair for JWT signing",
          keypair: {
            secretKey: fs.readFileSync("private_key.pem", "utf8"),
            publicKey: fs.readFileSync("public_key.pem", "utf8"),
            passphrase: "my-passphrase",  // Optional
          },
        });
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        import pulumiverse_cpln as cpln

        with open("private_key.pem") as f:
            secret_key = f.read()
        with open("public_key.pem") as f:
            public_key = f.read()

        keypair_secret = cpln.Secret("my-keypair",
            name="my-keypair",
            description="RSA keypair for JWT signing",
            keypair={
                "secret_key": secret_key,
                "public_key": public_key,
                "passphrase": "my-passphrase",  # Optional
            })
        ```
      </Tab>

      <Tab title="Go">
        ```go theme={null}
        package main

        import (
            "os"
            "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
            "github.com/pulumiverse/pulumi-cpln/sdk/go/cpln"
        )

        func main() {
            pulumi.Run(func(ctx *pulumi.Context) error {
                secretKey, _ := os.ReadFile("private_key.pem")
                publicKey, _ := os.ReadFile("public_key.pem")

                _, err := cpln.NewSecret(ctx, "my-keypair", &cpln.SecretArgs{
                    Name:        pulumi.String("my-keypair"),
                    Description: pulumi.String("RSA keypair for JWT signing"),
                    Keypair: &cpln.SecretKeypairArgs{
                        SecretKey:  pulumi.String(string(secretKey)),
                        PublicKey:  pulumi.String(string(publicKey)),
                        Passphrase: pulumi.String("my-passphrase"),  // Optional
                    },
                })
                return err
            })
        }
        ```
      </Tab>

      <Tab title="C#">
        ```csharp theme={null}
        using System.IO;
        using Pulumi;
        using Pulumiverse.Cpln;
        using Pulumiverse.Cpln.Inputs;

        return await Deployment.RunAsync(() =>
        {
            var keypairSecret = new Secret("my-keypair", new SecretArgs
            {
                Name = "my-keypair",
                Description = "RSA keypair for JWT signing",
                Keypair = new SecretKeypairArgs
                {
                    SecretKey = File.ReadAllText("private_key.pem"),
                    PublicKey = File.ReadAllText("public_key.pem"),
                    Passphrase = "my-passphrase",  // Optional
                },
            });
        });
        ```
      </Tab>
    </Tabs>
  </Tab>
</Tabs>

***

## Generating Key Pairs

### RSA Keys

```bash theme={null}
# Generate a 4096-bit RSA private key
openssl genrsa -out private_key.pem 4096

# Extract the public key
openssl rsa -in private_key.pem -pubout -out public_key.pem

# With passphrase protection
openssl genrsa -aes256 -out private_key.pem 4096
```

### Ed25519 Keys (for SSH)

```bash theme={null}
# Generate an Ed25519 keypair
ssh-keygen -t ed25519 -f my_key -C "my-workload"

# Convert to PEM format if needed
ssh-keygen -p -m PEM -f my_key
```

### ECDSA Keys

```bash theme={null}
# Generate an ECDSA private key (P-256 curve)
openssl ecparam -genkey -name prime256v1 -out private_key.pem

# Extract the public key
openssl ec -in private_key.pem -pubout -out public_key.pem
```

<Tip>
  For JWT signing, RSA with 2048 or 4096 bits and ECDSA P-256 are common choices. Ed25519 offers excellent security with smaller key sizes.
</Tip>

***

## Best Practices

<AccordionGroup>
  <Accordion title="Use strong key sizes">
    For RSA, use at least 2048 bits (4096 recommended). For ECDSA, use P-256 or higher curves.
  </Accordion>

  <Accordion title="Protect private keys with passphrases">
    Always encrypt private keys with a strong passphrase when storing them, adding an extra layer of protection.
  </Accordion>

  <Accordion title="Rotate keys regularly">
    Establish a key rotation schedule. When rotating, update the secret and ensure workloads can handle the transition.
  </Accordion>

  <Accordion title="Limit access with policies">
    Use Control Plane policies to restrict which workloads can access the keypair. Only services that need to sign or decrypt should have access.
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="TLS Secrets" icon="file-certificate" href="/guides/create-secret/tls">
    Store SSL/TLS certificates and keys
  </Card>

  <Card title="Using Secrets in Workloads" icon="cube" href="/guides/create-secret/overview#using-secrets-in-workloads">
    Learn how to grant access and inject secrets
  </Card>
</CardGroup>
