Game Data Security Best Practices For Indie Developers
Securing Player Data
Protecting player data should be a top priority for indie game developers. Players entrust developers with sensitive information like usernames, emails, and passwords that must be properly secured.
Hashing and Salting Passwords
All passwords collected from players should be hashed using secure one-way hashing algorithms like BCrypt, SCrypt, or PBKDF2. These hashes convert passwords into long strings of gibberish text that cannot be converted back into the original password. This way if a hacker gains access to the password hashes, they cannot reveal the actual passwords.
Hashing passwords alone is not enough though. Hashes of common passwords can be precomputed by hackers and stored in rainbow tables. To prevent this, passwords should also be salted before hashing. A salt is a random string added to each password before hashing. This ensures even identical passwords will have different hashes, preventing the use of rainbow tables.
Example Code for Secure Password Hashing in Unity
Here is C# code for securely handling passwords in a Unity game:
using System.Security.Cryptography; public static class PasswordHelper { public static string HashPassword(string password, string salt) { using (var sha256 = SHA256.Create()) { var saltedPassword = $"{password}{salt}"; var bytes = Encoding.UTF8.GetBytes(saltedPassword); var hashBytes = sha256.ComputeHash(bytes); return Convert.ToBase64String(hashBytes); } } public static string GenerateSalt() { var rng = RandomNumberGenerator.Create(); var buff = new byte[16]; rng.GetBytes(buff); return Convert.ToBase64String(buff); } }
To hash a password:
string salt = PasswordHelper.GenerateSalt(); string hash = PasswordHelper.HashPassword(password, salt); // Store salt together with hash to verify later
To verify a password:
string storedHash = ...; string storedSalt = ...; string userInputPassword = ...; string hashOfInput = PasswordHelper.HashPassword(userInputPassword, storedSalt); if (hashOfInput == storedHash) { // Valid password } else { // Invalid password }
Limiting Data Access
Access to sensitive player data should be limited only to code that requires it. This reduces the attack surface area for hackers.
Principle of Least Privilege
The principle of least privilege states that code should only have access to the bare minimum data and resources needed for its function. Any additional access beyond necessities increases risk. When structuring code, follow these practices:
- Categorize code by sensitivity level of data it handles
- Organize code into modules, classes, and methods based on data access needs
- Only expose data to calling code on a need-to-know basis
- Avoid placing sensitive data in publicly accessible scripts. Use namespace restrictions if needed.
Segmenting Data Across Multiple Databases
Storing all player data in a single database creates a lucrative target for attackers. Segment sensitive player information across multiple databases to limit data exposure from a single breach.
For example, an account management database may contain usernames, hashed passwords, emails and personal data for managing player accounts. This should be isolated from gameplay databases containing player progress, high scores, inventory and other game data.
Take care to properly encrypt network traffic between databases and implement access controls between application servers and databases based on data sensitivity requirements.
Encryption In Transit
All data transmitted over networks should be encrypted to prevent man-in-the-middle attacks that intercept communications.
Using HTTPS for Connections
The HTTPS protocol protects against tampering and eavesdropping by encrypting communication and authenticating servers through SSL/TLS certificates. Any connections between game servers, web APIs, databases and other external services should always use HTTPS.
For indie developers working solo or in very small teams, free certificates from Certificate Authorities like Let’s Encrypt are available to enable HTTPS. For larger studios needing custom domain validation, low cost SSL/TLS certificates can be purchased from most web hosting providers.
Encrypting Game Data Sent Over the Network
In addition to transport encryption through HTTPS, also consider selectively encrypting sensitive game data sent over the network. This provides an extra layer of protection in case an HTTPS connection is compromised.
For example, when transmitting player inventory and other gameplay data between a mobile game client and game servers, encrypt the data payload but not less sensitive metadata like timestamps or GeoIP country.
Use strong algorithms like AES-256 for encryption and securely distribute encryption keys between clients and servers. Limit access to decryption keys in server code according to principles of least privilege and segment data based on sensitivity as covered earlier.
Additional Safeguards
Some other best practices for securing player data:
Input Validation
All untrusted data input from players should be validated and sanitized to prevent code injection attacks like SQL injection or command injection. Never trust that input contains expected data.
Use allow lists over deny lists when possible. An allow list only permits known safe input formats and data types. A deny list attempts to block unsafe inputs but may still allow new attack vectors.
Rate Limiting Login Attempts
Brute force cracking of player passwords can be mitigated by rate limiting login attempts. Temporarily lock out login functionality after a handful of failed password attempts.
To prevent denial of service lockouts, failed attempts should be counted against source IP address and usernames separately. This prevents an attacker repeatedly failing logins for many different usernames from locking out access.
Automatic Account Lockouts
Related to rate limiting, automatically lock player accounts after a larger number of consecutive failed logins such as 10+ attempts. Require players to reset passwords or contact customer support to unlock.
Temporary automatic lockouts balance usability for legitimate players against hindering brute force password cracking attempts.