“Fidelius开发教程”的版本间差异

来自典枢
跳到导航 跳到搜索
标签手工回退
 
(未显示同一用户的15个中间版本)
第12行: 第12行:
就像其他开发教程一样,我们先从写一个最简单的“Hello World”程序开始。
就像其他开发教程一样,我们先从写一个最简单的“Hello World”程序开始。


需要 git clone example,然后软链接到 example 目录下,需要解释编译的步骤,release 版本签名的步骤,执行的步骤需要解释各个文件的作用和意义
详见以下章节《如何基于Fidelius开发算法》进行简单开发和运行程序。
 
下面来看一个完整的 hello world 程序。
下面来看一个完整的 hello world 程序。


第185行: 第186行:
== 下载 Fidelius 源码 ==
== 下载 Fidelius 源码 ==


   $ git clone https://github.com/YeeZTech/YeeZ-Privacy-Computing.git<
   $ git clone https://github.com/YeeZTech/YeeZ-Privacy-Computing.git
  $ git submodule update --init
 
== 下载算法样例代码 ==
 
  $ cd YeeZ-Privacy-Computing/example/
  $ git clone -b master https://github.com/YeeZTech/YPC-algo-example.git
 
== 编译 Fidelius 以及算法样例代码 ==


$ cd YeeZ-Privacy-Computing && mkdir build
== 编译 Fidelius ==


$ cmake -DSGX_MODE=Debug -DSGX_HW=OFF ../
  $ cd YeeZ-Privacy-Computing
  $ ./build.sh compile-project prerelease


'''注意''': 开发者可以根据需求修改编译选项,例如 Release 版本的编译选项应修改为SGX_MODE=Release与SGX_HW=ON。
'''注意''': 开发者可以根据需求修改编译选项,支持的编译模式有 Debug、PreRelease、Release。


Debug 模式下会自动对一些 Enclave 进行签名。
Debug、Prelease 模式下会自动对一些 Enclave 进行签名。


但是,在 Release 编译选项下还需要手动地对一些 Enclave 签名,这些 Enclave 包括密钥管理的 Enclave libkeymgr.so 和算法样例的 Enclave libhello.so。
但是,在 Release 编译选项下还需要手动地对一些 Enclave 签名,这些 Enclave 包括密钥管理的 Enclave libkeymgr.so 和算法样例的 Enclave libiris_parser.so。


手动签名操作需要依赖 openssl 工具,需事先安装 openssl ,签名步骤如下:
手动签名操作需要依赖 openssl 工具,需事先安装 openssl ,签名步骤如下:
$ make -j8


=== 生成 RSA-3072 的私钥和公钥(仅 Release 模式下需要)===
=== 生成 RSA-3072 的私钥和公钥(仅 Release 模式下需要)===


$ cd YeeZ-Privacy-Computing/lib
  $ cd YeeZ-Privacy-Computing/lib
 
  $ openssl genrsa -out private_key.pem -3 3072
$ openssl genrsa -out private_key.pem -3 3072
  $ openssl rsa -in private_key.pem -pubout -out public_key.pem
 
$ openssl rsa -in private_key.pem -pubout -out public_key.pem


生成的私钥文件为private_key.pem,公钥文件为public_key.pem,私钥文件用于对 Enclave 签名,公钥文件会 append 到 签名后的 Enclave 中。
生成的私钥文件为 private_key.pem,公钥文件为 public_key.pem,私钥文件用于对 Enclave 签名,公钥文件会 append 到 签名后的 Enclave 中。


=== 签名两个 Enclave(仅 Release 模式下需要)===
=== 签名两个 Enclave(仅 Release 模式下需要)===


$ openssl dgst -sha256 -out keymgr_sig.hex -sign private_key.pem -keyform PEM keymgr_hash.hex
  $ openssl dgst -sha256 -out keymgr_sig.hex -sign private_key.pem -keyform PEM keymgr_hash.hex
 
  $ openssl dgst -sha256 -out iris_parser_sig.hex -sign private_key.pem -keyform PEM iris_parser_hash.hex
$ openssl dgst -sha256 -out hello_sig.hex -sign private_key.pem -keyform PEM hello_hash.hex


文件keymgr_sig.hex与hello_sig.hex为私钥签名后的文件。
文件 keymgr_sig.hex 与 iris_parser_sig.hex 为私钥签名后的文件。


=== 生成签名后的 Enclave(仅 Release 模式下需要)===
=== 生成签名后的 Enclave(仅 Release 模式下需要)===


