Skip to content

Signing and Key Storage

The Scorbit SDK uses ECDSA P-2561 for signing authentication requests. This can be implemented either through a TPM2 or using some other form of encrypted, secure storage.

To ensure that a game talking to Scorbit is authentic and originating traffic only from the machine that it claims to be, we use a key pair3 shared between Scorbit and the provider. Specifically, the public key is shared with Scorbit, while the secret key is stored securely in the game code or within a TPM.

A TPM chip is a convenient way to store these keys in a safe, secure manner, and is often used when a manufacturer provisions games off the assembly line. Most often, a TPM is either on the MPU board of the game or added later to the game through the use of a USB key or WiFi module.

In order to communicate with the API, the SDK must first authenticate using a digitally signed4 nonce. The nonce is a unique number used to prevent replay attacks, and it is cryptographically signed to prove authenticity. This signing process is handled internally by the SDK using an encrypted key.

Implementing Authentication

The SDK uses an encrypted key for authentication, which is generated from your private key using the encrypt_tool. This approach enhances security by eliminating the need for the SDK to have direct access to the private key.

Key Generation

The encrypted key is generated using the encrypt_tool from your private key. This tool is provided with the SDK and should be used to generate the encrypted key before deploying your application.

1. Create the game state with encrypted key:

This example illustrates how to create a game state object using an encrypted key. The encrypted key is generated from your private key using the encrypt_tool.

scorbit::DeviceInfo device_info;
device_info.provider = "scorbitron";          // Mandatory: provider name
device_info.machineId = 4419;                 // Mandatory: Scorbit-assigned Machine ID
device_info.gameCodeVersion = "1.12.3";       // Mandatory: your game version
device_info.hostname = "production";          // Optional: server hostname
device_info.uuid = "";                        // Optional: device UUID
device_info.serialNumber = 0;                 // Optional: device serial number

// Use encrypt_tool to generate your encrypted key from your private key
std::string encrypted_key = "8qWNpMPeO1AbgcoPSsdeUORGmO/hyB70oyrpFyRlYWbaVx4Kuan0CAGaXZWS3JWdgmPL7p9k3UFTwAp5y16L8O1tYaHLGkW4p/yWmA==";

// Create game state object with encrypted key
scorbit::GameState gs = scorbit::createGameState(encrypted_key, std::move(device_info));
sb_device_info_t device_info = {
    .provider = "scorbitron",           // Mandatory: provider name
    .machine_id = 4419,                 // Mandatory: Scorbit-assigned Machine ID
    .game_code_version = "1.12.3",      // Mandatory: your game version
    .hostname = "production",           // Optional: server hostname
    .uuid = NULL,                       // Optional: device UUID
    .serial_number = 0                  // Optional: device serial number
};

// Use encrypt_tool to generate your encrypted key from your private key
const char* encrypted_key = "8qWNpMPeO1AbgcoPSsdeUORGmO/hyB70oyrpFyRlYWbaVx4Kuan0CAGaXZWS3JWdgmPL7p9k3UFTwAp5y16L8O1tYaHLGkW4p/yWmA==";

// Create game state object with encrypted key
sb_game_handle_t gs = sb_create_game_state2(encrypted_key, &device_info);
from scorbit import scorbit

info = scorbit.DeviceInfo()
info.provider = "scorbitron"           # Mandatory: provider name
info.machine_id = 4419                 # Mandatory: Scorbit-assigned Machine ID
info.game_code_version = "1.12.3"      # Mandatory: your game version
info.hostname = "production"           # Optional: server hostname
info.uuid = ""                         # Optional: device UUID
info.serial_number = 0                 # Optional: device serial number

# Use encrypt_tool to generate your encrypted key from your private key
encrypted_key = '8qWNpMPeO1AbgcoPSsdeUORGmO/hyB70oyrpFyRlYWbaVx4Kuan0CAGaXZWS3JWdgmPL7p9k3UFTwAp5y16L8O1tYaHLGkW4p/yWmA=='
gs = scorbit.create_game_state(encrypted_key, info)

Key Constants

Constant Value Description
SB_SIGNATURE_MAX_LENGTH 72 Maximum length of DER5-encoded ECDSA signature
SB_KEY_LENGTH 32 Length of private key6 in bytes
SB_DIGEST_LENGTH 32 Length of SHA-2567 digest in bytes

Key Requirements

The SDK uses ECDSA P-256 with the following specifications:

Component Description Specifications
Private Key ECDSA P-2568 private key - 32 bytes length
- Must be securely stored
Encrypted Key Base64-encoded encrypted private key - Generated using encrypt_tool
- Used for SDK initialization
Signature DER-encoded9 ECDSA signature - Maximum 72 bytes
- Generated per auth request
Digest SHA-25610 hash - 32 bytes length
- Provided by SDK

Key Security

Never expose the private key11 in logs or debug output. Only use the encrypted key generated by the encrypt_tool.

Signature Format

Signatures must be DER-encoded ECDSA signatures.

Best Practices

1. Key Storage

  • Use secure storage for your private key and preferably a TPM to store it
  • Generate encrypted keys using the encrypt_tool before deployment
  • Never commit private keys to source control

2. TPM Integration

  • If possible, use TPM for production environments
  • Implement proper error handling

  1. Elliptic Curve Digital Signature Algorithm using the P-256 curve 

  2. Trusted Platform Module - A dedicated microcontroller for secure key storage 

  3. A matched set of public and private cryptographic keys 

  4. Cryptographically marked to prove authenticity 

  5. Distinguished Encoding Rules - A standardized format for encoding data structures 

  6. The secret part of a key pair, used for signing data 

  7. Secure Hash Algorithm 2 - A cryptographic function that creates a 32-byte fingerprint of data 

  8. An open-source cryptography library used for secure communications 

  9. Elliptic Curve Key - A data structure for storing cryptographic keys 

  10. A data type for handling very large numbers in cryptography 

  11. A point on an elliptic curve used in cryptographic calculations