<commit_before># kms-pass

An experiment in secure password storage using a trusted third party.

**NOT A REAL THING, DO NOT USE THIS**

## The Problem

Storing passwords is hard. In the event of a breach, the contents of your database need to be
resistant to brute-force and dictionary attacks. This leads us to memory-hard algorithms like Scrypt
and Argon2, which level the computational playing field by running as slowly on ASICs and GPUs as
they do on general-purpose CPUs.

This is a good solution to reduce the scope of a breach, but does little to protect individual
passwords: limiting an attacker to tens of megahashes/sec still allows for targeted attacks against
low entropy passwords (i.e. 99% of passwords).

The fundamental problem is that an offline attack allows an attacker to bring unlimited
computational resources to bear across unlimited amounts of time and space. Once a breach occurs,
attackers have the rest of their lives to recover the passwords.

How do we fix this? We move the problem to an exclusively online system.

## The Solution

kms-pass implements a proposed solution which uses a managed cryptographic service like Google Cloud
Platform's Key Management Service to isolate a critical piece of information required for verifying
a candidate password.

### Storing A Password

1. Use HMAC-SHA2-256 and the system key (`sk`) to calculate a digest (`d`) of the user's password.
2. Use the Key Management Service to encrypt (`ed`) the digest.
3. Generate a key (`ek`) using scrypt, a random salt (`s`), and the user's password.
4. Encrypt (`eed`) the encrypted digest (`ed`) using AES-CTR and `ek`.
5. Store the salt (`s`), the scrypt params, and the doubly-encrypted digest (`eed`).

### Verifying A Password

1. Generate a key (`ek`) using scrypt, a random salt (`s`), and the user's password.
2. Decrypt the doubly-encrypted digest using `ek`.
3. Use Key Management Service to decrypt the encrypted digest.
4. Use HMAC and the system key to calculate a candidate digest of the user's password.
5. Use a constant-time comparison algorithm to compare the decrypted digest with the candidate.

<commit_msg>Some virtues of this design.<commit_after># kms-pass

An experiment in secure password storage using a trusted third party.

**NOT A REAL THING, DO NOT USE THIS**

## The Problem

Storing passwords is hard. In the event of a breach, the contents of your database need to be
resistant to brute-force and dictionary attacks. This leads us to memory-hard algorithms like Scrypt
and Argon2, which level the computational playing field by running as slowly on ASICs and GPUs as
they do on general-purpose CPUs.

This is a good solution to reduce the scope of a breach, but does little to protect individual
passwords: limiting an attacker to tens of megahashes/sec still allows for targeted attacks against
low entropy passwords (i.e. 99% of passwords).

The fundamental problem is that an offline attack allows an attacker to bring unlimited
computational resources to bear across unlimited amounts of time and space. Once a breach occurs,
attackers have the rest of their lives to recover the passwords.

How do we fix this? We move the problem to an exclusively online system.

## The Solution

kms-pass implements a proposed solution which uses a managed cryptographic service like Google Cloud
Platform's Key Management Service to isolate a critical piece of information required for verifying
a candidate password.

### Storing A Password

1. Use HMAC-SHA2-256 and the system key (`sk`) to calculate a digest (`d`) of the user's password.
2. Use the Key Management Service to encrypt (`ed`) the digest.
3. Generate a key (`ek`) using scrypt, a random salt (`s`), and the user's password.
4. Encrypt (`eed`) the encrypted digest (`ed`) using AES-CTR and `ek`.
5. Store the salt (`s`), the scrypt params, and the doubly-encrypted digest (`eed`).

### Verifying A Password

1. Generate a key (`ek`) using scrypt, a random salt (`s`), and the user's password.
2. Decrypt the doubly-encrypted digest using `ek`.
3. Use Key Management Service to decrypt the encrypted digest.
4. Use HMAC and the system key to calculate a candidate digest of the user's password.
5. Use a constant-time comparison algorithm to compare the decrypted digest with the candidate.

## The Virtues

* In order to perform a brute force attack on an entry, an attacker must obtain the system key, the
  non-exportable key in the Key Management Service, and the hash stored in your database.
* The data sent to the Key Management Service can't be used to reveal any user passwords without
  the system key.
* If an attacker gains access to your Key Management Service, they'll still need to derive a key
  using scrypt in order to decrypt the KMS ciphertext.

{'fraction_non_alphanumeric': 0.057885906040268456, 'fraction_numerical': 0.007130872483221477, 'mean_word_length': 4.2988888888888885, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1387713', 'n_tokens_mistral': 1281, 'n_tokens_neox': 1173, 'n_words': 761}