# TransTrust使用示例 ## 案例:土地证可流转凭证及流转管理 ### 背景 土地证是由地方人民政府颁发的,证明持证人对一定面积的土地享有所有权或使用权的书面文件,是持证人享有土地所有权或使用权的法律凭证。纸质土地证不易管理和保存,遗失补办程序和流转变更程序复杂,土地证持有者需要提供各种有效证明;在土地证抵押贷款等场景中,土地证的持有人身份变更不透明,不利于监管。通过使用TransTrust签发土地证可流转凭证,结合经过KYC验证的TransTrust DID,对于政府部门而言,可以提高土地证签发管理效率,在保护民众的隐私基础上增加了土地证的流转透明性,土地证的真实性验证也更加方便可靠。 ### 参与方 - 国家土地管理部门 - 各地方政府部门 - 土地拥有者(民众或企业) - 土地证验证机构 ### 解决方案及基本流程 本示例以国家土地管理部门作为TransTrust整体服务的系统管理员,逐步描述各个参与方如何通过使用TransTrust SDK来完成各个流程的操作。假设已经搭建了[FISCOBCOS区块链](https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/),在Java项目中引入TransTrust SDK后直接调用SDK接口。TransTrust SDK的使用可以参考[ TransTrust-demo](../Components/Demo/index.html)。 #### 1.TransTrust服务部署 本示例以[ TransTrust-demo](../Components/Demo/index.html)服务进行说明。通过swagger进行接口展示。 ![](../../images/demo/view.png) #### 2.公私钥生成 各参与方生成各自的公私钥,自己保存。 ![](../../images/demo/key_create.png) ![](../../images/demo/key_info.png) #### 3.TransTrust服务部署 国家土地管理部门作为系统管理员,部署WeID相关合约。使用自己的私钥,并设置链编号。合约部署后合约地址等相关信息会保存到工程根目录。 ![](../../images/demo/deploy.png) #### 4.DID创建 TransTrust服务初始化后,各个参与方都需要创建一个DID身份才能参与。 ```java /** * 根据公私钥创建weid. */ public ResponseData createWeIdAndSetAttr(String publicKey, String privateKey) { // create weId using the incoming public and private keys CreateWeIdArgs createWeIdArgs = new CreateWeIdArgs(); createWeIdArgs.setPublicKey(publicKey); createWeIdArgs.setWeIdPrivateKey(new WeIdPrivateKey()); createWeIdArgs.getWeIdPrivateKey().setPrivateKey(privateKey); ResponseData createResult = ctDIDClient.createWeId(createWeIdArgs); logger.info("createWeIdAndSetAttr response:{}", createResult); if (createResult.getErrorCode().intValue() != ErrorCode.SUCCESS.getCode()) { return createResult; } return createResult; } ``` 创建示例 ![](../../images/demo/did_create.png) ![](../../images/demo/did_info.png) #### 5.创建土地证CPT 国家土地管理部门首先要创建土地证的凭证模板CPT,即所有的土地证凭证都以土地证CPT的格式显示。在创建之前根据`json-schema`的格式,确定土地证特有属性字段及其数据类型和描述,示例: ```json { "cptDescription": "unit land certificate", "cptId": 2000000, "cptManagment": "0x57bc072ab8af771c0978f94bd3c9c76ad0cc6eff", "cptName": "landcertificate", "credentialType": { "cptTradeToken": "0x45d617c5157e9a07ac570d18692d362c3e50c852" }, "privateKey": "28354348400257293578085204282790324607891232742724770334587266909072589459877", "properties": { "claim": { "certificateNumber": { "type": "string", "description": "certificate number" }, "landType": { "type": "string", "description": "land type" }, "totalArea": { "type": "string", "description": "total area" }, "exclusiveArea": { "type": "string", "description": "exclusive area" }, "sharingArea": { "type": "string", "description": "sharing area" }, "useType": { "type": "string", "description": "use type" }, "landNumber": { "type": "string", "description": "land number" }, "holder": { "type": "string", "description": "holder" }, "gettingPrice": { "type": "string", "description": "getting price" }, "site": { "type": "string", "description": "site" } } }, "required": [ "landType", "totalArea" ], "supervisable": false, "url": "http://TransTrust.com", "weId": "did:weid:100:0x1cd7fa8518c82d5b87fd5a150930a30471b58906" } ``` 其中`privateKey`和`weId`为国家土地管理部门的私钥和DID。其他相关字段意义可以查看[TransTrust CPT规范](../CoreConcepts/CPT.html#id1)。调用CPT的registerCpt接口将CPT上传到区块链,返回创建的CPT的基本信息。 ```java /** * 注册cpt. */ public ResponseData registerCpt(CptModel cptModel) { CTCptMapArgs ctCptMapArgs = new CTCptMapArgs(); BeanUtils.copyProperties(cptModel, ctCptMapArgs); // 将CPT创建者的DID放进Credential构建参数对象 WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); weIdAuthentication.setWeId(cptModel.getWeId()); weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); weIdAuthentication.getWeIdPrivateKey().setPrivateKey(cptModel.getPrivateKey()); ctCptMapArgs.setWeIdAuthentication(weIdAuthentication); // 是否指定CptId ResponseData response = new ResponseData(); if (cptModel.getCptId() == null) { response = ctCptClient.registerCpt(ctCptMapArgs); } else { response = ctCptClient.registerCpt(ctCptMapArgs, cptModel.getCptId()); } return response; } ``` 创建示例: ![](../../images/demo/cpt_create.png) ![](../../images/demo/cpt_create_back.png) 可以通过查询接口查询详细信息: ![](../../images/demo/cpt_info.png) #### 6.签发土地证可流转凭证 各地方政府部门(issuer)可以根据已创建的土地证CPT向土地拥有者(recipient)签发土地证可流转凭证。调用Credential服务的createCredential接口,生成一个完整的土地证可流转凭证以及转化成规范化格式,即TransTrust CPT所规定的格式。规范化的土地证可流转凭证可以通过转化成json字符串导出到文件中,用户可以直接使用该文件来流转,展示和验证。模板: ```json { "claim": { "certificateNumber": "123456", "landType": "commerce", "totalArea": "15568.26m^2", "exclusiveArea": "14000m^2", "sharingArea": "1568.26m^2", "useType": "selling", "landNumber": "56-20-12", "holder": "China Evergrande", "gettingPrice": "500,000,000RMB", "site": "ShaHe XiLu 001" }, "cptId": 2000000, "issuer": "did:weid:100:0x6e97e5ba180a78cbf8f31ff4925d5072ceeb0c26", "issuerName": "China Land Managment", "privateKey": "30119508104847753222987231185900755642033370932964041072306491196350521581647", "recipient": "did:weid:100:0x05485b6415dfbcaa370a5b2724646e97ff7a7ac2", "recipientName": "China Evergrande" } ``` ```java /** * 创建电子凭证. */ public ResponseData createCredential( CreateCredentialPojoModel createCredentialPojoModel) { // 设置CPT相关信息 CTCreateCredentialPojoArgs ctCreateCredentialPojoArgs = new CTCreateCredentialPojoArgs(); BeanUtils.copyProperties(createCredentialPojoModel, ctCreateCredentialPojoArgs); String weId = createCredentialPojoModel.getIssuer(); // 将地方政府部门的DID放进Credential构建参数对象 WeIdAuthentication weIdAuthentication = new WeIdAuthentication(); weIdAuthentication.setWeId(weId); weIdAuthentication.setWeIdPrivateKey(new WeIdPrivateKey()); weIdAuthentication.getWeIdPrivateKey() .setPrivateKey(createCredentialPojoModel.getPrivateKey()); weIdAuthentication.setWeIdPublicKeyId(weId + "key-0"); ctCreateCredentialPojoArgs.setWeIdAuthentication(weIdAuthentication); // 设置凭证超时时间 ctCreateCredentialPojoArgs .setExpirationDate(System.currentTimeMillis() + 1000L * 60 * 60 * 24 * 365 * 100); // 设置发行者 Map issuer = new HashMap(2); issuer.put("WeID", weId); issuer.put("name", createCredentialPojoModel.getIssuerName()); ctCreateCredentialPojoArgs.setIssuer(issuer); // 设置接收者 Map recipient = new HashMap(2); recipient.put("WeID", createCredentialPojoModel.getRecipient()); recipient.put("name", createCredentialPojoModel.getRecipientName()); ctCreateCredentialPojoArgs.setRecipient(recipient); // 创建凭证 ResponseData data = ctCredentialClient.createCredential(ctCreateCredentialPojoArgs); log.info("createCredential CTCredentialPojo:{}", DataToolUtils.serialize(data.getResult())); return data; } ``` 创建示例: ![](../../images/demo/credential_create.png) ![](../../images/demo/credential_info.png) #### 7.验证电子凭证 验证电子凭证,模板: ```json { "credential": { "$schema": "http://json-schema.org/draft-04/schema#", "context": "https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1", "cptBaseInfo": { "cptId": 2000000, "cptVersion": 1 }, "ctCptMapArgs": { "cptDescription": "unit land certificate", "cptManagment": "0x57bc072ab8af771c0978f94bd3c9c76ad0cc6eff", "cptName": "landcertificate", "cptType": "ORIGINAL", "credentialType": { "cptTradeToken": "0x45d617c5157e9a07ac570d18692d362c3e50c852" }, "properties": {}, "required": [ "landType", "totalArea" ], "supervisable": "false", "url": "http://TransTrust.com", "weIdAuthentication": {} }, "docType": [ "VerifiableCredential", "original" ], "metaData": { "cptPublisher": "did:weid:100:0x1cd7fa8518c82d5b87fd5a150930a30471b58906", "cptSignature": "ATdzmrl6hLaKW3RH/peDNiXnJolMQbCvPTt7PVklWPpnc5ZlGcUA3S08mbZG8aEvST6gLKBhPRQ5DpM/rdZbOmM=", "created": 1636710016, "updated": 0 }, "proof": { "created": 1636714893, "creator": "did:weid:100:0x6e97e5ba180a78cbf8f31ff4925d5072ceeb0c26key-0", "salt": { "certificateNumber": "xaIml", "exclusiveArea": "4sHra", "gettingPrice": "6B4kI", "holder": "Ys7eO", "landNumber": "DDoNN", "landType": "jPWy9", "sharingArea": "9ieHs", "site": "AHu5c", "totalArea": "rjIpJ", "useType": "Re4fL" }, "signatureValue": "zTiHgyHMWf6kQw+6sg/OGTiinb4/3vTb0zfCGToDrqVN6vAbkS2AnirAhW74GbxeR6cikyMY16pbq/gNxIRwqwA=", "type": "Secp256k1" }, "properties": { "claim": { "certificateNumber": "123456", "exclusiveArea": "14000m^2", "gettingPrice": "500,000,000RMB", "holder": "China Evergrande", "landNumber": "56-20-12", "landType": "commerce", "sharingArea": "1568.26m^2", "site": "ShaHe XiLu 001", "totalArea": "15568.26m^2", "useType": "selling" }, "expirationDate": 4790314893, "id": "1dc6d2b1-a7f6-4eed-82d0-af31363efe7c", "issuanceDate": 1636714893, "issuer": { "WeID": "did:weid:100:0x6e97e5ba180a78cbf8f31ff4925d5072ceeb0c26", "name": "China Land Managment" }, "recipient": { "WeID": "did:weid:100:0x05485b6415dfbcaa370a5b2724646e97ff7a7ac2", "name": "China Evergrande" } }, "type": "object" }, "issuerWeId": "did:weid:100:0x6e97e5ba180a78cbf8f31ff4925d5072ceeb0c26" } ``` 验证: ![](../../images/demo/credential_verify.png) ![](../../images/demo/credential_result.png) #### 8.选择性披露 创建选择性披露电子凭证,模板: ```json { "credential": { "$schema": "http://json-schema.org/draft-04/schema#", "context": "https://github.com/WeBankFinTech/WeIdentity/blob/master/context/v1", "cptBaseInfo": { "cptId": 2000000, "cptVersion": 1 }, "ctCptMapArgs": { "cptDescription": "unit land certificate", "cptManagment": "0x57bc072ab8af771c0978f94bd3c9c76ad0cc6eff", "cptName": "landcertificate", "cptType": "ORIGINAL", "credentialType": { "cptTradeToken": "0x45d617c5157e9a07ac570d18692d362c3e50c852" }, "properties": {}, "required": [ "landType", "totalArea" ], "supervisable": "false", "url": "http://chinatrust.com", "weIdAuthentication": {} }, "docType": [ "VerifiableCredential", "original" ], "metaData": { "cptPublisher": "did:weid:100:0x1cd7fa8518c82d5b87fd5a150930a30471b58906", "cptSignature": "ATdzmrl6hLaKW3RH/peDNiXnJolMQbCvPTt7PVklWPpnc5ZlGcUA3S08mbZG8aEvST6gLKBhPRQ5DpM/rdZbOmM=", "created": 1636710016, "updated": 0 }, "proof": { "created": 1636714893, "creator": "did:weid:100:0x6e97e5ba180a78cbf8f31ff4925d5072ceeb0c26key-0", "salt": { "certificateNumber": "xaIml", "exclusiveArea": "4sHra", "gettingPrice": "6B4kI", "holder": "Ys7eO", "landNumber": "DDoNN", "landType": "jPWy9", "sharingArea": "9ieHs", "site": "AHu5c", "totalArea": "rjIpJ", "useType": "Re4fL" }, "signatureValue": "zTiHgyHMWf6kQw+6sg/OGTiinb4/3vTb0zfCGToDrqVN6vAbkS2AnirAhW74GbxeR6cikyMY16pbq/gNxIRwqwA=", "type": "Secp256k1" }, "properties": { "claim": { "certificateNumber": "123456", "exclusiveArea": "14000m^2", "gettingPrice": "500,000,000RMB", "holder": "China Evergrande", "landNumber": "56-20-12", "landType": "commerce", "sharingArea": "1568.26m^2", "site": "ShaHe XiLu 001", "totalArea": "15568.26m^2", "useType": "selling" }, "expirationDate": 4790314893, "id": "1dc6d2b1-a7f6-4eed-82d0-af31363efe7c", "issuanceDate": 1636714893, "issuer": { "WeID": "did:weid:100:0x6e97e5ba180a78cbf8f31ff4925d5072ceeb0c26", "name": "China Land Managment" }, "recipient": { "WeID": "did:weid:100:0x05485b6415dfbcaa370a5b2724646e97ff7a7ac2", "name": "China Evergrande" } }, "type": "object" }, "fieldsToBeDisclosed": { "landNumber": 1, "gettingPrice": 1, "totalArea": 1 } } ``` ```java /** * 通过原始凭证和披漏策略,创建选择性披露的电子凭证. */ public ResponseData createSelectiveCredential( CreateSelectiveCredentialModel model) { try { if (null == model || null == model.getCredential() || model.getCredential().isEmpty() || null == model.getFieldsToBeDisclosed() || model.getFieldsToBeDisclosed().isEmpty()) { return new ResponseData<>(null, ErrorCode.ILLEGAL_INPUT); } CTCredentialPojo ctCredentialPojo = DataToolUtils.mapToObj(model.getCredential(), CTCredentialPojo.class); // 选择性披露 ClaimPolicy claimPolicy = new ClaimPolicy(); claimPolicy.setFieldsToBeDisclosed( DataToolUtils.objToJsonStrWithNoPretty(model.getFieldsToBeDisclosed())); ResponseData data = ctCredentialClient.createSelectiveCredential(ctCredentialPojo, claimPolicy); log.info("createSelectiveCredential CTCredentialPojo:{}", DataToolUtils.serialize(data.getResult())); return data; } catch (Exception e) { logger.error("{} error", e); return new ResponseData<>(null, ErrorCode.TRANSACTION_EXECUTE_ERROR); } } ``` 创建示例: ![](../../images/demo/selective_credential_create.png)