$ /opt/intel/sgxsdk/bin/x64/sgx_sign catsig -enclave libkeymgr.so -config ../keymgr/default/enclave/ekeymgr.config.xml -out keymgr.signed.so -key public_key.pem -sig keymgr_sig.hex -unsigned keymgr_hash.hex
  $ /opt/intel/sgxsdk/bin/x64/sgx_sign catsig -enclave libkeymgr.so -config ../keymgr/default/enclave/ekeymgr.config.xml -out keymgr.signed.so -key public_key.pem -sig keymgr_sig.hex -unsigned keymgr_hash.hex
 
  $ /opt/intel/sgxsdk/bin/x64/sgx_sign catsig -enclave libiris_parser.so -config ../example/iris/analyzer/enclave/enclave.config.xml -out iris_parser.signed.so -key public_key.pem -sig iris_parser_sig.hex -unsigned iris_parser_hash.hex
$ /opt/intel/sgxsdk/bin/x64/sgx_sign catsig -enclave libhello.so -config ../example/YPC-algo-example/hello/enclave/enclave.config.xml -out hello.signed.so -key public_key.pem -sig hello_sig.hex -unsigned hello_hash.hex


签名后的 Enclave 实际上包括:算法原始文件、Enclave 配置文件、RSA-3072公钥、签名文件、算法哈希文件。
签名后的 Enclave 实际上包括:算法原始文件、Enclave 配置文件、RSA-3072公钥、签名文件、算法哈希文件。


== 运行算法示例 ==
== 运行算法示例 ==
 
  $ cd YeeZ-Privacy-Computing/test/integrate
=== 生成数据提供方的典密钥对 ===
  $ cd js && npm install && cd ..
 
  $ python3 test_iris.py
$ cd YeeZ-Privacy-Computing/bin
 
$ ./keymgr_tool --create
 
注意: 密钥对生成在$HOME/.yeez.key/路径下。
 
典密钥对包含public_key和private_key两个字段,分别表示公钥和私玥。
 
=== 生成数据使用方的枢密钥对 ===
 
$ ./yterminus --gen-key  --no-password  --output hello.key.json
 
枢密钥对包含public-key和private-key两个字段,分别表示公钥和私玥。
 
=== 获取算法样例的算法哈希 ===
 
$ ./ydump --enclave ../lib/hello.signed.so --output info.json
 
算法哈希文件中的enclave-hash表示算法哈希。
 
=== 加密枢私钥并使用典私钥签名相关信息 ===
 
$ ./yterminus --forward  --use-privatekey-file hello.key.json --tee-pubkey $TEE_PUBLIC_KEY --use-enclave-hash $ENCLAVE_HASH --output hello.request.shukey.foward.json
 
其中,$TEE_PUBLIC_KEY为步骤 4.1 生成的典公钥,$ENCLAVE_HASH为步骤 4.3 生成的算法哈希。
 
=== 加密算法的参数 ===
 
$ ./yterminus --request  --use-param hello --param-format text --use-publickey-file hello.key.json --output hello_param.json
 
=== 生成算法执行的输入 ===
 
$ python3 ../example/YPC-algo-example/generator/gen_input_params.py --dian-pkey $TEE_PUBLIC_KEY
 
其中,$TEE_PUBLIC_KEY为步骤 4.1 生成的典公钥。
 
=== 执行样例算法 ===
 
$ GLOG_logtostderr=1 ./fid_analyzer --input input_param.json --output result.json
 
文件result.json为算法运行的结果。


= Q&A =
= Q&A =

2023年3月8日 (三) 07:33的最新版本

介绍

简介

Fidelius 提供了自定义算法的能力。此处的算法用于分析数据,并将分析结果交付给用户。

Fidelius 的算法实现基于 C/C++11。一个算法是指一个运行在可信执行环境(TEE)中的代码,由于目前主要的支持硬件为 Intel SGX,因此编程方式符合 Intel SGX 的编程规范。

本文介绍的算法开发基于 Fidelius 的最新版本,请检查自己的版本。

Hello World

就像其他开发教程一样,我们先从写一个最简单的“Hello World”程序开始。

详见以下章节《如何基于Fidelius开发算法》进行简单开发和运行程序。

下面来看一个完整的 hello world 程序。

 #include ”corecommon/crypto/stdeth.h”
 #include ”stbox/tsgx/log.h”
 #include ”ypc_t/analyzer/algo_wrapper.h”
 #include ”ypc_t/analyzer/macro.h” 
 class hello_world {
 public:
   inline stbox::bytes do_parse(const stbox::bytes &param) {
     LOG(INFO) << ”hello world”;
     return param;
   }
 };
 ypc::algo_wrapper<ypc::crypto::eth_sgx_crypto, ypc::noinput_data_stream,
                   hello_world,
                   ypc::local_result> pw;
 YPC_PARSER_IMPL(pw);

