tlock

package module
v0.0.0-...-afc4a6d Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2023 License: Apache-2.0, MIT Imports: 14 Imported by: 0

README

tlock: Timelock Encryption/Decryption Made Practical

tlock gives you time based encryption and decryption capabilities by relying on a drand threshold network as described in our tlock paper. It is implemented here as a Go library, which is used to implement the tle command line tool enabling anybody to leverage timelock encryption. A compatible Typescript implementation can be found in tlock-js and a third-party implementation in Rust is available at tlock-rs.

Our timelock encryption system relies on an "unchained drand network".

Working endpoints to access it are, on mainnet:

On mainnet, the only chainhash supporting timelock encryption, with a 3s frequency and signatures on the G1 group is: dbd506d6ef76e5f386f41c651dcb808c5bcbd75471cc4eafa3f4df7ad4e4c493

This is a production-ready network with high-availability guarantees. It is considered fully secure by the drand team and ran by the same League of Entropy that has been running drand in production since 2019.

On testnet:

You can also spin up a new drand network and run your own, but note that the security guarantees boil down to the trust you have in your network.


See How It Works

For more details about the scheme and maths, please refer to our paper on eprint.


Table Of Contents


Install or Build the CLI

The tle tool is pure Go, it works without CGO (CGO_ENABLED=0). To install using Go:

go install github.com/drand/tlock/cmd/tle@latest

or locally with git:

git clone https://github.com/drand/tlock
go build cmd/tle/tle.go

Note: if you need to decrypt old ciphertexts produced before v1.0.0 against our testnet, you'll need to install the old binary using:

go install github.com/drand/tlock/cmd/tle@v0.1.0

We have changed in v1.0.0 the way we are mapping a hash to field element and this is not retro-compatible with the old ciphertext format. You can still produce ciphertexts against our testnet as explained below using the v1.0.0, but it will use the new hash to field mechanism.


tle CLI Usage

Usage:
	tle [--encrypt] (-r round)... [--armor] [-o OUTPUT] [INPUT]
	tle --decrypt [-o OUTPUT] [INPUT]

Options:
	-e, --encrypt  Encrypt the input to the output. Default if omitted.
	-d, --decrypt  Decrypt the input to the output.
	-n, --network  The drand API endpoint to use.
	-c, --chain    The chain to use. Can use either beacon ID name or beacon hash. Use beacon hash in order to ensure public key integrity.
	-r, --round    The specific round to use to encrypt the message. Cannot be used with --duration.
	-f, --force    Forces to encrypt against past rounds.
	-D, --duration How long to wait before the message can be decrypted.
	-o, --output   Write the result to the file at path OUTPUT.
	-a, --armor    Encrypt to a PEM encoded format.

If the OUTPUT exists, it will be overwritten.

NETWORK defaults to the drand mainnet endpoint https://api.drand.sh/.

CHAIN defaults to the chainhash of the fastnet network:
dbd506d6ef76e5f386f41c651dcb808c5bcbd75471cc4eafa3f4df7ad4e4c493

You can also use the drand test network:
https://pl-us.testnet.drand.sh/
and its unchained network with chain hash 7672797f548f3f4748ac4bf3352fc6c6b6468c9ad40ad456a397545c6e2df5bf
Note that if you encrypted something prior to March 2023, this was the only available network and used to be the default.

DURATION, when specified, expects a number followed by one of these units:
"ns", "us" (or "µs"), "ms", "s", "m", "h", "d", "M", "y".

Example:
    $ tle -D 10d -o encrypted_file data_to_encrypt

After the specified duration:
    $ tle -d -o dencrypted_file.txt encrypted_file
Timelock Encryption

Files can be encrypted using a duration (--duration/-D) in which the encrypted_data can be decrypted.

Example using the testnet network and a duration of 5 seconds:

$ tle -n="https://pl-us.testnet.drand.sh/" -c="7672797f548f3f4748ac4bf3352fc6c6b6468c9ad40ad456a397545c6e2df5bf" -D=5s -o=encrypted_data data.txt

If a round (--round/-R) number is known, it can be used instead of the duration. The data can be decrypted only when that round becomes available in the network.

Example using the fastnet mainnet network and a given round:

