开发TEE的踩坑之开发TEE

news2024/9/9 6:53:17

系统:Ubuntu20.04(双系统,非虚拟机)

  • 一、前置说明
    • 1、TEE平台的选择
    • 2、机器间的通信方式
    • 3、程序和数据集的示例
    • 4、结果文件的解密
  • 二、服务器部署
  • 三、客户端部署
  • 四、工程应用

本系列为笔者开发TEE(Trusted Execution Environment,可信执行环境)的系列踩坑文,给广大开发者分享自己所谓的“经验”,希望对大家有帮助。

开发路线为:

  1. 装Ubuntu20.04的双系统(不展开,B站有很多教程)
  2. 配置SGX环境(前提是SGX机器,最好是SGX2)
  3. 配置PCCS(很蛋疼,英特尔官方github的步骤也未必行得通)
  4. 开发TEE(花的时间最多)

本篇文章分享开发TEE的踩坑
笔者是在某蚁集团的Occlum的基础上,结合ChatGPT给出的回答去解决途中遇到的问题的

一、前置说明

1、TEE平台的选择

TEE平台有众多选择,在此之前,笔者已在某语的TrustedFlow踩过无数坑了。但奈何若要使用他们的平台开发TEE,需要有可以支持SGX_2的CPU,否则一切都是徒劳,只能用仿真模式,这无异于把程序放在裸机上跑,已与TEE毫无相关;还有一个致命之处是他们例程的角色过于复杂,若要用于实际的落地工程,需要具备良好的密码学功底,并花费大量时间刨出自己所需要的模块为己所用。
基于以上缺陷,笔者最后选择了某蚁集团的Occlum开发TEE。

2、机器间的通信方式

在介绍通信方式之前,首先要明确一点:TEE沙箱是作为服务器(Server),而机构是作为客户端(Client),且二者同处一个局域网内,否则是否“可信”要打上问号了。明确角色后,且两台机器同处于一个局域网内,那么通信方式便怎么简单怎么来。
此处笔者以flask(基于Python的Web框架)进行客户端和服务器的通信(该通信方式不含双向远程认证),

3、程序和数据集的示例

对于没接触过Occlum的读者可以模仿这篇文章跑一份程序体验一下。
【注意:机器一定要预先配置好SGX环境,可参考该系列踩坑文的配置SGX环境】
笔者开发TEE的场景是隐私求交,但目前做的还只是明文求交,只不过程序确实是在TEE环境(Enclave,飞地)运行的,是可以保证“可信”。
程序语言选用C,之所以不采用Python,是因为求交所需要安装的库和依赖之间有版本冲突不兼容的问题,此处笔者已踩过坑,读者可尝试并留下评论互相学习噢。
进行求交的数据集此处采用经典的乳腺癌数据集:alice和bob.

4、结果文件的解密

若读者有接触过Occlum,相信第一次使用一定会遇到读取数据集的路径问题;若还定义了生成结果文件的路径,也肯定会遇到生成结果文件是密文且多个的问题,这些密文文件是保存在/occlum_instance/run/mount/__ROOT,如下图:
在这里插入图片描述
笔者已询问过Occlum的官方人员,但回答是使用挂载mount进行解密。笔者至今仍不明白目录挂载与结果文件的解密有何联系,亦没有渠道对这些密文结果文件(里面都是乱码)进行解密,有兴趣的读者可研究一番并留下评论互相学习噢。
基于Occlum的这种生成密文结果的机制,笔者将计就计,绕开这个问题,却依然能输出明文结果并返回给客户端。读者且保持耐心继续往下浏览。

二、服务器部署

1、起特权模式、映射/dev/sgx和mount文件夹(mount用于在外部宿主机也存储结果文件)、与宿主机的时间同步、映射50054和50055端口号(一个用于通信请求,一个用于被访问结果文件,此处以50054和50055为例)的容器。

sudo docker run -it --privileged -v /dev/sgx:/dev/sgx -v /home/yunqi/mount:/root/mount -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro -p 50054:50054 -p 50055:50055 <你的镜像源>/occlum:latest-ubuntu20.04

【温馨提示:6月份的时候,由于某些不可抗拒的原因,国内的dockerhub已经禁止访问了,因此读者可以参考该视频,把你需要的docker镜像用Github放在自己的阿里云上】

