Skip to main content

Hands-On: Encrypt, Decrypt, Sign, and Verify with the Qpher Playground

~7 min readIntermediate

This is a hands-on tutorial. You will use the Qpher Playground to encrypt data with Kyber768, sign messages with Dilithium3, inspect PQC key pairs, and rotate keys โ€” all without writing a single line of code. By the end, you will have a concrete, experiential understanding of every PQC operation Qpher supports.

Prerequisites

You need a free Qpher account to access the Playground. Sign up at portal.qpher.ai โ€” it takes 30 seconds. The free tier includes 5,000 API calls per month, more than enough for this tutorial.

Accessing the Playgroundโ€‹

Open portal.qpher.ai/playground after signing in. The Playground has three panels:

  • Left panel โ€” Key Inspector: View and manage your PQC keys. Shows algorithm, key version, status, and public key.
  • Center panel โ€” Operations: Encrypt, Decrypt, Sign, and Verify tabs. This is where you perform PQC operations.
  • Right panel โ€” Code Snippets: Auto-generated SDK code for every operation you perform. Copy this into your project when you are ready to integrate.

Exercise 1 โ€” Generate a KEM Keyโ€‹

Your first step: create a Kyber768 key pair for encryption.

  1. In the Key Inspector panel, click Generate Key.
  2. Select Kyber768 as the algorithm.
  3. Click Generate.

Observe:

  • The public key is displayed โ€” 1,184 bytes of base64-encoded lattice data.
  • The private key shows "[Non-exportable]". It is not hidden for convenience โ€” it physically cannot leave the server. This is the non-exportable key guarantee in action.
  • Key version = 1, Status = active.
Non-exportable private keys

The private key is not shown because it never leaves the Qpher KMS-Orchestrator. There is no API endpoint to retrieve it. There is no admin override. This is a deliberate architectural constraint โ€” you learned in the Kyber article that the security of KEM depends on the private key remaining secret.

Exercise 2 โ€” Encrypt Dataโ€‹

Now use your Kyber768 key to encrypt data.

  1. Switch to the Encrypt tab in the center panel.
  2. Enter plaintext: Hello, Quantum World!
  3. Select key_version: 1 (the key you just created).
  4. Click Encrypt.

Observe:

  • The ciphertext is a large base64 blob โ€” much larger than the plaintext.
  • The ciphertext structure breakdown shows each component: KEM ciphertext (1,088 bytes), IV (12 bytes), AES ciphertext (matching your plaintext length), and the GCM auth tag (16 bytes).
  • The Code Snippets panel on the right shows the equivalent Python, Node.js, and cURL code.

Experiment: Click Encrypt again with the exact same plaintext and key version. The ciphertext is different every time. This is because a fresh shared secret is generated for each encrypt call, as described in the KEM-DEM Hybrid article. An attacker cannot tell whether two ciphertexts contain the same plaintext.

Exercise 3 โ€” Decrypt Dataโ€‹

Reverse the process to recover your plaintext.

  1. Copy the ciphertext from Exercise 2 (the Playground provides a copy button).
  2. Switch to the Decrypt tab.
  3. Paste the ciphertext.
  4. Specify key_version: 1.
  5. Click Decrypt.

Observe: Your original plaintext โ€” Hello, Quantum World! โ€” is recovered exactly.

Experiment: Go back to the ciphertext and change a single character (flip one letter in the base64 string). Try decrypting again. The operation fails with an authentication error. This is AES-256-GCM's tamper detection: the 16-byte authentication tag validates the entire ciphertext, and any modification โ€” even one bit โ€” causes decryption to reject the input.

Exercise 4 โ€” Sign and Verifyโ€‹

Switch from encryption to signatures. You will create a Dilithium3 key and use it to sign and verify a message.

Generate a Signature Keyโ€‹

  1. In the Key Inspector, click Generate Key.
  2. Select Dilithium3.
  3. Click Generate.

You now have two key pairs: Kyber768 (key version 1) for encryption, and Dilithium3 (key version 1, or whichever version was assigned) for signatures.

Sign a Messageโ€‹

  1. Switch to the Sign tab.
  2. Enter a message: Invoice #QP-2026-001 Total: $10,000
  3. Select the Dilithium3 key version.
  4. Click Sign.

Observe: The signature is a large base64 string โ€” 3,293 bytes. Compare this to an ECDSA signature, which would be just 64 bytes. This size difference is the tradeoff for quantum resistance, as discussed in the Dilithium article.

Verify the Signatureโ€‹

  1. Switch to the Verify tab.
  2. The message and signature should auto-populate (or paste them manually).
  3. Select the same key version.
  4. Click Verify.

Observe: The result is Valid.

Experiment: Change a single character in the message โ€” for example, change the total from $10,000 to $10,001. Verify again. The result is Invalid. The signature protects the exact content of the message. Any modification, no matter how small, invalidates the signature.

Signatures vs. encryption

Encryption keeps data secret. Signatures prove data is authentic and unmodified. In the real world, you often need both: encrypt sensitive data with Kyber768, then sign it with Dilithium3 to guarantee integrity.

Exercise 5 โ€” Key Rotationโ€‹

Keys should be rotated periodically as a security best practice. This exercise demonstrates Qpher's key lifecycle.

  1. In the Key Inspector, find your Kyber768 key (version 1).
  2. Click Rotate.

Observe the key lifecycle transition:

  • Key version 2 appears with status active.
  • Key version 1 changes to status retired.

Now test what retired means:

  1. Switch to the Encrypt tab. Try encrypting with key version 1 (retired). The operation fails โ€” retired keys cannot encrypt new data.
  2. Switch to the Decrypt tab. Decrypt the ciphertext from Exercise 2 using key version 1. The operation succeeds โ€” retired keys can still decrypt existing data.
  3. Encrypt new data with key version 2 (active). This succeeds.

This is the key lifecycle in action:

  • Active keys: encrypt and decrypt.
  • Retired keys: decrypt only (for data encrypted before rotation).
  • Archived keys: no operations allowed.

The Key Management guide covers rotation strategies and best practices for production use.

From Playground to Codeโ€‹

Every operation you performed in the Playground has a corresponding API call. The Code Snippets panel (right side) showed the equivalent SDK code for each operation in Python, Node.js, and cURL.

To move from Playground to production:

  1. Copy the code snippet for any operation you performed.
  2. Install the SDK โ€” see the Python SDK, Node.js SDK, or Go SDK documentation.
  3. Replace the API key with your production key from the Qpher dashboard.
  4. Follow the Quickstart โ€” the Quickstart guide walks through your first real API integration in under 5 minutes.

What You Learnedโ€‹

Across five exercises, you experienced every core PQC operation:

  1. Key generation โ€” Kyber768 and Dilithium3 key pairs with non-exportable private keys
  2. Encryption โ€” Quantum-safe, non-deterministic ciphertext via KEM-DEM
  3. Decryption โ€” Recovery with authenticated integrity checking
  4. Signing and verification โ€” Tamper-evident digital signatures
  5. Key rotation โ€” Active/retired lifecycle with backward compatibility

These are the same operations your application will use in production. The Playground gave you the mental model; the SDK gives you the code.

Ready to build?

Create a free Qpher account and follow the Quickstart guide to integrate quantum-safe encryption into your application. The Learning Path is complete โ€” you have the knowledge. Time to build.