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的更多使用方法,如果某些同僚更为了解,欢迎分享,大家互相学习互相进步!

热门文章

编程学习 ·

vue打包后修改服务器地址

1.在public文件下新建config.js文件2.修改config.js文件 var PLATFROM_CONFIG = {}; // 本地环境 PLATFROM_CONFIG.baseUrl = "服务器地址" // 正式环境 // PLATFROM_CONFIG.baseUrl = "服务器地址"3.在封装好的axios里面去修改,我的是4.在index.html中引…
编程学习 ·

Java 常见校验汇总

1.手机号校验(境内11位) String phontNo="12356772112"; Pattern pattern = Pattern.compile("^((13[0-9])|(14[5,7,9])|(15[0-3,5-9])|(166)|(17[3,5,6,7,8])" + "|(18[0-9])|(19[8,9]))\\d{8}$"); if (!pattern.matcher(para.getPhoneNo()).ma…
编程学习 ·

Python使用Request库实现PC端学小易(适用app版本1.0.6)

Python使用Request库实现PC端学小易app(适用app版本1.0.6)前言抓包登录操作抓包搜题操作抓包数据分析登录搜题重点代码实现导入库tkinter实现简易图形界面部分request库实现登录部分搜题部分整理输出至tkinter部分完整代码重点 前言 一直以来学小易只有安卓段与IOS端的app,在…
编程学习 ·

ubuntu:beyond compare 4 This license key has been revoked 解决办法

错误如图所示:解决办法:(1)先用find命令找到bcompare所在位置:sudo find /home/ -name *bcompare(2)进入 /home/whf/.config,删除/bcomapre文件夹注意一般.config为隐藏文件,通过 ctrl+h 可以显示:(3)cd /usr/lib/beyondcompare/ (4)sudo sed -i "s/keexjEP3…
编程学习 ·

MySQL

MySQL MySql基础 1:基本数据库命令 命令行连接 #使用cmd连接mysql --连接数据库 mysql -uroot -p123456 -- 修改用户密码 update mysql.user set authentication_string=password(123456) where user=root and Host = localhost; -- 刷新权限 flush privileges;-- 所有的sql语…
编程学习 ·

Less 基础

1. 维护CSS的弊端 CSS是一门非程序式语言,没有变量、函数、SCOPE(作用域)等概念。CSS需要书写大量看似没有逻辑的代码,CSS冗余度是比较高的。 不方便维护及扩展,不利于复用。 CSS没有很好的计算能力 非前端开发工程师来讲,往往会因为缺少CSS编写经验而很难写出组织良好且易…
编程学习 ·

如何更好的使用大数据

在互联网时代,依靠大数据是未来的发展趋势。大数据分析现在非常流行,但是我们需要知道的是,大数据的价值体现在有效而正确的分析中。只有通过正确有效的分析工具和分析方法来解释现有的大数据,大数据才能为我们带来有价值的结果。今天,中琛魔方将教您如何有效运用大数据。…
编程学习 ·

Spark1.x升级Spark2.x常见异常Kafka篇【TopicMetadataRequest】

一.原因分析 当Spark从1.x升级到2.x时,如果使用SparkStreaming加载Kafka的数据,即使Kafka版本没有变化【一般会有所升级】,对应的spark-streaming-kafka也必须升级到对应版本,访问方式也会有所变化。 此处是从Spark1.6.0升级到Spark2.4.3,Kafka略有升级【从2.1.0升级到2.2…
编程学习 ·

单词学习2020

1. mindset: 心态;观念模式,思维倾向(1)This old mindset has not changed这个旧的思想意识还未转变(2)Enhancing leadership commitment and proactive mindset.增强领导力承诺和积极进取的心态(3)He faces all challenges by aggressive mindset他以积极的心态面对所…
编程学习 ·

Spring依赖注入:@Autowired,@Resource和@Inject区别与实现原理

注入实现方式@Autowired是spring框架提供的实现依赖注入的注解,主要支持在set方法,field,构造函数中完成bean注入,注入方式为通过类型查找bean,即byType的,如果存在多个同一类型的bean,则使用@Qualifier来指定注入哪个beanName的bean。与JDK的@Resource的区别:@Resourc…
编程学习 ·

MongoDB安装及服务配置

MongoDB安装官网下载:https://www.mongodb.com/download-center/community----介绍https://www.cnblogs.com/dreamsqin/p/10885038.html 安装到D盘MongoDB目录下,将D:\MongoDB\bin配置到环境变量path下 在MongoDB下创建data、log文件夹 测试MongDB是否安装成功 – 打开cmd命令…
编程学习 ·

利用Spring提供的事务监听ApplicationEvent完成事件

前段时间开发项目时,碰到一个数据库事务还没提交,但是发送MQ已经被消费者消费,导致了数据不同步问题。具体是这样子的,一般我们会在@Service类中去处理数据库的操作及其他服务处理,一般都会在涉及到数据库的增删改的方法上添加@Transactional注解,表示这个方法被托管给sp…
编程学习 ·

面试必问之 == 与 equals

== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:情况1:类没有覆盖 equals() 方法。则通过 equals() 比…
编程学习 ·

JavaScript-从入门到入土(五)

BOM BOM(Browser Object Model): 浏览器对象模型,是用来描述与浏览器进行交互的方法和接口 BOM下面有一个核心的对象 – window对象。 window下面的常用的事件操作: onload() 页面内容加载完成后执行这里的代码 onscroll() 浏览器的滚动条触发时触发此事件 onresize(…
编程学习 ·

SpringCloud 整合 zookeeper 学习

SpringCloud 整合 zookeeper 学习 支付微服务注册zookeeper创建支付微服务 - cloud-provider-payment8004 pom.xml<dependencies><!--自定义的api--><dependency><groupId>org.huiyuanai</groupId><artifactId>cloud-api-common</artif…