2、在容器内安装flask库(采用阿里云镜像源更快),用于客户端(机构)和服务器(TEE沙箱)间的通信,前面已有介绍。

pip3 install Flask -i https://mirrors.aliyun.com/pypi/simple/

3、用于存放程序的文件夹

mkdir program

4、用于存放服务器的流程代码和自动化指令

mkdir server_file

5、新建用于求交的程序

cd ./program
touch psi.c
vim psi.c

运行的程序一般是放在/occlum_instance/image/bin,且由于Occlum的特性,读者不必质疑define的路径

#psi.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FILE1_PATH "/bin/file1.csv"
#define FILE2_PATH "/bin/file2.csv"

#define MAX_LINE_LENGTH 1024

typedef struct {
  char id[100];
  char attributes[900];
} Record;

void trim_newline(char *str) {
  char *newline = strchr(str, '\n');
  if (newline) {
    *newline = '\0';
  }
}

int main() {
  FILE *File1 = fopen(FILE1_PATH, "r");
  FILE *File2 = fopen(FILE2_PATH, "r");

  if (!File1 || !File2) {
    fprintf(stderr, "Error opening file.\n");
    return 1;
  }

  char line[MAX_LINE_LENGTH];
  Record Records1[1000];
  Record Records2[1000];
  int Count1 = 0, Count2 = 0;

  // Read file1
  while (fgets(line, MAX_LINE_LENGTH, File1)) {
    trim_newline(line);
    char *token = strtok(line, ",");
    strcpy(Records1[Count1].id, token);
    token = strtok(NULL, "");
    if (token != NULL) {
      strcpy(Records1[Count1].attributes, token);
    } else {
      strcpy(Records1[Count1].attributes, "");
    }
    Count1++;
  }
  fclose(File1);

  // Read file2
  while (fgets(line, MAX_LINE_LENGTH, File2)) {
    trim_newline(line);
    char *token = strtok(line, ",");
    strcpy(Records2[Count2].id, token);
    token = strtok(NULL, "");
    if (token != NULL) {
      strcpy(Records2[Count2].attributes, token);
    } else {
      strcpy(Records2[Count2].attributes, "");
    }
    Count2++;
  }
  fclose(File2);

  // Find intersection and print results
  printf("The intersection result is as follows\n");
  for (int i = 0; i < Count1; i++) {
    for (int j = 0; j < Count2; j++) {
      if (strcmp(Records1[i].id, Records2[j].id) == 0) {
        printf("%s,%s,%s\n", Records1[i].id, Records1[i].attributes, Records2[j].attributes);
      }
    }
  }

  return 0;
}

6、新建存放自动化指令的文件

cd ../server_file
touch commands.txt
vim commands.txt
occlum-gcc -o psi psi.c
mkdir occlum_instance
cd ./occlum_instance
occlum init
cp ../file1.csv ./image/bin
cp ../file2.csv ./image/bin
cp ../psi ./image/bin
occlum build --sgx-mode HW
occlum run /bin/psi

7、新建服务器的流程代码文件

touch task_server.py
vim task_server.py
# task_server.py
from flask import Flask, jsonify, request, send_from_directory
import subprocess
import shutil
import uuid
import os
import csv
import threading
import time

app = Flask(__name__)
http_server_process = None

def start_http_server(): 
    global http_server_process
    if not http_server_process:
        # 用于被客户端访问结果文件
        http_server_process = subprocess.Popen(['python3', '-m', 'http.server', '50055'], cwd="/root/mount")
        time.sleep(2)

def stop_http_server():
    global http_server_running
    if http_server_process:
        http_server_process.terminate()
        http_server_process.wait()
        http_server_process = None

