diff --git a/cmd/tle/commands/commands.go b/cmd/tle/commands/commands.go index 8b77529..ec9af5a 100644 --- a/cmd/tle/commands/commands.go +++ b/cmd/tle/commands/commands.go @@ -7,7 +7,6 @@ import ( "fmt" "log" "os" - "github.com/kelseyhightower/envconfig" ) @@ -23,18 +22,23 @@ const usage = `tlock v1.0.0 -- github.com/drand/tlock Usage: tle [--encrypt] (-r round)... [--armor] [-o OUTPUT] [INPUT] +If input is a string (not a file) + tle [--encrypt] (-r round)... [--armor] [-o OUTPUT] [--input "INPUT string"] + 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. + -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. + -t, --time Exact time (UTC) when the message can be decrypted + -o, --output Write the result to the file at path OUTPUT. + -a, --armor Encrypt to a PEM encoded format. + -I, --input Encrypt the input string to the output If the OUTPUT exists, it will be overwritten. @@ -72,8 +76,10 @@ type Flags struct { Network string Chain string Round uint64 + Time string Duration string Output string + RawInput string Armor bool } @@ -124,9 +130,15 @@ func parseCmdline(f *Flags) { flag.StringVar(&f.Duration, "D", f.Duration, "how long to wait before being able to decrypt") flag.StringVar(&f.Duration, "duration", f.Duration, "how long to wait before being able to decrypt") + flag.StringVar(&f.Time, "T", f.Time, "a UTC time value in RFC3339 format") + flag.StringVar(&f.Time, "time", f.Time, "a UTC time value in RFC3339 format") + flag.StringVar(&f.Output, "o", f.Output, "the path to the output file") flag.StringVar(&f.Output, "output", f.Output, "the path to the output file") + flag.StringVar(&f.RawInput, "I", f.RawInput, "raw input to be encrypted") + flag.StringVar(&f.RawInput, "input", f.RawInput, "raw input to be encrypted") + flag.BoolVar(&f.Armor, "a", f.Armor, "encrypt to a PEM encoded format") flag.BoolVar(&f.Armor, "armor", f.Armor, "encrypt to a PEM encoded format") @@ -143,6 +155,9 @@ func validateFlags(f *Flags) error { if f.Duration != "" { return fmt.Errorf("-D/--duration can't be used with -d/--decrypt") } + if f.Time != "" { + return fmt.Errorf("-T/--time can't be used with -d/--decrypt") + } if f.Round != 0 { return fmt.Errorf("-r/--round can't be used with -d/--decrypt") } @@ -161,11 +176,24 @@ func validateFlags(f *Flags) error { if f.Chain == "" { return fmt.Errorf("-c/--chain can't be empty") } + if f.Duration == "" && f.Round == 0 && f.Time == "" { + return fmt.Errorf("one of -D/--duration, -r/--round or -T/--time must be specified") + } if f.Duration != "" && f.Round != 0 { return fmt.Errorf("-D/--duration can't be used with -r/--round") } - if f.Duration == "" && f.Round == 0 { - return fmt.Errorf("-D/--duration or -r/--round must be specified") + if f.Duration != "" && f.Time != "" { + return fmt.Errorf("-D/--duration can't be used with -T/--time") + } + if f.Time != "" && f.Round != 0 { + return fmt.Errorf("-T/--time can't be used with -r/--round") + } + if f.Time != "" { + duration, err := timestampToDuration(f.Time) + if err != nil { + return err + } + f.Duration = duration } } diff --git a/cmd/tle/commands/encrypt.go b/cmd/tle/commands/encrypt.go index d19ceb4..1fa618d 100644 --- a/cmd/tle/commands/encrypt.go +++ b/cmd/tle/commands/encrypt.go @@ -120,3 +120,15 @@ func durationFrom(start time.Time, value int, duration rune) time.Duration { } return 0 } + +func timestampToDuration(timestamp string) (string, error) { + t, err := time.Parse(time.RFC3339, timestamp) + if err != nil { + return "", fmt.Errorf("time format must be RFC3339 (\"2006-01-02T15:04:05Z07:00\")") + } + duration := time.Until(t) + if duration <= 0 { + return "", fmt.Errorf("must specify a future time") + } + return fmt.Sprintf("%ds", uint64(duration.Seconds())), nil +} diff --git a/cmd/tle/commands/flags_test.go b/cmd/tle/commands/flags_test.go index 01926ae..e31c36e 100644 --- a/cmd/tle/commands/flags_test.go +++ b/cmd/tle/commands/flags_test.go @@ -46,6 +46,78 @@ func Test(t *testing.T) { }, shouldError: true, }, + { + name: "parsing encrypt with duration, round as well as timestamp fails", + flags: []KV{ + { + key: "TLE_ENCRYPT", + value: "true", + }, + { + key: "TLE_DURATION", + value: "1d", + }, + { + key: "TLE_ROUND", + value: "1", + }, + { + key: "TLE_TIME", + value: "2999-04-23T08:15:05Z", + }, + }, + shouldError: true, + }, + { + name: "parsing encrypt with both round and timestamp fails", + flags: []KV{ + { + key: "TLE_ENCRYPT", + value: "true", + }, + { + key: "TLE_ROUND", + value: "1", + }, + { + key: "TLE_TIME", + value: "2999-04-23T08:15:05Z", + }, + }, + shouldError: true, + }, + { + name: "parsing encrypt with both duration and timestamp fails", + flags: []KV{ + { + key: "TLE_ENCRYPT", + value: "true", + }, + { + key: "TLE_DURATION", + value: "1d", + }, + { + key: "TLE_TIME", + value: "2999-04-23T08:15:05Z", + }, + }, + shouldError: true, + }, + { + name: "parsing encrypt with timestamp passes", + flags: []KV{ + { + key: "TLE_ENCRYPT", + value: "true", + }, + { + key: "TLE_TIME", + value: "2999-04-23T08:15:05Z", + }, + }, + shouldError: false, + }, { name: "parsing encrypt with round passes", flags: []KV{ diff --git a/cmd/tle/tle.go b/cmd/tle/tle.go index 79cfd86..f06d40b 100644 --- a/cmd/tle/tle.go +++ b/cmd/tle/tle.go @@ -7,6 +7,7 @@ import ( "io" "log" "os" + "strings" "github.com/drand/tlock" "github.com/drand/tlock/cmd/tle/commands" @@ -42,15 +43,19 @@ func run() error { } var src io.Reader = os.Stdin - if name := flag.Arg(0); name != "" && name != "-" { - f, err := os.OpenFile(name, os.O_RDONLY, 0600) - if err != nil { - return fmt.Errorf("failed to open input file %q: %v", name, err) + if rawInput := flags.RawInput; rawInput != "" && rawInput != "-" { + src = strings.NewReader(rawInput) + } else { + if name := flag.Arg(0); name != "" && name != "-" { + f, err := os.OpenFile(name, os.O_RDONLY, 0600) + if err != nil { + return fmt.Errorf("failed to open input file %q: %v", name, err) + } + defer func(f *os.File) { + err = f.Close() + }(f) + src = f } - defer func(f *os.File) { - err = f.Close() - }(f) - src = f } var dst io.Writer = os.Stdout diff --git a/go.mod b/go.mod index 6c89c81..6bc0b7d 100644 --- a/go.mod +++ b/go.mod @@ -10,37 +10,38 @@ require ( github.com/stretchr/testify v1.8.2 ) -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) - require ( github.com/BurntSushi/toml v1.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/kelseyhightower/envconfig v1.4.0 github.com/kilic/bls12-381 v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/nikkolasg/hexjson v0.1.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.14.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.10.0 // indirect + go.uber.org/goleak v1.1.12 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/crypto v0.7.0 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/sys v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect - google.golang.org/genproto v0.0.0-20230320184635-7606e756e683 // indirect google.golang.org/grpc v1.53.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +require ( + github.com/golang/protobuf v1.5.3 // indirect + github.com/kelseyhightower/envconfig v1.4.0 + github.com/prometheus/common v0.42.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + google.golang.org/genproto v0.0.0-20230320184635-7606e756e683 // indirect google.golang.org/protobuf v1.30.0 // indirect ) diff --git a/go.sum b/go.sum index d7aa107..ce6f832 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,11 @@ github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dv github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4= github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= @@ -80,6 +83,7 @@ github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= @@ -88,27 +92,54 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/weaveworks/common v0.0.0-20230208133027-16871410fca4 h1:8eoXaryYVOWJZCnCzULYXtxiHHLrJpvoD7p283ogmo8= github.com/weaveworks/promrus v1.2.0 h1:jOLf6pe6/vss4qGHjXmGz4oDJQA+AOCqEL3FvvZGz7M= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= go.dedis.ch/protobuf v1.0.11 h1:FTYVIEzY/bfl37lu3pR4lIj+F9Vp1jE8oh91VmxKgLo= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20230320184635-7606e756e683 h1:khxVcsk/FhnzxMKOyD+TDGwjbEOpcPuIpmafPGFmhMA= google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= @@ -118,6 +149,7 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/tlock_test.go b/tlock_test.go index 6734bbc..52e571a 100644 --- a/tlock_test.go +++ b/tlock_test.go @@ -92,6 +92,52 @@ func TestEarlyDecryptionWithRound(t *testing.T) { require.ErrorIs(t, err, tlock.ErrTooEarly) } +func TestEncryptionWithTimestamp(t *testing.T) { + if testing.Short() { + t.Skip("skipping live testing in short mode") + } + + network, err := http.NewNetwork(testnetHost, testnetChainHash) + require.NoError(t, err) + + // ========================================================================= + // Encrypt + + // Read the plaintext data to be encrypted. + in, err := os.Open("test_artifacts/data.txt") + require.NoError(t, err) + defer in.Close() + + // Write the encoded information to this buffer. + var cipherData bytes.Buffer + + // Timestamp to duration + timestamp := time.Now().Add(4 * time.Second).Format(time.RFC3339) + tstamp, err := time.Parse(time.RFC3339, timestamp) + require.NoError(t, err) + duration := time.Until(tstamp) + + // Encryption with duration + roundNumber := network.RoundNumber(time.Now().Add(duration)) + err = tlock.New(network).Encrypt(&cipherData, in, roundNumber) + require.NoError(t, err) + + // ========================================================================= + // Decrypt + + time.Sleep(5 * time.Second) + + // Write the decoded information to this buffer. + var plainData bytes.Buffer + + err = tlock.New(network).Decrypt(&plainData, &cipherData) + require.NoError(t, err) + + if !bytes.Equal(plainData.Bytes(), dataFile) { + t.Fatalf("decrypted file is invalid; expected %d; got %d", len(dataFile), len(plainData.Bytes())) + } +} + func TestEncryptionWithDuration(t *testing.T) { if testing.Short() { t.Skip("skipping live testing in short mode")