diff --git a/README.md b/README.md index 1e9d7ed..ac74546 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,8 @@ Now you're ready to build applications with EGo! To start, check out the followi * [remote_attestation](samples/remote_attestation) shows how to use the basic remote attestation API of EGo. * [attested_tls](samples/attested_tls) is similar to the above, but uses a higher level API to establish an attested TLS connection. * [vault](samples/vault) demonstrates how to port a Go application exemplified by Hashicorp Vault. -* [wasmer](samples/wasmer) shows how to run WebAssembly inside EGo using Wasmer. +* [estore](samples/estore) shows how to securely persist data using [EStore](https://github.com/edgelesssys/estore). +* [wasmer](samples/wasmer) and [wasmtime](samples/wasmtime) show how to run WebAssembly inside EGo. * [embedded_file](samples/embedded_file) shows how to embed files into an EGo enclave. * [reproducible_build](samples/reproducible_build) builds the helloworld sample reproducibly, resulting in the same UniqueID. * [cgo](samples/cgo) demonstrates the experimental cgo support. @@ -108,6 +109,12 @@ Now you're ready to build applications with EGo! To start, check out the followi * The [EGo documentation](https://docs.edgeless.systems/ego) covers building, signing, running, and debugging confidential apps. * The [EGo API](https://pkg.go.dev/github.com/edgelesssys/ego) provides access to *remote attestation* and *sealing* to your confidential app at runtime. +## Beyond EGo + +* Use [MarbleRun](https://github.com/edgelesssys/marblerun) to create distributed EGo applications and run them on Kubernetes. +* Use [EStore](https://github.com/edgelesssys/estore) to securely persist your application's data. +* Not only using Go? Check out [Contrast](https://github.com/edgelesssys/contrast) to run your confidential containers on Kubernetes. + ## Community & help * Got a question? Please get in touch via [Discord][discord] or file an [issue](https://github.com/edgelesssys/ego/issues). diff --git a/docs/docs/getting-started/examples.md b/docs/docs/getting-started/examples.md index 5eed412..a556697 100644 --- a/docs/docs/getting-started/examples.md +++ b/docs/docs/getting-started/examples.md @@ -18,9 +18,14 @@ Similar to the above, but the server manages remote attestation by itself. This Vault is a common way to store secrets and share them on dynamic infrastructures. With EGo, you can build a confidential version of unmodified Vault. -## [WebAssembly with Wasmer](https://github.com/edgelesssys/ego/tree/master/samples/wasmer) +## [Secure storage with EStore](https://github.com/edgelesssys/ego/tree/master/samples/estore) -You can run WebAssembly inside EGo using Wasmer. +You should use strong encryption for your application's data at rest. +Using EStore with EGo makes this easy. + +## WebAssembly with [Wasmer](https://github.com/edgelesssys/ego/tree/master/samples/wasmer) or [Wasmtime](https://github.com/edgelesssys/ego/tree/master/samples/wasmtime) + +You can run WebAssembly inside EGo. ## [Microsoft Azure Attestation (MAA)](https://github.com/edgelesssys/ego/tree/master/samples/azure_attestation) diff --git a/docs/docs/knowledge/storage.md b/docs/docs/knowledge/storage.md new file mode 100644 index 0000000..41e5a5e --- /dev/null +++ b/docs/docs/knowledge/storage.md @@ -0,0 +1,23 @@ +# Secure storage + +EGo provides several ways to store data securely, which are described in the following sections. + +## In-enclave-memory filesystem + +By default, when an EGo app writes a file, it's stored in the enclave's memory. +This is secure, but the data is lost when the enclave is terminated. + +For persistence, you can [mount a host directory](../reference/config.md#mounts) into the enclave. +You should encrypt the data before writing it to the untrusted host filesystem. +You can use one of the following methods for this. + +## Sealing + +Sealing is the process of encrypting data with a key derived from the enclave and the CPU it's running on. +Use the [EGo API](https://pkg.go.dev/github.com/edgelesssys/ego/ecrypto) to seal and unseal data. + +## EStore + +[EStore](https://github.com/edgelesssys/estore) is a key-value store with authenticated encryption for data at rest. +It's particularly well suited for use inside an enclave. +Check out the [EStore sample](https://github.com/edgelesssys/ego/tree/master/samples/estore) for a demonstration. diff --git a/docs/sidebars.js b/docs/sidebars.js index 1df7891..fecc0c8 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -83,6 +83,11 @@ const sidebars = { label: 'Limitations', id: 'knowledge/limitations', }, + { + type: 'doc', + label: 'Secure storage', + id: 'knowledge/storage', + }, { type: 'doc', label: 'TLS inside the enclave', diff --git a/docs/styles/config/vocabularies/edgeless/accept.txt b/docs/styles/config/vocabularies/edgeless/accept.txt index 6d9e432..d0b9568 100644 --- a/docs/styles/config/vocabularies/edgeless/accept.txt +++ b/docs/styles/config/vocabularies/edgeless/accept.txt @@ -5,6 +5,7 @@ cloud collateral dereference env +EStore MarbleRun OCALL SignerID @@ -12,3 +13,4 @@ uncomment UniqueID untrusted Wasmer +Wasmtime diff --git a/samples/estore/README.md b/samples/estore/README.md new file mode 100644 index 0000000..12a6b5a --- /dev/null +++ b/samples/estore/README.md @@ -0,0 +1,34 @@ +# EStore sample + +This sample shows how to use [EStore](https://github.com/edgelesssys/estore) with EGo. +EStore is a key-value store with authenticated encryption for data at rest. +It's particularly well suited for use inside an enclave. + +The sample uses SGX sealing to securely store the encryption key of the database. +Alternatively, you can use [MarbleRun](https://github.com/edgelesssys/marblerun) to manage the key. + +You can build and run the sample as follows: + +```bash +ego-go build +ego sign estore-sample +ego run estore-sample +``` + +You should see an output similar to: + +```shell-session +$ ego run estore-sample +[erthost] loading enclave ... +[erthost] entering enclave ... +[ego] starting application ... +Creating new DB +hello=world + +$ ego run estore-sample +[erthost] loading enclave ... +[erthost] entering enclave ... +[ego] starting application ... +Found existing DB +hello=world +``` diff --git a/samples/estore/enclave.json b/samples/estore/enclave.json new file mode 100644 index 0000000..08e9871 --- /dev/null +++ b/samples/estore/enclave.json @@ -0,0 +1,15 @@ +{ + "exe": "estore-sample", + "key": "private.pem", + "debug": true, + "heapSize": 512, + "productID": 1, + "securityVersion": 1, + "mounts": [ + { + "source": "db", + "target": "/db", + "type": "hostfs" + } + ] +} diff --git a/samples/estore/go.mod b/samples/estore/go.mod new file mode 100644 index 0000000..05c3d35 --- /dev/null +++ b/samples/estore/go.mod @@ -0,0 +1,34 @@ +module estore-sample + +go 1.21 + +require ( + github.com/edgelesssys/ego v1.5.3 + github.com/edgelesssys/estore v1.1.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cockroachdb/errors v1.11.3 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/redact v1.1.5 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/getsentry/sentry-go v0.28.1 // indirect + github.com/go-jose/go-jose/v4 v4.0.2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.54.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect +) diff --git a/samples/estore/go.sum b/samples/estore/go.sum new file mode 100644 index 0000000..045f4e8 --- /dev/null +++ b/samples/estore/go.sum @@ -0,0 +1,100 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= +github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/edgelesssys/ego v1.5.3 h1:Ec8lAjGQnKT9s+4U4o+AdSp2tYH5JN99cJMnNAfMEuU= +github.com/edgelesssys/ego v1.5.3/go.mod h1:xpgzdPWmxBGeF/d6X3Nk78hSjUfW6f05X28/jkXLRzE= +github.com/edgelesssys/estore v1.1.0 h1:dx4StUlOKds7nChMcX5/IYPr6vxWb2Lg3UPErm2BAcc= +github.com/edgelesssys/estore v1.1.0/go.mod h1:6VwPBea8aA5NsHdNfe+6U7vqDgFHANVhsfk4WZq5kWI= +github.com/getsentry/sentry-go v0.28.1 h1:zzaSm/vHmGllRM6Tpx1492r0YDzauArdBfkJRtY6P5k= +github.com/getsentry/sentry-go v0.28.1/go.mod h1:1fQZ+7l7eeJ3wYi82q5Hg8GqAPgefRq+FP/QhafYVgg= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= +github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8= +github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +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.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +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-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +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/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/samples/estore/main.go b/samples/estore/main.go new file mode 100644 index 0000000..b4379e8 --- /dev/null +++ b/samples/estore/main.go @@ -0,0 +1,88 @@ +package main + +import ( + "crypto/rand" + "errors" + "fmt" + "log" + "os" + + "github.com/edgelesssys/ego/ecrypto" + "github.com/edgelesssys/estore" +) + +const keyFile = "/db/sealed_key" + +func main() { + // Open existing DB or create a new one + var db *estore.DB + sealedKey, err := os.ReadFile(keyFile) + if err == nil { + fmt.Println("Found existing DB") + db, err = openExistingDB(sealedKey) + } else if errors.Is(err, os.ErrNotExist) { + fmt.Println("Creating new DB") + db, err = createNewDB() + } + + if err != nil { + log.Fatal(err) + } + defer db.Close() + + // Get the value of the key + value, closer, err := db.Get([]byte("hello")) + if err != nil { + log.Fatal(err) + } + defer closer.Close() + fmt.Printf("hello=%s\n", value) +} + +func createNewDB() (*estore.DB, error) { + // Generate an encryption key + encryptionKey := make([]byte, 16) + _, err := rand.Read(encryptionKey) + if err != nil { + return nil, err + } + + // Seal the encryption key + sealedKey, err := ecrypto.SealWithUniqueKey(encryptionKey, nil) + if err != nil { + return nil, err + } + if err := os.Mkdir("/db", 0o700); err != nil { + return nil, err + } + if err := os.WriteFile(keyFile, sealedKey, 0o600); err != nil { + return nil, err + } + + // Create an encrypted store + opts := &estore.Options{ + EncryptionKey: encryptionKey, + } + db, err := estore.Open("/db", opts) + if err != nil { + return nil, err + } + + // Set a key-value pair + if err := db.Set([]byte("hello"), []byte("world"), nil); err != nil { + return nil, err + } + + return db, nil +} + +func openExistingDB(sealedKey []byte) (*estore.DB, error) { + encryptionKey, err := ecrypto.Unseal(sealedKey, nil) + if err != nil { + return nil, err + } + opts := &estore.Options{ + EncryptionKey: encryptionKey, + } + return estore.Open("/db", opts) +}