algo_wrapper

 template<typename Crypto, typename DataSession, typename ParserT,
          typename Result, typename ModelT = void,
          template<typename> class DataAllowancePolicy = ignore_data_allowance,
          template<typename> class ModelAllowancePolicy = ignore_model_allowance>
 class algo_warpper ;

代码来源core/include/ypc_t/analyzer/algo_wrapper.h‎

  • Crypto:密码协议簇,目前支持ypc::crypto::eth_sgx_crypto,兼容以太坊。
  • DataSession:数据源方式,支持noinput_data_stream, raw_data_stream, sealed_data_stream, multi_data_stream
  • ParserT:表示自定义的算法类。
  • Result:表示结果的类型,支持local_result, onchain_result, offchain_result, forward_result
  • ModelT:表示模型的类型,是ff::util::ntobject<...>
  • DataAllowancePolicy:表示数据源的许可验证策略,支持ignore_data_allowance, check_data_allowance
  • ModelAllowancePolicy:表示模型的许可验证策略,支持ignore_model_allowance, check_model_allowance

通过对上述参数的选择和组合,可以支持不同的场景。

HPDA

算法的主体通常使用 HPDA(High Performance Data Analysis)完成。HPDA 算法由输入(input)、处理单元(processor)、输出(output)三种不同的功能单元 组成,其中输入、处理有一个或多个,输出仅有一个。

一个 HPDA 算法可以表示一个如下的有向图,其中节点表示功能单元,即输入、处理单元或输出,边表示数据。自然地,输入只有出边,输出只有入边, 处理单元有一个或多个入边,且有一个或多个出边。

算法的执行过程一般分为连个阶段:1)构造 HPDA 的图;2)运行算法。算法一旦开始运行,则会开始读取输入、产生输出,直到所有的输入读取完成。

Iris 为例

 class enclave_iris_means_parser {
 public:
   enclave_iris_means_parser(ypc::data_source ∗source):m_source(source){};
   inline stbox::bytes do_parse(const stbox::bytes &param) {
     ypc::to_type<extra_nt_t> converter(m_source);
     transform_format trans(&converter);
     typedef hpda::algorithm::kmeans::kmeans_processor<
       hpda::ntobject<iris_data, species>,
       iris_data, double, iid> kmeans_t;
     kmeans_t km(&trans, 3, 0.001);
     hpda::output::memory_output<iid, kmeans_t::mean_point, kmeans_t::average_distance> mo(km.means_stream());
     mo.get_engine()−>run();
     ...
   }
 protected:
   ypc::data_source ∗m_source;
 };

该算法可以表示为如下的图

Iris例图1.png

图中的边—数据类型

在 HPDA 所表示的有向图中,一条边可以表示为 (A, B),我们称 A 是 B 的输入源,A 的输出数据类型和 B 的输入数据类型必须一致,否则会产生编译错误。我们将 A 的输出数据类型(或 B 的输入数据类型)称为边 (A, B) 上的数据类型。

边的数据类型为

template<typename ...ARGS> ff::util::ntobject;

600PX

data_source

data_source 是一个表示输入的虚基类,其输出为 bytes 类型。一般后面会跟一个 converter,用于将 bytes 转换为自定义的结构。

处理单元(processor)

处理单元用于完成对数据的转换、处理等。目前系统已有的处理单元包括:

  • filter 用于过滤,仅输出满足条件的数据。
  • concat 用于连接不同的数据,在一个输入源结束后,输出另一个输入源。
  • group 用于在指定的域相同的数据上完成相应的操作,这些操作包括取平均 (avg),求最大 (max),求最小(min),求和(sum),求数量(count)。
  • split 用于将一个输入复制为多个输出。
  • kmeans_processor 用于在指定的数据上完成 kmeans 聚类算法。

memory_output

memory_output是一个将结果存放在内存的输出单元。可以使用如下方式遍历

所有的输出

 for(auto it : mo.values()) {
   ...
 }

自定义处理单元

