本文档适用于有高安全性、高隐私性、知识产权等数据存储、分发、商业化等需求的企业和个人。通过本文档,指导开发者使用迅雷链文件系统,进行数据的上传、下载、复制、删除、授权等行为,并基于此文档进行二次开发,使产品具备大数据分布式存储与信息上链等特性,让产品快速集成海量存储、不可篡改、可追溯、永不丢失、安全加密、授权转移等能力。
v3.0.2(2019/1/7)
迅雷链文件系统(简称TCFS,全称为Thunder Chain File System)是迅雷在百万级共享计算节点的基础上,使用独创的分布式技术专为区块链打造的数据云存储与授权分发的开放式文件系统。开发者可使自己的产品具备文件数据分布式存储与信息上链等特性,从而快速集成公开透明、不可篡改、可追溯、高可靠、安全加密、海量存储、授权转移等能力。
主要有四个特性:
APP ID指开发者在开放平台注册时生成的用于标明所属应用的编号。
APP Key指开发者在开放平台注册时与APP ID一起生成的,不可外露,它通过MD5加密作为APP ID的令牌(标记为APP Sign,具体加密方法详见3.3)。
APP Sign指APP Key经过MD5加密生成的令牌,调用SDK接口时,需要将APP ID 和APP Sign一起传给SDK进行验证身份。 APP Sign生成方式: MD5(APP ID+APP Key+ts),其中ts是签名的过期时间(unix时间戳),单位为秒,计算示例详见5.2.3。
公钥(Public Key)与私钥(PrivateKey)是通过非对称加密算法得到的一个密钥对(即一个公钥和一个私钥)。地址(Address)是由公钥经过单向的加密哈希算法计算得到的编码值。在系统中,Address是用来标识用户, 标识文件的拥有者信息,这些信息会用于用户签名(User Sign)。Public Key/Private Key/Address是以keyjson的格式存储,生成方法见6.8.2节。
用户签名用于证明当前操作经过特定用户的授权,签名一般有以下几种获取方式:
TCFS Path是基于授权的内容寻址规范,是将用户授权与merkle DAG目录结构结合的一种路径形式,格式定义如下:
格式:/tcfs/[owner]:[visitor]:[ts]:[sign]:[pathlength]/[newest or hash]/[path]/[filename]
详细见5.8节 TCFS Path详细说明
个人或者企业开发者要使用迅雷链文件系统前,必须先注册为开放平台的用户。手机号码是用户唯一标识。注册成功后,可以绑定邮箱,个人/企业认证,应用创建等操作,参见迅雷链新手指南
开发者完成应用创建并通过审核便会下发APP ID和App Key给到开发者,可在管理中心-应用中心-应用详情中查阅 APP ID指开发者在云存储注册时生成的用于标名所属业务的编号,App Key指开发者APP ID对应的加密key,作为APP ID的令牌,App Key需要开发者妥善保管。
规格 | 购买12个月 | 当前优惠活动 |
---|---|---|
100GB | 优惠价99链克 | 满12个月返还99链克 |
说明:每次购买只能是100GB的整数倍。
企业和个人开发者需要进行注册,经过审批后,会得到一个APP ID以及对应的APP Key。在调用接口时,需要传入APP ID以及部分参数的MD5值,迅雷链文件系统内部会校验两者是否匹配和合法,以验证身份。
APP ID/APP Key的验证逻辑在迅雷链文件系统的所有接口中均需要使用。
举例说明:
APP ID = de61d625adef267d69d63ca711939d685ffc8007
APP Key = 4daa50d08a107185af2c015cba126575781f7b20
ts = 1529114930
APP Sign = md5sum("de61d625adef267d69d63ca711939d685ffc80074daa50d08a107185af2c015cba126575781f7b201529114930")=2b2cface59cc85b0916a6c46b68f2f20
其中ts是签名的过期时间(unix时间戳) 在 6.1参数结构定义中,传入的参数如下
TCFSAppCertification ac{
appid=”de61d625adef267d69d63ca711939d685ffc8007”
timestamp=1529114930
appSign=”2b2cface59cc85b0916a6c46b68f2f20”
}
使用迅雷链文件系统中AddFile接口进行文件上传,需要进行APP ID/APP Key的验证,以及Address的身份签名认证。验证通过后将读取本地文件,对文件进行编码切片,然后将切片分发到共享节点,并且将文件的文件信息写入迅雷链文件系统。
第三方App在需要文件上传时,只需要完成如下步骤即可完成文件上传:
使用迅雷链文件系统对文件进行下载时,是只能下载上传过的文件,没有上传过的文件以及没有权限的文件是不能进行下载的。下载文件需要进行APPID/APPKey的验证,以及Address的身份签名认证。
第三方App在需要下载文件时,只需要完成如下步骤即可完成文件下载:
迅雷链文件系统中的复制功能是用于将用户A(AddressA)所拥有的文件FA复制给用户B(AddressB),用户B的存储空间中也将拥有文件FA。
第三方App在需要下复制文件时,只需要完成如下步骤即可完成文件复制:
通过第三方后台获取APP Sign,计算方式详见3.3
通过5.7节中描述的方式获取要分享路径的签名,并生成带有sign的tcfspath 通过SDK签名函数签名的分享路径示例:
1)needSignData = Address_A(文件拥有者地址) + Address_B(要分享给目的地址) + ts(是签名的过期时间,unix时间戳) + path(要分享的path,例如/tcfs/::::/newest/abc, 则path是/newest/abc)
2)通过TCFS_UserSign获取needSignData的签名数据signData
3)用signData生成带sign的tcfspath,详见5.8
调用TCFS_Copy接口
迅雷链文件系统中的删除功能是将用户A(addressA)的文件FA从最新的目录树中删除,该文件不再参与计费。系统定期清理未付费文件,所以删除后一段时间可能仍被成功访问,但文件的操作历史会一直保留。
第三方App在删除文件时,只需要需要完成如下步骤即可完成文件删除:
签名是指在接口中用于验证Address身份是否合法的认证信息。设计sign的目的是在用户的钱包用私钥进行签名时需要使用用户私钥,为了简化多次使用私钥,所以设计带有时限的签名用于一次签名后将签名保存起来,每次调用迅雷链文件系统SDK接口时将签名直接传入,以达到一次签名多次使用的目的。
一般的,TCFS_UserSign (keyjson, passwd, data,sign, signLen),其中keyjson为此用户钱包对应的keystore文件, passwd表示用户的密码,data是要签名的数据, sign是签名存放的地址,signlLen签名地址最大存放的字节数。
签名sign获取,一般由以下三种获取方式:
/tcfs/[owner]:[visitor]:[ts]:[sign]:[pathlength]/[newest/hash]/[pathname]/[filename]
其中:
/为保留字符
tcfs为关键字,不可更改
owner为此路径的所有者地址
visitor为此路径的访问者地址
ts是签名的过期时间(unix时间戳)
sign表示文件所有者owner给访问者visitor此文件的授权签名,其中sign=UserSign(owner+visitor+ts+path[0:pathlength]),迅雷链文件系统会对签名进行验证,在有效时间戳时间内,签名一致,即可认为授权通过
pathlength表示文件路径中需要授权的文件路径长度
[newest/hash]/[pathname]/[filename]为文件路径的2种表示格式,newest/[pathname]/[filename]表示此文件对应的最新版本;hash/[pathname]/[filename]表示此文件对应的hash路径下的文件。
文件路径的格式是基于目录结构的。并且目录结构需要支持newest与hash访问2种方式,在目录节点上,所有的节点都有版本信息,对应的hash值,以及newest指向当前目录结构的最新版本节点。
上图中,初始时newest指向空,添加f1结点后,newest指向version1。
上图中,添加d2/f2文件后,newest指针指向version2版本,并且所有的节点都有hash信息,用于提供hash目录查询功能。比如访问f1,采用hash的方式为/hash_v1/f1或者/hash_v2/f1均可以访问;采用newest的方式为/newest/f1。
以下对格式进行详细举例说明:
格式1,带签名的newest格式
/tcfs/owner:visitor:ts:sign:pathlength/newest/[pathname]/[filename]
/tcfs/0x7eff122b94897ea5b0e2a9abf47b86337fafebdc:0xd5e51811fd8d4525aaa247e5d96800462b057db3:1535709360:0x052cb64baeeb12f49dd6c5d6db7ec93f0c5d45dc1bc1f728d0a2170bdd52af4f75fb02b4ed09825756dccdc55b8b09c6ab0ad11ccab441c9c9d0b7cb25e002b500:12/newest/abc/lib/
owner:0x7eff122b94897ea5b0e2a9abf47b86337fafebdc,表示此owner对目录/newest/abc/lib/的所有权
visitor: 0xd5e51811fd8d4525aaa247e5d96800462b057db3,表示此visitor需要访问/newest/abc/lib/目录
ts: 1535709360,表示owner对visitor访问owner所有目录/newest/abc/lib/的授权签名有效截止时间戳(unix时间戳)。
sign: 0x052cb64baeeb12f49dd6c5d6db7ec93f0c5d45dc1bc1f728d0a2170bdd52af4f75fb02b4ed09825756dccdc55b8b09c6ab0ad11ccab441c9c9d0b7cb25e002b500,表示此owner对visitor访问owner所有目录/newest/abc/lib/的授权签名。
pathlength:12。表示是对目录授权路径的长度,12表示是对/newest/abc/目录签名,并且规定对父路径签名之后,对子路径也拥有访问权。
path:/newest/abc/lib/,表示visitor需要访问的目录。
格式2,不带签名的newest格式
/tcfs/::::/newest/[pathname]/[filename]
/tcfs/::::/newest/中文目录3/abc/ddd
path: /newest/中文目录3/abc/ddd。表示owner需要访问的目录。注意没有签名sign字段时,只能是owner访问自己的目录。在6节接口列表中会由其它参数传递owner。
格式3,带签名的hash格式
/tcfs/0x7eff122b94897ea5b0e2a9abf47b86337fafebdc:0xd5e51811fd8d4525aaa247e5d96800462b057db3:1536148761:0xde2baffe959990d641be0aff1864fa27149212b2ccd774614c8a8bf63552d44c5bc9b334ded33722b52c7e53d91e68480574fe9342c2ad5e49f9f025af2348ce00:46/5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/
owner:0x7eff122b94897ea5b0e2a9abf47b86337fafebdc,表示此owner对目录/5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/的所有权
visitor: 0xd5e51811fd8d4525aaa247e5d96800462b057db3,表示此visitor需要访问/5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/目录
ts: 1536148761,表示owner对visitor访问owner所有目录授权签名有效截止时间戳(unix时间戳)。
sign: 0xde2baffe959990d641be0aff1864fa27149212b2ccd774614c8a8bf63552d44c5bc9b334ded33722b52c7e53d91e68480574fe9342c2ad5e49f9f025af2348ce00,表示此owner对visitor访问owner所有目录的授权签名。
pathlength:46。表示是对目录授权路径的长度,46表示是对/5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/目录签名,并且规定对父路径签名之后能够对子路径拥有访问权。
path: /5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/,表示visitor需要访问的目录。
格式4,不带签名的hash格式
/tcfs/::::/5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/
path: /5415dc5c31c6e4849fb6063ba09ff18365c25a21/abc/。表示owner需要访问的目录。注意没有签名sign字段时,只能是owner访问自己的目录
注意:目前为止,TCFS SDK仅仅支持ubuntu 16.04(x64)系统
//Error code
enum{
TCFS_ERRCODE_OK = 0,
TCFS_ERRCODE_INITIALIZE_ERROR,
TCFS_ERRCODE_ALREADY_INITIALIZED,
TCFS_ERRCODE_UNINITIALIZED,
TCFS_ERRCODE_PATH_ERROR,
TCFS_ERRCODE_TCFS_PATH_ERROR,
TCFS_ERRCODE_APPID_VERIFY_FAILED,
TCFS_ERRCODE_ADDRESS_VERIFY_FAILED,
TCFS_ERRCODE_NO_ENOUGH_SPACE,
TCFS_ERRCODE_SIGN_FAILED,
TCFS_ERRCODE_EXCCED_USER_MEM,
TCFS_ERRCODE_ACCESS_SERVER_FAILED,
TCFS_ERRCODE_ACCESS_FILE_FAILED,
TCFS_ERRCODE_EXCCED_MAX_FILE_NUM
};
//文件或文件夹信息
struct TreeNodeT
{
char path[MAX_PATH_LEN + 1]; //文件或文件夹路径
char hash[HASH_LEN + 1]; //在目录树中的HASH
uint64_t ctime; //创建时间
uint64_t size; //文件大小,是文件夹时没有意义
int type; //标明是文件还是文件夹,0是文件,1是文件夹
};
struct TCFSAppCertification { // 开发者签发的证书
char appid[64]; // 开发者标识
uint64_t timestamp; // sign的过期时间点(秒)
char appSign[64]; // 对开发者身份的校验值
};
struct TCFSUserCertification { // 用户签发的证书
char address[64]; // 用户身份标识
uint64_t timestamp; // 签名的过期时间点(秒)
char userSign[128]; // 对结构体中成员的签名,用于对用户身份进行自校验
};
int TCFS_Init()
参数名 | 类型 | 说明 |
---|---|---|
ret | int | 如果上传任务添加成功返回0,失败返回ErrorCode |
int TCFS_Uninit()
参数名 | 类型 | 说明 |
---|---|---|
ret | int | 如果上传任务添加成功返回0,失败返回ErrorCode |
int TCFS_Upload(TCFSAppCertification appCert, TCFSUserCertification userCert, const char srcPath, const char tcfsPath, bool isDir);
参数名 | 类型 | 说明 |
---|---|---|
appCert | TCFSAppCertification* | 用于传入开发者的鉴权信息 |
userCert | TCFSUserCertification* | 用于传入文件拥有者鉴权信息,其中userSign= TCFS_UserSign(keyjson, passwd, addr+appid+timestamp) |
srcPath | const char* | 指需要上传的文件路径,只支持本地文件 |
tcfsPath | const char* | 指目的TCFS目录,不带sign的newest格式 |
isDir | bool | 表明上传的是文件还是文件夹 |
参数名 | 类型 | 说明 |
---|---|---|
ret | int | 如果上传任务添加成功返回0,失败返回ErrorCode |
int TCFS_Download(TCFSAppCertification appCert, TCFSUserCertification userCert, const char dstPath, const char tcfsPath, bool isDir)
参数名 | 类型 | 说明 |
---|---|---|
appCert | TCFSAppCertification* | 用于传入开发者的鉴权信息 |
userCert | TCFSUserCertification* | 用于传入文件拥有者鉴权信息,其中userSign= TCFS_UserSign(keyjson, passwd, addr+appid+timestamp) |
dstPath | const char* | 下载的目标路径 |
tcfsPath | const char* | 指需要取回的文件TCFS路径,支持目录 |
isDir | bool | 用于指定要下载的是文件还是文件夹 |
参数名 | 类型 | 说明 |
---|---|---|
ret | int | 如果下载任务添加成功返回0,失败返回ErrorCode |
int TCFS_Delete(TCFSAppCertification appCert, TCFSUserCertification userCert, const char *tcfsPath, int isDir)
参数名 | 类型 | 说明 |
---|---|---|
appCert | TCFSAppCertification* | 用于传入开发者的鉴权信息 |
userCert | TCFSUserCertification* | 用于传入文件拥有者鉴权信息,其中userSign= TCFS_UserSign(keyjson, passwd, addr+appid+timestamp) |
tcfsPath | const char* | 指需要删除的文件路径,支持目录 |
参数名 | 类型 | 说明 |
---|---|---|
ret | int | 如果删除成功返回0,失败返回ErrorCode |
int TCFS_Copy(TCFSAppCertification appCert, TCFSUserCertification userCert, const char signTcfsPath, const char tcfsPath)
参数名 | 类型 | 说明 |
---|---|---|
appCert | TCFSAppCertification* | 用于传入开发者的鉴权信息 |
userCert | TCFSUserCertification* | 用于传入文件拥有者鉴权信息,其中userSign= TCFS_UserSign(keyjson, passwd, addr+appid+timestamp) |
signTcfsPath | const char* | 指需要拷贝的TCFS文件路径,支持目录,必须为带sign的newest/hash的TCFS路径格式 |
tcfsPath | const char* | 指目的TCFS目录,不带sign的newest格式 |
参数名 | 类型 | 说明 |
---|---|---|
ret | int | 如果拷贝成功返回0,失败返回ErrorCode |
int TCFS_UserSign(const char keyjson, const char password, const char data, char signData, int signLen)
参数名 | 类型 | 说明 |
---|---|---|
keyjson | const char* | 用户的私钥文件串keyjson, 获取详见6.8.2 |
password | const char* | 用户私钥文件对应的密码 |
data | const char* | 需要进行签名的数据 |
signData | char* | 用于返回得到的签名数据数组 |
signLen | int | sign数组的长度 |
参数名 | 类型 | 说明 |
---|---|---|
ret | int | 如果成功返回0,失败返回ErrorCode |
const keyJson = `{
"address":"7eff122b94897ea5b0e2a9abf47b86337fafebdc",
"id":"f86a62b4-0621-4616-99af-c4b7f38fcc48","version":3,
"crypto":{
"cipher":"aes-128-ctr","ciphertext":"19de8a919e2f4cbdde2b7352ebd0be8ead2c87db35fc8e4c9acaf74aaaa57dad",
"cipherparams":{"iv":"ba2bd370d6c9d5845e92fbc6f951c792"},
"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"c7cc2380a96adc9eb31d20bd8d8a7827199e8b16889582c0b9089da6a9f58e84"},
"mac":"ff2c0caf051ca15d8c43b6f321ec10bd99bd654ddcf12dd1a28f730cc3c13730"
}
}`
pwd := "1234"
appid := "de61d625adef267d69d63ca711939d685ffc8007"
address := "0x7eff122b94897ea5b0e2a9abf47b86337fafebdc"
ts := 1529216849
filehash := ""
sign_str := appid + address + fmt.Sprintf("%d", ts) + nonce + filehash
sign, err := UserSign (keyJson, pwd, sign_str)
其中:
ts是签名的过期时间(unix时间戳)
sign_str= de61d625adef267d69d63ca711939d685ffc80070x7eff122b94897ea5b0e2a9abf47b86337fafebdc1529216849abcdefgh
sign= a54a4c369f608d3966dc531324795073585e288fd908e47c017302e514f8790a7bd41a2cb020230f14a48fb4d9d6f88eb33019b3b1f6ef097c486938324f593601
以下是使用链克口袋生成keyjson的步骤:
新建账户
点击右上角 新建账户,在新建页面输入 密码。
导出keystore文件
导出备份,就可以获取keystore文件, keystore文件内容即是keyjson。
int TCFS_ListDir(TCFSAppCertification appCert, TCFSUserCertification userCert, const char tcfsPath, int start, int len, TreeNodeT node[], int maxNodeNum, int realNodeNum)
参数名 | 类型 | 说明 |
---|---|---|
appCert | TCFSAppCertification* | 用于传入开发者的鉴权信息 |
userCert | TCFSUserCertification* | 用于传入文件拥有者鉴权信息,其中userSign= TCFS_UserSign(keyjson, passwd, addr+appid+timestamp) |
tcfsPath | const char* | 指目的TCFS目录,不带sign的newest/hash格式 |
start | int | 需要返回的起始的节点 |
length | int | 需要返回的节点个数 |
node | TreeNodeT*[] | 用于存放返回的文件或者文件夹数组 |
maxNodeNum | int | 用于指定最大可存放文件或者文件夹条目 |
realNodeNum | int | 用于返回真正存储的文件或者文件夹条目 |
参数名 | 类型 | 说明 |
---|---|---|
ret | int | 如果成功返回0,失败返回ErrorCode |
int TCFS_ListTree(TCFSAppCertification appCert, TCFSUserCertification userCert, const char tcfsPath, TreeNodeT node[], int maxNodeNum, int realNodeNum)
参数名 | 类型 | 说明 |
---|---|---|
appCert | TCFSAppCertification* | 用于传入开发者的鉴权信息 |
userCert | TCFSUserCertification* | 用于传入文件拥有者鉴权信息,其中userSign= TCFS_UserSign(keyjson, passwd, addr+appid+timestamp) |
tcfsPath | const char* | 指目的TCFS目录,不带sign的newest/hash格式 |
start | int | 需要返回的起始的节点 |
length | int | 需要返回的节点个数 |
node | TreeNodeT*[] | 用于存放返回的文件或者文件夹数组 |
maxNodeNum | int | 用于指定最大可存放文件或者文件夹条目 |
realNodeNum | int | 用于返回真正存储的文件或者文件夹条目 |
参数名 | 类型 | 说明 |
---|---|---|
ret | int | 如果成功返回0,失败返回ErrorCode |
int TCFS_GetSpace(TCFSAppCertification appCert, TCFSUserCertification userCert, uint64_t totalSize, uint64_t usedSize)
参数名 | 类型 | 说明 |
---|---|---|
appCert | TCFSAppCertification* | 用于传入开发者的鉴权信息 |
userCert | TCFSUserCertification* | 用于传入文件拥有者鉴权信息,其中userSign= TCFS_UserSign(keyjson, passwd, addr+appid+timestamp) |
totalSize | uint64_t* | 用于返回用户总空间 |
usedSize | uint64_t* | 用于返回用户已用空间 |
参数名 | 类型 | 说明 |
---|---|---|
ret | int | 如果成功返回0,失败返回ErrorCode |