Conclave

Protect your data during processing with a confidential computing system based on Intel® SGX.

Securely share, protect and analyze data

What is Conclave?

Conclave enables you to process data with tamperproof computing resources. It exposes convenient abstractions to use secure computing enclaves like Intel® Software Guard Extensions (SGX). This lets you focus on your application while working in the language of your choice.

Visit Conclave Docs Get Conclave
What is Conclave
Conclave Protecting Data in Use

Developer friendly platform

Protecting data in use

Conclave makes application development with Intel® SGX easy!

doneBuild in Java, Kotlin, or JavaScript – new languages added regularly

doneAPI designs that easily guide you through SGX best practices

doneFull support for auditing enclaves over the internet

Explore Conclave

Take your next steps towards confidential computing with Conclave. Build secured Conclave apps with JVM-based high-level languages like Java and Kotlin, with more being added. Write three simple programs to create a Conclave app.

Build your Enclave

Write your enclaves to process confidential data. Enclaves load into protected memory space, stay assured your data can’t be seen or tempered.

Conclave Build Your Enclave
        
package com.r3.conclave.sample.auction.enclave;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.r3.conclave.enclave.Enclave;
import com.r3.conclave.enclave.EnclavePostOffice;
import com.r3.conclave.mail.EnclaveMail;
import com.r3.conclave.sample.auction.common.Message;
import com.r3.conclave.sample.auction.common.MessageSerializer;
import com.r3.conclave.shaded.kotlin.Pair;

import java.io.ByteArrayInputStream;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;

public class AuctionEnclave extends Enclave {

    private Map userRouteMap = new HashMap<>();
    private Map userBidsMap = new HashMap<>();
    private Kryo kryo = new Kryo();

    private Pair auctionAdmin = null;

    // Mails send from clients to the enclave are received here
    @Override
    protected void receiveMail(long id, EnclaveMail mail, String userRoute) {
        Message message = readMail(mail);
        PublicKey senderPK = mail.getAuthenticatedSender();
        if (message.getType().equals("BID")) {
            userBidsMap.put(senderPK, message.getBid());
            userRouteMap.put(senderPK, userRoute);
        } else if (message.getType().equals("PROCESS-BID")) {
            auctionAdmin = new Pair<>(userRoute, senderPK);
            processBids();
        }
    }

    // Process user bids. The highest bidder wins.
    private void processBids() {
        PublicKey winner = null;
        int maxBid = 0;
        for (PublicKey publicKey : userBidsMap.keySet()) {
            Integer bid = userBidsMap.get(publicKey);

            if (bid > maxBid) {
                maxBid = bid;
                winner = publicKey;
            }
        }

        sendAuctionResult(winner);
    }

    // Send auction result back to the client
    private void sendAuctionResult(PublicKey winner){

        for(PublicKey publicKey: userRouteMap.keySet()){
            if(publicKey.equals(winner)){
                sendMail(publicKey, userRouteMap.get(publicKey), "Congratulations! Your made the winning bid");
            }else{
                sendMail(publicKey, userRouteMap.get(publicKey), "Better Luck Next Time!");
            }
        }

        sendMail(auctionAdmin.getSecond(), auctionAdmin.getFirst(), "The winning bid is: " + userBidsMap.get(winner));

    }

    private void sendMail(PublicKey key, String routingHint, String message) {
        EnclavePostOffice postOffice = this.postOffice(key);
        byte[] result = postOffice.encryptMail(message.getBytes());
        postMail(result, routingHint);
    }


    private Message readMail(EnclaveMail mail) {
        kryo.register(Message.class, new MessageSerializer());
        Input input = new Input(new ByteArrayInputStream(mail.getBodyAsBytes()));
        return kryo.readObject(input, Message.class);
    }

}
        
    

Build your host

Build your host to send and receive encrypted data between the client and the enclave.

Conclave Build Your Host
        
package com.r3.conclave.sample.auction.host;