$ tle -n="https://api.drand.sh/" -c="dbd506d6ef76e5f386f41c651dcb808c5bcbd75471cc4eafa3f4df7ad4e4c493" -r=123456 -o=encrypted_data data.txt

It is also possible to encrypt the data to a PEM encoded format using the armor (--armor/-a) flag, and to rely on the default network and chain hash (which is the fastnet one on api.drand.sh):

$ tle -a -D 20s -o=encrypted_data.PEM data.txt
Timelock Decryption

For decryption, it's only necessary to specify the network if you're not using the default one.

Using the default ("fastnet" network on mainnet) and printing on stdout:

$ tle -d encrypted_data

Using the old testnet unchained network and storing the output in a file named "decrypted_data":

$ tle -d -n="https://pl-us.testnet.drand.sh/" -c="7672797f548f3f4748ac4bf3352fc6c6b6468c9ad40ad456a397545c6e2df5bf"
 -o=decrypted_data encrypted_data

Note it will overwrite the decrypted_data file if it already exists.

If decoding an armored source you don't need to specify -a again.


Library Usage

These example show how to use the API to time lock encrypt and decrypt data.

Time Lock Encryption
// Open an io.Reader to the data to be encrypted.
in, err := os.Open("data.txt")
if err != nil {
	log.Fatalf("open: %s", err)
	return
}
defer in.Close()

// Construct a network that can talk to a drand network. Example using the mainnet fastnet network.
// host:      "https://api.drand.sh/"
// chainHash: "dbd506d6ef76e5f386f41c651dcb808c5bcbd75471cc4eafa3f4df7ad4e4c493"
network,err := http.NewNetwork(host, chainHash)
if err != nil {
	log.Fatalf("new network: %s", err)
	return
}
// Specify how long we need to wait before the file can be decrypted.
duration := 10 * time.Second

// Use the network to identify the round number that represents the duration.
roundNumber := network.RoundNumber(time.Now().Add(duration))


// Write the encrypted file data to this buffer.
var cipherData bytes.Buffer

// Encrypt the data for the given round.
if err := tlock.New(network).Encrypt(&cipherData, in, roundNumber); err != nil {
	log.Fatalf("encrypt: %v", err)
	return
}
Time Lock Decryption
// Open an io.Reader to the data to be decrypted.
in, err := os.Open("data.tle")
if err != nil {
	log.Fatalf("open: %v", err)
	return
}
defer in.Close()

// Construct a network that can talk to a drand network.
// host:      "https://api.drand.sh/"
// chainHash: "dbd506d6ef76e5f386f41c651dcb808c5bcbd75471cc4eafa3f4df7ad4e4c493"
network,err := http.NewNetwork(host, chainHash)
if err != nil {
	log.Fatalf("new network: %s", err)
	return
}
// Write the decrypted file data to this buffer.
var plainData bytes.Buffer

// Decrypt the data. If you try to decrypt the data *before* the specified
// duration, it will fail with the message: "too early to decrypt".
if err := tlock.New(network).Decrypt(&plainData, in); err != nil {
	log.Fatalf("decrypt: %v", err)
	return
}

Applying another layer of encryption

The recommended way of doing "hybrid" encryption where you both encrypt your data using timelock encryption, but also with another encryption scheme, such as a public-key or a symmetric-key scheme is to simple re-encrypt your encrypted data using tlock.

For example, you can use the age cli to encrypt your data with a passphrase as follows.

Encrypting Data With Passphrase
$ cat data.txt | age -p | tle -D 30s -o encrypted_data
Decrypting Data With Passphrase
$ cat encrypted_data | tle -d | age -d -o data.txt

Note that you could do the same with PGP or any other encryption tool.


Security considerations

The security of our timelock encryption mechanism relies on four main things:

  • The security of the underlying Identity Encryption Scheme (proposed in 2001) and its implementation that we're using.
  • The security of the threshold BLS scheme (proposed in 2003), and its impementation by the network you're relying on.
  • The security of age's underlying primitives, and that of the age implementation we're using to encrypt the data, since we rely on the hybrid encryption principle, where we only timelock encrypt ("wrap") a random symmetric key that is used by age to actually symmetrically encrypt the data using Chacha20Poly1305).
  • The security of the threshold network providing you with its BLS signatures at a given frequency, for instance the default for tle is to rely on drand and its existing League of Entropy network.

In practice this means that if you trust there are never more than the threshold t malicious nodes on the network you're relying on, you are guaranteed that you timelocked data cannot be decrypted earlier than what you intended.

Please note that neither BLS nor the IBE scheme we are relying on are "quantum resistant", therefore shall a Quantum Computer be built that's able to threaten their security, our current design wouldn't resist. There are also no quantum resistant scheme that we're aware of that could be used to replace our current design since post-quantum signatures schemes do not "thresholdize" too well in a post-quantum IBE-compatible way.

However, such a quantum computer seems unlikely to be built within the next 5-10 years and therefore we currently consider that you can expect a "long term security" horizon of at least 5 years by relying on our design.

Finally, relying on the League of Entropy Testnet should not be considered secure and be used only for testing purposes. We recommend relying on the League of Entropy fastnet beacon chain running on Mainnet for securing timelocked content.

Our timelock scheme and code was reviewed by cryptography and security experts from Kudelski and the report is available on IPFS at QmWQvTdiD3fSwJgasPLppHZKP6SMvsuTUnb1vRP2xM7y4m.


Get in touch


License

This project is licensed using the Permissive License Stack which means that all contributions are available under the most permissive commonly-used licenses, and dependent projects can pick the license that best suits them.

Therefore, the project is dual-licensed under Apache 2.0 and MIT terms:

Documentation

Overview

Package tlock provides an API for encrypting/decrypting data using drand time lock encryption. This allows data to be encrypted and only decrypted in the future.

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidPublicKey = errors.New("the public key received from the network to encrypt this was infinity and thus insecure")
View Source
var ErrTooEarly = errors.New("too early to decrypt")

ErrTooEarly represents an error when a decryption operation happens early.

View Source
var ErrWrongChainhash = errors.New("invalid chainhash")

Functions

func BytesToCiphertext

func BytesToCiphertext(scheme crypto.Scheme, b []byte) (*ibe.Ciphertext, error)

BytesToCiphertext converts bytes to a ciphertext.

func CiphertextToBytes

func CiphertextToBytes(scheme crypto.Scheme, ciphertext *ibe.Ciphertext) ([]byte, error)

CiphertextToBytes converts a ciphertext value to a set of bytes.

func TimeLock

func TimeLock(scheme crypto.Scheme, publicKey kyber.Point, roundNumber uint64, data []byte) (*ibe.Ciphertext, error)

TimeLock encrypts the specified data for the given round number. The data can't be decrypted until the specified round is reached by the network in use.

func TimeUnlock

func TimeUnlock(scheme crypto.Scheme, publicKey kyber.Point, beacon chain.Beacon, ciphertext *ibe.Ciphertext) ([]byte, error)

TimeUnlock decrypts the specified ciphertext for the given beacon. The ciphertext can't be decrypted until the specified round is reached by the network in use.

Types

type Network

type Network interface {
	ChainHash() string
	Current(time.Time) uint64
	PublicKey() kyber.Point
	Scheme() crypto.Scheme
	Signature(roundNumber uint64) ([]byte, error)
}

Network represents a system that provides support for encrypting/decrypting a DEK based on a future time.

type Tlock

type Tlock struct {
	// contains filtered or unexported fields
}

Tlock provides an API for time lock encryption and decryption.

func New

func New(network Network) Tlock

New constructs a tlock for the specified network which can encrypt data that can be decrypted until the future.

func (Tlock) Decrypt

func (t Tlock) Decrypt(dst io.Writer, src io.Reader) error

Decrypt will decrypt the source and write that to the destination. The decrypted data will not be decryptable unless the specified round from the encrypt call is reached by the network.

func (Tlock) Encrypt

func (t Tlock) Encrypt(dst io.Writer, src io.Reader, roundNumber uint64) (err error)

Encrypt will encrypt the source and write that to the destination. The encrypted data will not be decryptable until the specified round is reached by the network.

func (Tlock) Metadata

func (t Tlock) Metadata(dst io.Writer) (err error)

Metadata will return details about the drand network

Directories

Path Synopsis
cmd
tle
tle/commands
Package commands implements the processing of the command line flags and processing of the encryption operation.
Package commands implements the processing of the command line flags and processing of the encryption operation.
networks
http
Package http implements the Network interface for the tlock package.
Package http implements the Network interface for the tlock package.

Jump to

Keyboard shortcuts

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