WeIdentity RestService API 说明文档¶
基于私钥托管模式的RestService API¶
1. 总体介绍¶
每个API的入参都是满足以下格式的json字符串:
{
"functionArg": 随调用SDK方法而变的入参json字符串 {
...
},
"transactionArg": 交易参数json字符串 {
"invokerWeId": 用于索引私钥的WeIdentity DID,服务器端会凭此找到所托管的私钥(非必须)
}
"functionName": 调用SDK方法名
"v": API版本号
}
参数说明:
functionArg是随不同的SDK调用方法而变的,具体的参数可以查看SDK接口文档;后文会为每个所提及的接口给出对应的链接
- transactionArg仅包括一个变量invokerWeId,由传入方决定使用在服务器端托管的具体哪个WeIdentity DID所对应的私钥
- 非必需,只有在那些需要使用不同身份进行写交易签名的方法(如CreateAuthorityIssuer等)才会需要;后文中详细说明
functionName是调用的SDK方法名,用于决定具体调用WeIdentity Java SDK的什么功能
v是调用的API方法版本
每个API的接口返回都是满足以下格式的json字符串:
{
"respBody": 随调用SDK方法而变的输出值json字符串 {
}
"ErrorCode": 错误码
"ErrorMessage": 错误信息,成功时为"success"
}
其中具体的输出值result亦是随不同的SDK调用方法而变的。
在后文中,我们将会逐一说明目前所提供的功能及其使用方式。
2. 创建WeIdentity DID(无参创建方式)¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/invoke |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
functionName | createWeId | Y |
functionArg | Y | |
transactionArg | Y | |
v | 版本号 | Y |
注解
基于托管模式的RestService不允许通过传入公钥参数的方式创建WeID。这是因为,这样生成的WeID私钥不存在于RestService本地,因此无法在后续过程中被调用。如果您需要通过传入公钥方式创建WeID,请使用基于轻客户端方式的接口创建。
接口入参示例:
{
"functionArg": {
},
"transactionArg": {
},
"functionName": "createWeId",
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | WeIdentity DID |
返回示例:
{
"ErrorCode": 0,
"ErrorMessage": "success",
"respBody": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
}
3. 获取WeIdentity DID Document¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/invoke |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
functionName | getWeIdDocument | Y |
functionArg | Y | |
functionArg.weId | WeIdentity DID,与SDK直接调用的方式入参要求一致,下同 | Y |
transactionArg | N,传空 | |
v | 版本号 | Y |
接口入参示例:
{
"functionArg": {
"weId": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
},
"transactionArg": {
},
"functionName": "getWeIdDocument",
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | WeIdentity DID Document |
返回示例:
{
"respBody": {
"@context" : "https://w3id.org/did/v1",
"id" : "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"created" : 1553224394993,
"updated" : 1553224394993,
"publicKey" : [ ],
"authentication" : [ ],
"service" : [ ]
},
"ErrorCode": 0,
"ErrorMessage": "success"
}
4. 创建AuthorityIssuer¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/invoke |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
functionName | registerAuthorityIssuer | Y |
functionArg | Y | |
functionArg.weId | WeIdentity DID,与SDK直接调用的方式入参一致,下同 | Y |
functionArg.name | 机构名 | Y |
transactionArg | Y | |
transactionArg.invokerWeId | 用于索引私钥的WeIdentity DID,服务器端会凭此找到所托管的私钥。注意:如果在这里填入了预先定义在application.properties里的暗语,则可确保有足够的权限。 | Y |
v | 版本号 | Y |
接口调用示例:
{
"functionArg": {
"weid": "did:weid:0x1Ae5b88d37327830307ab8da0ec5D8E8692A35D3",
"name": "Sample College"
},
"transactionArg": {
"invokerWeId": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
},
"functionName": "registerAuthorityIssuer",
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | True/False |
返回示例:
{
"ErrorCode": 0,
"ErrorMessage": "success",
"respBody": True
}
5. 查询AuthorityIssuer¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/invoke |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
functionName | queryAuthorityIssuer | Y |
functionArg | Y | |
functionArg.weId | WeIdentity DID,与SDK直接调用的方式入参一致,下同 | Y |
transactionArg | N,传空 | |
v | 版本号 | Y |
接口入参示例:
{
"functionArg": {
"weId": "did:weid:0x1ae5b88d37327830307ab8da0ec5d8e8692a35d3"
},
"transactionArg": {
},
"functionName": "queryAuthorityIssuer",
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | 完整的Authority Issuer信息 |
{
"respBody": {
"accValue": ,
"created": 16845611984115,
"name": "Sample College",
"weid": "did:weid:0x1ae5b88d37327830307ab8da0ec5d8e8692a35d3"
}
"ErrorCode": 0
"ErrorMessage": "success"
}
6. 创建CPT¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/invoke |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
functionName | registerCpt | Y |
functionArg | Y | |
functionArg.cptJsonSchema | CPT Json Schema,与SDK直接调用的方式入参一致,下同 | Y |
functionArg.weId | CPT创建者 | Y |
transactionArg | Y | |
transactionArg.invokerWeId | 用于索引私钥的WeIdentity DID,服务器端会凭此找到所托管的私钥 | Y |
v | 版本号 | Y |
CPT Json Schema是什么?应该满足什么格式?
答:Json Schema是一种用来定义Json字符串格式的Json字符串,它定义了CPT应包括的字段、属性及规则。
WeIdentity可以接受 http://json-schema.org/draft-04/schema# 所定义第四版及之前版本作为入参。
接口入参示例:
{
"functionArg": {
"weId": "did:weid:0x1ae5b88d37327830307ab8da0ec5d8e8692a35d3",
"cptJsonSchema":{
"title": "cpt",
"description": "this is cpt",
"properties": {
"name": {
"type": "string",
"description": "the name of certificate owner"
},
"gender": {
"enum": [
"F",
"M"
],
"type": "string",
"description": "the gender of certificate owner"
},
"age": {
"type": "number",
"description": "the age of certificate owner"
}
},
"required": [
"name",
"age"
]
}
},
"transactionArg": {
"invokerWeId": "did:weid:0x1ae5b88d37327830307ab8da0ec5d8e8692a35d3"
},
"functionName": "registerCpt",
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | cptBaseInfo |
返回示例:
{
"respBody": {
"cptId": 2000001,
"cptVersion": 1
},
"ErrorCode": 0,
"ErrorMessage": "success"
}
7. 查询CPT¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/invoke |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
functionName | queryCpt | Y |
functionArg | Y | |
functionArg.cptId | CPT ID,与SDK直接调用的方式入参一致。 | Y |
transactionArg | N,传空 | |
v | 版本号 | Y |
接口入参示例:
{
"functionArg": {
"cptId": 10,
},
"transactionArg": {
},
"functionName": "queryCpt",
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | 完整的CPT信息 |
接口返回示例:
{
"respBody": {
"cptBaseInfo" : {
"cptId" : 10,
"cptVersion" : 1
},
"cptId" : 10,
"cptJsonSchema" : {
"$schema" : "http://json-schema.org/draft-04/schema#",
"title" : "a CPT schema",
"type" : "object"
},
"cptPublisher" : "did:weid:0x104a58c272e8ebde0c29083552ebe78581322908",
"cptSignature" : "HJPbDmoi39xgZBGi/aj1zB6VQL5QLyt4qTV6GOvQwzfgUJEZTazKZXe1dRg5aCt8Q44GwNF2k+l1rfhpY1hc/ls=",
"cptVersion" : 1,
"created" : 1553503354555,
"metaData" : {
"cptPublisher" : "did:weid:0x104a58c272e8ebde0c29083552ebe78581322908",
"cptSignature" : "HJPbDmoi39xgZBGi/aj1zB6VQL5QLyt4qTV6GOvQwzfgUJEZTazKZXe1dRg5aCt8Q44GwNF2k+l1rfhpY1hc/ls=",
"created" : 1553503354555,
"updated" : 0
},
"updated" : 0
},
"ErrorCode": 0,
"ErrorMessage": "success"
}
8. 创建Credential¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/invoke |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
functionName | createCredential | Y |
functionArg | Y | |
functionArg.claim | claim Json结构体,与SDK直接调用的方式入参一致,下同 | Y |
functionArg.cptId | CPT ID | Y |
functionArg.issuer | issuer WeIdentity DID | Y |
functionArg.expirationDate | 过期时间(使用UTC格式) | Y |
transactionArg | Y | |
transactionArg.invokerWeId | 用于索引私钥的WeIdentity DID,服务器端会凭此找到所托管的私钥 | Y |
v | 版本号 | Y |
接口入参:Json,以signature代替私钥
{
"functionArg": {
"cptId": 10,
"issuer": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"expirationDate": "2019-04-18T21:12:33Z",
"claim": {
"name": "zhang san",
"gender": "F",
"age": 18
},
},
"transactionArg": {
"invokerWeId": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
},
"functionName": "createCredential",
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | 完整的Credential信息 |
接口返回示例:
{
"respBody": {
"@context": "https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1",
"claim": {
"content": "b1016358-cf72-42be-9f4b-a18fca610fca",
"receiver": "did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754",
"weid": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
},
"cptId": 2000156,
"expirationDate": "2100-04-18T21:12:33Z",
"id": "da6fbdbb-b5fa-4fbe-8b0c-8659da2d181b",
"issuanceDate": "2020-02-06T22:24:00Z",
"issuer": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"proof": {
"created": "1580999040000",
"creator": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"signature": "G0XzzLY+MqUAo3xXkS3lxVsgFLnTtvdXM24p+G5hSNNMSIa5vAXYXXKl+Y79CO2ho5DIGPPvSs2hvAixmfIJGbw=",
"type": "Secp256k1"
}
},
"errorCode": 0,
"errorMessage": "success"
}
9. 验证Credential¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/invoke |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
functionName | verifyCredential | Y |
functionArg | Y | |
functionArg.claim | claim Json 结构体,与SDK直接调用的方式入参一致,下同 | Y |
functionArg.cptId | CPT ID | Y |
functionArg.context | context值 | Y |
functionArg.uuid | Credential的UUID | Y |
functionArg.issuer | issuer WeIdentity DID | Y |
functionArg.issuranceDate | 颁发时间 | Y |
functionArg.expirationDate | 过期时间 | Y |
functionArg.proof | Credential签名结构体 | Y |
transactionArg | N,传空 | |
v | 版本号 | Y |
接口入参:
{
"functionArg": {
"@context": "https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1",
"claim": {
"content": "b1016358-cf72-42be-9f4b-a18fca610fca",
"receiver": "did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754",
"weid": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
},
"cptId": 2000156,
"expirationDate": "2100-04-18T21:12:33Z",
"id": "da6fbdbb-b5fa-4fbe-8b0c-8659da2d181b",
"issuanceDate": "2020-02-06T22:24:00Z",
"issuer": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"proof": {
"created": "1580999040000",
"creator": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"signature": "G0XzzLY+MqUAo3xXkS3lxVsgFLnTtvdXM24p+G5hSNNMSIa5vAXYXXKl+Y79CO2ho5DIGPPvSs2hvAixmfIJGbw=",
"type": "Secp256k1"
}
},
"transactionArg": {
},
"functionName": "verifyCredential"
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | True/False |
接口返回:
{
"respBody": true,
"ErrorCode": 0,
"ErrorMessage": "success"
}
10. 创建CredentialPojo¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/invoke |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
functionName | createCredentialPojo | Y |
functionArg | Y | |
functionArg.claim | claim Json结构体,与SDK直接调用的方式入参一致,下同 | Y |
functionArg.cptId | CPT ID | Y |
functionArg.issuer | issuer WeIdentity DID | Y |
functionArg.expirationDate | 过期时间(使用UTC格式) | Y |
transactionArg | Y | |
transactionArg.invokerWeId | 用于索引私钥的WeIdentity DID,服务器端会凭此找到所托管的私钥 | Y |
v | 版本号 | Y |
接口入参:Json,以signature代替私钥
{
"functionArg": {
"cptId": 10,
"issuer": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"expirationDate": "2019-04-18T21:12:33Z",
"claim": {
"name": "zhang san",
"gender": "F",
"age": 18
},
},
"transactionArg": {
"invokerWeId": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
},
"functionName": "createCredentialPojo",
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | 完整的CredentialPojo信息 |
接口返回示例:
{
"respBody": {
"cptId": 2000156,
"issuanceDate": 1580996777,
"context": "https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1",
"claim": {
"content": "b1016358-cf72-42be-9f4b-a18fca610fca",
"receiver": "did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754",
"weid": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
},
"id": "21d10ab1-75fe-4733-9f1d-f0bad71b5922",
"proof": {
"created": 1580996777,
"creator": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa#keys-0",
"salt": {
"content": "ncZ5F",
"receiver": "L0c40",
"weid": "I4aop"
},
"signatureValue": "HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=",
"type": "Secp256k1"
},
"type": [
"VerifiableCredential",
"hashTree"
],
"issuer": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"expirationDate": 4111737153
},
"errorCode": 0,
"errorMessage": "success"
}
11. 验证CredentialPojo¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/invoke |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
functionName | verifyCredentialPojo | Y |
functionArg | Y | |
functionArg.claim | claim Json 结构体,与SDK直接调用的方式入参要求一致,下同 | Y |
functionArg.cptId | CPT ID | Y |
functionArg.context | context值 | Y |
functionArg.uuid | CredentialPojo的UUID | Y |
functionArg.issuer | issuer WeIdentity DID | Y |
functionArg.issuranceDate | 颁发时间 | Y |
functionArg.expirationDate | 过期时间 | Y |
functionArg.proof | Credential签名值 | Y |
transactionArg | N,传空 | |
v | 版本号 | Y |
接口入参:
{
"functionArg": {
"cptId": 2000156,
"issuanceDate": 1580996777,
"context": "https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1",
"claim": {
"content": "b1016358-cf72-42be-9f4b-a18fca610fca",
"receiver": "did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754",
"weid": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
},
"id": "21d10ab1-75fe-4733-9f1d-f0bad71b5922",
"proof": {
"created": 1580996777,
"creator": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa#keys-0",
"salt": {
"content": "ncZ5F",
"receiver": "L0c40",
"weid": "I4aop"
},
"signatureValue": "HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8=",
"type": "Secp256k1"
},
"type": [
"VerifiableCredential",
"hashTree"
],
"issuer": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"expirationDate": 4111737153
},
"transactionArg": {
},
"functionName": "verifyCredentialPojo"
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | True/False |
接口返回:
{
"respBody": true,
"ErrorCode": 0,
"ErrorMessage": "success"
}
基于轻客户端模式的RestService API¶
1. 总体介绍¶
基于轻客户端模式的API的入参形式与基于私钥托管模式的API相同,也是满足以下格式的json字符串。 最大的区别在于,流程包括两次交互,第一次是轻客户端提供接口参数发给RestService服务端,后者进行组装、编码区块链原始交易串并返回;第二次是轻客户端在本地使用自己的私钥,对原始交易串进行符合ECDSA的sha3签名,发给RestService服务端,后者打包并直接执行交易。
- 第一次交互
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/encode |
Method | POST |
Content-Type | application/json |
接口入参(Body):
{
"functionArg": 随调用SDK方法而变的入参json字符串 {
...
},
"transactionArg": 交易参数json字符串 {
"nonce": 用于防止重放攻击的交易随机数
}
"functionName": 调用SDK方法名
"v": API版本号
}
参数说明:
functionArg是随不同的SDK调用方法而变的,具体的参数可以查看SDK接口文档;后文会为每个所提及的接口给出对应的链接
- transactionArg仅包括一个变量nonce,用于防止重放攻击的交易随机数,您可以使用RestService jar的getNonce(),或其他类似方法生成此随机数。
- 必需,且必须妥善保存,这个nonce在第二次交互中还会用到
functionName是调用的SDK方法名,用于决定具体调用WeIdentity Java SDK的什么功能
v是调用的API方法版本
第一次交互的接口返回是以下格式的json字符串:
{
"respBody": {
"blockLimit": 建议使用的交易处理期限,
"encodedTransaction": 基于Base64编码的原始交易串信息
"data": 交易特征值
}
"ErrorCode": 错误码
"ErrorMessage": 错误信息,成功时为"success"
}
返回结构体包含encodedTransaction和data两项。 调用者随后需要使用自己的私钥对encodeTransaction进行交易签名,然后使用Base64对其进行编码,和data、nonce一起待用, 进行第二次交互。
注解
请注意使用的ECDSA签名算法的编码格式。WeID Java SDK所使用的是椭圆曲线Secp256k1算法,这也是WeID Go轻客户端的默认算法。一般来说,ECDSA的签名算法会生成R,S,V三个值,其中R和S是32个字节的二进制字节数组,而V,以太坊原生的Secp256k1算法的结果一般是0或1。
注解
当您生成签名的R,S,V之后,您需要将R,S,V存入一个65个字节长的二进制字节数组,再进行Base64编码方可正确由RestService解析。RestService只接受两种组成方式: 1. 按照R, S, V的顺序拼接成一个65个字节长的数组并使用Base64编码(这是WeID Go轻客户端默认方式) 2. 按照V, R, S的顺序拼接成一个65个字节长的数组并使用Base64编码(这是WeID Java SDK默认序列化方式)
您可以使用WeID Java SDK代码,使用默认Secp256k1私钥进行签名和Base64编码的范例代码见下(可以在WeID Java SDK的签名测试用例里编写和执行下面代码):
// 依赖weid-java-sdk 3.1.1-rc.1
byte[] decodeTransaction = DataToolUtils.base64Decode("<encodedTransaction的值>".getBytes());
String decodeTransactionStr = new String(decodeTransaction);
RsvSignature signatureResult = DataToolUtils.signToRsvSignature(decodeTransactionStr, privateKey);
String base64SignedMsg = DataToolUtils.SigBase64Serialization(signatureResult);
- 第二次交互
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/transact |
Method | POST |
Content-Type | application/json |
接口入参:
{
"functionArg": 空 {
},
"transactionArg": 交易参数json字符串 {
"nonce": 用于防止重放攻击的交易随机数
"blockLimit": 用于限制交易处理期限,需和第一步中返回值一致,
"signType": 签名类型,"1"表示RSV,"2"表示VRS,如果使用上面WeID Java SDK示例代码来签名,则填"2"
"data": 交易特征值,需和第一步中返回值一致
"signedMessage": 基于Base64编码的、使用私钥签名之后的encodedTransaction签名值
}
"functionName": 调用SDK方法名
"v": API版本号
}
这一步的目的是将已签名交易的参数发给RestService,并由后者将交易打包上链。参数说明:
- functionArg此时为空
- transactionArg包括第一次交互起始阶段生成的nonce、第一次交互收到的data,以及最重要的,使用调用者本地私钥签名并通过Base64编码的encodedTransaction的签名值
- functionName是调用的SDK方法名,用于决定具体调用WeIdentity Java SDK的什么功能
- v是调用的API方法版本
第二次交互的接口返回是以下格式的json字符串:
{
"respBody": 随调用SDK方法而变的输出值json字符串 {
}
"ErrorCode": 错误码
"ErrorMessage": 错误信息,成功时为"success"
}
其中具体的输出值result亦是随不同的SDK调用方法而变的。 可以看到,基于轻客户端的交易方式,本质上,是因为签名操作必须在本地完成,因此将原始交易串分成了两次交互完成。 基于轻客户端的每个API的入参,也仅仅在第一次交互中不同。因此,在下文的介绍中,我们会忽略第二次交互的入参,只提供第一次交互的入参和第二次交互的返回值。
1. 创建WeIdentity DID(有参创建方式)¶
第一次交互,POST /weid/api/encode 的接口入参:
Key | Value | Required |
---|---|---|
functionName | createWeId | Y |
functionArg | Y | |
functionArg.publicKey | ECDSA公钥,需要为10进制的整型数字,以字符串形式传入 | Y |
transactionArg | Y | |
transactionArg.nonce | 交易随机数 | Y |
v | 版本号 | Y |
第一次交互,POST /weid/api/encode 接口入参示例:
{
"functionArg": {
"publicKey": "712679236821355231513532168231727831978932132185632517152735621683128"
},
"transactionArg": {
"nonce": "1474800601011307365506121304576347479508653499989424346408343855615822146039"
},
"functionName": "createWeId",
"v": "1.0.0"
}
第二次交互,POST /weid/api/transact 接口入参示例:
{
"functionArg": {},
"transactionArg": {
"nonce": "1474800601011307365506121304576347479508653499989424346408343855615822146039",
"data": "809812638256c1235b1231000e000000001231287bacf213c",
"signedMessage": "HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8="
},
"functionName": "createWeId",
"v": "1.0.0"
}
第二次交互的接口返回:
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | WeIdentity DID |
返回示例:
{
"ErrorCode": 0,
"ErrorMessage": "success",
"respBody": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
}
3. 注册Authority Issuer¶
第一次交互,POST /weid/api/encode 的接口入参:
Key | Value | Required |
---|---|---|
functionName | registerAuthorityIssuer | Y |
functionArg | Y | |
functionArg.name | 机构名 | Y |
functionArg.weId | WeIdentity DID,与SDK直接调用的方式入参要求一致 | Y |
transactionArg | Y | |
transactionArg.nonce | 交易随机数 | Y |
v | 版本号 | Y |
第一次交互,POST /weid/api/encode 接口入参示例:
{
"functionArg": {
"name": "BV-College",
"weId": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
},
"transactionArg": {
"nonce": "1474800601011307365506121304576347479508653499989424346408343855615822146039"
},
"functionName": "registerAuthorityIssuer",
"v": "1.0.0"
}
第二次交互,POST /weid/api/transact 接口入参示例:
{
"functionArg": {},
"transactionArg": {
"nonce": "1474800601011307365506121304576347479508653499989424346408343855615822146039",
"data": "809812638256c1235b1231000e000000001231287bacf213c",
"signedMessage": "HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8="
},
"functionName": "registerAuthorityIssuer",
"v": "1.0.0"
}
第二次交互的接口返回:
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | Authority Isser信息 |
返回示例:
{
"ErrorCode": 0,
"ErrorMessage": "success",
"respBody": {
"accValue": ,
"created": "1581420650",
"name": "BV-College",
"weId": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
}
}
4. 创建CPT¶
第一次交互,POST /weid/api/encode 的接口入参:
Key | Value | Required |
---|---|---|
functionName | registerCpt | Y |
functionArg | Y | |
functionArg.cptJsonSchema | CPT Json Schema,与SDK直接调用的方式入参要求一致,下同 | Y |
functionArg.weId | CPT创建者 | Y |
functionArg.cptSignature | 创建者使用自己的私钥对cptJsonSchema的签名(和私钥托管方式不同,本方式特有) | Y |
transactionArg | Y | |
transactionArg.nonce | 交易随机数 | Y |
v | 版本号 | Y |
第一次交互,POST /weid/api/encode 接口入参示例:
{
"functionArg": {
"weId": "did:weid:0x1ae5b88d37327830307ab8da0ec5d8e8692a35d3",
"cptJsonSchema": {
"title": "cpt",
"description": "this is cpt",
"properties": {
"name": {
"type": "string",
"description": "the name of certificate owner"
},
"gender": {
"enum": [
"F",
"M"
],
"type": "string",
"description": "the gender of certificate owner"
},
"age": {
"type": "number",
"description": "the age of certificate owner"
}
},
"required": [
"name",
"age"
]
}
"cptSignature": "BaUeP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8="
},
"transactionArg": {
"nonce": "1474800601011307365506121304576347479508653499989424346408343855615822146039"
},
"functionName": "registerCpt",
"v": "1.0.0"
}
第二次交互,POST /weid/api/transact 接口入参示例:
{
"functionArg": {},
"transactionArg": {
"nonce": "1474800601011307365506121304576347479508653499989424346408343855615822146039",
"data": "809812638256c1235b1231000e000000001231287bacf213c",
"signedMessage": "HEugP13uDVBg2G0kmmwbTkQXobsrWNqtGQJW6BoHU2Q2VQpwVhK382dArRMFN6BDq7ogozYBRC15QR8ueX5G3t8="
},
"functionName": "registerAuthorityIssuer",
"v": "1.0.0"
}
第二次交互的接口返回:
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | Authority Isser信息 |
返回示例:
{
"ErrorCode": 0,
"ErrorMessage": "success",
"respBody": {
"cptId": 2000001,
"cptVersion": 1
}
}
5. 创建CredentialPojo¶
创建CredentialPojo不需要进行区块链交互,因此,只需要进行一次交互POST /weid/api/encode,然后对返回的结果进行签名即可:
POST /weid/api/encode 接口入参
Key | Value | Required |
---|---|---|
functionName | createCredentialPojo | Y |
functionArg | Y | |
functionArg.claim | claim Json结构体,与SDK直接调用的方式入参一致,下同 | Y |
functionArg.cptId | CPT ID | Y |
functionArg.issuer | issuer WeIdentity DID | Y |
functionArg.expirationDate | 过期时间(使用UTC格式) | Y |
transactionArg | 为空 | Y |
v | 版本号 | Y |
接口入参:Json,以signature代替私钥
{
"functionArg": {
"cptId": 10,
"issuer": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"expirationDate": "2019-04-18T21:12:33Z",
"claim": {
"name": "zhang san",
"gender": "F",
"age": 18
},
},
"transactionArg": {
},
"functionName": "createCredentialPojo",
"v": "1.0.0"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | 完整的CredentialPojo信息 |
接口返回示例:
{
"respBody": {
"cptId": 2000156,
"issuanceDate": 1580996777,
"context": "https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1",
"claim": {
"content": "b1016358-cf72-42be-9f4b-a18fca610fca",
"receiver": "did:weid:101:0x7ed16eca3b0737227bc986dd0f2851f644cf4754",
"weid": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa"
},
"id": "21d10ab1-75fe-4733-9f1d-f0bad71b5922",
"proof": {
"created": 1580996777,
"creator": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa#keys-0",
"salt": {
"content": "ncZ5F",
"receiver": "L0c40",
"weid": "I4aop"
},
"signatureValue": "HJPbDmoi39xgZBGi/aj1zB6VQL5QLyt4qTV6GOvQwzfgUJEZTazKZXe1dRg5aCt8Q44GwNF2k+l1rfhpY1hc/ls=",
"type": "Secp256k1"
},
"type": [
"VerifiableCredential",
"hashTree"
],
"issuer": "did:weid:101:0xfd28ad212a2de77fee518b4914b8579a40c601fa",
"expirationDate": 4111737153
},
"errorCode": 0,
"errorMessage": "success"
}
请注意,这个生成的CredentialPojo的签名值(proof中的signatureValue项)并没有经过私钥签名。正确的签名方式包括下面几步: - base64解码,生成一个二进制字节数组 - 对解码的byte[]做一次secp256k1或sm3的hash - 对完成hash过byte[],再做一次hash(如果您使用的是Java web3sdk的SignMessage(),这一步它替您完成了) - 传入私钥,进行签名,得到r,s,v - 对进行序列化 - 把序列化的byte进行base64编码发回RestService
使用ECDSA或SM2私钥进行签名和Base64编码的范例代码见下(Java和Go):
RsvSignature signature = DataToolUtils.signToRsvSignature(new String(DataToolUtils.base64Decode(signatureValue)), privateKey);
base64SignatureValue := credentialEncodeResponse.RespBody.Proof.SignatureValue
signatureValue, err3 := base64.StdEncoding.DecodeString(base64SignatureValue)
hashedMsg := Hash(signatureValue)
doubleHashedMsg := Hash(hashedMsg)
privateKeyBytes := ConvertPrivateKeyBigIntToPrivateKeyBytes(privateKeyBigInt)
signatureBytes, err4 := SignSignature(doubleHashedMsg, privateKeyBytes)
signatureBase64String := base64.StdEncoding.EncodeToString(signatureBytes)
WeIdentity Endpoint Service API¶
1. 获取所有已注册的Endpoint信息¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/endpoint |
Method | GET |
Content-Type | application/json |
接口入参:无
接口返回:
{
"ErrorCode": 0,
"ErrorMessage": "success",
"respBody": [
{
"requestName": "create-passphrase",
"inAddr": [
"127.0.0.1:6010",
"127.0.0.1:6011"
],
"description": "Create a valid random passphrase"
},
{
"requestName": "verify-passphrase",
"inAddr": [
"127.0.0.1:6012",
"127.0.0.1:6013"
],
"description": "Verify a passphrase"
}
]
}
2. 进行Endpoint调用¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/endpoint/{endpoint} |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
/{endpoint} | 在API路径中标明的API名,String | Y |
body | 以```分隔的多个传入服务端用于执行API的参数 | Y |
接口入参示例:
{
"body": "did:weid:0xfd28ad212a2de77fee518b4914b8579a40c601fa```25"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | SDK侧的返回值,String |
接口返回:
{
"ErrorCode": 0,
"ErrorMessage": "success",
"respBody": "did:weid:0x1Ae5b88d37327830307ab8da0ec5D8E8692A35D3",
}
WeIdentity 数据授权 API¶
调用接口:
标题 | 描述 |
---|---|
接口名 | weid/api/authorize/fetch-data |
Method | POST |
Content-Type | application/json |
接口入参:
Key | Value | Required |
---|---|---|
authToken | CPT101数据授权凭证,需通过DataToolUtils.serialize()方式生成 | Y |
signedNonce | 签名的Nonce值(当前暂不校验,可任意填入) | Y |
接口入参示例:
{
"authToken": {
"claim": {
"duration": 360000,
"fromWeId": "did:weid:101:0x69cd071e4be5fd878e1519ff476563dc2f4c6168",
"resourceId": "4b077c17-9612-42ee-9e36-3a3d46b27e81",
"serviceUrl": "http://127.0.0.1:6010/fetch-data",
"toWeId": "did:weid:101:0x68bedb2cbe55b4c8e3473faa63f121c278f6dba9"
},
"context": "https://github.com/WeBankBlockchain/WeIdentity/blob/master/context/v1",
"cptId": 101,
"expirationDate": 1581347039,
"id": "48b75424-9411-4d22-b925-4e730b445a31",
"issuanceDate": 1580987039,
"issuer": "did:weid:101:0x69cd071e4be5fd878e1519ff476563dc2f4c6168",
"proof": {
"created": 1580987039,
"creator": "did:weid:101:0x69cd071e4be5fd878e1519ff476563dc2f4c6168#keys-0",
"salt": {
"duration": "fmk5A",
"fromWeId": "DEvFy",
"resourceId": "ugVeN",
"serviceUrl": "nVdeE",
"toWeId": "93Z1E"
},
"signatureValue": "HCZwyTzGst87cjCDaUEzPrO8QRlsPvCYXvRTUVBUTDKRSoGDgu4h4HLrMZ+emDacRnmQ/yke38u1jBnilNnCh6c=",
"type": "Secp256k1"
},
"type": ["VerifiableCredential", "hashTree"]
},
"signedNonce": "123123"
}
接口返回: application/json
Key | Value |
---|---|
ErrorCode | 错误码,0表示成功 |
ErrorMessage | 错误信息 |
respBody | SDK侧的返回值,String |
接口返回:
{
"ErrorCode": 0,
"ErrorMessage": "success",
"respBody": "sample data",
}