模型商业化时产权保护有何技术手段?protege 专为数据分析/机器学习建模而打造

数据分析/机器学习模型的构建是极其复杂的活动,涵盖了业务的深入理解,数据的梳理选取,特征的表达试错,算法的设计改造,样本的逐条核对,模型的调参训练等一系列工作,有时甚至要对数据产生、传输、存储、加工等整个链路中可能存在的问题进行调研,以确保采用合适的方法对数据进行清理。因此每一个能够在生产环境产生有效价值的分析预测模型,都是应当有相应的知识产权保护的,这样才会有更多的人愿意沉下心来投入到这项高难度的工作中,生产更多的有价值的成果。

本文的protege就是为模型的产权保护而产生。

与PMML的理念完全不同,PMML的目的是实现模型的共享,如果模型采用了PMML,那么该模型所使用的数据、特征、算法完全是公开的。protege认为模型构建是一项创造性工作,模型的构建方法、思路是否公开,应该由创造者决定。

What is it

protege是一个提供模块加密、授权和验证的Python包,用以保护创造性的程序开发。它的产生源于预测和分析类模型的商业授权。

protege is a Python package providing module encryption, authorization, and authentication to protect creative programming. It originated from the commercial authorization of prediction and analysis models.

Main Features

protege的主要功能特点:

  • 开发者可以自定义长度为8的密钥(字符串)。
  • 开发者可以通过授权项的参数来控制模块授权的时限、授权的机器,具体授权项如下:
授权项注释
module授权标识,参数为字符串,函数式应用可以自定义授权标识;作为protege.Protege子类应用,授权标识为module_name.class_name。
expire授权时限,参数为数值或日期字符串,默认值为无限期;数值表示授权的时长(单位:天);日期字符串表示授权的到期日(格式:YYYY-MM-DD)。
mid授权机器码,参数为字符串。
bind_mid是否绑定机器码,True/False,默认值为True,如果为True,将判断授权机器码与实际是否一致。
check_systime是否验证系统时间,True/False,默认值为False,如果为True,将判断操作系统的时间是否可能有误。
  • 开发者可以对模块输出的关键信息进行加密,并通过授权项的参数控制关键信息解密的时限、次数、数量,具体授权项如下:
授权项注释
iden_expire解密时限,参数为数值或日期字符串,数值表示解密的时长(单位:天);日期字符串表示解密的到期日(格式:YYYY-MM-DD)。
iden_1st_expire首次解密时限,参数为数值或日期字符串,数值表示首次解密的时长(单位:天);日期字符串表示首次解密的到期日(格式:YYYY-MM-DD)。
iden_max_interval两次解密最大间隔,参数为数值,表示两次解密时间之间的最大间隔(单位:天)。
iden_times解密次数,参数为数值,解密的最大次数。
iden_quantity解密的数量,参数为数值,解密的最大数量。
iden_filt_func解密过滤条件,参数为以callable对象为内容的字符串,如’sum’、‘lambda x:x>1’,默认值是’lambda x:random.random()<0.1’。
iden_over解密数量或次数超限的处理,‘raise’/‘update’,默认值为’raise’,'raise’表示抛出异常,'update’表示更换解密密钥(该密钥用以加密模块输出的关键信息,由protege随机生成,不是开发者自定义的密钥)。
iden_imprint是否记录解密次数、数量,True/False,,默认值为False,如果为True,将记录解密的累计次数和数量。
  • 当模块还依赖其它需要授权的模块时,开发者可以通过requires授权项,给予依赖模块同等授权,具体授权项如下:
授权项注释
requires依赖模块,参数为list,list中列出所有依赖模块的授权标识。
  • 开发者可以新增自定义授权项,如授权等级。
  • 开发者可以设置外部无法访问的类属性。
  • 签发授权时,授权项可以忽略。如果授权项有默认值,忽略表示采用默认值;
    如果授权项没有默认值,忽略表示不验证这一项。
  • 指定授权标识和提供开发者自定义的密钥,可以查看授权项和参数。
  • 开发者自定义的密钥不可查看。
  • protege的验证功能不可更改,以防止欺骗验证。
  • 开发者可以用protege对自己开发的模块进行编译,避免提供源码。

Where to get it

最新版本的protege源码和编译安装包可以在Python package index获取。

The source code and binary installers for the latest released version are available at the [Python package index].

https://pypi.org/project/protege

可以用pip安装protege。

You can install protege like this:

pip install protege

