TimeLock Cryptographic Service
Timelock.zone aims to serve as a public platform that allows companies and individuals to encrypt data for future decryption with support for various cryptographic systems, including the most popular Elliptic curves.
Timelock is being developed by the Aragon ZK Research team using Gears, a COSMOS SDK written in Rust.
Development Timeline
How It Works?
Choose your preferred cryptographic scheme and a future day (up to 10 years in advance) or hour (up to 2 years in advance) and obtain a public key. You can now encrypt your data and safely share it with others, knowing it can only be decrypted at the specified time in the future, when the corresponding private key will be published on timelock.zone.
Security
Our system reiles on the the well-known League of Entropy randomness beacon, drand.love. In addition, a single honest party participating in the computation of the public key is enough to ensure that the private key cannot be uncovered ahead of time. In order to increase security even further, we will allow public participation during the private key preparation phase.
For formal security proof of the protocol read this section.
Alpha Service Demo
Here we provide a TLCS Alpha Demo.
General Information
This is the alpha implementation of the timelock service. There are currently many keys already available and during this alpha period you can request keys be made at no cost.
NOTE: These keys should not be used for real world encryption and are for testing purposes only
How to Build a Time Lock Crypto Service based on League of Entropy (drand)
Setting and motivation
We assume the reader to be familiar with the League of Entropy (a.k.a. drand) system but the presentation of our treatment is self-contained. In the following we denote by \( g_1,g_2 \)
the generators of the groups \(G_1,G_2\) of some prime order \(p\) used by LOE, and by \(PK_L\) the public key of LOE that has the form \(PK_L=g_2^{sk_L}\) where \(sk_L\in Z_p\) is the corresponding secret key that is shared by the LOE members. For simplicity, in the following we will often say that at time \(C\) LOE releases a secret key \(SK_C\) whereas we should actually refer to a round number rather than a time. We recall that LOE is a coalition of members who, at each time interval \(C \), release a BLS signature \(\sigma_C=Hash(C)^{SK_L}\), where \(Hash\) is a (standardized hash function) that maps bit strings to points in \(G_1\) (we skip technical details about the actual encodings of \(C \) . This signature is jointly computed in a threshold fashion by the LOE members in a way that a minority of the members cannot obtain the secret key \(SK_L\) (that is shared by the members). To ease our presentation, henceforth we denote by \(SK_C\) the signature \(\sigma_C\) for time \(C\) and we say that \(SK_C\) is the secret key of LOE for time \(C\) . For the purpose of our treatment, the reader does not need to know the details of the LOE protocol but simply that at each time interval \(C\) the afore-mentioned secret key \(SK_C\) is publicly available.
We want a cryptographic protocol among a set of parties to jointly construct a public key \(PK\) whose corresponding secret key \(sk\) can be publicly computed only at time greater or equal than \(C\) when the secret key \(SK_C\) of LOE for time \(C\) will be made available; here \(C\) is a public input to all parties. The public key \(PK\) should have the form \(g^{sk}\) where \(g\) is the generator of a group of some prime order \(q\), so \(sk \in Z_q\). We look for generic approaches so we consider any kind of prime order group in which the Dlog Assumption holds: that is elliptic curve groups (both bilinear and non-bilinear groups) and multiplicative groups of prime order; later on we will also cover a specific RSA setting. This public key \(PK\) can be then used for encryption using any encryption scheme defined over the group generated by \(g\) (later on we will also discuss other applications to digital signatures and zero-knowledge proofs).
Observe that this problem, though related, is independent from the recently proposed timelock encryption primitive. Indeed, a user Alice can use the public key \(PK \), that was part of the output of an execution of the TLCS protocol for time \(C \), to encrypt measages without specifying any time and only performing cryptographic operations related to the group generated by \(g\) . After time \(C \), using \(SK_C\) and the transcript of the TLCS protocol anyone (and thus a smart contract) can compute the secret key \(sk\) corresponding to \(PK\). Bob can use \(sk\) to decrypt Alice's messages. Observe that, unlike timelock encryption, here the computations of Alice and Bob are completely independent from the LOE system.
We assume that there is a blockchain on which anyone (or possibly only registered people to avoid DoS) can post data as a mean to generate a public key PK and some related data that can be used by anyone, and so by a smart contract, to obtain the corresponding secret key \(sk\) at time \(C \) .
Additionally, we want that there is a committee of members that anyone can freely join, that is the set of participants in a particular execution of the protocol is not fixed, and we want the protocol to require just one message of interaction from each participant (assuming a perfect broadcast channel like a blockchain).
Warmup: a TLCS protocol from general-purpose NIZK proofs
Consider the following protocol. The generic party \(i=1,... \) does the following. It computes \(PK_i=g^{sk_i} \), where \(sk_i \) is randomly chosen in \(Z_q \). It chooses random \(t_i \) from \(Z_p \) and computes \(T_i=g_2^{t_i} \), \(Z_i=e(H(C),PK_L)^{t_i} \) and \(y_i=H(Z_i) \oplus sk_i \). The party \(i \) posts on the blokchain: \)(T_i, y_i) \). Note that \(Z_i \) is not posted, and the honest party is required to delete \(Z_i, t_i,sk_i \) from his memory, so that until time \(C \) nobody can get \(sk_i \).
At some point, the public key construction phase terminates and no new party can participate. Then, the public key \(PK \) is set to \(PK=\prod_i PK_i=g^{sk} \), where \(sk=\sum_i sk_i \mod q \).
When the secret \(SK_C=H(C)^{sk_L} \) of LOE is published at time \(C \), anyone can publicly do the following based on the information posted on the blockchain. For any \(i \) compute \(e(SK_C,T_i)=Z_i \) and then can compute \(sk_i=y_i \oplus H(Z_i) \).
From all \(sk_i \)'s, anyone can then recover \(sk=\sum_i sk_i \mod q \).
The security here guarantees that if only a single party is trusted in having deleted his memory at the of the computation, then the secret key \(sk \) corresponding to \(PK \) is protected until time \(C \) assuming that the majority of LOE members are honest. That is, the only added assumption beyond LOE is that there is a single honest party. Observe that, since anyone can publicly participate in the protocol (that is the committee allows on-fly join), if someone does not trust the system can decide on participating in the protocol freely.
To be able to decrypt we need to assume that the values \(y_i \)'s posted on the blockchain are computed correctly according to the above procedure, so each \(y_i \) needs to be accompained with a ZK proof of well-formedness, that is a proof that the tuple \((g_2,PK_L,C,T_i,PK_i,y_i) \) is such that there exist values \(t_i\in Z_p \), \(sk_i\in Z_q \) such that \(T_i=g_2^{t_i} \), \(Z_i=e(H(C),PK_L)^{t_i} \), \(y_i=H(Z_i) \oplus sk_i \) and \(PK_i=g^{sk_i} \). The proof system needs to be non-malleable to prevent attacks in which the last party can induce a public key of which he knows the corresponding secret key; alternatively, a standard non-interactive Schnorr's proof must be attacked to each partial public key \(PK_i \).
This requires a NIZK proof of computation of exponentiation in the target group. Notice that if a tuple \((PK_i,T_i,y_i) \) does not come with a valid proof, it will not be used for the computation of \(PK \).
An efficient TLCS protocol that avoids general-purpose NIZK proofs
The above NIZK proof could be implemented with general-purpose SNARK for circuits that compute operations in the target group of the LOE's curve. In this section we show how to implement a variant of the above protocol that avoids general-purpose NIZK proofs.
(In the following we will be focusing on a single party so we will remove the subscript \(i \) that refers to the parties. So when you read \(PK \), this is actually \(PK_i \) of the previous notation and not the public key that is the result of the shares of all committee members. We choose to do that to minimize the number of subscripts to fit better in hackmd.)
We will construct an interactive protocol. This can be done non-interactive via the FS transform.
There is a security parameter \(k \) that affects the soundness error, precisely the soundness error will be \(2^{-k} \) so there is a trade-off: we have freedom to choose \(k \) as large as possible to reduce the soundness error and as small as possible to make the system more efficient.
The generic party (the prover) has a public key \(PK=g^{sk} \), where \(sk\in Z_q \) is known to the prover but not to the verifier. For \(j=1,\ldots,k \) the prover chooses two random values \(sk_{j,1},sk_{j,2} \) that sum up to \( sk \) and sets \( PK_{j,1}=g^{sk_{j,1}},PK_{j,2}=g^{sk_{j,2}} \).
For \(j=1,\ldots, k \), the prover chooses random \(t_{j,1},t_{j,2} \) from \(Z_p \) and computes \(T_{j,1}=g_2^{t_{j,1}} \), \(Z_{j,1}=e(H(C),PK_L)^{t_{j,1}} \) and \(y_{j,1}=H(Z_{j,1}) \oplus sk_{j,1} \) and similarly \(T_{j,2},Z_{j,2},y_{j,2} \). The prover sends to the verifier the value \(PK \) and the list of tuples: \)(PK_{j,b},T_{j,b_j},y_{j,b})_{j\in[k],b\in{1,2}} \).
(Note: as explained before here we removed the subscript \(i \) so \(PK \) refers to the contribution of a generic party and not to the final public key that is computed as product of the public keys of all members. We do not include the further subscript \(i \) to avoid many subscripts like "\(PK_{i,j,b_j} \)", etc.)
The verifier chooses a vector of \(k \) random values \(b_1,\ldots,b_k \) in \({1,2} \) and sends it to the prover. For all \(j\in[k] \) the prover sets \(t_j=t_{j,b_j} \) and sends back to the verifier the tuple \((t_j)_{j\in[k]} \). The verifier accepts iff all the following checks pass:
-
- For all \(j=1,\ldots,k \) check that \(PK_{j,1}* PK_{j,2}=PK \). That is, the verifier checks that all the pairs of public keys form a \(2 \) out of \(2 \) secret sharing of the same public key \(PK \). This also convinces the verifier that the same condition holds with respect to the secret keys, that is that for all \(i=1,\ldots,k \), \(sk_{j,1}+sk_{j,2}=sk \) modulo \(q \), where \(PK=g^{sk} \).
-
- The verifier now checks that the tuple \(PK_{j,b_j},T_{j,b_j},y_{j,b_j} \) is well-formed in the following way. The verifier computes \(Z_j=e(H(C),PK_L)^{t_j} \). If \(t_j \) was equal to \(t_{j,b_j} \) then it holds that \(Z_j=Z_{j,b_j} \). The verifier computes \(s_j=H(Z_j) \oplus y_{j,b_j}. \) If \(t_j \) was equal to \(t_{j,b_j} \) then it holds that \(s_j=sk_{j,b_j} \). The verifier checks that \(PK_{j,b_j}=g^{s_j} \) and that \(T_{j,b_j}=g_2^{t_j} \). This convinces the verifier that \(s_j=sk_{j,b_j} \) and that \(sk_{j,b_j} \) is the secret key corresponding to \(PK_{j,b_j} \).
Let \(s_{j,1} \) and \(s_{j,2} \) be the values induced by \(SK_C \) that should be equal to resp. \(sk_{j,1} \) and \(sk_{j,2} \) if the prover is honest. If \(PK \) was not invertible (that is if \(sk \) is not equal to \(s_{j,1}+s_{j,2}\ mod\ q \) then: if the first check with respect to a generic \(j \) passes then the second check with respect to the same \(j \) can pass only with prob. at most \(1/2 \) over the choice of \(b_j \). So the prob. that a malicious committee member convinces the verifier is \(1/2^k \).
If the proof passes the public key \(PK \) of the party is accepted and is used to compute the public key for time \(C \) by multiplying together all the public keys of all parties whose proofs were accepted.
At time \(C \), to recover the corresponding secret key \(sk \) using the value \(SK_C=H(C)^{SK_L} \) released by LOE, one runs the following procedure. - for j=1 to k:
- For all \( b\in{1,2} \) compute \(e(H(C)^{SK_L},T_{j,b})=Z_{j,b} \), \(s_{j,b}=H(Z_{j,b}) \oplus y_{j,b} \).
- If \( g^{s_{j,1}}=PK_{j,1} \) and \(g^{s_{j,2}}=PK_{j,2} \) and \(PK_{j,1} * PK_{j,2}=PK \) then return \(sk=s_{j,1}+s_{j,2}\ mod\ q \) else continue;
The previous proof can be made non-interactive by having the prover to choose the vector \(b_1,...,b_k \) as hash of the string \([PK,(PK_{j,b},T_{j,b_j},y_{j,b})_{j\in[k]}] \). The verifier does the same to recompute the vector \(b_1,...,b_k \) in a deterministic way. Under mild conditions the non-interactive variant can be made weak simulation sound extractable (see here) since the previous TLCS protocol is a sigma protocol. * TODO: check that the conditions are satisfied.
Variants based on general secret sharing
The above system can be modified having in each repetition e.g. a prob. of error of \(1/3 \) instead of \(1/2 \) and with overall shorter proofs. The idea is the following. For each \(j\in[k] \) we can choose e.g. \(3 \) secret keys \(sk_{j,1},...,sk_{j,3} \) so that they form e.g. a \(2 \) out of \(3 \) secret sharing of \(sk \). That is, for all \(i\in[3] \), \(sk_{j,i}=p_j(i) \), where \(p_j \) is a random degree one polynomial whose constant term equals \(sk \). Thus, by means of the Lagrange coefficients, any subset of size \(2 \) of such keys can be used to reconstruct \(sk \). Then we let as before \(PK_{j,1},...,PK_{j,3} \) be the corresponding public keys. The verifier in check 1 is changed as follows. The verifier will verify that any subset \(S \) of \({1,...,3} \) of cardinality \(2 \) of such public keys is such that \(\prod_{l\in S} PK_{j,l}^{\lambda_{S,l}}=PK \), where the values \(\lambda_{S,l},l\in S \) are the Lagrange coefficients for set \(S \). Since there are \(3 \) subsets of \( {1,...,3} \) of cardinality \(2 \), check \(1 \) requires \( 3*2=6 \) exponentiations in the cyclic group. In check \(2 \) the verifier will do the checks as above except for the following change. Before, the check was with respect to a single random bit. Now the check is with respect to a random index \(k \) in \({1,...,3} \). Now we notice that if the check \(1 \) passes the party could cheat only if there exists at most one index \(k' \) such that the public key \(PK_{j,k'} \) is invertible and the verifier happens to choose \(k=k' \) and this occurs with prob. \(1/3 \). So, with still one exponentiation in the target group per iteration we get error \(1/3 \) and we decreased the communication (the size of the proof).
Experiments show that, though the time performance may not be much better, this approach is preferable when attempting to reduce the communication cost. The time verification cost depends on the ratio of efficiency between exponentiations in target group and exponentiations in the cyclic groups. If for some cyclic group this ratio were high (that is exponentiations in the target group were much more expensive than exponentiations in the cyclic group), the approach on general secret sharing would also be more efficient in terms of time costs for the verifier. For example, in some applications the period between publication of the tlock public key and revealing of the corresponding secret key could be short; in such case it could make sense to use cyclic groups with short security parameters so that the secret sharing variant could improve more on verification time. In most cases this variant improves slightly on proof size.
For the concrete case of e.g. a 2 out of 3 SS one can choose the interpolation points so as to make the Lagrange coefficients to be small integers.
Random check trick
Another trick to make the SS variant more efficient is the following. Let us assume a 2 out of 4 SS as above. The verifier can be modified so as to choose random scalars \(r_j,j\in[k] \) and to set for each \(l\in [4] \):
$$RPK_{l}=\prod_{j\in[k]}PK_{j,l}^{r_j} $$
Then, the verifier can check for each subset \(S \) of \([4] \) of cardinality \(2 \) that:
\( \prod_{l\in S} RPK_{l}^{\lambda_{S,l}}=PK^{\sum_{j\in[k]} r_j} \) In this way, the verifier would do a number of exponentiations in the cyclic group of the order \(4k+13 \) rather than \(12k \), and this should make the verifier of the 2 out of 4 SS variant more efficient.
- TODO: check the soundness of the approach and implement it.
Generalization to any homomorphic OWF and thus to RSA
The previous protocol only uses the following facts: - The exponentiation in a cyclic group is difficult to invert (for security). - The exponentiation in a cyclic group is easy to check, that is given \(sk \) and \(PK \) it is easy to check if \(PK=g^{sk} \). - The exponentiation in a cyclic group is homomorphic, that is the product of two public keys \(PK_1,PK_2 \) whose secret keys are resp. \(sk_1,sk_2 \) is a public key \(PK \) such that the corresponding secret key \(sk \) equals \(sk_1+sk_2 \) modulo the order of the group.
This can be generalized to any homomorphic one-way function (OWF). Exponentiation in cyclic groups are examples of homomorphic OWFs but another notable example is RSA. Given a modulus \(N \) product of two safe primes and an exponent \(d\in Z_{\phi(\phi(N))} \), the RSA function \(f_{RSA} \) is the function that maps \(x \) to \(x^d\ mod\ N \). This function can be seen to be also homomorphic. Note that we do not claim that we can use this directly for OAEP or related RSA-based encryption schemes.
Additioanlly, we have a trapdoor: if a party has the factorization of the modulus, this party is able to invert the evaluation of the function \(PK=f_{RSA}(sk) \) before the prescribed time to get the corresponding secret key \(sk \). Observe that the variant with general secret sharing does not generalize to RSA and all homomorphic OWF.
How to guarantee that anyone can freely join without spamming the blockchain?
Depending on the resources of the nodes it might be possible only to verify proofs and accept the contribution of a small fraction of the total committee members, especially if huge number of parties want to contribute. For concreteness, it might be that the nodes have resources to work only on \(N \) committee members. In that case, the blockchain can do the following. There is a time \(d \) before which parties can submit their contribution. At time \(d \) one sees the random beacon published by LOE and this value is used to select (e.g., via a cryptographic hash function) a random subset of committee members of size \(N \) among all committee members who took part in the protocol. The unpredictability of the random beacon of LOE makes hard to cheat and allows fair choice of the committee members in the limit of the resources of the nodes.
From TLCS to timed signatures and timed proofs
Borrowing ideas from the celebrated Feige-Lapidot-Shamir technique, the Schnorr signature scheme can be modified so that the underlying sigma protocol on which it is based proves knowledge of a witness to the following \(NP \) statement: "I know a secret key corresponding to \(PK_{A} \) OR I know a secret key corresponding to \(PK \)", where \(PK_A \) is a known public key of a user Alice and \(PK \) is a TLCS public key \(PK \) for some time \(C \).
In this way a resulting signature is such that: a valid signature by Alice looks convincing to Bob before time \(C \) but if Bob transfers this signature to Peggy after time \(C \), such signature will not look convincing to Peggy since it might have been generated by anyone using the simulator algorithm of the sigma protocol using the secret key corresponding to \(PK \) (that may be assumed to be known by anyone after time \(C \)).
The same concept can be extended to general-purpose NIZK proofs that can be made to guarantee the following property: they are publicly verifiable until a given time \(C \) but after \(C \) they will be no longer transferable (that is, they will no longer look convincing to any receiver).
Correctness
Security
Curve implementations
Now our TLCs protocol support some popular elliptic curves, that are implemented in arkwrorks library:
BLS12-381 and embedded curves ark-bls12-381: Implements the BLS12-381 pairing-friendly curve ark-ed-on-bls12-381: Implements a Twisted Edwards curve atop the scalar field of BLS12-381 ark-ed-on-bls12-381-bandersnatch: Implements Bandersnatch, another Twisted Edwards curve atop the scalar field of BLS12-381 BLS12-377 and related curves ark-bls12-377: Implements the BLS12-377 pairing-friendly curve
ark-ed-on-bls12-377: Implements a Twisted Edwards curve atop the scalar field of BLS12-377
ark-bw6-761: Implements the BW6-761 pairing-friendly curve, which is a curve whose scalar field equals the base field of BLS12-377
ark-ed-on-bw6-761: Implements a Twisted Edwards curve atop the scalar field of BW6-761
ark-cp6-782: Implements the CP6-782 pairing-friendly curve, which is a curve whose scalar field equals the base field of BLS12-377
ark-ed-on-cp6-782: Implements a Twisted Edwards curve atop the scalar field of CP6-782. This is the same curve as in ark-ed-on-bw6-761
BN254 and related curves ark-bn254: Implements the BN254 pairing-friendly curve ark-ed-on-bn254: Implements a Twisted Edwards curve atop the scalar field of BN254 ark-grumpkin: Implements the Grumpkin curve. A curve that forms a cycle with bn254. MNT-298 cycle of curves and related curves ark-mnt4-298: Implements the MNT4-298 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT6-298 ark-mnt6-298: Implements the MNT6-298 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT4-298 ark-ed-on-mnt4-298: Implements a Twisted Edwards curve atop the scalar field of MNT4-298 MNT-753 cycle of curves and related curves ark-mnt4-753: Implements the MNT4-753 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT6-753 ark-mnt6-753: Implements the MNT6-753 pairing-friendly curve. This curve forms a pairing-friendly cycle with MNT4-753 ark-ed-on-mnt4-753: Implements a Twisted Edwards curve atop the scalar field of MNT4-753 Pasta cycle of curves ark-pallas: Implements Pallas, a prime-order curve that forms an amicable pair with Vesta ark-vesta: Implements Vesta, a prime-order curve that forms an amicable pair with Pallas
Implementation
An implementation in C/C++ of the efficient TLCS protocol described above is available here.
TLCS - C++
Overview
The repository provides implementation of the efficient TLCS protocol described in this note that builds on the LOE (a.k.a. drand ) service. The implementation is based on the mcl library and openssl.
The TLCS library allows to create public keys for virtually any elliptic curve supported by openssl and in addition the G1
group of the BLS12_381
curve and the babyjubjub curve.
To use the G1
group set -D_CYC_GRP_BLS_G1=1
in the Makefile
before installation or use the corresponding library. Observe that in this case you should be sure that cryptosystem is secure in that group. To use RSA set -D_CYC_GRP_RSA=1
or use the corresponding library.
Installation
git clone https://github.com/herumi/mcl.git
cd mcl
make all
cd ..
chmod u+x install.sh
./install.sh
APIs
The APIs can be divided in routines for:
- the prover contained in the file
src/prover.c
- for the verifier in
src/verifier.c
- for inversion of the public key in
src/invert.c
- aggregation of the participants' public keys in
src/aggregate.c
The prover, verifier and inversion have corresponding versions for the secret sharing variant.
News
- 20-May-2023 Added experimental support for the secret sharing variant.
- 16-May-2023 Added experimental support for babyjubjub ec.
- 14-May-2023 Added support for RSA.
- 07-May-2023 Launch!
Demo
The source code contains a file * examples/tlcs.c
implementing a demo simulation of a TLCS activity using the routines in the library.
The demo is supposed to simulate locally a TLCS protocol consisting of proving, verification, aggregation and inversion phases.
Example of usage of the demo
./bin/demo_prover proof
The previous command will simulate a party that creates his public key and proof and writes it to the file named proof
.
The demo will ask you for which type of curve you want to generate your public key and for a round number T
of LOE with respect to which you want that the protocol is executed.
The file is intented to simulate a blockchain activity so if you will re-execute the same command with same file, you will simulate another party who wrote to the blockchain.
Let us suppose we executed the command twice and in each execution we used the same file proof
, the same curve number (e.g., 714
) and we selected the same input T
.
Now, the file proof
contains the public keys and the proofs of two parties.
./bin/demo_verifier proof verificationresult
The previous command simulates a verifier that reads the fil proof
and writes an array of 0/1 results in the file verificationresult
. The i-th element of the array is 1
if the proof of the i-th party is verifid successfully and 0
otherwise.
So, in our example after the execution of the last command, the fil verificationresult
will contain the string 1 1
to indicate that both proofs of the two parties were successfully verified.
./bin/demo_aggregator proof aggregated_pk 1 1
The previous commands simulates the aggregation phase of the protocol. The aggregator reads the file proof
that in our example contains the output of two parties and uses the list 1 1
to know which party computed valid proof (in our example both parties computed valid proofs so the list is 1 1
) and outputs the aggregated public key in the file aggregated_pk
.
At time corresponding to round number T
, LOE publishes a signature for the round T
(the link where to get this signature was printed out after executing demo_prover
).
./bin/demo_invert proof aggregated_pk 1 1
The previous command simulates the inversion phase in which after time corresponding to round T
we aim at inverting the aggregated public key contained in the file aggregated_pk
. To this purpose we pass as input to the latter program the file proof
that contains the public keys of all parties who participated in the protocol and their respective proofs, the aggregate public key file aggregated_pk
and, in our example, the list of 0/1 values 1 1
to indicate that the file proof
contains two proofs that are both accepted.
The program will ask for you for the signature of LOE of round T
and should print out the secret key corresponding to the aggregated public key in the file aggregated_pk
.
How to use our TLCS system
See our How to Use page for examples on how to use our system to encrypt.
Contacts
Vincenzo Iovino (vincenzo@aragon.org)
Aragon ZK Research Team: https://research.aragon.org/
References
Vincenzo Iovino. How to Build a Time Lock Crypto Service based on League of Entropy, May 2023.
rust
Here you can find the TLCS in Rust. The repository provides implementation of the efficient TLCS protocol (in rust
), described in this note that builds on the LOE (a.k.a. drand ) service. In this implementation we used arkworks
which is a rust
ecosystem for zkSNARK programming.
Important Note:
- This section is still a work in progress and has not reached its completion.
- This portion of the code is experimental and not yet ready for usage in the main project.
- Some of the components in this repo have not yet passed the required tests.
- More information on the protocol and methods can be found here: azkr-timelock-zone and How to Build a Time Lock Crypto Service based on League of Entropy.
Goal:
The TLCS library allows to create public keys for any elliptic curve supported by arkwork
and in addition the G1
group of the BLS12_381
curve and the babyjubjub curve.
Timelock Encryption
Commitment
ZK with expiration time
e-voting
time document release
timelock.fs
timelock.fs
is an extension for the timelock.zone service that enables to encrypt to the future and decrypts any file using Windows Explorer.
See also tlcs-c, tlcs-rust, Timelock.zone.AndroidExample, timelock.public.disclosure and TLCS Usage.
Disclaimer: currently we used a very old version of bouncycastle
for simplicity and we did not care about enforcing more stringent level of security for ECIES
. This repo is only for testing timelock.zone
functionalities. You can easy adapt all code to any bouncycastle
version and different ECIES
variant.
Installation
Install from source
Add as dependencies bcprov-jdk15on-168.jar
, json-simple-1.1.jar
and timelock.zone.jar
.
Use Java
tools or any IDE to build from the source code a runnable Jar file named timelock.fs.jar
and stores it in the bin
folder or in any other folder: the only requirement is that the files install.bat
and uninstall.bat
must reside in the same folder as the runnable Jar you created.
Edit the file install.bat
with any editor (e.g. Notepad) and change the line:
setx YOUR_JAVA "C:\Program Files\Java\jdk-15.0.2"
to:
setx YOUR_JAVA "Path"
where Path
is a path to your Java Runtime Environment (JRE
) installation you used for the compilation.
You can download JREs from here. Usually Path
has the form C:\Program Files\Java\jdk-XX.Y.Z
. If your JRE
is installed correctly you should have a file javaw.exe
under the folder Path\bin
.
Once you edited the file install.bat
as described before, you can run install.bat
, grant admin permissions (needed to install the Windows extensions) and you are done.
Install without compilation
Download the file timelock.fs.zip
and unzip it. The so created folder timelock.fs
contains (among others) a file named install.bat
.
Download JDK 17 or higher if you do not have already JDK
/JRE
installed.
Run install.bat
, grant admin permissions (needed to install the Windows extensions) and you are done.
Installation issues
The Jar timelock.fs.jar
in the file timelock.fs.zip
has been compiled with Java Runtime Environment (JRE
) 17. If the installation does not work it is because you could have an older JRE
. In such case, download JRE
17 (see above) and set JAVA_HOME
environment variable to point to the new JRE
folder. Another reason of installation failure could be that JAVA_HOME
is not set at all, in such case set it to point to your JRE
folder.
Usage
Encrypt to the future
You can right click on any file, e.g. MyFile.pdf
, in Windows Explorer, select Show more options
(this may depend on your Windows version) and then click on timelock.fs.encrypt
.
You will be prompted to choose a date in the future in the format DD/MM/YYYY and an hour. Then you will just have to click on the Encrypt
button. It will be created a file MyFile.pdf.tlcs
that contains the encrypted version of the file MyFile.pdf
. You can now delete the original file MyFile.pdf
if you want to hide it until the chosen day.
Decrypt
The encrypted file is protected until the day before the chosen date.
When the chosen day and hour is reached you can right click on the file MyFile.pdf.tlcs
, select Show more options
(this may depend on your Windows version) and then click on timelock.fs.decrypt
. Your file will be decrypted and you will recover the file MyFile.pdf
.
Uninstall
To uninstall the timelock.fs
extensions, run uninstall.bat
(you must grant admin permissions) from the same folder where you launched install.bat
.