通常,系统内置的处理单元并不能满足特定的数据处理需求,因此,需要自定义处理单元。此时需要继承hpda中的处理单元基类,如下:

 typedef ff::util::ntobject<sepal_len,sepal_wid,petal_len,petal_wid,species> extra_nt_t;
 class transform_format
   : public hpda::processor::processor_base_t<extra_nt_t, user_item_t> {
 public:
   transform_format(::hpda::processor_with_output_t<extra_nt_t> *t)
       : hpda::processor::processor_base_t<extra_nt_t, user_item_t>(t) {}
   virtual bool process() {
     if (!has_input_value()) {
       return false;
     }
     auto t = base::input_value();
     m_data.get<iris_data>().set<sepal_len, sepal_wid, petal_len, petal_wid>(
         t.get<sepal_len>(), t.get<sepal_wid>(), t.get<petal_len>(),
         t.get<petal_wid>());
     m_data.set<species>(t.get<species>());
     base::consume_input_value();
     return true;
   }
   virtual user_item_t output_value() { return m_data; }
 protected:
   user_item_t m_data;
 };

高级

直接访问上下文

上下文是指算法在执行过程中的信息,包括该算法的 hash,与 keymgr 的会话等。可以在算法类中添加如下方法以获得上下文的指针

 void set_context(ypc::analyzer_context ∗context){
   m_context = context;
 }

algo_wrapper会自动检测到该方法的存在,并编译生成相应的代码。

自定义输入数据格式

Fidelius 内置了对于 CSV,mysql 的支持,可以通过定义一个简单的 JSON 描述文件完成文件的加密、读取。然而,对于自定义的文件格式,开发者需要额外的开发工作。

首先,该数据必须可以描述为一个 bytes 的数组,这在大多数场景下是适用的。例如,视频可以描述为一个数组,数组的每一个元素为一帧图像;一个图片可以表示为一个数组,数组的每一个元素为图片中的一个像素点。Fidelius 的算法每次读如数组中的一个或多个元素。受限于 Intel SGX 的内存限制,一个元素的大小通常不超过 128KB。

其次,对于自定义的数据格式,需要实现如下的方法,并编译为.so 的插件库。

 void ∗create_item_reader(const char ∗extra_param, int len);
 int reset_for_read(void ∗handle);
 int read_item_data(void ∗handle, char ∗buf, int ∗len);
 int close_item_reader(void ∗handle);
 uint64_t get_item_number();

如何基于Fidelius开发算法

下载 Fidelius 源码

 $ git clone https://github.com/YeeZTech/YeeZ-Privacy-Computing.git

编译 Fidelius

 $ cd YeeZ-Privacy-Computing
 $ ./build.sh compile-project prerelease

注意: 开发者可以根据需求修改编译选项,支持的编译模式有 Debug、PreRelease、Release。

Debug、Prelease 模式下会自动对一些 Enclave 进行签名。

但是,在 Release 编译选项下还需要手动地对一些 Enclave 签名,这些 Enclave 包括密钥管理的 Enclave libkeymgr.so 和算法样例的 Enclave libiris_parser.so。

手动签名操作需要依赖 openssl 工具,需事先安装 openssl ,签名步骤如下:

生成 RSA-3072 的私钥和公钥(仅 Release 模式下需要)

 $ cd YeeZ-Privacy-Computing/lib
 $ openssl genrsa -out private_key.pem -3 3072
 $ openssl rsa -in private_key.pem -pubout -out public_key.pem

生成的私钥文件为 private_key.pem,公钥文件为 public_key.pem,私钥文件用于对 Enclave 签名,公钥文件会 append 到 签名后的 Enclave 中。

签名两个 Enclave(仅 Release 模式下需要)

 $ openssl dgst -sha256 -out keymgr_sig.hex -sign private_key.pem -keyform PEM keymgr_hash.hex
 $ openssl dgst -sha256 -out iris_parser_sig.hex -sign private_key.pem -keyform PEM iris_parser_hash.hex

文件 keymgr_sig.hex 与 iris_parser_sig.hex 为私钥签名后的文件。

生成签名后的 Enclave(仅 Release 模式下需要)

 $ /opt/intel/sgxsdk/bin/x64/sgx_sign catsig -enclave libkeymgr.so -config ../keymgr/default/enclave/ekeymgr.config.xml -out keymgr.signed.so -key public_key.pem -sig keymgr_sig.hex -unsigned keymgr_hash.hex
 $ /opt/intel/sgxsdk/bin/x64/sgx_sign catsig -enclave libiris_parser.so -config ../example/iris/analyzer/enclave/enclave.config.xml -out iris_parser.signed.so -key public_key.pem -sig iris_parser_sig.hex -unsigned iris_parser_hash.hex

签名后的 Enclave 实际上包括:算法原始文件、Enclave 配置文件、RSA-3072公钥、签名文件、算法哈希文件。

运行算法示例

 $ cd YeeZ-Privacy-Computing/test/integrate
 $ cd js && npm install && cd ..
 $ python3 test_iris.py

Q&A