/api/rke/encrypt

GET

Encrypts data using an active RKE session's AES-256-CTR encryption key. Returns the ciphertext and nonce needed for decryption.

Description

Encrypts arbitrary data using the session's derived AES-256-CTR encryption key. The encryption uses a randomly generated 16-byte nonce for each operation, ensuring that identical plaintext produces different ciphertext each time.

AES-256-CTR Encryption

This endpoint uses AES-256 in Counter (CTR) mode:

  • Key Size: 256 bits (32 bytes)
  • Nonce Size: 128 bits (16 bytes)
  • Mode: Counter mode (streaming cipher)
  • No Padding: Output size equals input size
Important: Save the Nonce!

The nonce returned in the response is required for decryption. You must store it alongside the ciphertext. Without the correct nonce, the data cannot be decrypted.

Parameters

session_id
string (query)
Required

The 32-character hexadecimal session ID from /api/rke/session.

Format: 32 hexadecimal characters (a-f, 0-9)

Example: a1b2c3d4e5f67890a1b2c3d4e5f67890

plaintext
string (query)
Required

The data to encrypt, encoded as Base64.

Format: Standard Base64 encoding (A-Z, a-z, 0-9, +, /, =)

Max Size: Limited by URL length (recommended < 8KB)

Encoding Examples:

  • "Hello World!"SGVsbG8gV29ybGQh
  • "Test 123"VGVzdCAxMjM=
  • Binary data → Use standard Base64 encoding

JavaScript: btoa(text) or Buffer.from(data).toString('base64')

Note: URL-encode the Base64 string if it contains +, /, or = characters.

Response

Response Properties (Success)

command string
Always "rke_encrypt".
success boolean
True if encryption succeeded.
ciphertext string
The encrypted data, Base64 encoded. Same length as plaintext after decoding.
nonce string
The 32-character hexadecimal nonce (16 bytes). Required for decryption!
length integer
Original plaintext length in bytes.

Example Response (Success)

{
  "command": "rke_encrypt",
  "success": true,
  "ciphertext": "xK7mPqR5tY2wZn8=",
  "nonce": "0123456789abcdef0123456789abcdef",
  "length": 12
}

Example Response (Error - Session Not Found)

{
  "error": true,
  "message": "Session not found or expired",
  "code": 404,
  "session_id": "expired0000000000000000000000000"
}

Example Response (Error - Invalid Base64)

{
  "error": true,
  "message": "Invalid base64 encoding",
  "code": 400
}

Examples

JavaScript (fetch)

const API_HOST = 'http://localhost:8080';

/**
 * Encrypt a string using an RKE session
 * @param {string} sessionId - The 32-char session ID
 * @param {string} plaintext - The text to encrypt
 * @returns {Promise<{ciphertext: string, nonce: string}>}
 */
async function rkeEncrypt(sessionId, plaintext) {
    // Convert plaintext to Base64
    const base64Plaintext = btoa(plaintext);

    // URL-encode the Base64 string (handles +, /, = characters)
    const encodedPlaintext = encodeURIComponent(base64Plaintext);

    const url = `${API_HOST}/api/rke/encrypt?session_id=${sessionId}&plaintext=${encodedPlaintext}`;
    const response = await fetch(url);
    const result = await response.json();

    if (!result.success) {
        throw new Error(result.message);
    }

    return {
        ciphertext: result.ciphertext,
        nonce: result.nonce,
        length: result.length
    };
}

// Usage example
async function encryptMessage() {
    const sessionId = 'a1b2c3d4e5f67890a1b2c3d4e5f67890';
    const message = 'Hello, Content Server!';

    try {
        const encrypted = await rkeEncrypt(sessionId, message);
        console.log('Ciphertext:', encrypted.ciphertext);
        console.log('Nonce:', encrypted.nonce);
        console.log('Length:', encrypted.length, 'bytes');

        // Store ciphertext and nonce together for later decryption
        const encryptedPackage = {
            ciphertext: encrypted.ciphertext,
            nonce: encrypted.nonce
        };
        localStorage.setItem('encrypted_message', JSON.stringify(encryptedPackage));
    } catch (error) {
        console.error('Encryption failed:', error.message);
    }
}

encryptMessage();

cURL

# Encrypt "Hello World!" (Base64: SGVsbG8gV29ybGQh)
SESSION_ID="a1b2c3d4e5f67890a1b2c3d4e5f67890"
PLAINTEXT_B64="SGVsbG8gV29ybGQh"

curl "http://localhost:8080/api/rke/encrypt?session_id=$SESSION_ID&plaintext=$PLAINTEXT_B64"

# Encrypt and extract ciphertext + nonce
curl "http://localhost:8080/api/rke/encrypt?session_id=$SESSION_ID&plaintext=$PLAINTEXT_B64" | jq '{ciphertext, nonce}'

# Encode text to Base64 first (Linux/macOS)
echo -n "Secret message" | base64
# Output: U2VjcmV0IG1lc3NhZ2U=

# Full example with encoding
MESSAGE="Secret message"
B64=$(echo -n "$MESSAGE" | base64)
curl "http://localhost:8080/api/rke/encrypt?session_id=$SESSION_ID&plaintext=$B64"

Go

package main

import (
    "encoding/base64"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
)

const ApiHost = "http://localhost:8080"

type EncryptResponse struct {
    Command    string `json:"command"`
    Success    bool   `json:"success"`
    Ciphertext string `json:"ciphertext"`
    Nonce      string `json:"nonce"`
    Length     int    `json:"length"`
}

func RkeEncrypt(sessionId, plaintext string) (*EncryptResponse, error) {
    // Encode plaintext to Base64
    b64Plaintext := base64.StdEncoding.EncodeToString([]byte(plaintext))

    apiUrl := fmt.Sprintf("%s/api/rke/encrypt?session_id=%s&plaintext=%s",
        ApiHost, sessionId, url.QueryEscape(b64Plaintext))

    resp, err := http.Get(apiUrl)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)
    var result EncryptResponse
    json.Unmarshal(body, &result)
    return &result, nil
}

func main() {
    sessionId := "a1b2c3d4e5f67890a1b2c3d4e5f67890"
    message := "Hello, Content Server!"

    encrypted, _ := RkeEncrypt(sessionId, message)
    if encrypted.Success {
        fmt.Printf("Ciphertext: %s\n", encrypted.Ciphertext)
        fmt.Printf("Nonce: %s\n", encrypted.Nonce)
    }
}

Related Endpoints

/api/rke/decrypt

Decrypt data using the same session.

/api/rke/session

Create a session first.