也可以用setup.py安装。

Or in the protege directory, execute:

python setup.py install

How to use it

查看用户机器码

import protege
protege.identity()

运行结果示例

'896d9225bfb14429d603e5bad069a21a'

开发者签发授权

import protege
passport=[
{'module':'test_1',#第一个授权模块的授权标识
 'level':'trail',#自定义的授权项
 'expire':365*10,#授权时限3650天
 'mid':'896d9225bfb14429d603e5bad069a21a',#授权机器码,与用户机器码保持一致
 'bind_mid':True,#绑定机器码
 'check_systime':True,#验证系统时间
 'requires':['test_3'],#依赖模块
 'iden_times':100,#解密10次
 'iden_quantity':600000,#解密数量600000个
 'iden_expire':365,#解密时限365天
 'iden_1st_expire':'2022-03-01',#首次解密不晚于2022-03-01
 'iden_max_interval':90,#两次解密最大间隔不超过90天
 'iden_over':'update',#解密数量或次数超限后,更换解密密钥
 'iden_filt_func':'lambda x:True',#解密过滤条件,当待解密信息满足“索引1的值能被5整除”时才解密
 },
{'module':'__main__.test_2',#第二个授权模块的授权标识,__main__为模块名,test_2为类名
 'mid':'123',#授权机器码,
 'bind_mid':False,#不绑定机器码,授权机器码可不与用户机器码保持一致
 'expire':'2022-12-31',#授权时限至2022-12-31
 'iden_filt_func':'lambda x:int(x[1])%5==0',#解密过滤条件,全部解密
 'iden_imprint':False#不记录解密次数、数量
 }
]

protege.issue(passport,key='12345678')

运行结果示例

'<pass time="1655012229.5737512" cipher="jHjiOEBXSTHZPR5eqAHy/jp03cjRsaVUzKKFz3nadfAbHGNq5Xt3v/cTvHMFTub0xlafWlr2FZjUeXCA7pR/vv15L52BDN83+3oe" flag="receipt"/>'

将签发的授权保存为文件,passport为文件名

protege.issue(passport,key='12345678',file_path='passport')

查看授权

import protege
protege.check('test_2',key='12345678',file_path='passport')

运行结果示例

{'bind_mid': True,
 'check_systime': True,
 'expire': 1970372507.8829,
 'iden_1st_expire': 1665012507.0,
 'iden_expire': 1695012507.0,
 'iden_filt_func': <function protege.protege.<lambda>>,
 'iden_max_interval': 90,
 'iden_over': 'update',
 'iden_quantity': 600000,
 'iden_times': 100,
 'issue_time': 1655012507.8829,#签发授权的时间
 'level': 'trail',
 'mid': '896d9225bfb14429d603e5bad069a21a',
 'module': 'test_1',
 'receipt_time': 1655012507.9315019,#接受授权的时间
 'remain': 3649.9998979187785,#授权剩余时长(单位:天)
 'requires': ['test_3'],
 'status': {}}

用户接受授权

注意:用户接受授权为非必要操作,如果执行该操作,将会把授权信息嵌入protege包内,那么在验证授权时就无需再提供授权文件的路径

import protege
protege.receipt(file_path='passport')

模块验证授权

函数式应用
import protege
def test(file_path):
    checked=protege.check('test_1',key='12345678',file_path=file_path)
    print('test_1 checked success')
    #do something, you can use the item of checked

test(file_path='passport')
protege.Protege子类应用
import protege,sys
class test_2(protege.Protege):
    def __init__(self,**kwargs):
        super(test_2,self).__init__(attrs=kwargs.get('attrs',[]),file_path=kwargs.get('file_path'))
        self._1=1
        self._2=2
    
    def func_1(self):
        f_global_name=sys._getframe().f_globals['__name__']; sys._getframe().f_globals['__name__']=self.__module__+'.'+self.__class__.__name__
        print('self._1',self._1,'self._2',self._2)
        sys._getframe().f_globals['__name__']=f_global_name

    def func_2(self):
        self.check='12345678'
        checked=self.check
        print('test_2.func_2 checked success')
        
    def func_3(self):
        self.check='12345678'
        checked=self.check
        checked['iden_filt_func']=lambda x:True
        print('test_2.func_3.iden success:',self.iden([1,2,3],checked=checked))
        
    def func_4(self,ids,id_var,file_path):
        self.check='12345678'
        checked=self.check
        self.iden(ids,id_var=id_var,checked=checked,update=True,file_path=file_path)
        print('test_2.func_4.iden success, 解密信息已保存在:',file_path)
        