import com.r3.conclave.common.EnclaveInstanceInfo;
import com.r3.conclave.host.AttestationParameters;
import com.r3.conclave.host.EnclaveHost;
import com.r3.conclave.host.EnclaveLoadException;
import com.r3.conclave.host.MailCommand;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;

public class AuctionHost {

    private static final String ENCLAVE_CLASS_NAME =
            "com.r3.conclave.sample.auction.enclave.AuctionEnclave";
    private EnclaveHost enclaveHost;
    private Map clientMap = new HashMap<>();

    public static void main(String[] args) throws EnclaveLoadException, IOException {
        AuctionHost host = new AuctionHost();
        host.verifyPlatformSupport();
        host.initializeEnclave();
        host.startServer();
    }

    private void startServer() throws IOException{
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(5051);
        }catch (IOException ioe){
            ioe.printStackTrace();
            throw ioe;
        }
        System.out.println("Listening on port 5051");
        while (true) {
            Socket clientSocket = null;
            try {
                assert serverSocket != null;
                clientSocket = serverSocket.accept();

                String routingHint = UUID.randomUUID().toString();
                clientMap.put(routingHint, clientSocket);

                final EnclaveInstanceInfo attestation = enclaveHost.getEnclaveInstanceInfo();
                final byte[] attestationBytes = attestation.serialize();
                sendMessageToClient(routingHint, attestationBytes);
                recieveMailFromClientAndDeliverToEnclave(clientSocket, routingHint);
            } catch (IOException e) {
                System.out.println("I/O error: " + e);
                throw e;
            }
        }
    }

    private void sendMessageToClient(String routingHint, byte[] content){
        try {
            Socket clientSocket = clientMap.get(routingHint);
            DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
            outputStream.writeInt(content.length);
            outputStream.write(content);
            outputStream.flush();
        }catch (IOException ioe){
            ioe.printStackTrace();
        }
    }


    private void recieveMailFromClientAndDeliverToEnclave(Socket clientSocket, String routingHint){
        try {
            DataInputStream input = new DataInputStream(clientSocket.getInputStream());
            byte[] mailBytes = new byte[input.readInt()];
            input.readFully(mailBytes);

            enclaveHost.deliverMail(1, mailBytes, routingHint);
        }catch (IOException ioException){
            ioException.printStackTrace();
        }
    }

    private  void verifyPlatformSupport(){
        try {
            EnclaveHost.checkPlatformSupportsEnclaves(true);
            System.out.println("This platform supports enclaves in simulation, debug and release mode.");
        } catch (EnclaveLoadException e) {
            System.out.println("This platform does not support hardware enclaves: " + e.getMessage());
        }
    }

    private void initializeEnclave() throws EnclaveLoadException{
        enclaveHost = EnclaveHost.load(ENCLAVE_CLASS_NAME);
        enclaveHost.start(
            new AttestationParameters.DCAP(), mailCommands -> {
                    for (MailCommand command : mailCommands) {
                        if (command instanceof MailCommand.PostMail) {
                            String routingHint = ((MailCommand.PostMail) command).getRoutingHint();
                            byte[] content = ((MailCommand.PostMail) command).getEncryptedBytes();
                            sendMessageToClient(routingHint, content);
                        }
                    }
                }
        );
    }

}
        
    

Build your client

Build the client to talk to the enclave via the host. All data sent to the host is encrypted using private key.

Conclave Build Your Client
        
package com.r3.conclave.sample.auction.client;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Output;
import com.r3.conclave.client.EnclaveConstraint;
import com.r3.conclave.common.EnclaveInstanceInfo;
import com.r3.conclave.mail.Curve25519PrivateKey;
import com.r3.conclave.mail.EnclaveMail;
import com.r3.conclave.mail.PostOffice;
import com.r3.conclave.sample.auction.common.Message;
import com.r3.conclave.sample.auction.common.MessageSerializer;
import com.r3.conclave.shaded.kotlin.Pair;

import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.security.PrivateKey;
import java.util.UUID;

public class AuctionClient {

    // Kryo library used for serialization
    private static Kryo kryo;

