# elm-secret-sharing

An implementation of [Shamir's Secret Sharing](https://en.wikipedia.org/wiki/Shamir's_Secret_Sharing): your secret is encrypted into `N` keys, of which only `K` are needed to reconstruct the original secret.

Port of [`simbo1905/shamir`](https://github.com/simbo1905/shamir).

Example usage:
```elm
secret : String
secret =
    "Hello there!"

allKeysAndNewSeed : Result Secret.EncryptError ( List Key, Random.Seed )
allKeysAndNewSeed =
    Secret.encryptString
        -- README sin #1: Don't use a static seed in production!
        { seed = Random.initialSeed 0
        , parts = 5
        , minPartsNeeded = 3
        }
        secret

onlySomeKeys : List Key
onlySomeKeys =
    allKeys
        -- README sin #2: Don't throw away the advanced seed either!
        |> Result.map Tuple.first
        |> Result.withDefault []
        |> List.drop 2

decryptedSecret : Result Secret.DecryptError String
decryptedSecret =
    Secret.decryptString onlySomeKeys

-- decryptedSecret == Ok secret
```

## Seed choice

Since this dives into the cryptography area, a few rules/recommendations apply
whenever you're expecting safety:

* Don't use a hardcoded static seed (eg. `Random.initialSeed 0`)
* Don't use the current time as a seed (it's not safe enough, could be
  bruteforce-able)
* Use a cryptographically random value as a seed. For example, pass an integer
  generated by [`crypto.getRandomValues`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues)
  into your Elm app via flags:
* Don't reuse a seed. All functions that _use_ the seed typically give you a new
  seed alongside the generated value (or at least they should). Replace the seed
  in your model with it!

```javascript
const seed = crypto.getRandomValues(new Uint32Array(1))[0];
const app = Elm.Main.init({flags: {initialSeed: seed}});
```

```elm
type alias Flags =
    { initialSeed : Int }


type alias Model =
    { seed : Random.Seed }


init flags =
    ( { seed = Random.initialSeed flags.initialSeed }
    , Cmd.none
    )


-- later:
Secret.encryptString
    { seed = model.seed -- Tada!
    , parts = 5
    , minPartsNeeded = 3
    }
    secret
```

## Advanced usage:

It's possible to have a tiered sharing: let's say you want to have admin keys and
user keys; allowing either two admin keys or one admin key and three user keys to
recover the secret.

For more info on how to do that check [this link](https://github.com/simbo1905/shamir#tiered-sharing-java).
Essentially you generate one extra higher-tiered key and instead of giving it to
somebody split it into the lower-tiered keys.