t=test_2(attrs=['_1'],file_path='passport')
t=test_2(attrs=['_1'],file_path=['passport','passport'])#多个授权文件,文件名放在list里

#_1是外部无法访问的属性,查看_1、_2在内外部无法访问时的区别
print('self._1',t._1,'self._2',t._2)
t.func_1()

#验证
t.func_2()

#加密关键信息
t.func_3()

运行结果示例

self._1 None self._2 2
self._1 1 self._2 2

test_2.func_2 checked success

test_2.func_3.iden success: [(1, 'obA7E/ZedeQ='), (2, 'cvm4Ezf4A84='), (3, 'TRoMrlqLxls=')]
#制作关键信息解密文件,
import numpy,pandas
ids=pandas.DataFrame(numpy.random.randint(1,20,size=(100,3)))
t.func_4(ids,id_var=2,file_path='iden')

解密文件保存在iden文件中,该文件内容如下所示:

4,IHvbSM2wwX8=
7,XnLremSGBNc=
12,DXre50LiYcc=
8,HL2kXHECV14=
8,HL2kXHECV14=
6,0iSEPK9aGEI=
7,XnLremSGBNc=
4,IHvbSM2wwX8=
1,mhhAZ5BSE9c=
5,UkSOItgDANM=
11,F2RpOJKIC70=
19,dW/H5Di+cDI=
...

按照授权项{'iden_filt_func':'lambda x:int(x[1])%5==0'}, ids中当列1的值能被5整除时,被加密的列2才是正确的,当列1的值不能被5整除时,被加密的列2是随机输出的。

模块编译

开发者在应用protege时,需要在程序使用自定义的密钥,为了不泄漏密钥,开发者可以对程序进行编译,将程序编译成.c、以及.pyd(Windows)或.o(Linux),编译后的模块可直接作为python模块,使用import导入。

注意:模块编译需要操作系统具备C编译库,Windows需要Microsoft Visual C++ 14.0,Linux需要glibc-2.14

示例,将如下代码保存为test.py文件。

import protege
def test(file_path):
    checked=protege.check('test_1',key='12345678',file_path=file_path)
    print('test_1 checked success')
    #do something, you can use the item of checked

执行编译

import protege
protege.build('test.py')

运行成功后,即可在当前目录下看到test.pydtest.o文件,在test.py同目录下,可以看到test.c文件

假设,test.pydtest.o放在C:/目录下,用如下方式导入和使用模块:

import sys
sys.path.append('C:/')

import test
test.test(file_path='passport')

Exceptions

  • key must be not None
    protege.issue()签发授权时,key不能为空

  • no pass
    protege.receipt()接受授权时,passport和file_path不能全为空

  • pass cannot be found
    protege.check()授权验证时,无法找到授权项

  • pass cannot be parsed
    protege.check()授权验证时,由于提供的key不对,无法解析授权项

  • pass not this module
    protege.check()授权验证时,没有发现本模块的授权,需检查授权标识是否正确,protege.Protege子类的授权标识为module_name.class_name,当类不属于任何module时,module_name是__main__

  • pass not this machine
    protege.check()授权验证时,没有与实际机器码一致的授权

  • sys time error
    protege.check()授权验证时,发现操作系统时间可能存在误差,如果是微小的误差,可以稍后再试

  • pass expired
    protege.check()授权验证时,已超过授权期限

  • used_times or used_quantity more than limit
    Protege.iden()制作关键信息解密文件时,已超过次数或数量限制

  • iden_expire
    Protege.iden()制作关键信息解密文件时,已超过期限

  • iden_1st_expire
    Protege.iden()制作关键信息解密文件时,已超过首次期限

  • iden_max_interval
    Protege.iden()制作关键信息解密文件时,已超过两次最大时间间隔

  • Microsoft Visual C++ 14.0 is required
    protege.build()编译模块时,操作系统没有C++编译库;Linux下会报glic错误。

  • each element of ‘ext_modules’ option must be an Extension instance or 2-tuple
    protege.build()编译模块时,操作系统没有C++编译库,在spyder等集成开发环境下会报这个错。

Others

如何确保protege不被修改

通过md5验证protege的文件是否被更改,可以确保protege不被修改

import protege,hashlib
hashlib.md5(open(protege.protege.__file__,'rb').read()).hexdigest()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值