Obliv-C使用详解(混淆电路)

前期说明

Obliv-C是一款GCC包装器,其作者在C语言的基础上对其进行了一定的类C处理,添加了一些规则限制,用于模拟实现混淆电路

Obliv-C不需要手动混淆,只需要调用其中的函数便可实现混淆电路,其不涉及真实硬件电路仿真,即无法导出函数对应的基本元电路(也可能是博主没有成功实现,但其提供的所有帮助文档论文中没有提及该方面的内容,若某位同僚有解决的方法,欢迎分享学习)

Obliv-C源码公开在GitHub中,可从中下载安装Obliv-C使用,因其自带的安装教程简单实用,在此不提及其安装的操作方法(GitHub网址:Obliv-C

Obliv-C的设计团队为其编写了一个官方网站:Obliv-C
从中可获取Obliv-C的原著论文(PDF版)以及其帮助文档、实现项目等具体资料

倘若刚开始接触使用Obliv-C,建议仔细阅读其论文以及帮助文档,论文中详细说明了Obliv-C编程的规则,而帮助文档则提供了简单的案例分析

硬件平台

Obliv-C运行于Linux系统上,博主使用了Ubuntu系统,具体的系统支持可查看GitHub中提供的Obliv-C帮助手册

文件目录

Obliv-C的设计者并没有提供其各个文件的具体介绍,简单使用Obliv-C软件也仅需了解其如何编程、如何运行、如何调试即可

打开安装好的obliv-c文件夹,可在一级目录中找到一个名为 test 的文件夹,打开它

在这里插入图片描述
打开后,找到一个名为 oblivc 的文件夹,打开它

在这里插入图片描述
打开后所显示的文件目录即为设计者提供的一系列已完成案例,其中 README.txt 文件中详细说明了各个案例的功能实现,该文件位置也是Obliv-C编程的workspace(图中某些文件夹是博主自己创建的项目文件)

在这里插入图片描述
对于obliv-c的其他文件夹,可暂时忽略,如果之后需要查看某一文件内容,可直接在obliv-c文件夹中搜索该文件

案例分析

million 文件夹为例,该文件夹中包含了百万富翁问题的混淆电路实现

million文件目录如下(未编译过该程序不会有a.out文件):

在这里插入图片描述
其中 a.out 为可执行程序,相当于Windows系统中的exe文件;
million.c、million.h、million.oc 文件均为代码文件,可对其进行编程;
README.txt 介绍了该代码程序如何编译、运行的方法

代码编程

学习一个案例先从其程序代码开始,即图中的 million.c、million.h、million.oc 文件,因Obliv-C使用类C语言,所以要求使用者要有一定的C语言基础

million.c 文件:编程规则与C语言完全相同,用于获取命令行参数、设置混淆电路环境、输出混淆计算结果等

million.h 文件:编程规则与C语言完全相同,用于定义混淆电路相关结构体、声明函数等

million.oc 文件:编程规则与C语言类似,具体差别可查看Obliv-C论文内容,用于定义混淆计算函数

million.h 代码如下:

typedef struct protocolIO
{ int cmp; // -1,0, or 1
  int mywealth;
} protocolIO;

void millionaire(void* args);

protocolIO结构体中定义参与混淆计算的全部参数,包括各方的秘密输入(mywealth)以及最后的共享结果(cmp),特别地,各方的秘密输入可以定义为同一变量名,也可以定义为不同的变量

对于protocolIO结构体,其中的变量不能使用指针,需要用数组代替,否则编译可能不会报错,但最终运行结果错误

millionaire 函数为混淆计算函数的声明,具体的函数定义可在 million.oc 代码中查看编写

million.c 代码如下:

#include<stdio.h>
#include<obliv.h>

#include"million.h"

int main(int argc,char *argv[])
{
  ProtocolDesc pd;
  protocolIO io;
  if(argc<3)
  { if(argc<2) fprintf(stderr,"Party missing\n");
    else fprintf(stderr,"Wealth missing\n");
    fprintf(stderr,"Usage: %s <1|2> <wealth>\n",argv[0]);
    return 1;
  }

  // skip input sanitization
  sscanf(argv[2],"%d",&io.mywealth);
  protocolUseStdio(&pd);
  setCurrentParty(&pd,argv[1][0]=='1'?1:2);
  execYaoProtocol(&pd,millionaire,&io);
  cleanupProtocol(&pd);
  fprintf(stderr,"Result: %d\n",io.cmp);
  return 0;
}

头文件声明部分,包含了 stdio.h、obliv.h、million.h 三个头文件,stdio.h 为C语言编程必要的头文件,不过多描述;obliv.h 头文件声明了混淆电路相关的内容,若想查看其中详细内容,可通过搜索该文件直接打开阅读;million.h 头文件是自行定义的文件,因此需要使用 “” 声明

main函数需要从命令行中获得相关参数,因此固定 int main(int argc,char *argv[]) 写法,其中:
argc 统计程序运行时发送给main函数的命令行参数的个数
argv[0] 指向程序运行的全路径名
argv[1] 指向在DOS命令行中执行程序名后的第一个字符串
argv[2] 指向执行程序名后的第二个字符串
argv[3] 指向执行程序名后的第三个字符串

ProtocolDesc pd 该部分并未找到对其的具体说明,但涉及混淆电路的函数都将其作为自己的参数,特此注意

protocolIO io 为在 million.h 头文件中定义的结构体

以下代码用于判断命令行输入的格式是否正确,实际使用时可根据自身需求修改判断(argc 统计程序运行时发送给main函数的命令行参数的个数)

if(argc<3)
  { if(argc<2) fprintf(stderr,"Party missing\n");
    else fprintf(stderr,"Wealth missing\n");
    fprintf(stderr,"Usage: %s <1|2> <wealth>\n",argv[0]);
    return 1;
  }

sscanf(argv[2],"%d",&io.mywealth); 赋值语句,通过获取命令行输入,赋值给对应结构体中的变量

protocolUseStdio(&pd); 未找到对应的解释说明,博主后续的编程中从未使用过该函数,遂可忽略

setCurrentParty(&pd,argv[1][0]==‘1’?1:2); 设置混淆计算的各方,判断该程序是哪一方在使用,argv[1][0]==‘1’?1:2 判断语句,参数类型 int

execYaoProtocol(&pd,millionaire,&io); 执行混淆计算,millionaire 为混淆计算函数,&io 为存储有混淆计算输入输出的结构体

cleanupProtocol(&pd); 固定用法,清除 ProtocolDesc pd

fprintf(stderr,“Result: %d\n”,io.cmp); 混淆结果输出到命令行

million.oc 代码如下:

#include<obliv.oh>
#include"million.h"

void millionaire(void* args)
{
  protocolIO *io=args;
  obliv int v1,v2;
  bool eq,lt;
  
  v1 = feedOblivInt(io->mywealth,1);
  v2 = feedOblivInt(io->mywealth,2);
  revealOblivBool(&eq,v1==v2,0);
  revealOblivBool(&lt,v1<v2,0);
  io->cmp = (!eq?lt?-1:1:0);
}

头文件部分与 million.c 类似,不再描述

void millionaire(void* args) 为混淆计算函数,囊括该次混淆计算的具体计算过程

protocolIO *io=args; 混淆计算参数对应结构体获取

obliv int v1,v2; 随机值替换后的参数变量,注意 obliv 关键字

v1 = feedOblivInt(io->mywealth,1); 混淆数据获取,feedOblivInt 函数专用于 int 类型数据,第一个参数为数据,第二个参数为参与计算的某方,其余 feedObliv* 函数可查看 obliv.oh 头文件中的内容获取其声明用法

revealOblivBool(&eq,v1==v2,0); 解密计算,revealObliv* 函数与 feedObliv* 函数类似,都可在 obliv.oh 头文件中找到其具体的声明,该函数用于将混淆计算结果解密,在Obliv-C中,有且仅有该函数可以解密混淆数据

最后注意一下,虽然提供了 million.h 头文件,但写入该头文件中的头文件声明在 million.c 与 million.oc 中不起作用,因此,million.c 与 million.oc 需要的头文件必须在各自的代码中声明

编译运行

了解具体代码的功能实现后,便可编译运行,查看结果,此时可打开 README.txt 文件,按其中的步骤实现

文件中涉及程序编译的命令如下:

/path/to/oblivcc million.c million.oc -I .

其中 /path/to/oblivcc 要按照自身的 oblivcc 所在位置修改,可直接搜索该文件获取其位置目录,博主最后的编译命令如下:

../../../bin/oblivcc million.c million.oc -I .

命令行编译结果如下:

在这里插入图片描述
编译成功后,会产生 a.out 文件,而后找到运行命令:

cycle './a.out 1 15 | ./a.out 2 10'

若没有 cycle 命令,直接回车,将会报错:

在这里插入图片描述
此时可查看文件中的描述,它提供了一个网址,可下载该命令:cycle
下载完成后,修改命令所在的位置,再回车运行,便可获得结果:

在这里插入图片描述
该部分使用了million作为案例进行详细分析,对于Obliv-C的初学者而言,仅仅掌握一个案例是远远不够的,建议将全部的范例都浏览试运行一遍,再入手编写自己的混淆电路程序,会更加明了

实战编程

该部分不会涉及具体的代码编写,代码函数的解释学习在案例分析中已经描述得足够详尽,因此,该部分主要介绍如何创建自己的项目、编译、运行

创建项目

推荐将自己的项目创建在与案例相同的位置,项目的创建其实就是文件夹与文件的建立过程
(1)在oblivc文件目录下新建文件夹,自主命名
(2)在新建的文件夹中建立三个文件,分别为 .c、.h、.oc 类型文件,文件命名自定,推荐命名相同便于使用
至此,便可编写 .c、.h、.oc 类型文件,实现自己的混淆电路(可复制某一案例的代码,修改其中的函数变量等,实现自己所需的功能)

编译

除去million案例的编译方法,在某些案例中,提供有 Makefile 文件,该文件中说明了项目的具体编译操作

Obliv-C大多案例中提供的 Makefile 文件内容如下:

testName=editdist
include ../common/Makefile.simple

这是一个简易的 Makefile 文件,基于 …/common/Makefile.simple 实现,可以打开 …/common/Makefile.simple 文件查看内部内容:

$(if $(testName),,$(error 'testName' must be defined before Makefile.simple is used))
CILPATH=../../../
REMOTE_HOST=localhost
CFLAGS += -DREMOTE_HOST=$(REMOTE_HOST) -O3
./a.out: $(testName).oc $(testName).c ../common/util.c $(CILPATH)/_build/libobliv.a
	$(CILPATH)/bin/oblivcc $(CFLAGS) -I . $(testName).oc $(testName).c ../common/util.c
clean:
	rm -f a.out

很明显可以将这两个 Makefile 文件内容合并,修改一下其中涉及的文件位置即可

testName=editdist 为项目名称,若 .c、.h、.oc 类型文件命名相同,可使用该方法,若不同,则需手动修改命令中涉及的相关文件名

以下为错误提示,可直接复制使用:

$(if $(testName),,$(error 'testName' must be defined before Makefile.simple is used))

以下可以看做一些变量的赋值,可直接复制,修改一下文件位置便可:

CILPATH=../../../
REMOTE_HOST=localhost
CFLAGS += -DREMOTE_HOST=$(REMOTE_HOST) -O3

以下为编译命令,一般可直接复制使用,同样可能需要修改文件位置,若有特殊编译要求,可在其基础上按需修改:

./a.out: $(testName).oc $(testName).c ../common/util.c $(CILPATH)/_build/libobliv.a
	$(CILPATH)/bin/oblivcc $(CFLAGS) -I . $(testName).oc $(testName).c ../common/util.c

以下为清除命令:

clean:
	rm -f a.out

Makefile 文件的编译只需在对应的文件目录打开命令行终端,输入 make 回车,清除命令输入 make clean 即可

编译成功,同样产生一个 a.out 可执行程序文件

运行

一般运行,打开终端,执行 a.out 文件,不同的案例会有不同的参数要求,按提供的格式输入便可,同样,某些案例在一个终端中输入命令便可运行,某些案例可能会需求打开两个终端,进行连接通信后,才可运行,具体的运行方法案例中都会说明,试运行所有案例后便可寻求一个最适合自己代码的运行方法

备注

Obliv-C实现了混淆电路,也有许多成功的项目,但其也存在一定的缺陷,例如,无法使用常用库、不能真正实现电路、仅支持C语言而不能使用C++等

对于Obliv-C的更多使用方法,如果某些同僚更为了解,欢迎分享,大家互相学习互相进步!

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值