@app.route('/execute-task', methods=['POST'])
def execute_task():
    global http_server_thread, http_server_running
    try:
        # 生成唯一的任务ID,格式为uuid
        task_id = str(uuid.uuid4())

        # 获取当前时间,并创建以当前时间命名的occlum工程文件夹
        current_time = subprocess.check_output("date +'%Y-%m-%d_%H-%M-%S'", shell=True).decode('utf-8').strip()
        folder_name = f'/root/{current_time}'
        os.makedirs(folder_name, exist_ok=True)

        # 拷贝求交的C程序到occlum工程文件夹
        source_c_file = '/root/program/psi.c'
        destination_c_file = os.path.join(folder_name, 'psi.c')
        shutil.copy(source_c_file, destination_c_file)

        # 保存客户端发送来的csv数据集到occlum工程文件夹
        file1_path = os.path.join(folder_name, 'file1.csv')
        file2_path = os.path.join(folder_name, 'file2.csv')
        if 'file1' in request.files:
          file1 = request.files['file1']
          file1.save(file1_path)
        if 'file2' in request.files:
          file2 = request.files['file2']
          file2.save(file2_path)

        # 进入occlum工程文件夹
        os.chdir(folder_name)

        # 读取并执行命令文件中的occlum指令
        command_file = '/root/server_file/commands.txt'
        with open(command_file, 'r') as file:
          commands = file.readlines()

        # 使用 `/bin/bash -c` 执行整个命令字符串,并捕获输出
        command_str = '\n'.join(commands)
        result =  subprocess.run(f'/bin/bash -c "{command_str}"', shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

        # 获取求交C程序的打印输出
        c_program_output = result.stdout

        # 找到C程序输出的"The intersection result is as follows"这一行的位置
        lines = c_program_output.splitlines()
        start_index = lines.index("The intersection result is as follows") + 1

        # 提取该行之后的内容
        output_lines = lines[start_index:]

        # 将提取的内容写入并保存csv结果文件
        output_csv_file_name = f'{current_time}_result_psi.csv'
        output_csv_file = os.path.join("/root/mount", output_csv_file_name)
        with open(output_csv_file, 'w', newline='') as csvfile:
            csvwriter = csv.writer(csvfile)
            for line in output_lines:
                if line.strip():
                    csvwriter.writerow(line.split(','))

        # 启动http服务器,以便客户端可以访问TEE沙箱的/root/mount的csv结果文件
        start_http_server()

        # 返回任务ID和生成的结果文件名给客户端
        return jsonify({'task_id': task_id, 'file_name': output_csv_file_name})

    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/download/<filename>', methods=['GET'])
def download_file(filename):
    directory = "/root/mount"
    response = send_from_directory(directory, filename)
    stop_http_server()
    return response

if __name__ == '__main__':
  # 用于接受通信请求
  app.run(host='0.0.0.0', port=50054)

三、客户端部署

相较于服务器的部署工作,客户端就显得尤为简洁了,只需做好发送数据集和通信请求的工作就好了。
【注意:服务器和客户端的系统都是Ubuntu20.04】

mkdir client_file
<存放alice和bob的数据集在此处>
touch request_client.py
vim request_client.py
# request_client.py
import requests

# 替换为TEE沙箱的IP地址和Occlum容器用于接受通信请求的端口号
url = 'http://<TEE沙箱的IP地址>:50054/execute-task' 
files = {
    'file1': open('/home/<用户名>/client_file/alice.csv', 'rb'),
    'file2': open('/home/<用户名>/client_file/bob.csv', 'rb')
}

response = requests.post(url, files=files)

if response.status_code == 200:
    data = response.json()
    print("Task execution triggered successfully.")
    print("Task ID:", data['task_id'])
    print("Generated file name:", data['file_name'])
else:
    print("Failed to trigger task execution.")
    print("Error:", response.text)

四、工程应用

做好以上部署工作后,读者们可以开始正式感受TEE了。

1、服务器先运行

python3 task_server.py

2、客户端再运行

python3 request_client.py

3、服务器和客户端的输出分别是
在这里插入图片描述
可以看到服务器已经打开了50055的端口号,等待客户端访问。

在这里插入图片描述
可以看到客户端已经接收到服务器返回的任务ID和结果文件名.

4、此时,在客户端的浏览器可以输入<服务器的IP地址>:50055进入服务器的/root/mount文件夹,查看并下载求交的结果文件,如下图
在这里插入图片描述
5、此工程代码还有一大优势:
只要服务器一旦执行了python3 task_server.py后,理论上来说客户端是可以无限次向服务器执行求交请求的,服务器可以不再需要人工操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1918765.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为USG6000V防火墙v1

目录 一、实验拓扑图 二、要求 三、IP地址规划 四、实验配置 1&#x1f923;防火墙FW1web服务配置 2.网络配置 要求1&#xff1a;DMZ区内的服务器&#xff0c;办公区仅能在办公时间内(9:00-18:00)可以访问&#xff0c;生产区的设备全天可以访问 要求2&#xff1a;生产区不…

【ARMv8/v9 GIC 系列 1.7 -- GIC PPI | SPI | SGI | LPI 中断使能配置概述】

请阅读【ARM GICv3/v4 实战学习 】 文章目录 GIC 各种中断使能配置PPIs(每个处理器私有中断)SPIs(共享外设中断)SGIs(软件生成的中断)LPIs(局部中断)GIC 各种中断使能配置 在ARM GICv3和GICv4架构中,不同类型的中断(如PPIs、SPIs、SGIs和LPIs)可以通过不同的方式进…

09磁盘管理

一、磁盘管理 1.磁盘基础知识 &#xff08;1&#xff09;磁盘接口类型 个人电脑&#xff0c; 硬盘接口分为IDE类型和SATA类型 服务器版分为SCSI类型和SAS类型 &#xff08;2&#xff09;磁盘命名方式 windows中硬盘命名方式是c&#xff0c;d,e盘 linux中硬盘命名方式为 系统…

uiautomation: debug记录

文章目录 1. pyinstaller打包后运行涉及uiautomation时出现的的错误1.1 [WinError 3] The system cannot find the path specified: C:\\Users\\g\\AppData\\Local\\Temp\\_MEI192482\\uiautomation\\bin 1. pyinstaller打包后运行涉及uiautomation时出现的的错误 1.1 [WinErr…

JUC八股(持续更新中)

写在前面&#xff1a;本文为个人八股复习所用&#xff0c;整合了其他平台的答案加自己的理解&#xff0c;希望能对大家的八股复习有所帮助&#xff0c;答案可能存在出入&#xff0c;请大家理性食用~~ 1. 进程和线程的区别 进程&#xff1a; 进程是操作系统资源分配的基本单位…

神器!3个免费PPT成品网站推荐+3款AIPPT工具盘点!

熬夜加班做PPT却没有头绪&#xff1f;别再自己憋着想了&#xff01;现在凡事主打一个“抄作业”&#xff0c;想做ppt却没想法&#xff0c;可以去到ppt成品网站搜集PPT模板&#xff0c;或是使用时下流行的AI生成PPT工具&#xff0c;只需输入PPT主题&#xff0c;即可快速生成一份…

Linux 命令探秘:揭秘那些有趣的小命令

目录 1.发现隐藏在终端的惊喜小命令 2.小火车 1.安装EPEL 2.小火车出发准备 3.输入命令 3.linux_logo 1.安装linux_logo 2.输入命令 3.linux_logo介绍 4.牛讲话 1.安装命令 2.输入命令 5. figlet 1.安装命令 2.输入命令 “如果您在解决类似问题时也遇到了困…

前端面试题49(如何集成和使用CSP 来增强前端安全性?)

Content Security Policy (CSP) 是一种帮助防止跨站脚本(XSS)和其他代码注入攻击的安全策略。通过明确指定浏览器可以加载或执行哪些资源&#xff0c;CSP 有效限制了恶意内容的执行。下面是如何在实际项目中集成和使用 CSP 的步骤&#xff1a; 1. 确定CSP策略 首先&#xff0…

欧科云链研究院:坎昆升级后,Layer2变得更好了吗?

本文由欧科云链研究院OKG Research联合PANews出品&#xff1a;以数据为导向&#xff0c;洞察真实的链上世界。 作者&#xff5c;Jason Jiang, OKG Research 坎昆升级后&#xff0c;以太坊L2的交易费用降低明显且吞吐量有所提升&#xff0c;但整体生态并没有迎来想象中的繁荣景…

leetcode165.解密数字

题目表述&#xff1a; 这道题目和斐波那契数列以及跳台阶问题十分相似。 斐波那契数列&#xff1a;0、1、1、2、3、5, 8、13、21、34 …… leetcode跳台阶问题&#xff1a;1、1、2、3、5, 8、13、21、34....... 这类题目的特点都是第N项的结果等于前两项的和。 但是解密数…

Spring中的单例模式应用详解

1. DefaultListableBeanFactory 在Spring中&#xff0c;所有由Spring容器管理的Bean默认都是单例的。Spring框架中最经典的单例模式实现是在BeanFactory中。BeanFactory是Spring IoC容器的核心接口&#xff0c;其实现类DefaultListableBeanFactory在加载Bean定义时&#xff0c…

手机m4a怎么转换成mp3,手机端即可完成格式转换

M4A&#xff08;MPEG-4 Audio&#xff09;是一种无损压缩的音频格式&#xff0c;通常用于苹果设备和 iTunes 上&#xff0c;因为它能提供较高的音质同时占用较小的存储空间。 然而&#xff0c;MP3 作为最普及的音频格式之一&#xff0c;兼容性更强&#xff0c;几乎所有的播放设…

【代码随想录】【算法训练营】【第65天】 [卡码94]城市间货物运输I

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 卡码网。 day 65&#xff0c;周四&#xff0c;继续ding~ [卡码94] 城市间货物运输I 题目描述 卡码94 城市间货物运输I 解题思路 前提&#xff1a; 思路&#xff1a; 重点&#xff1a; 代码实现 C语言 Be…

maven7——(重要,构建项目)maven项目构建(命令)

Maven的常用命令管理项目的生命周期 clean命令 清除编译产生的target文件夹内容&#xff0c;可以配合相应命令在cmd中使用&#xff0c;如mvn clean package&#xff0c; mvn clean test D:\工作\公司培训-4班\day20\day20\untitled1>mvn clean compile命令 该命令可以…

C语言之指针的奥秘(二)

一、数组名的理解 int arr[10]{1,2,3,4,5,6,7,8,9,10}; int *p&arr[0]; 这里使用 &arr[0] 的⽅式拿到了数组第⼀个元素的地址&#xff0c;但是其实数组名本来就是地址&#xff0c;而且是数组首元素的地址。如下&#xff1a; 我们发现数组名和数组⾸元素的地址打印出…

电影购票小程序论文(设计)开题报告

一、课题的背景和意义 随着互联网技术的不断发展&#xff0c;人们对于购票的需求也越来越高。传统的购票方式存在着排队时间长、购票流程繁琐等问题&#xff0c;而网上购票则能够有效地解决这些问题。电影购票小程序是网上购票的一种新型应用&#xff0c;它能够让用户随时随地…

电气工程VR虚拟仿真实训平台以趣味化方式增强吸引力

在工业4.0时代和教育信息化的双重推动下&#xff0c;我们致力于推动实训课件的跨界合作与共创。VR实训课件不仅促进了不同领域、不同行业之间的紧密合作&#xff0c;更让学习变得生动直观。我们凭借3D技术生动、直观、形象的特点&#xff0c;开发了大量配套3D教材&#xff0c;让…

vue-router history 模式下将所有资源文件js/css/img都存放在oss 利用 cdn 访问整体思路汇总

背景 我们有一个域名https://example.com&#xff0c;但是ssl证书很贵&#xff0c;搞子域名来承接新站点有点费钱&#xff0c;所以我们想用一个目录https://example.com/admin/ 来作为管理后台的站点&#xff0c;这个站点是单页面应用&#xff0c;我又想让其用history router的…

C++入门到进阶(图文详解,持续更新中)

C入门到进阶&#xff08;图文详解&#xff0c;持续更新中&#xff09; 目录 C入门到进阶&#xff08;图文详解&#xff0c;持续更新中&#xff09; 数据 数据类型 基本数据类型/内置数据类型 C常用运算符 赋值运算符 关系运算符 逻辑运算符 杂项运算符 数据的本地化…

VBA即用型代码手册:删除完全空白的行

我给VBA下的定义&#xff1a;VBA是个人小型自动化处理的有效工具。可以大大提高自己的劳动效率&#xff0c;而且可以提高数据的准确性。我这里专注VBA,将我多年的经验汇集在VBA系列九套教程中。 作为我的学员要利用我的积木编程思想&#xff0c;积木编程最重要的是积木如何搭建…