In this tutorial, you will learn how to leverage an application developer secret by using the IEXEC_APP_DEVELOPER_SECRET environment variable in your application code.
Familiarity with the basic concepts of Intel® SGX and SCONE framework.
Trusted Execution Environments offer a huge advantage from a security perspective. They guarantee that the behavior of execution does not change even when launched on an untrusted remote machine. The data inside this type of environment is also protected, which allows its monetization while preventing leakage.
With iExec, it is possible to securely associate an application developer secret to the runtime of an application. This association is performed through the usage of environment variables which cannot leak outside of the enclave memory.
The app developer secret is only exposed to your app inside authorized enclaves and never leaves them.
Your secrets are transferred with the SDK from your machine to the SMS over a TLS channel.
Let's see how to do all of that!
Prepare your application
For demo purposes, we omitted some development best practices in these examples.
Make sure to check your field's best practices before going to production.
Let's develop an application designed to evaluate the function: f(x)=ax3+bx2+cx+d
where the coefficients a, b, c and d are kept confidential using an application secret, and the input x is given as argument of the app.
Let's create a directory tree for this app in ~/iexec-projects/.
constfsPromises=require("fs").promises;(async () => {try {constiexecOut=process.env.IEXEC_OUT;// get the secret endpoint from app developer secretconstsecret=process.env.IEXEC_APP_DEVELOPER_SECRET;let a =1, b =1, c =1, d =1; // Default valuesif (!secret) {console.log("missing IEXEC_APP_DEVELOPER_SECRET"); } else {// Split the secret into coefficientslet coefficients =secret.split(";");if (coefficients.length!==4) {console.log("problem length IEXEC_APP_DEVELOPER_SECRET"); } else { [a, b, c, d] =coefficients.map(parseFloat); } }// Function to compute f(x)functioncubicPolynomial(x) {return a *Math.pow(x,3) + b *Math.pow(x,2) + c * x + d; }// Get the value of x from command-line argumentslet x;if (process.argv.length!==3) {console.log( "Usage: exactly one argument required for this dapp: x ; to compute f(x)=a.x^3 + b.x^2 + c.x + d , x=1 by default"
); x =1; } else { x =parseFloat(process.argv[2]); }// Compute f(x)let result =cubicPolynomial(x);// Create result objectconstresultObj= { x: x, result: result, };// Convert result object to JSON stringconstresultJson=JSON.stringify(resultObj);// Write result to fileawaitfsPromises.writeFile(`${iexecOut}/result.txt`, resultJson);// Declare everything is computedconstcomputedJsonObj= {"deterministic-output-path":`${iexecOut}/result.txt`, };awaitfsPromises.writeFile(`${iexecOut}/computed.json`,JSON.stringify(computedJsonObj) ); } catch (e) {// do not log anything that could reveal the app developer secret!console.log(e);process.exit(1); }})();
src/app.py
import osimport sysimport jsontry: iexec_out = os.environ["IEXEC_OUT"]# Get the secret endpoint from the app developer secrettry: secret = os.environ["IEXEC_APP_DEVELOPER_SECRET"]# Split the secret into coefficients coefficients = secret.split(";")iflen(coefficients)!=4:raiseValueError("Incorrect number of coefficients provided") a, b, c, d =map(float, coefficients)exceptKeyError:print("Missing IEXEC_APP_DEVELOPER_SECRET")exit(1)exceptValueErroras e:print("Invalid coefficients:", e)exit(1)# Function to compute f(x)defcubic_polynomial(x):return a * x**3+ b * x**2+ c * x + d# Get the x value from command-line argumentsiflen(sys.argv)!=2: result="Usage: exactly one argument required for this dapp: x ; to compute f(x)=a.x^3 + b.x^2 + c.x + d , x=1 by default"
print(result) _x=1else: _x=sys.argv[1] x =float(_x)# Compute f(x) result =cubic_polynomial(x)# Write the result to a JSON filewithopen(iexec_out +"/result.json", "w+")as f: json.dump({"x= ": x, ";f(x)=": result}, f) f.close()# Declare computation completewithopen(iexec_out +"/computed.json", "w+")as f: json.dump({"deterministic-output-path": iexec_out +"/result.json"}, f) f.close()exceptExceptionas e:print("Something went wrong:", e)exit(1)
As seen above, a single slot is dedicated to store the application developer secret. If you want to use multiple secrets, feel free to pack your secrets into a single one and unpack them when reading the IEXEC_APP_DEVELOPER_SECRET environment variable from the application code.
# Starting from a base image supported by SCONEFROMnode:14-alpine3.11# install your dependenciesRUNmkdir/app&&cd/appCOPY./src/appENTRYPOINT [ "node","/app/app.js"]
For a Python application:
FROMpython:3.7.3-alpine3.10### install python dependencies if you have someCOPY./src/appENTRYPOINT ["python3", "/app/app.py"]
Update the sconify.sh script with the variables as follow:
# Declare image related variablesIMG_NAME=tee-scone-secret-functionIMG_FROM=<docker-hub-user>/secret-function:1.0.0IMG_TO=<docker-hub-user>/${IMG_NAME}:1.0.0-debug
Run the sconify.sh script to build the Scone TEE application: