horcrux

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 8, 2021 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package horcrux provides security question style secret recovery while preserving end-to-end cryptographic security.

Given N pairs of security questions and answers, the secret is split using Shamir's Secret Sharing algorithm into N shares, one for each question. A 256-bit key is derived from the answer to each question using scrypt, and the share is then encrypted with that key using ChaCha20Poly1305.

To recover the secret given K of N answers, the secret keys are re-derived and the shares are decrypted and combined.

Example
package main

import (
	"fmt"

	"github.com/lukasmalkmus/horcrux/horcrux"
)

func main() {
	secret := []byte("my favorite password")
	questions := []horcrux.Question{
		{"Tim", "What's your first pet's name?", "Spot"},
		{"Jay", "What's your least favorite food?", "Broccoli"},
		{"Tom", "What's your mother's maiden name?", "Hernandez"},
		{"Joe", "What's your real name?", "Rumplestiltskin"},
	}

	// Split into four fragments, any two of which can be combined to recover
	// the secret.
	fragments, err := horcrux.Split(secret, questions, 2)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Answer two of the security questions.
	answers := make([]horcrux.Answer, 2)
	for i := range answers {
		answers[i] = horcrux.Answer{
			Fragment: fragments[i],
			Answer:   questions[i].Answer,
		}
	}

	// Recover the original secret.
	s, err := horcrux.Recover(answers)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Printf("%s", s)
}
Output:

my favorite password

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Recover

func Recover(answers []Answer) ([]byte, error)

Recover combines the given answers and returns the original secret.

Types

type Answer

type Answer struct {
	// Fragment is the previously encrypted fragment.
	*Fragment
	// Answer is the answer to the security question.
	Answer string
}

Answer is an encrypted fragment of the secret and the answer to the security question.

type Fragment

type Fragment struct {
	// ID of the fragment. Every fragment from the same split has the same ID.
	ID string
	// Owner of the fragment.
	Owner string
	// Question is the security question.
	Question string
	// Threshold is the number of fragments required to recover the secret.
	// Must be between 2 and 255.
	Threshold int
	// Nonce is the random nonce used for encryption.
	Nonce []byte
	// Salt is the random salt used for scrypt.
	Salt []byte
	// Value is the encrypted share.
	Value []byte
}

Fragment is an encrypted fragment of the secret associated with a security question.

func Split

func Split(secret []byte, questions []Question, threshold int) ([]*Fragment, error)

Split the given secret into as much encrypted fragments as security questions given. The threshold specifies how many fragments are needed to recover the secret and ranges from 2 to 255.

type Question

type Question struct {
	// Owner of the question.
	Owner string
	// Text is the actual question text.
	Text string
	// Answer is the answer to that question.
	Answer string
}

Question is a securtiy question composed of the actual question and the answer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL