Security Considerations

Splinter’s security-related features start with support for cryptographic signing with public/private keys, then continue with additional levels of security and customizable permissions. This topic summarizes how Splinter uses key-based signing, provides Biome to map user credentials to keys, and supports organization-based smart permissions with the Pike smart contract. It also describes Splinter’s port requirements and security recommendations for REST API connections.

Cryptographic Signing with Public/Private Keys

Like Sawtooth and other distributed ledgers, Splinter supports key-based cryptographic signing. Specifically, Splinter uses the Cylinder library for loading keys, signing, and verifying signatures.

Scabbard, the default distributed ledger service included in Splinter, uses public/private keys to sign all transactions that affect shared state. Each user and transaction-submitting entity has a public key and a private key for signing transactions. This includes smart contract operations (uploads, configuration, and changes), as well as transaction-related functions performed by the Splinter daemon and application-specific services.

Splinter also uses public/private keys to sign operations such as creating a circuit and identification between nodes during challenge authorization. For example, the admin service checks the signing key for each circuit payload and verifies that circuit proposals and votes are signed with the key of a circuit admin, as described in the next section.

Connection Authorization

When Splinter nodes connect, they must go through a “handshake” to verify the identity of the other node. Splinter supports two authorization types, trust and challenge. The required authorization type is set within the circuit definition.

Trust Authorization takes the identity provided from the node without further verification. Trust was the only authorization type implemented in 0.4, and should only be used for backwards compatibility or development.

The authorization type that provides a better guarantee the nodes are actually who they say they are is challenge authorization. Challenge Authorization requires a node’s ID to be tied to a public key/private key pair and a node must prove they have access to that key by signing a random nonce, providing the resulting signature and their public key. The expected public key associated with a node is stored in the circuit member list, and therefore must be shared with other members of the network.

NOTE: The challenge authorization key is different then the key discussed below for circuit admins.

Circuit Administration

Each Splinter node has one or more circuit admins who can propose new circuits and vote on circuit proposals. Usually, each node in the circuit has at least one circuit admin. The Splinter registry stores the public key of each node’s circuit admin (or admins) in the node entry.

NOTE: The admins must share their registry entries (either out-of-band or in an external node registry file) before the circuit can be approved and created. When creating a circuit, the circuit admin signs the proposal with their private key (using the --key option in the splinter circuit propose command). Each node verifies that this private key corresponds with the public key that is defined in the registry.

Likewise, the circuit admin’s private key is required when voting on a circuit proposal with the --key option in the splinter circuit vote command.

For more information, see Splinter Registry and the man pages splinter-circuit-propose(1) and splinter-circuit-vote(1).

Smart Contract Administration with Scabbard

Each circuit has at least one contract admin who can manage smart contracts for that circuit

The contract admin (or admins) are defined in a circuit proposal (with splinter circuit propose). The circuit admin includes one or more admin_keys service arguments in the format --service-arg *::admin_keys=<public_key>.

The contract admin can upload new smart contracts, configure new contracts (create a contract registry, namespace, and namespace permissions), and update or delete existing contracts. The contract admin also defines owners for the contract registry and namespace.

  • A contract registry owner can update contract versions. When creating a contract registry, the contract admin uses scabbard cr create --owners to specify at least one contract registry owner. To add an owner for an existing contract registry, the contract admin uses scabbard cr update --owners.

  • A namespace owner can change the namespace permissions for the contract. When creating the contract namespace, the contract admin uses scabbard ns create --owners to specify at least one contract registry owner. To add an owner for an existing contract namespace, the contract admin uses scabbard cr update --owners.

For more information, see Uploading a Smart Contract, the Grid README, and the man pages splinter-circuit-propose(1), scabbard-contract-upload(1), scabbard-cr(1), scabbard-ns(1), and scabbard-perm(1).

User and Credential Management with Biome

Biome is the Splinter component that manages the relationship between user-based data and Splinter’s key-based user information. Put simply, Biome maps user IDs and passwords (or other authentication credentials) to the public/private keys that the rest of Splinter uses to sign transactions.

Biome isolates all user-based data from the rest of Splinter, using a Biome-specific database to store the mapping between user data and keys. All other Splinter functions use only key-based signing to identify actors and verify that they have permission for the requested operation.

It’s important to note that the private keys stored in Biome are encrypted on the client side; Splinter does not re-encrypt private keys within the REST API. The client application is responsible for encryption before submitting a private key.

For more information, see Biome User Management.

Smart Permissions for Organizations and Agents with Pike

Pike is a smart contract in Grid that handles organization and identity permissions with Sawtooth Sabre. Pike provides organization-specific business logic for agents (actors within the organization) and roles (sets of permissions).

The predefined admin role in Pike identifies the user or process who can create and change agents and roles for that organization. Other roles can be defined by organization admins or smart contracts as necessary.

Pike runs as WebAssembly (WASM) code, like other smart contracts. Smart permission data is stored in a portion of the Sabre namespace that other smart contracts and applications can access, if necessary.

For an example of a smart contract that uses Pike smart permissions, see the “intkey-multiply” smart contract in Sawtooth Sabre.

For more information, see the Pike Transaction Family Specification, Sawtooth Sabre: Smart Permissions, and Sawtooth Sabre Application Developer’s Guide.

REST API Security

The Splinter REST API provides authentication/authorization out-of-the-box. There are currently 3 types of client authentication that the REST API supports: Biome (user) credentials, OAuth2, and Cylinder JWT. Cylinder JWT authentication is enabled by default for the Splinter daemon, and administrators can configure which of the other authentication types is available on their node. Any combination of authentication types is allowed.

The Splinter REST API provides 2 ways to configure authorization for clients: a file-based list of admin keys and a database-backed, role-based access control system. The REST API provides various permissions for its endpoints based on the part of the system they affect and if they are read or write operations. These permissions allow administrators to control which parts of the system a client or user can access and what kind of operations they can perform.

For more information on REST API security and how to configure authentication/authorization for the splinterd REST API, see Configuring REST API Authorization.

Ports and Connections

By default, Splinter uses ports 8044 and 8080 for communication. Other nodes must be able to connect on port 8044. Applications and CLIs used to manage Splinter will connect to the Splinter REST API on port 8080.

Splinter supports several connection protocols for node-to-node communication:

  • Transport Layer Security (TLS), using X.509 certificates and associated keys for the certificate authority on each Splinter node

  • WebSocket secure (WSS) when the application protocol is HTTPS

  • Raw TCP (intended for development and testing only)