    public static void main(String[] args) throws Exception{
        kryo = new Kryo();
        String messageType = args[0];
        String constraint = args[1];

        // Establish a TCP connection with the host
        Pair streams = establishConnection();
        DataInputStream fromHost = streams.getFirst();
        DataOutputStream toHost = streams.getSecond();

        // Verify attestation before sending sensitive data to the enclave
        EnclaveInstanceInfo attestation = verifyAttestatiom(fromHost, constraint);

        // Get bid from the user
        int bid = getUserBidInput(args);

        // Serialize, encrypt and send the bid data to the enclave for processing.
        Output serializedOutput = serializeMessage(messageType, bid);
        PrivateKey myKey = Curve25519PrivateKey.random();
        PostOffice postOffice = attestation.createPostOffice(myKey, UUID.randomUUID().toString());
        byte[] encryptedMail = postOffice.encryptMail(serializedOutput.getBuffer());

        System.out.println("Sending the encrypted mail to the host.");
        toHost.writeInt(encryptedMail.length);
        toHost.write(encryptedMail);

        // Receive Enclave's reply
        byte[] encryptedReply = new byte[fromHost.readInt()];
        System.out.println("Reading reply mail of length " + encryptedReply.length + " bytes.");
        fromHost.readFully(encryptedReply);
        EnclaveMail reply = postOffice.decryptMail(encryptedReply);
        System.out.println("Enclave gave us the answer '" + new String(reply.getBodyAsBytes()) + "'");

        toHost.close();
        fromHost.close();
    }

    private static Output serializeMessage(String messageType, int bid){
        Message message = new Message(messageType, bid);
        Output output = new Output(new ByteArrayOutputStream());
        kryo.register(Message.class, new MessageSerializer());
        kryo.writeObject(output, message);
        output.close();
        return output;
    }

    private static int getUserBidInput(String args[]) throws Exception{
        if(args.length > 0 && args[0].equals("BID")) {
            System.out.println("Please enter your Bid Amount");
            System.out.println();
            System.out.println("---------------------------");
            System.out.println("Bid Amount: ");
            BufferedReader reader =
                    new BufferedReader(new InputStreamReader(System.in));
            String bidAmount = reader.readLine();
            return Integer.parseInt(bidAmount);
        }
        return 0;
    }

    private static Pair establishConnection() throws Exception{
        DataInputStream fromHost;
        DataOutputStream toHost;
        while (true) {
            try {
                System.out.println("Attempting to connect to Host at localhost:5051");
                Socket socket = new Socket();
                socket.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), 5051), 10000);
                fromHost = new DataInputStream(socket.getInputStream());
                toHost = new DataOutputStream(socket.getOutputStream());
                break;
            } catch (Exception e) {
                System.err.println("Retrying: " + e.getMessage());
                Thread.sleep(2000);
            }
        }
        return new Pair<>(fromHost, toHost);
    }

    private static EnclaveInstanceInfo verifyAttestatiom(DataInputStream fromHost, String constraint) throws Exception{
        byte[] attestationBytes = new byte[fromHost.readInt()];
        fromHost.readFully(attestationBytes);
        EnclaveInstanceInfo attestation = EnclaveInstanceInfo.deserialize(attestationBytes);

        System.out.println("Attestation Info received:  " + attestation);

        EnclaveConstraint.parse("C:"+ constraint +" SEC:INSECURE").check(attestation);

        return attestation;
    }
}
        
    

Conclave developer highlights

Latest blog posts

Conclave • November 10, 2021 • By: Iryna Tsimashenka

How to write your first Conclave app

Confidential Computing is an emerging area for protecting sensitive data while processing it simultaneously. It consists of hardware and software components. The hardware comp...

Read blog post

Conclave • October 4, 2021 • By: Sneha Damle

What has been cooking in Conclave?

Conclave is a very effective framework, primarily focusing on protecting data in use. For those who haven’t heard about it yet, let’s review the key concept.

Read blog post

Upcoming event

There are no upcoming events at this time. Check back soon.

Featured video

Subscribe now to be the first to learn about the latest developer news, tools, and community highlights.