Skip to content

Secure Channel v2 Protocol

Protocol Identity

PropertyValue
MagicSC
Version2
Content-Typeapplication/json;charset=UTF-8

Message Types

ConstantValueDescription
TYPE_KEY_EXCHANGE1Key exchange handshake type. Contains an RSA-encrypted AES key.
TYPE_SESSION_DATA2Session reuse type. No longer carries the RSA-encrypted key.
TYPE_RESPONSE_DATA129Response data type. Encrypted with the session response key.

Key Sizes

ConstantBytesDescription
KEY_ID_LEN_SIZE1KEY_ID length field size. Uses 1 byte for compact encoding.
REQ_KEY_LEN_SIZE2REQ_KEY length field size. Uses 2 bytes for length encoding.
RESP_KEY_LEN_SIZE2RESP_KEY length field size. Uses 2 bytes for length encoding.

Protocol Headers

HeaderConstantDescription
X-SC-Session-IdSESSION_ID_HEADERSecure Channel session identifier
X-SC-VersionVERSION_HEADERProtocol version (currently 2)

Client-Side Integration

Binary Envelope Format

The SCv2 binary envelope is a compact byte layout used for encrypted request payloads. When a client sends an encrypted request, the HTTP body is replaced with this binary format instead of JSON.

Type 1 -- Key Exchange (first request in a session):

[2B magic "SC"] [1B version] [1B type=1]
[1B keyIdLen] [keyIdLen B keyId]
[2B reqKeyLen] [reqKeyLen B encryptedReqKey]
[2B respKeyLen] [respKeyLen B encryptedRespKey]
[remaining bytes: AES-GCM encrypted payload]

Type 2 -- Session Data (subsequent requests):

[2B magic "SC"] [1B version] [1B type=2]
[remaining bytes: AES-GCM encrypted payload]

Type 129 -- Response Data (server responses):

[2B magic "SC"] [1B version] [1B type=129]
[remaining bytes: AES-GCM encrypted payload]

The AES-GCM encrypted payload contains a 12-byte IV (nonce) followed by the ciphertext with a 16-byte authentication tag appended.

Key Exchange Flow

  1. Get server public key: GET /web/v1/secure-channel/public-key
    • Returns the active RSA public key (keyId, publicKey, algorithm)
  2. Generate AES session keys: Client generates two random AES-256 keys:
    • Request key -- used by the client to encrypt request payloads
    • Response key -- used by the server to encrypt response payloads
  3. Create session: POST /web/v1/secure-channel/session
    • Client RSA-encrypts both AES keys using the server's public key
    • Server decrypts and stores the keys, returns a sessionId
  4. Client stores the sessionId and both AES keys locally

Request Encryption Flow

Once a session is established:

  1. Serialize the JSON request body to UTF-8 bytes
  2. Encrypt the bytes using AES-256-GCM with the request key and a random 12-byte IV
  3. Build the binary envelope:
    • First request: use Type 1 (includes the RSA-encrypted keys)
    • Subsequent requests: use Type 2 (session reuse, no key material)
  4. Set the X-SC-Session-Id header to the session ID
  5. Send the binary envelope as the HTTP body (Content-Type remains application/json;charset=UTF-8)

Response Decryption Flow

  1. Read the binary response body
  2. Verify the magic bytes (SC) and version (2)
  3. Confirm message type is 129 (response data)
  4. Extract the AES-GCM payload (IV + ciphertext + auth tag)
  5. Decrypt using the response key
  6. Parse the decrypted bytes as UTF-8 JSON

Session Lifecycle

  • Sessions expire after a configured TTL (server-side)
  • Sessions are bound to a user after authentication (bindSessionToUser)
  • Per-user session limits are enforced
  • Clients should explicitly close sessions when flows complete: POST /web/v1/secure-channel/session/close

Server SDK Reference

getPublicKey()

Returns: RsaPublicKeyInfo

Retrieves the active RSA public key used for client key exchange.

getActiveKeyId()

Returns: String

Returns the active RSA key ID.

rotateKeys()

Returns: void

Rotates the RSA key pair.

decrypt(byte[])

Returns: DecryptionResult

Decrypts an SCv2 envelope-formatted encrypted payload.

decrypt(byte[], String)

Returns: DecryptionResult

Decrypts an encrypted payload with optional session reuse.

encrypt(byte[], String)

Returns: byte[]

Encrypts a response payload using the session's AES key.

encrypt(byte[], SessionContext)

Returns: byte[]

Encrypts a response payload using an existing session context.

encryptPayload(byte[], SessionContext)

Returns: AesGcmCipher.GcmPayload

Encrypts a response payload using the session response key.

decryptPayload(AesGcmCipher.GcmPayload, String)

Returns: byte[]

Decrypts a request payload using the session request key.

createSession(String, String, String)

Returns: SessionContext

Creates a session from RSA-encrypted AES keys.

getSession(String)

Returns: Optional<SessionContext>

Retrieves an existing session by ID.

isSessionValid(String)

Returns: boolean

Checks whether a session exists and is valid.

invalidateSession(String)

Returns: void

Invalidates a session.

clearAllSessions()

Returns: void

Clears all sessions.

getConfig()

Returns: SecureChannelConfig

Returns the SDK configuration.

bindSessionToUser(String, String)

Returns: void

Binds an unbound KEY_EXCHANGE session to an authenticated user and enforces per-user session limits.

isEncryptedPayload(byte[])

Returns: boolean

Checks if a payload appears to be encrypted using SCv2 format.

Builder Methods

MethodReturnsDescription
sessionTtl(Duration)BuilderSets the session TTL (time to live)
maxSessions(int)BuilderSets the maximum sessions per user
sessionStore(SessionStore)BuilderSets a custom session store implementation
keyStore(KeyStore)BuilderSets a custom key store implementation
build()SecureChannelSDKBuilds the SDK instance

SlaunchX Internal Documentation